Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/v8/include/v8-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 14
#define V8_MINOR_VERSION 2
#define V8_BUILD_NUMBER 231
#define V8_PATCH_LEVEL 14
#define V8_PATCH_LEVEL 16

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
33 changes: 27 additions & 6 deletions deps/v8/src/codegen/loong64/macro-assembler-loong64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,18 +194,34 @@ void MacroAssembler::PreCheckSkippedWriteBarrier(Register object,
bind(&not_ok);
}

void MacroAssembler::MaybeJumpIfReadOnlyOrSmallSmi(Register value,
Label* dest) {
#if V8_STATIC_ROOTS_BOOL
// Quick check for Read-only and small Smi values.
static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize);
JumpIfUnsignedLessThan(value, kRegularPageSize, dest);
#endif // V8_STATIC_ROOTS_BOOL
}

// Clobbers object, dst, value, and ra, if (ra_status == kRAHasBeenSaved)
// The register 'object' contains a heap object pointer. The heap object
// tag is shifted away.
void MacroAssembler::RecordWriteField(Register object, int offset,
Register value, RAStatus ra_status,
SaveFPRegsMode save_fp,
SmiCheck smi_check, SlotDescriptor slot) {
SmiCheck smi_check,
ReadOnlyCheck ro_check,
SlotDescriptor slot) {
ASM_CODE_COMMENT(this);
DCHECK(!AreAliased(object, value));
// First, check if a write barrier is even needed. The tests below
// catch stores of Smis.
// catch stores of Smis and read-only objects.
Label done;

if (ro_check == ReadOnlyCheck::kInline) {
MaybeJumpIfReadOnlyOrSmallSmi(value, &done);
}

// Skip barrier if writing a smi.
if (smi_check == SmiCheck::kInline) {
JumpIfSmi(value, &done);
Expand All @@ -228,7 +244,7 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
}

RecordWrite(object, Operand(offset - kHeapObjectTag), value, ra_status,
save_fp, SmiCheck::kOmit, slot);
save_fp, SmiCheck::kOmit, ReadOnlyCheck::kOmit, slot);

bind(&done);
}
Expand Down Expand Up @@ -703,7 +719,7 @@ void MacroAssembler::MoveObjectAndSlot(Register dst_object, Register dst_slot,
void MacroAssembler::RecordWrite(Register object, Operand offset,
Register value, RAStatus ra_status,
SaveFPRegsMode fp_mode, SmiCheck smi_check,
SlotDescriptor slot) {
ReadOnlyCheck ro_check, SlotDescriptor slot) {
DCHECK(!AreAliased(object, value));

if (v8_flags.slow_debug_code) {
Expand All @@ -726,9 +742,14 @@ void MacroAssembler::RecordWrite(Register object, Operand offset,
}

// First, check if a write barrier is even needed. The tests below
// catch stores of smis and stores into the young generation.
// catch stores of smis and read-only objects, as well as stores into the
// young generation.
Label done;

if (ro_check == ReadOnlyCheck::kInline) {
MaybeJumpIfReadOnlyOrSmallSmi(value, &done);
}

if (smi_check == SmiCheck::kInline) {
DCHECK_EQ(0, kSmiTag);
JumpIfSmi(value, &done);
Expand Down Expand Up @@ -5311,7 +5332,7 @@ void MacroAssembler::ReplaceClosureCodeWithOptimizedCode(
FieldMemOperand(closure, JSFunction::kCodeOffset));
RecordWriteField(closure, JSFunction::kCodeOffset, optimized_code,
kRAHasNotBeenSaved, SaveFPRegsMode::kIgnore, SmiCheck::kOmit,
SlotDescriptor::ForCodePointerSlot());
ReadOnlyCheck::kOmit, SlotDescriptor::ForCodePointerSlot());
}

// Read off the flags in the feedback vector and check if there
Expand Down
28 changes: 18 additions & 10 deletions deps/v8/src/codegen/loong64/macro-assembler-loong64.h
Original file line number Diff line number Diff line change
Expand Up @@ -817,18 +817,20 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// Jump the register contains a smi.
void JumpIfSmi(Register value, Label* smi_label);

void JumpIfEqual(Register a, int32_t b, Label* dest) {
UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire();
li(scratch, Operand(b));
Branch(dest, eq, a, Operand(scratch));
inline void JumpIf(Condition cond, Register x, int32_t y, Label* dest) {
Branch(dest, cond, x, Operand(y));
}

void JumpIfLessThan(Register a, int32_t b, Label* dest) {
UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire();
li(scratch, Operand(b));
Branch(dest, lt, a, Operand(scratch));
inline void JumpIfEqual(Register x, int32_t y, Label* dest) {
Branch(dest, eq, x, Operand(y));
}

inline void JumpIfLessThan(Register x, int32_t y, Label* dest) {
Branch(dest, lt, x, Operand(y));
}

inline void JumpIfUnsignedLessThan(Register x, int32_t y, Label* dest) {
Branch(dest, lo, x, Operand(y));
}

// Push a standard frame, consisting of ra, fp, context and JS function.
Expand Down Expand Up @@ -1058,6 +1060,10 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
// ---------------------------------------------------------------------------
// GC Support

// Performs a fast check for whether `value` is a read-only object or a small
// Smi. Only enabled in some configurations.
void MaybeJumpIfReadOnlyOrSmallSmi(Register value, Label* dest);

// Notify the garbage collector that we wrote a pointer into an object.
// |object| is the object being stored into, |value| is the object being
// stored.
Expand All @@ -1066,13 +1072,15 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase {
void RecordWriteField(
Register object, int offset, Register value, RAStatus ra_status,
SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline,
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());

// For a given |object| notify the garbage collector that the slot at |offset|
// has been written. |value| is the object being stored.
void RecordWrite(
Register object, Operand offset, Register value, RAStatus ra_status,
SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline,
ReadOnlyCheck ro_check = ReadOnlyCheck::kInline,
SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot());

// ---------------------------------------------------------------------------
Expand Down
21 changes: 8 additions & 13 deletions deps/v8/src/compiler/backend/arm64/instruction-selector-arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5817,19 +5817,14 @@ void InstructionSelector::VisitI8x16Shuffle(OpIndex node) {
int lane_size = kBitsPerByte * kSimd128Size / lanes;
Emit(kArm64S128Dup | LaneSizeField::encode(lane_size), dup,
g.UseRegister(dup_input), g.UseImmediate(dup_index));
if (is_swizzle) {
Emit(shuffle_op, g.DefineAsRegister(node), g.UseRegister(input0), dup);
return;
} else {
// For non-swizzles, we first need to perform the shuffles with the two
// original inputs, into a temp register.
InstructionOperand temp = g.TempSimd128Register();
Emit(shuffle_op, temp, g.UseRegister(input0), g.UseRegister(input1));
// Then we need to move the dup result into the top 8 bytes.
Emit(kArm64S128MoveLane | LaneSizeField::encode(64),
g.DefineSameAsFirst(node), temp, dup, g.UseImmediate(1),
g.UseImmediate(1));
}
// First need to perform the shuffles with the two original inputs, into a
// temp register.
InstructionOperand temp = g.TempSimd128Register();
Emit(shuffle_op, temp, g.UseRegister(input0), g.UseRegister(input1));
// Then we need to move the dup result into the top 8 bytes.
Emit(kArm64S128MoveLane | LaneSizeField::encode(64),
g.DefineSameAsFirst(node), temp, dup, g.UseImmediate(1),
g.UseImmediate(1));
};

std::array<uint8_t, kSimd128HalfSize> bottom_shuffle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Register scratch = i.TempRegister(0);
auto ool = zone()->New<OutOfLineVerifySkippedWriteBarrier>(
this, object, value, scratch);
__ MaybeJumpIfReadOnlyOrSmallSmi(value, ool->exit());
__ JumpIfNotSmi(value, ool->entry());
__ bind(ool->exit());

Expand Down Expand Up @@ -1128,6 +1129,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Register scratch = i.TempRegister(1);
auto ool = zone()->New<OutOfLineVerifySkippedWriteBarrier>(
this, object, value, scratch);
__ MaybeJumpIfReadOnlyOrSmallSmi(value, ool->exit());
__ JumpIfNotSmi(value, ool->entry());
__ bind(ool->exit());

Expand Down
7 changes: 7 additions & 0 deletions deps/v8/test/mjsunit/wasm/half-dup-shuffles.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ function Test(config) {

(function SplatAndShuffleTest(config) {
const dup_byte_0 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
const dup_half_0 = [0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 ]
const dup_half_8 = [0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11 ]
const dup_word_1 = [0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07 ]

const even_bytes = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e ]
const interleave_high_halves = [0x08, 0x09, 0x18, 0x19, 0x0a, 0x0b, 0x1a, 0x1b ]
const transpose_odd_words = [0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17 ]
const reverse_16x2 = [0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05 ]

const splat_and_shuffle_tests =[
{
Expand All @@ -77,6 +79,11 @@ function Test(config) {
dup_shuffle: dup_word_1,
shuffle: transpose_odd_words,
},
{
name: "dup and reverse 16x2",
dup_shuffle: dup_half_0,
shuffle: reverse_16x2,
},
];

for (const config of splat_and_shuffle_tests) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3627,23 +3627,23 @@ std::ostream& operator<<(std::ostream& os, const DupAndShuffleInst& inst) {
const DupAndShuffleInst kDupAndShuffles[] = {
{"Dup 0 and UnzipLeft",
kArm64S128UnzipLeft,
2,
3,
0,
16,
0,
true,
{{0, 1, 4, 5, 8, 9, 12, 13, 0, 1, 0, 1, 0, 1, 0, 1}}},
{"Dup 1 and UnzipLeft",
kArm64S128UnzipLeft,
2,
3,
0,
16,
1,
true,
{{0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 2, 3, 2, 3, 2, 3}}},
{"Dup 0 and UnzipRight",
kArm64S128UnzipRight,
2,
3,
0,
16,
0,
Expand Down Expand Up @@ -3738,28 +3738,29 @@ TEST_P(TurboshaftInstructionSelectorDupAndShuffleTest, DupAndShuffle) {
Stream s = m.Build();
EXPECT_EQ(inst.expected_num_insts, s.size());

if (inst.expected_num_insts > 1) {
if (inst.expected_num_insts == 3) {
// The dup
EXPECT_EQ(kArm64S128Dup, s[0]->arch_opcode());
EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[0]->opcode()));
EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)),
s.ToVreg(m.Parameter(inst.expected_param_index)));
EXPECT_EQ(s.ToInt32(s[0]->InputAt(1)), inst.index);

EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[0]->opcode()));
// The shuffle
EXPECT_EQ(inst.arch_opcode, s[1]->arch_opcode());
EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[1]->opcode()));

if (inst.expected_num_insts == 3) {
EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(m.Parameter(0)));
EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(1)));
EXPECT_EQ(kArm64S128MoveLane, s[2]->arch_opcode());
EXPECT_EQ(1U, s[2]->OutputCount());
EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(m.Parameter(0)));
if (inst.is_swizzle) {
EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(0)));
} else {
EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)),
s.ToVreg(m.Parameter(inst.expected_param_index)));
EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(s[0]->Output()));
EXPECT_EQ(1U, s[1]->OutputCount());
EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(1)));
}

// Copy the top half of the dup into the result register.
EXPECT_EQ(kArm64S128MoveLane, s[2]->arch_opcode());
EXPECT_EQ(1U, s[2]->OutputCount());
} else {
DCHECK_EQ(inst.expected_num_insts, 1);
EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
}
}
Expand Down
Loading