Commit 10dc8ef0 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[arm64][x64][liftoff] Fix trap handling on load lane

This is a reland of 1786f8d7. It turned
out that also x64 is broken, and only for TurboFan. Both is fixed now.

Original change's description:
> [arm64][liftoff] Fix trap handling on load lane
>
> This fixes the registered {protected_load_pc} to (always) point to the
> actual load instruction. If {dst != src} we would emit a register move
> before the load, and the trap handler would then not recognize the PC
> where the signal occurs, leading to a segfault.
>
> R=thibaudm@chromium.org
>
> Bug: chromium:1242300, v8:12018
> Change-Id: I3ed2a8307e353fd85a7ddedf6ecb73e90a112d32
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3136454
> Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
> Commit-Queue: Clemens Backes <clemensb@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#76642}

Bug: chromium:1242300, v8:12018
Change-Id: I79284ab9815f5363f759569d98c8c4b52d48e738
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3140609Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76698}
parent 54f66184
...@@ -2024,16 +2024,17 @@ using NoAvxFn = void (Assembler::*)(XMMRegister, Src, uint8_t); ...@@ -2024,16 +2024,17 @@ using NoAvxFn = void (Assembler::*)(XMMRegister, Src, uint8_t);
template <typename Src> template <typename Src>
void PinsrHelper(Assembler* assm, AvxFn<Src> avx, NoAvxFn<Src> noavx, void PinsrHelper(Assembler* assm, AvxFn<Src> avx, NoAvxFn<Src> noavx,
XMMRegister dst, XMMRegister src1, Src src2, uint8_t imm8, XMMRegister dst, XMMRegister src1, Src src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr,
base::Optional<CpuFeature> feature = base::nullopt) { base::Optional<CpuFeature> feature = base::nullopt) {
if (CpuFeatures::IsSupported(AVX)) { if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(assm, AVX); CpuFeatureScope scope(assm, AVX);
if (load_pc_offset) *load_pc_offset = assm->pc_offset();
(assm->*avx)(dst, src1, src2, imm8); (assm->*avx)(dst, src1, src2, imm8);
return; return;
} }
if (dst != src1) { if (dst != src1) assm->movaps(dst, src1);
assm->movaps(dst, src1); if (load_pc_offset) *load_pc_offset = assm->pc_offset();
}
if (feature.has_value()) { if (feature.has_value()) {
DCHECK(CpuFeatures::IsSupported(*feature)); DCHECK(CpuFeatures::IsSupported(*feature));
CpuFeatureScope scope(assm, *feature); CpuFeatureScope scope(assm, *feature);
...@@ -2045,40 +2046,41 @@ void PinsrHelper(Assembler* assm, AvxFn<Src> avx, NoAvxFn<Src> noavx, ...@@ -2045,40 +2046,41 @@ void PinsrHelper(Assembler* assm, AvxFn<Src> avx, NoAvxFn<Src> noavx,
} // namespace } // namespace
void TurboAssembler::Pinsrb(XMMRegister dst, XMMRegister src1, Register src2, void TurboAssembler::Pinsrb(XMMRegister dst, XMMRegister src1, Register src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrb, &Assembler::pinsrb, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrb, &Assembler::pinsrb, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
} }
void TurboAssembler::Pinsrb(XMMRegister dst, XMMRegister src1, Operand src2, void TurboAssembler::Pinsrb(XMMRegister dst, XMMRegister src1, Operand src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrb, &Assembler::pinsrb, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrb, &Assembler::pinsrb, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
} }
void TurboAssembler::Pinsrw(XMMRegister dst, XMMRegister src1, Register src2, void TurboAssembler::Pinsrw(XMMRegister dst, XMMRegister src1, Register src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrw, &Assembler::pinsrw, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrw, &Assembler::pinsrw, dst, src1, src2,
imm8); imm8, load_pc_offset);
} }
void TurboAssembler::Pinsrw(XMMRegister dst, XMMRegister src1, Operand src2, void TurboAssembler::Pinsrw(XMMRegister dst, XMMRegister src1, Operand src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrw, &Assembler::pinsrw, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrw, &Assembler::pinsrw, dst, src1, src2,
imm8); imm8, load_pc_offset);
} }
void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Register src2, void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Register src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
// Need a fall back when SSE4_1 is unavailable. Pinsrb and Pinsrq are used // Need a fall back when SSE4_1 is unavailable. Pinsrb and Pinsrq are used
// only by Wasm SIMD, which requires SSE4_1 already. // only by Wasm SIMD, which requires SSE4_1 already.
if (CpuFeatures::IsSupported(SSE4_1)) { if (CpuFeatures::IsSupported(SSE4_1)) {
PinsrHelper(this, &Assembler::vpinsrd, &Assembler::pinsrd, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrd, &Assembler::pinsrd, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
return; return;
} }
Movd(kScratchDoubleReg, src2); Movd(kScratchDoubleReg, src2);
if (load_pc_offset) *load_pc_offset = pc_offset();
if (imm8 == 1) { if (imm8 == 1) {
punpckldq(dst, kScratchDoubleReg); punpckldq(dst, kScratchDoubleReg);
} else { } else {
...@@ -2088,16 +2090,17 @@ void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Register src2, ...@@ -2088,16 +2090,17 @@ void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Register src2,
} }
void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2, void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
// Need a fall back when SSE4_1 is unavailable. Pinsrb and Pinsrq are used // Need a fall back when SSE4_1 is unavailable. Pinsrb and Pinsrq are used
// only by Wasm SIMD, which requires SSE4_1 already. // only by Wasm SIMD, which requires SSE4_1 already.
if (CpuFeatures::IsSupported(SSE4_1)) { if (CpuFeatures::IsSupported(SSE4_1)) {
PinsrHelper(this, &Assembler::vpinsrd, &Assembler::pinsrd, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrd, &Assembler::pinsrd, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
return; return;
} }
Movd(kScratchDoubleReg, src2); Movd(kScratchDoubleReg, src2);
if (load_pc_offset) *load_pc_offset = pc_offset();
if (imm8 == 1) { if (imm8 == 1) {
punpckldq(dst, kScratchDoubleReg); punpckldq(dst, kScratchDoubleReg);
} else { } else {
...@@ -2106,24 +2109,26 @@ void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2, ...@@ -2106,24 +2109,26 @@ void TurboAssembler::Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2,
} }
} }
void TurboAssembler::Pinsrd(XMMRegister dst, Register src2, uint8_t imm8) { void TurboAssembler::Pinsrd(XMMRegister dst, Register src2, uint8_t imm8,
Pinsrd(dst, dst, src2, imm8); uint32_t* load_pc_offset) {
Pinsrd(dst, dst, src2, imm8, load_pc_offset);
} }
void TurboAssembler::Pinsrd(XMMRegister dst, Operand src2, uint8_t imm8) { void TurboAssembler::Pinsrd(XMMRegister dst, Operand src2, uint8_t imm8,
Pinsrd(dst, dst, src2, imm8); uint32_t* load_pc_offset) {
Pinsrd(dst, dst, src2, imm8, load_pc_offset);
} }
void TurboAssembler::Pinsrq(XMMRegister dst, XMMRegister src1, Register src2, void TurboAssembler::Pinsrq(XMMRegister dst, XMMRegister src1, Register src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrq, &Assembler::pinsrq, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrq, &Assembler::pinsrq, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
} }
void TurboAssembler::Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2, void TurboAssembler::Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2,
uint8_t imm8) { uint8_t imm8, uint32_t* load_pc_offset) {
PinsrHelper(this, &Assembler::vpinsrq, &Assembler::pinsrq, dst, src1, src2, PinsrHelper(this, &Assembler::vpinsrq, &Assembler::pinsrq, dst, src1, src2,
imm8, base::Optional<CpuFeature>(SSE4_1)); imm8, load_pc_offset, {SSE4_1});
} }
void TurboAssembler::Absps(XMMRegister dst, XMMRegister src) { void TurboAssembler::Absps(XMMRegister dst, XMMRegister src) {
......
...@@ -418,16 +418,26 @@ class V8_EXPORT_PRIVATE TurboAssembler ...@@ -418,16 +418,26 @@ class V8_EXPORT_PRIVATE TurboAssembler
// Non-SSE2 instructions. // Non-SSE2 instructions.
void Pextrd(Register dst, XMMRegister src, uint8_t imm8); void Pextrd(Register dst, XMMRegister src, uint8_t imm8);
void Pinsrb(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8); void Pinsrb(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8,
void Pinsrb(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8); uint32_t* load_pc_offset = nullptr);
void Pinsrw(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8); void Pinsrb(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8,
void Pinsrw(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8); uint32_t* load_pc_offset = nullptr);
void Pinsrd(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8); void Pinsrw(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8,
void Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8); uint32_t* load_pc_offset = nullptr);
void Pinsrd(XMMRegister dst, Register src2, uint8_t imm8); void Pinsrw(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8,
void Pinsrd(XMMRegister dst, Operand src2, uint8_t imm8); uint32_t* load_pc_offset = nullptr);
void Pinsrq(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8); void Pinsrd(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8,
void Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8); uint32_t* load_pc_offset = nullptr);
void Pinsrd(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr);
void Pinsrd(XMMRegister dst, Register src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr);
void Pinsrd(XMMRegister dst, Operand src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr);
void Pinsrq(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr);
void Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8,
uint32_t* load_pc_offset = nullptr);
void Absps(XMMRegister dst, XMMRegister src); void Absps(XMMRegister dst, XMMRegister src);
void Negps(XMMRegister dst, XMMRegister src); void Negps(XMMRegister dst, XMMRegister src);
......
...@@ -1000,24 +1000,23 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen, ...@@ -1000,24 +1000,23 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
} \ } \
} while (false) } while (false)
#define ASSEMBLE_PINSR(ASM_INSTR) \ #define ASSEMBLE_PINSR(ASM_INSTR) \
do { \ do { \
EmitOOLTrapIfNeeded(zone(), this, opcode, instr, __ pc_offset()); \ XMMRegister dst = i.OutputSimd128Register(); \
XMMRegister dst = i.OutputSimd128Register(); \ XMMRegister src = i.InputSimd128Register(0); \
XMMRegister src = i.InputSimd128Register(0); \ uint8_t laneidx = i.InputUint8(1); \
uint8_t laneidx = i.InputUint8(1); \ uint32_t load_offset; \
if (HasAddressingMode(instr)) { \ if (HasAddressingMode(instr)) { \
__ ASM_INSTR(dst, src, i.MemoryOperand(2), laneidx); \ __ ASM_INSTR(dst, src, i.MemoryOperand(2), laneidx, &load_offset); \
break; \ } else if (instr->InputAt(2)->IsFPRegister()) { \
} \ __ Movq(kScratchRegister, i.InputDoubleRegister(2)); \
if (instr->InputAt(2)->IsFPRegister()) { \ __ ASM_INSTR(dst, src, kScratchRegister, laneidx, &load_offset); \
__ Movq(kScratchRegister, i.InputDoubleRegister(2)); \ } else if (instr->InputAt(2)->IsRegister()) { \
__ ASM_INSTR(dst, src, kScratchRegister, laneidx); \ __ ASM_INSTR(dst, src, i.InputRegister(2), laneidx, &load_offset); \
} else if (instr->InputAt(2)->IsRegister()) { \ } else { \
__ ASM_INSTR(dst, src, i.InputRegister(2), laneidx); \ __ ASM_INSTR(dst, src, i.InputOperand(2), laneidx, &load_offset); \
} else { \ } \
__ ASM_INSTR(dst, src, i.InputOperand(2), laneidx); \ EmitOOLTrapIfNeeded(zone(), this, opcode, instr, load_offset); \
} \
} while (false) } while (false)
#define ASSEMBLE_SEQ_CST_STORE(rep) \ #define ASSEMBLE_SEQ_CST_STORE(rep) \
......
...@@ -1707,13 +1707,13 @@ void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src, ...@@ -1707,13 +1707,13 @@ void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src,
UseScratchRegisterScope temps(this); UseScratchRegisterScope temps(this);
MemOperand src_op{ MemOperand src_op{
liftoff::GetEffectiveAddress(this, &temps, addr, offset_reg, offset_imm)}; liftoff::GetEffectiveAddress(this, &temps, addr, offset_reg, offset_imm)};
*protected_load_pc = pc_offset();
MachineType mem_type = type.mem_type(); MachineType mem_type = type.mem_type();
if (dst != src) { if (dst != src) {
Mov(dst.fp().Q(), src.fp().Q()); Mov(dst.fp().Q(), src.fp().Q());
} }
*protected_load_pc = pc_offset();
if (mem_type == MachineType::Int8()) { if (mem_type == MachineType::Int8()) {
ld1(dst.fp().B(), laneidx, src_op); ld1(dst.fp().B(), laneidx, src_op);
} else if (mem_type == MachineType::Int16()) { } else if (mem_type == MachineType::Int16()) {
......
...@@ -2407,18 +2407,17 @@ void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src, ...@@ -2407,18 +2407,17 @@ void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src,
uintptr_t offset_imm, LoadType type, uintptr_t offset_imm, LoadType type,
uint8_t laneidx, uint32_t* protected_load_pc) { uint8_t laneidx, uint32_t* protected_load_pc) {
Operand src_op = liftoff::GetMemOp(this, addr, offset_reg, offset_imm); Operand src_op = liftoff::GetMemOp(this, addr, offset_reg, offset_imm);
*protected_load_pc = pc_offset();
MachineType mem_type = type.mem_type(); MachineType mem_type = type.mem_type();
if (mem_type == MachineType::Int8()) { if (mem_type == MachineType::Int8()) {
Pinsrb(dst.fp(), src.fp(), src_op, laneidx); Pinsrb(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc);
} else if (mem_type == MachineType::Int16()) { } else if (mem_type == MachineType::Int16()) {
Pinsrw(dst.fp(), src.fp(), src_op, laneidx); Pinsrw(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc);
} else if (mem_type == MachineType::Int32()) { } else if (mem_type == MachineType::Int32()) {
Pinsrd(dst.fp(), src.fp(), src_op, laneidx); Pinsrd(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc);
} else { } else {
DCHECK_EQ(MachineType::Int64(), mem_type); DCHECK_EQ(MachineType::Int64(), mem_type);
Pinsrq(dst.fp(), src.fp(), src_op, laneidx); Pinsrq(dst.fp(), src.fp(), src_op, laneidx, protected_load_pc);
} }
} }
......
...@@ -1478,8 +1478,9 @@ ...@@ -1478,8 +1478,9 @@
############################################################################## ##############################################################################
['variant == instruction_scheduling or variant == stress_instruction_scheduling', { ['variant == instruction_scheduling or variant == stress_instruction_scheduling', {
# BUG(12018): This test currently fails with --turbo-instruction-scheduling. # BUG(12018): These tests currently fail with --turbo-instruction-scheduling.
'regress/wasm/regress-1231950': [SKIP], 'regress/wasm/regress-1231950': [SKIP],
'regress/wasm/regress-1242300': [SKIP],
}], # variant == instruction_scheduling or variant == stress_instruction_scheduling }], # variant == instruction_scheduling or variant == stress_instruction_scheduling
################################################################################ ################################################################################
......
// 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.
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addMemory(16, 32);
builder.addFunction(undefined, kSig_i_iii)
.addBody([
kExprI32Const, 0x7f, // i32.const
kExprI32Const, 0x1e, // i32.const
kSimdPrefix, kExprI8x16Splat, // i8x16.splat
kExprI32Const, 0, // i32.const
kSimdPrefix, kExprI8x16Splat, // i8x16.splat
kExprI32Const, 0, // i32.const
kSimdPrefix, kExprI8x16Splat, // i8x16.splat
kSimdPrefix, kExprS128Select, // s128.select
kSimdPrefix, kExprS128Load32Lane, 0x00, 0x89, 0xfe, 0x03, 0x00, // s128.load32_lane
kExprUnreachable,
]);
builder.addExport('main', 0);
const instance = builder.instantiate();
assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(1, 2, 3));
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