Commit a0ace8a8 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm] Interpret table.grow result as 32 bit

In Liftoff, the result of table.grow was smi-untagged and sign-extended
to a ptr-sized value. However the result is typed as i32, so the upper
32 bits should be cleared on 64 bit platforms. In particular this is
observable when the value is used as an index for a memory operand,
which leads to the repro in the attached issue.

Match the TF behavior by untagging the value as a 32-bit int.

R=clemensb@chromium.org
CC=ahaas@chromium.org

Bug: chromium:1251465
Change-Id: Ia57fd8a69ecb2787b42bbf8217e448976aa1dbd9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3173680Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77044}
parent 4e769f09
......@@ -518,6 +518,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
mov(dst, Operand::SmiUntag(src), s);
}
void SmiToInt32(Register smi) { SmiUntag(smi); }
// Load an object from the root table.
void LoadRoot(Register destination, RootIndex index) final {
LoadRoot(destination, index, al);
......
......@@ -1091,6 +1091,19 @@ void TurboAssembler::SmiUntag(Register dst, const MemOperand& src) {
void TurboAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); }
void TurboAssembler::SmiToInt32(Register smi) {
DCHECK(smi.Is64Bits());
if (FLAG_enable_slow_asserts) {
AssertSmi(smi);
}
DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
if (COMPRESS_POINTERS_BOOL) {
Asr(smi.W(), smi.W(), kSmiShift);
} else {
Lsr(smi, smi, kSmiShift);
}
}
void TurboAssembler::JumpIfSmi(Register value, Label* smi_label,
Label* not_smi_label) {
STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0));
......
......@@ -559,6 +559,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
inline void SmiUntag(Register dst, const MemOperand& src);
inline void SmiUntag(Register smi);
inline void SmiToInt32(Register smi);
// Calls Abort(msg) if the condition cond is not satisfied.
// Use --debug_code to enable.
void Assert(Condition cond, AbortReason reason);
......
......@@ -199,6 +199,8 @@ class V8_EXPORT_PRIVATE TurboAssembler
SmiUntag(output);
}
void SmiToInt32(Register reg) { SmiUntag(reg); }
// Before calling a C-function from generated code, align arguments on stack.
// After aligning the frame, arguments must be stored in esp[0], esp[4],
// etc., not pushed. The argument count assumes all arguments are word sized.
......
......@@ -1356,6 +1356,16 @@ void TurboAssembler::SmiUntag(Register dst, Operand src) {
}
}
void TurboAssembler::SmiToInt32(Register reg) {
STATIC_ASSERT(kSmiTag == 0);
DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
if (COMPRESS_POINTERS_BOOL) {
sarl(reg, Immediate(kSmiShift));
} else {
shrq(reg, Immediate(kSmiShift));
}
}
void TurboAssembler::SmiCompare(Register smi1, Register smi2) {
AssertSmi(smi1);
AssertSmi(smi2);
......
......@@ -352,6 +352,9 @@ class V8_EXPORT_PRIVATE TurboAssembler
void SmiUntag(Register dst, Register src);
void SmiUntag(Register dst, Operand src);
// Convert smi to 32-bit value.
void SmiToInt32(Register reg);
// Loads the address of the external reference into the destination
// register.
void LoadAddress(Register destination, ExternalReference source);
......
......@@ -4897,7 +4897,7 @@ class LiftoffCompiler {
__ cache_state()->stack_state.pop_back(2);
RegisterDebugSideTableEntry(decoder, DebugSideTableBuilder::kDidSpill);
__ SmiUntag(kReturnRegister0);
__ SmiToInt32(kReturnRegister0);
__ PushRegister(kI32, LiftoffRegister(kReturnRegister0));
}
......
// Copyright 2021 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.
// Flags: --wasm-staging --experimental-wasm-gc --liftoff-only
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addMemory(16, 32, false, false);
builder.addType(makeSig([], [kWasmI32]));
builder.addTable(kWasmFuncRef, 1, 1, undefined)
builder.addFunction(undefined, 0 /* sig */)
.addBodyWithEnd([
kExprI32Const, 0x00,
kExprI32Const, 0x00,
kExprTableGet, 0x00,
kExprI32Const, 0xff, 0x01,
kNumericPrefix, kExprTableGrow, 0x00,
kExprF32Const, 0x00, 0x00, 0x00, 0x00,
kExprF32StoreMem, 0x00, 0x01,
kExprEnd
]);
builder.addExport('main', 0);
const instance = builder.instantiate();
assertThrows(() => instance.exports.main(), WebAssembly.RuntimeError);
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