| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c9578dc commit 76d6be5
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,7 +11,7 @@ | |||
| 11 | 11 | #define V8_MAJOR_VERSION 14 | |
| 12 | 12 | #define V8_MINOR_VERSION 2 | |
| 13 | 13 | #define V8_BUILD_NUMBER 231 | |
| 14 | - #define V8_PATCH_LEVEL 14 | ||
| 14 | + #define V8_PATCH_LEVEL 16 | ||
| 15 | 15 | ||
| 16 | 16 | // Use 1 for candidates and 0 otherwise. | |
| 17 | 17 | // (Boolean macro values are not supported by all preprocessors.) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -194,18 +194,34 @@ void MacroAssembler::PreCheckSkippedWriteBarrier(Register object, | |||
| 194 | 194 | bind(¬_ok); | |
| 195 | 195 | } | |
| 196 | 196 | ||
| 197 | + void MacroAssembler::MaybeJumpIfReadOnlyOrSmallSmi(Register value, | ||
| 198 | + Label* dest) { | ||
| 199 | + #if V8_STATIC_ROOTS_BOOL | ||
| 200 | + // Quick check for Read-only and small Smi values. | ||
| 201 | + static_assert(StaticReadOnlyRoot::kLastAllocatedRoot < kRegularPageSize); | ||
| 202 | + JumpIfUnsignedLessThan(value, kRegularPageSize, dest); | ||
| 203 | + #endif // V8_STATIC_ROOTS_BOOL | ||
| 204 | + } | ||
| 205 | + | ||
| 197 | 206 | // Clobbers object, dst, value, and ra, if (ra_status == kRAHasBeenSaved) | |
| 198 | 207 | // The register 'object' contains a heap object pointer. The heap object | |
| 199 | 208 | // tag is shifted away. | |
| 200 | 209 | void MacroAssembler::RecordWriteField(Register object, int offset, | |
| 201 | 210 | Register value, RAStatus ra_status, | |
| 202 | 211 | SaveFPRegsMode save_fp, | |
| 203 | - SmiCheck smi_check, SlotDescriptor slot) { | ||
| 212 | + SmiCheck smi_check, | ||
| 213 | + ReadOnlyCheck ro_check, | ||
| 214 | + SlotDescriptor slot) { | ||
| 204 | 215 | ASM_CODE_COMMENT(this); | |
| 216 | + DCHECK(!AreAliased(object, value)); | ||
| 205 | 217 | // First, check if a write barrier is even needed. The tests below | |
| 206 | - // catch stores of Smis. | ||
| 218 | + // catch stores of Smis and read-only objects. | ||
| 207 | 219 | Label done; | |
| 208 | 220 | ||
| 221 | + if (ro_check == ReadOnlyCheck::kInline) { | ||
| 222 | + MaybeJumpIfReadOnlyOrSmallSmi(value, &done); | ||
| 223 | + } | ||
| 224 | + | ||
| 209 | 225 | // Skip barrier if writing a smi. | |
| 210 | 226 | if (smi_check == SmiCheck::kInline) { | |
| 211 | 227 | JumpIfSmi(value, &done); | |
@@ -228,7 +244,7 @@ void MacroAssembler::RecordWriteField(Register object, int offset, | |||
| 228 | 244 | } | |
| 229 | 245 | ||
| 230 | 246 | RecordWrite(object, Operand(offset - kHeapObjectTag), value, ra_status, | |
| 231 | - save_fp, SmiCheck::kOmit, slot); | ||
| 247 | + save_fp, SmiCheck::kOmit, ReadOnlyCheck::kOmit, slot); | ||
| 232 | 248 | ||
| 233 | 249 | bind(&done); | |
| 234 | 250 | } | |
@@ -703,7 +719,7 @@ void MacroAssembler::MoveObjectAndSlot(Register dst_object, Register dst_slot, | |||
| 703 | 719 | void MacroAssembler::RecordWrite(Register object, Operand offset, | |
| 704 | 720 | Register value, RAStatus ra_status, | |
| 705 | 721 | SaveFPRegsMode fp_mode, SmiCheck smi_check, | |
| 706 | - SlotDescriptor slot) { | ||
| 722 | + ReadOnlyCheck ro_check, SlotDescriptor slot) { | ||
| 707 | 723 | DCHECK(!AreAliased(object, value)); | |
| 708 | 724 | ||
| 709 | 725 | if (v8_flags.slow_debug_code) { | |
@@ -726,9 +742,14 @@ void MacroAssembler::RecordWrite(Register object, Operand offset, | |||
| 726 | 742 | } | |
| 727 | 743 | ||
| 728 | 744 | // First, check if a write barrier is even needed. The tests below | |
| 729 | - // catch stores of smis and stores into the young generation. | ||
| 745 | + // catch stores of smis and read-only objects, as well as stores into the | ||
| 746 | + // young generation. | ||
| 730 | 747 | Label done; | |
| 731 | 748 | ||
| 749 | + if (ro_check == ReadOnlyCheck::kInline) { | ||
| 750 | + MaybeJumpIfReadOnlyOrSmallSmi(value, &done); | ||
| 751 | + } | ||
| 752 | + | ||
| 732 | 753 | if (smi_check == SmiCheck::kInline) { | |
| 733 | 754 | DCHECK_EQ(0, kSmiTag); | |
| 734 | 755 | JumpIfSmi(value, &done); | |
@@ -5312,7 +5333,7 @@ void MacroAssembler::ReplaceClosureCodeWithOptimizedCode( | |||
| 5312 | 5333 | FieldMemOperand(closure, JSFunction::kCodeOffset)); | |
| 5313 | 5334 | RecordWriteField(closure, JSFunction::kCodeOffset, optimized_code, | |
| 5314 | 5335 | kRAHasNotBeenSaved, SaveFPRegsMode::kIgnore, SmiCheck::kOmit, | |
| 5315 | - SlotDescriptor::ForCodePointerSlot()); | ||
| 5336 | + ReadOnlyCheck::kOmit, SlotDescriptor::ForCodePointerSlot()); | ||
| 5316 | 5337 | } | |
| 5317 | 5338 | ||
| 5318 | 5339 | // Read off the flags in the feedback vector and check if there | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -817,18 +817,20 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase { | |||
| 817 | 817 | // Jump the register contains a smi. | |
| 818 | 818 | void JumpIfSmi(Register value, Label* smi_label); | |
| 819 | 819 | ||
| 820 | - void JumpIfEqual(Register a, int32_t b, Label* dest) { | ||
| 821 | - UseScratchRegisterScope temps(this); | ||
| 822 | - Register scratch = temps.Acquire(); | ||
| 823 | - li(scratch, Operand(b)); | ||
| 824 | - Branch(dest, eq, a, Operand(scratch)); | ||
| 820 | + inline void JumpIf(Condition cond, Register x, int32_t y, Label* dest) { | ||
| 821 | + Branch(dest, cond, x, Operand(y)); | ||
| 825 | 822 | } | |
| 826 | 823 | ||
| 827 | - void JumpIfLessThan(Register a, int32_t b, Label* dest) { | ||
| 828 | - UseScratchRegisterScope temps(this); | ||
| 829 | - Register scratch = temps.Acquire(); | ||
| 830 | - li(scratch, Operand(b)); | ||
| 831 | - Branch(dest, lt, a, Operand(scratch)); | ||
| 824 | + inline void JumpIfEqual(Register x, int32_t y, Label* dest) { | ||
| 825 | + Branch(dest, eq, x, Operand(y)); | ||
| 826 | + } | ||
| 827 | + | ||
| 828 | + inline void JumpIfLessThan(Register x, int32_t y, Label* dest) { | ||
| 829 | + Branch(dest, lt, x, Operand(y)); | ||
| 830 | + } | ||
| 831 | + | ||
| 832 | + inline void JumpIfUnsignedLessThan(Register x, int32_t y, Label* dest) { | ||
| 833 | + Branch(dest, lo, x, Operand(y)); | ||
| 832 | 834 | } | |
| 833 | 835 | ||
| 834 | 836 | // Push a standard frame, consisting of ra, fp, context and JS function. | |
@@ -1058,6 +1060,10 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase { | |||
| 1058 | 1060 | // --------------------------------------------------------------------------- | |
| 1059 | 1061 | // GC Support | |
| 1060 | 1062 | ||
| 1063 | + // Performs a fast check for whether `value` is a read-only object or a small | ||
| 1064 | + // Smi. Only enabled in some configurations. | ||
| 1065 | + void MaybeJumpIfReadOnlyOrSmallSmi(Register value, Label* dest); | ||
| 1066 | + | ||
| 1061 | 1067 | // Notify the garbage collector that we wrote a pointer into an object. | |
| 1062 | 1068 | // |object| is the object being stored into, |value| is the object being | |
| 1063 | 1069 | // stored. | |
@@ -1066,13 +1072,15 @@ class V8_EXPORT_PRIVATE MacroAssembler : public MacroAssemblerBase { | |||
| 1066 | 1072 | void RecordWriteField( | |
| 1067 | 1073 | Register object, int offset, Register value, RAStatus ra_status, | |
| 1068 | 1074 | SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline, | |
| 1075 | + ReadOnlyCheck ro_check = ReadOnlyCheck::kInline, | ||
| 1069 | 1076 | SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot()); | |
| 1070 | 1077 | ||
| 1071 | 1078 | // For a given |object| notify the garbage collector that the slot at |offset| | |
| 1072 | 1079 | // has been written. |value| is the object being stored. | |
| 1073 | 1080 | void RecordWrite( | |
| 1074 | 1081 | Register object, Operand offset, Register value, RAStatus ra_status, | |
| 1075 | 1082 | SaveFPRegsMode save_fp, SmiCheck smi_check = SmiCheck::kInline, | |
| 1083 | + ReadOnlyCheck ro_check = ReadOnlyCheck::kInline, | ||
| 1076 | 1084 | SlotDescriptor slot = SlotDescriptor::ForDirectPointerSlot()); | |
| 1077 | 1085 | ||
| 1078 | 1086 | // --------------------------------------------------------------------------- | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5817,19 +5817,14 @@ void InstructionSelector::VisitI8x16Shuffle(OpIndex node) { | |||
| 5817 | 5817 | int lane_size = kBitsPerByte * kSimd128Size / lanes; | |
| 5818 | 5818 | Emit(kArm64S128Dup | LaneSizeField::encode(lane_size), dup, | |
| 5819 | 5819 | g.UseRegister(dup_input), g.UseImmediate(dup_index)); | |
| 5820 | - if (is_swizzle) { | ||
| 5821 | - Emit(shuffle_op, g.DefineAsRegister(node), g.UseRegister(input0), dup); | ||
| 5822 | - return; | ||
| 5823 | - } else { | ||
| 5824 | - // For non-swizzles, we first need to perform the shuffles with the two | ||
| 5825 | - // original inputs, into a temp register. | ||
| 5826 | - InstructionOperand temp = g.TempSimd128Register(); | ||
| 5827 | - Emit(shuffle_op, temp, g.UseRegister(input0), g.UseRegister(input1)); | ||
| 5828 | - // Then we need to move the dup result into the top 8 bytes. | ||
| 5829 | - Emit(kArm64S128MoveLane | LaneSizeField::encode(64), | ||
| 5830 | - g.DefineSameAsFirst(node), temp, dup, g.UseImmediate(1), | ||
| 5831 | - g.UseImmediate(1)); | ||
| 5832 | - } | ||
| 5820 | + // First need to perform the shuffles with the two original inputs, into a | ||
| 5821 | + // temp register. | ||
| 5822 | + InstructionOperand temp = g.TempSimd128Register(); | ||
| 5823 | + Emit(shuffle_op, temp, g.UseRegister(input0), g.UseRegister(input1)); | ||
| 5824 | + // Then we need to move the dup result into the top 8 bytes. | ||
| 5825 | + Emit(kArm64S128MoveLane | LaneSizeField::encode(64), | ||
| 5826 | + g.DefineSameAsFirst(node), temp, dup, g.UseImmediate(1), | ||
| 5827 | + g.UseImmediate(1)); | ||
| 5833 | 5828 | }; | |
| 5834 | 5829 | ||
| 5835 | 5830 | std::array<uint8_t, kSimd128HalfSize> bottom_shuffle; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1068,6 +1068,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | |||
| 1068 | 1068 | Register scratch = i.TempRegister(0); | |
| 1069 | 1069 | auto ool = zone()->New<OutOfLineVerifySkippedWriteBarrier>( | |
| 1070 | 1070 | this, object, value, scratch); | |
| 1071 | + __ MaybeJumpIfReadOnlyOrSmallSmi(value, ool->exit()); | ||
| 1071 | 1072 | __ JumpIfNotSmi(value, ool->entry()); | |
| 1072 | 1073 | __ bind(ool->exit()); | |
| 1073 | 1074 | ||
@@ -1128,6 +1129,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | |||
| 1128 | 1129 | Register scratch = i.TempRegister(1); | |
| 1129 | 1130 | auto ool = zone()->New<OutOfLineVerifySkippedWriteBarrier>( | |
| 1130 | 1131 | this, object, value, scratch); | |
| 1132 | + __ MaybeJumpIfReadOnlyOrSmallSmi(value, ool->exit()); | ||
| 1131 | 1133 | __ JumpIfNotSmi(value, ool->entry()); | |
| 1132 | 1134 | __ bind(ool->exit()); | |
| 1133 | 1135 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -54,12 +54,14 @@ function Test(config) { | |||
| 54 | 54 | ||
| 55 | 55 | (function SplatAndShuffleTest(config) { | |
| 56 | 56 | const dup_byte_0 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] | |
| 57 | + const dup_half_0 = [0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 ] | ||
| 57 | 58 | const dup_half_8 = [0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11 ] | |
| 58 | 59 | const dup_word_1 = [0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07 ] | |
| 59 | 60 | ||
| 60 | 61 | const even_bytes = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e ] | |
| 61 | 62 | const interleave_high_halves = [0x08, 0x09, 0x18, 0x19, 0x0a, 0x0b, 0x1a, 0x1b ] | |
| 62 | 63 | const transpose_odd_words = [0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17 ] | |
| 64 | + const reverse_16x2 = [0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05 ] | ||
| 63 | 65 | ||
| 64 | 66 | const splat_and_shuffle_tests =[ | |
| 65 | 67 | { | |
@@ -77,6 +79,11 @@ function Test(config) { | |||
| 77 | 79 | dup_shuffle: dup_word_1, | |
| 78 | 80 | shuffle: transpose_odd_words, | |
| 79 | 81 | }, | |
| 82 | + { | ||
| 83 | + name: "dup and reverse 16x2", | ||
| 84 | + dup_shuffle: dup_half_0, | ||
| 85 | + shuffle: reverse_16x2, | ||
| 86 | + }, | ||
| 80 | 87 | ]; | |
| 81 | 88 | ||
| 82 | 89 | for (const config of splat_and_shuffle_tests) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3627,23 +3627,23 @@ std::ostream& operator<<(std::ostream& os, const DupAndShuffleInst& inst) { | |||
| 3627 | 3627 | const DupAndShuffleInst kDupAndShuffles[] = { | |
| 3628 | 3628 | {"Dup 0 and UnzipLeft", | |
| 3629 | 3629 | kArm64S128UnzipLeft, | |
| 3630 | - 2, | ||
| 3630 | + 3, | ||
| 3631 | 3631 | 0, | |
| 3632 | 3632 | 16, | |
| 3633 | 3633 | 0, | |
| 3634 | 3634 | true, | |
| 3635 | 3635 | {{0, 1, 4, 5, 8, 9, 12, 13, 0, 1, 0, 1, 0, 1, 0, 1}}}, | |
| 3636 | 3636 | {"Dup 1 and UnzipLeft", | |
| 3637 | 3637 | kArm64S128UnzipLeft, | |
| 3638 | - 2, | ||
| 3638 | + 3, | ||
| 3639 | 3639 | 0, | |
| 3640 | 3640 | 16, | |
| 3641 | 3641 | 1, | |
| 3642 | 3642 | true, | |
| 3643 | 3643 | {{0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 2, 3, 2, 3, 2, 3}}}, | |
| 3644 | 3644 | {"Dup 0 and UnzipRight", | |
| 3645 | 3645 | kArm64S128UnzipRight, | |
| 3646 | - 2, | ||
| 3646 | + 3, | ||
| 3647 | 3647 | 0, | |
| 3648 | 3648 | 16, | |
| 3649 | 3649 | 0, | |
@@ -3738,28 +3738,29 @@ TEST_P(TurboshaftInstructionSelectorDupAndShuffleTest, DupAndShuffle) { | |||
| 3738 | 3738 | Stream s = m.Build(); | |
| 3739 | 3739 | EXPECT_EQ(inst.expected_num_insts, s.size()); | |
| 3740 | 3740 | ||
| 3741 | - if (inst.expected_num_insts > 1) { | ||
| 3741 | + if (inst.expected_num_insts == 3) { | ||
| 3742 | + // The dup | ||
| 3742 | 3743 | EXPECT_EQ(kArm64S128Dup, s[0]->arch_opcode()); | |
| 3744 | + EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[0]->opcode())); | ||
| 3743 | 3745 | EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), | |
| 3744 | 3746 | s.ToVreg(m.Parameter(inst.expected_param_index))); | |
| 3745 | 3747 | EXPECT_EQ(s.ToInt32(s[0]->InputAt(1)), inst.index); | |
| 3746 | 3748 | ||
| 3747 | - EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[0]->opcode())); | ||
| 3749 | + // The shuffle | ||
| 3748 | 3750 | EXPECT_EQ(inst.arch_opcode, s[1]->arch_opcode()); | |
| 3749 | 3751 | EXPECT_EQ(inst.lane_size, LaneSizeField::decode(s[1]->opcode())); | |
| 3750 | - | ||
| 3751 | - if (inst.expected_num_insts == 3) { | ||
| 3752 | - EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(m.Parameter(0))); | ||
| 3753 | - EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(1))); | ||
| 3754 | - EXPECT_EQ(kArm64S128MoveLane, s[2]->arch_opcode()); | ||
| 3755 | - EXPECT_EQ(1U, s[2]->OutputCount()); | ||
| 3752 | + EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(m.Parameter(0))); | ||
| 3753 | + if (inst.is_swizzle) { | ||
| 3754 | + EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(0))); | ||
| 3756 | 3755 | } else { | |
| 3757 | - EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), | ||
| 3758 | - s.ToVreg(m.Parameter(inst.expected_param_index))); | ||
| 3759 | - EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(s[0]->Output())); | ||
| 3760 | - EXPECT_EQ(1U, s[1]->OutputCount()); | ||
| 3756 | + EXPECT_EQ(s.ToVreg(s[1]->InputAt(1)), s.ToVreg(m.Parameter(1))); | ||
| 3761 | 3757 | } | |
| 3758 | + | ||
| 3759 | + // Copy the top half of the dup into the result register. | ||
| 3760 | + EXPECT_EQ(kArm64S128MoveLane, s[2]->arch_opcode()); | ||
| 3761 | + EXPECT_EQ(1U, s[2]->OutputCount()); | ||
| 3762 | 3762 | } else { | |
| 3763 | + DCHECK_EQ(inst.expected_num_insts, 1); | ||
| 3763 | 3764 | EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode()); | |
| 3764 | 3765 | } | |
| 3765 | 3766 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments