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}
This commit is contained in:
dusan.simicic 2016-12-07 01:13:22 -08:00 committed by Commit bot
parent a25e768864
commit c35cc1419c
6 changed files with 80 additions and 40 deletions

View File

@ -552,6 +552,17 @@ class Assembler : public AssemblerBase {
static const int kDebugBreakSlotLength = static const int kDebugBreakSlotLength =
kDebugBreakSlotInstructions * kInstrSize; 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. // Code generation.
@ -1166,6 +1177,9 @@ class Assembler : public AssemblerBase {
} }
bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
static bool IsCompactBranchSupported() {
return IsMipsArchVariant(kMips32r6);
}
inline int UnboundLabelsCount() { return unbound_labels_count_; } inline int UnboundLabelsCount() { return unbound_labels_count_; }
@ -1440,13 +1454,6 @@ class Assembler : public AssemblerBase {
// branch instruction generation, where we use jump instructions rather // branch instruction generation, where we use jump instructions rather
// than regular branch instructions. // than regular branch instructions.
bool trampoline_emitted_; 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; static const int kInvalidSlotPos = -1;
// Internal reference positions, required for unbounded internal reference // Internal reference positions, required for unbounded internal reference

View File

@ -208,6 +208,12 @@ class MacroAssembler: public Assembler {
Heap::RootListIndex index, Heap::RootListIndex index,
BranchDelaySlot bdslot = PROTECT); 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 // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a
// functor/function with 'Label *func(size_t index)' declaration. // functor/function with 'Label *func(size_t index)' declaration.
template <typename Func> template <typename Func>
@ -1832,13 +1838,13 @@ template <typename Func>
void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count,
Func GetLabelFunction) { Func GetLabelFunction) {
if (kArchVariant >= kMips32r6) { if (kArchVariant >= kMips32r6) {
BlockTrampolinePoolFor(case_count + 5); BlockTrampolinePoolFor(case_count + kSwitchTablePrologueSize);
addiupc(at, 5); addiupc(at, 5);
Lsa(at, at, index, kPointerSizeLog2); Lsa(at, at, index, kPointerSizeLog2);
lw(at, MemOperand(at)); lw(at, MemOperand(at));
} else { } else {
Label here; Label here;
BlockTrampolinePoolFor(case_count + 10); BlockTrampolinePoolFor(case_count + kSwitchTablePrologueSize);
push(ra); push(ra);
bal(&here); bal(&here);
sll(at, index, kPointerSizeLog2); // Branch delay slot. sll(at, index, kPointerSizeLog2); // Branch delay slot.

View File

@ -559,6 +559,13 @@ class Assembler : public AssemblerBase {
static const int kDebugBreakSlotLength = static const int kDebugBreakSlotLength =
kDebugBreakSlotInstructions * kInstrSize; 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. // Code generation.
@ -1223,6 +1230,7 @@ class Assembler : public AssemblerBase {
} }
bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; } bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
static bool IsCompactBranchSupported() { return kArchVariant == kMips64r6; }
inline int UnboundLabelsCount() { return unbound_labels_count_; } inline int UnboundLabelsCount() { return unbound_labels_count_; }
@ -1495,9 +1503,6 @@ class Assembler : public AssemblerBase {
// branch instruction generation, where we use jump instructions rather // branch instruction generation, where we use jump instructions rather
// than regular branch instructions. // than regular branch instructions.
bool trampoline_emitted_; 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; static const int kInvalidSlotPos = -1;
// Internal reference positions, required for unbounded internal reference // Internal reference positions, required for unbounded internal reference

View File

@ -236,6 +236,13 @@ class MacroAssembler: public Assembler {
Heap::RootListIndex index, Heap::RootListIndex index,
BranchDelaySlot bdslot = PROTECT); 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 // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a
// functor/function with 'Label *func(size_t index)' declaration. // functor/function with 'Label *func(size_t index)' declaration.
template <typename Func> template <typename Func>
@ -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 // Ensure that dd-ed labels following this instruction use 8 bytes aligned
// addresses. // addresses.
if (kArchVariant >= kMips64r6) { if (kArchVariant >= kMips64r6) {
BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 6); BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 +
kSwitchTablePrologueSize);
// Opposite of Align(8) as we have odd number of instructions in this case. // Opposite of Align(8) as we have odd number of instructions in this case.
if ((pc_offset() & 7) == 0) { if ((pc_offset() & 7) == 0) {
nop(); nop();
@ -1984,7 +1992,8 @@ void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count,
ld(at, MemOperand(at)); ld(at, MemOperand(at));
} else { } else {
Label here; Label here;
BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 11); BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 +
kSwitchTablePrologueSize);
Align(8); Align(8);
push(ra); push(ra);
bal(&here); bal(&here);

View File

@ -297,16 +297,21 @@ TEST(jump_tables6) {
v8::internal::CodeObjectRequired::kYes); v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler; MacroAssembler* masm = &assembler;
const int kNumCases = 40; const int kSwitchTableCases = 40;
const int kFillInstr = 32551;
const int kMaxBranchOffset = (1 << (18 - 1)) - 1; const int kInstrSize = Assembler::kInstrSize;
const int kTrampolineSlotsSize = 4 * Instruction::kInstrSize; const int kMaxBranchOffset = Assembler::kMaxBranchOffset;
const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize;
const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize;
const int kMaxOffsetForTrampolineStart = const int kMaxOffsetForTrampolineStart =
kMaxBranchOffset - 16 * kTrampolineSlotsSize; 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)); isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases]; Label labels[kSwitchTableCases];
Label near_start, end, done; Label near_start, end, done;
__ Push(ra); __ Push(ra);
@ -316,7 +321,7 @@ TEST(jump_tables6) {
int gen_insn = 0; int gen_insn = 0;
__ Branch(&end); __ Branch(&end);
gen_insn += 2; gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2;
__ bind(&near_start); __ bind(&near_start);
// Generate slightly less than 32K instructions, which will soon require // Generate slightly less than 32K instructions, which will soon require
@ -326,23 +331,24 @@ TEST(jump_tables6) {
} }
gen_insn += kFillInstr; gen_insn += kFillInstr;
__ GenerateSwitchTable(a0, kNumCases, __ GenerateSwitchTable(a0, kSwitchTableCases,
[&labels](size_t i) { return labels + i; }); [&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]); __ bind(&labels[i]);
__ li(v0, values[i]); __ li(v0, values[i]);
__ Branch(&done); __ 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 // If offset from here to first branch instr is greater than max allowed
// offset for trampoline ... // offset for trampoline ...
CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1);
// ... number of generated instructions must be greater then "gen_insn", // ... number of generated instructions must be greater then "gen_insn",
// as we are expecting trampoline generation // 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); __ bind(&done);
__ Pop(ra); __ Pop(ra);
@ -360,7 +366,7 @@ TEST(jump_tables6) {
code->Print(std::cout); code->Print(std::cout);
#endif #endif
F1 f = FUNCTION_CAST<F1>(code->entry()); F1 f = FUNCTION_CAST<F1>(code->entry());
for (int i = 0; i < kNumCases; ++i) { for (int i = 0; i < kSwitchTableCases; ++i) {
int res = int res =
reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
::printf("f(%d) = %d\n", i, res); ::printf("f(%d) = %d\n", i, res);

View File

@ -365,16 +365,22 @@ TEST(jump_tables6) {
v8::internal::CodeObjectRequired::kYes); v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler; MacroAssembler* masm = &assembler;
const int kNumCases = 40; const int kSwitchTableCases = 40;
const int kFillInstr = 32551;
const int kMaxBranchOffset = (1 << (18 - 1)) - 1; const int kInstrSize = Assembler::kInstrSize;
const int kTrampolineSlotsSize = 2 * Instruction::kInstrSize; const int kMaxBranchOffset = Assembler::kMaxBranchOffset;
const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize;
const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize;
const int kMaxOffsetForTrampolineStart = const int kMaxOffsetForTrampolineStart =
kMaxBranchOffset - 16 * kTrampolineSlotsSize; 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)); isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases]; Label labels[kSwitchTableCases];
Label near_start, end, done; Label near_start, end, done;
__ Push(ra); __ Push(ra);
@ -384,7 +390,7 @@ TEST(jump_tables6) {
int gen_insn = 0; int gen_insn = 0;
__ Branch(&end); __ Branch(&end);
gen_insn += 2; gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2;
__ bind(&near_start); __ bind(&near_start);
// Generate slightly less than 32K instructions, which will soon require // Generate slightly less than 32K instructions, which will soon require
@ -394,23 +400,24 @@ TEST(jump_tables6) {
} }
gen_insn += kFillInstr; gen_insn += kFillInstr;
__ GenerateSwitchTable(a0, kNumCases, __ GenerateSwitchTable(a0, kSwitchTableCases,
[&labels](size_t i) { return labels + i; }); [&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]); __ bind(&labels[i]);
__ li(v0, values[i]); __ li(v0, values[i]);
__ Branch(&done); __ 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 // If offset from here to first branch instr is greater than max allowed
// offset for trampoline ... // offset for trampoline ...
CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1);
// ... number of generated instructions must be greater then "gen_insn", // ... number of generated instructions must be greater then "gen_insn",
// as we are expecting trampoline generation // 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); __ bind(&done);
__ Pop(ra); __ Pop(ra);
@ -428,7 +435,7 @@ TEST(jump_tables6) {
code->Print(std::cout); code->Print(std::cout);
#endif #endif
F1 f = FUNCTION_CAST<F1>(code->entry()); F1 f = FUNCTION_CAST<F1>(code->entry());
for (int i = 0; i < kNumCases; ++i) { for (int i = 0; i < kSwitchTableCases; ++i) {
int64_t res = reinterpret_cast<int64_t>( int64_t res = reinterpret_cast<int64_t>(
CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
::printf("f(%d) = %" PRId64 "\n", i, res); ::printf("f(%d) = %" PRId64 "\n", i, res);