From c35cc1419cdc3451433bb3d2462c1be125c568c5 Mon Sep 17 00:00:00 2001 From: "dusan.simicic" Date: Wed, 7 Dec 2016 01:13:22 -0800 Subject: [PATCH] MIPS[64]: Fix jump_tables6 test for r6 architectures This patch fixes jump_tables6 test for mips32r6 and mips64r6. This is regression from CL: https://crrev.com/d735f3ab12061f0a588b3f0538f9229cf747f818 BUG= Review-Url: https://codereview.chromium.org/2547033002 Cr-Commit-Position: refs/heads/master@{#41543} --- src/mips/assembler-mips.h | 21 +++++++++----- src/mips/macro-assembler-mips.h | 10 +++++-- src/mips64/assembler-mips64.h | 11 ++++++-- src/mips64/macro-assembler-mips64.h | 13 +++++++-- test/cctest/test-macro-assembler-mips.cc | 32 ++++++++++++--------- test/cctest/test-macro-assembler-mips64.cc | 33 +++++++++++++--------- 6 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h index 1b93829682..c03d9bd9ae 100644 --- a/src/mips/assembler-mips.h +++ b/src/mips/assembler-mips.h @@ -552,6 +552,17 @@ class Assembler : public AssemblerBase { static const int kDebugBreakSlotLength = kDebugBreakSlotInstructions * kInstrSize; + // Max offset for instructions with 16-bit offset field + static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; + + // Max offset for compact branch instructions with 26-bit offset field + static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1; + +#ifdef _MIPS_ARCH_MIPS32R6 + static const int kTrampolineSlotsSize = 2 * kInstrSize; +#else + static const int kTrampolineSlotsSize = 4 * kInstrSize; +#endif // --------------------------------------------------------------------------- // Code generation. @@ -1166,6 +1177,9 @@ class Assembler : public AssemblerBase { } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } + static bool IsCompactBranchSupported() { + return IsMipsArchVariant(kMips32r6); + } inline int UnboundLabelsCount() { return unbound_labels_count_; } @@ -1440,13 +1454,6 @@ class Assembler : public AssemblerBase { // branch instruction generation, where we use jump instructions rather // than regular branch instructions. bool trampoline_emitted_; -#ifdef _MIPS_ARCH_MIPS32R6 - static const int kTrampolineSlotsSize = 2 * kInstrSize; -#else - static const int kTrampolineSlotsSize = 4 * kInstrSize; -#endif - static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; - static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1; static const int kInvalidSlotPos = -1; // Internal reference positions, required for unbounded internal reference diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index ec4c27d97a..700afe5518 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -208,6 +208,12 @@ class MacroAssembler: public Assembler { Heap::RootListIndex index, BranchDelaySlot bdslot = PROTECT); +// Number of instructions needed for calculation of switch table entry address +#ifdef _MIPS_ARCH_MIPS32R6 + static const int kSwitchTablePrologueSize = 5; +#else + static const int kSwitchTablePrologueSize = 10; +#endif // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a // functor/function with 'Label *func(size_t index)' declaration. template @@ -1832,13 +1838,13 @@ template void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, Func GetLabelFunction) { if (kArchVariant >= kMips32r6) { - BlockTrampolinePoolFor(case_count + 5); + BlockTrampolinePoolFor(case_count + kSwitchTablePrologueSize); addiupc(at, 5); Lsa(at, at, index, kPointerSizeLog2); lw(at, MemOperand(at)); } else { Label here; - BlockTrampolinePoolFor(case_count + 10); + BlockTrampolinePoolFor(case_count + kSwitchTablePrologueSize); push(ra); bal(&here); sll(at, index, kPointerSizeLog2); // Branch delay slot. diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h index caf3ecfc93..e3786a7e8c 100644 --- a/src/mips64/assembler-mips64.h +++ b/src/mips64/assembler-mips64.h @@ -559,6 +559,13 @@ class Assembler : public AssemblerBase { static const int kDebugBreakSlotLength = kDebugBreakSlotInstructions * kInstrSize; + // Max offset for instructions with 16-bit offset field + static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; + + // Max offset for compact branch instructions with 26-bit offset field + static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1; + + static const int kTrampolineSlotsSize = 2 * kInstrSize; // --------------------------------------------------------------------------- // Code generation. @@ -1223,6 +1230,7 @@ class Assembler : public AssemblerBase { } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } + static bool IsCompactBranchSupported() { return kArchVariant == kMips64r6; } inline int UnboundLabelsCount() { return unbound_labels_count_; } @@ -1495,9 +1503,6 @@ class Assembler : public AssemblerBase { // branch instruction generation, where we use jump instructions rather // than regular branch instructions. bool trampoline_emitted_; - static const int kTrampolineSlotsSize = 2 * kInstrSize; - static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; - static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1; static const int kInvalidSlotPos = -1; // Internal reference positions, required for unbounded internal reference diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index 24abd28c36..f1c6c42032 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -236,6 +236,13 @@ class MacroAssembler: public Assembler { Heap::RootListIndex index, BranchDelaySlot bdslot = PROTECT); +// Number of instructions needed for calculation of switch table entry address +#ifdef _MIPS_ARCH_MIPS64R6 + static const int kSwitchTablePrologueSize = 6; +#else + static const int kSwitchTablePrologueSize = 11; +#endif + // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a // functor/function with 'Label *func(size_t index)' declaration. template @@ -1974,7 +1981,8 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, // Ensure that dd-ed labels following this instruction use 8 bytes aligned // addresses. if (kArchVariant >= kMips64r6) { - BlockTrampolinePoolFor(static_cast(case_count) * 2 + 6); + BlockTrampolinePoolFor(static_cast(case_count) * 2 + + kSwitchTablePrologueSize); // Opposite of Align(8) as we have odd number of instructions in this case. if ((pc_offset() & 7) == 0) { nop(); @@ -1984,7 +1992,8 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, ld(at, MemOperand(at)); } else { Label here; - BlockTrampolinePoolFor(static_cast(case_count) * 2 + 11); + BlockTrampolinePoolFor(static_cast(case_count) * 2 + + kSwitchTablePrologueSize); Align(8); push(ra); bal(&here); diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc index deeb13cc7e..40a3313897 100644 --- a/test/cctest/test-macro-assembler-mips.cc +++ b/test/cctest/test-macro-assembler-mips.cc @@ -297,16 +297,21 @@ TEST(jump_tables6) { v8::internal::CodeObjectRequired::kYes); MacroAssembler* masm = &assembler; - const int kNumCases = 40; - const int kFillInstr = 32551; - const int kMaxBranchOffset = (1 << (18 - 1)) - 1; - const int kTrampolineSlotsSize = 4 * Instruction::kInstrSize; + const int kSwitchTableCases = 40; + + const int kInstrSize = Assembler::kInstrSize; + const int kMaxBranchOffset = Assembler::kMaxBranchOffset; + const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize; + const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize; + const int kMaxOffsetForTrampolineStart = kMaxBranchOffset - 16 * kTrampolineSlotsSize; + const int kFillInstr = (kMaxOffsetForTrampolineStart / kInstrSize) - + (kSwitchTablePrologueSize + kSwitchTableCases) - 20; - int values[kNumCases]; + int values[kSwitchTableCases]; isolate->random_number_generator()->NextBytes(values, sizeof(values)); - Label labels[kNumCases]; + Label labels[kSwitchTableCases]; Label near_start, end, done; __ Push(ra); @@ -316,7 +321,7 @@ TEST(jump_tables6) { int gen_insn = 0; __ Branch(&end); - gen_insn += 2; + gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2; __ bind(&near_start); // Generate slightly less than 32K instructions, which will soon require @@ -326,23 +331,24 @@ TEST(jump_tables6) { } gen_insn += kFillInstr; - __ GenerateSwitchTable(a0, kNumCases, + __ GenerateSwitchTable(a0, kSwitchTableCases, [&labels](size_t i) { return labels + i; }); - gen_insn += (10 + kNumCases); + gen_insn += (kSwitchTablePrologueSize + kSwitchTableCases); - for (int i = 0; i < kNumCases; ++i) { + for (int i = 0; i < kSwitchTableCases; ++i) { __ bind(&labels[i]); __ li(v0, values[i]); __ Branch(&done); } - gen_insn += (4 * kNumCases); + gen_insn += + ((Assembler::IsCompactBranchSupported() ? 3 : 4) * kSwitchTableCases); // If offset from here to first branch instr is greater than max allowed // offset for trampoline ... CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); // ... number of generated instructions must be greater then "gen_insn", // as we are expecting trampoline generation - CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / Instruction::kInstrSize); + CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / kInstrSize); __ bind(&done); __ Pop(ra); @@ -360,7 +366,7 @@ TEST(jump_tables6) { code->Print(std::cout); #endif F1 f = FUNCTION_CAST(code->entry()); - for (int i = 0; i < kNumCases; ++i) { + for (int i = 0; i < kSwitchTableCases; ++i) { int res = reinterpret_cast(CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); ::printf("f(%d) = %d\n", i, res); diff --git a/test/cctest/test-macro-assembler-mips64.cc b/test/cctest/test-macro-assembler-mips64.cc index eb706d5cad..2347d67b76 100644 --- a/test/cctest/test-macro-assembler-mips64.cc +++ b/test/cctest/test-macro-assembler-mips64.cc @@ -365,16 +365,22 @@ TEST(jump_tables6) { v8::internal::CodeObjectRequired::kYes); MacroAssembler* masm = &assembler; - const int kNumCases = 40; - const int kFillInstr = 32551; - const int kMaxBranchOffset = (1 << (18 - 1)) - 1; - const int kTrampolineSlotsSize = 2 * Instruction::kInstrSize; + const int kSwitchTableCases = 40; + + const int kInstrSize = Assembler::kInstrSize; + const int kMaxBranchOffset = Assembler::kMaxBranchOffset; + const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize; + const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize; + const int kMaxOffsetForTrampolineStart = kMaxBranchOffset - 16 * kTrampolineSlotsSize; + const int kFillInstr = (kMaxOffsetForTrampolineStart / kInstrSize) - + (kSwitchTablePrologueSize + 2 * kSwitchTableCases) - + 20; - int values[kNumCases]; + int values[kSwitchTableCases]; isolate->random_number_generator()->NextBytes(values, sizeof(values)); - Label labels[kNumCases]; + Label labels[kSwitchTableCases]; Label near_start, end, done; __ Push(ra); @@ -384,7 +390,7 @@ TEST(jump_tables6) { int gen_insn = 0; __ Branch(&end); - gen_insn += 2; + gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2; __ bind(&near_start); // Generate slightly less than 32K instructions, which will soon require @@ -394,23 +400,24 @@ TEST(jump_tables6) { } gen_insn += kFillInstr; - __ GenerateSwitchTable(a0, kNumCases, + __ GenerateSwitchTable(a0, kSwitchTableCases, [&labels](size_t i) { return labels + i; }); - gen_insn += (11 + 2 * kNumCases); + gen_insn += (kSwitchTablePrologueSize + 2 * kSwitchTableCases); - for (int i = 0; i < kNumCases; ++i) { + for (int i = 0; i < kSwitchTableCases; ++i) { __ bind(&labels[i]); __ li(v0, values[i]); __ Branch(&done); } - gen_insn += (4 * kNumCases); + gen_insn += + ((Assembler::IsCompactBranchSupported() ? 3 : 4) * kSwitchTableCases); // If offset from here to first branch instr is greater than max allowed // offset for trampoline ... CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); // ... number of generated instructions must be greater then "gen_insn", // as we are expecting trampoline generation - CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / Instruction::kInstrSize); + CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / kInstrSize); __ bind(&done); __ Pop(ra); @@ -428,7 +435,7 @@ TEST(jump_tables6) { code->Print(std::cout); #endif F1 f = FUNCTION_CAST(code->entry()); - for (int i = 0; i < kNumCases; ++i) { + for (int i = 0; i < kSwitchTableCases; ++i) { int64_t res = reinterpret_cast( CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); ::printf("f(%d) = %" PRId64 "\n", i, res);