Commit 601f1fdf authored by ivica.bogosavljevic's avatar ivica.bogosavljevic Committed by Commit bot

MIPS[64]: Fix deoptimizer generate table for large deoptimization tables

Fix 233b6926

With the introduction of upfront deopt table generation, case where
deoptimization tables have more than 8000 entries become much more common
and bugs started to appear.

This CL fixes the issue, but it is far from perfect. We had to
increase number of instruction per table entry from 2 to 3 in
order to accommodate larger tables.

TEST=mjsunit/array-sort,mjsunit/json,mjsunit/md5
BUG=

Review-Url: https://codereview.chromium.org/2901393003
Cr-Commit-Position: refs/heads/master@{#45531}
parent 7a9cc704
...@@ -323,14 +323,14 @@ void Deoptimizer::TableEntryGenerator::Generate() { ...@@ -323,14 +323,14 @@ void Deoptimizer::TableEntryGenerator::Generate() {
// Maximum size of a table entry generated below. // Maximum size of a table entry generated below.
const int Deoptimizer::table_entry_size_ = 2 * Assembler::kInstrSize; const int Deoptimizer::table_entry_size_ = 3 * Assembler::kInstrSize;
void Deoptimizer::TableEntryGenerator::GeneratePrologue() { void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
// Create a sequence of deoptimization entries. // Create a sequence of deoptimization entries.
// Note that registers are still live when jumping to an entry. // Note that registers are still live when jumping to an entry.
Label table_start, done, done_special, trampoline_jump; Label table_start, done, trampoline_jump;
__ bind(&table_start); __ bind(&table_start);
int kMaxEntriesBranchReach = (1 << (kImm16Bits - 2))/ int kMaxEntriesBranchReach = (1 << (kImm16Bits - 2))/
(table_entry_size_ / Assembler::kInstrSize); (table_entry_size_ / Assembler::kInstrSize);
...@@ -343,6 +343,7 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() { ...@@ -343,6 +343,7 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
DCHECK(is_int16(i)); DCHECK(is_int16(i));
__ BranchShort(USE_DELAY_SLOT, &done); // Expose delay slot. __ BranchShort(USE_DELAY_SLOT, &done); // Expose delay slot.
__ li(at, i); // In the delay slot. __ li(at, i); // In the delay slot.
__ nop();
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start)); DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start));
} }
...@@ -353,34 +354,29 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() { ...@@ -353,34 +354,29 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
__ Push(at); __ Push(at);
} else { } else {
// Uncommon case, the branch cannot reach. // Uncommon case, the branch cannot reach.
// Create mini trampoline and adjust id constants to get proper value at // Create mini trampoline to reach the end of the table
// the end of table. for (int i = 0, j = 0; i < count(); i++, j++) {
for (int i = kMaxEntriesBranchReach; i > 1; i--) {
Label start; Label start;
__ bind(&start); __ bind(&start);
DCHECK(is_int16(i)); DCHECK(is_int16(i));
__ BranchShort(USE_DELAY_SLOT, &trampoline_jump); // Expose delay slot. if (j >= kMaxEntriesBranchReach) {
__ li(at, - i); // In the delay slot. j = 0;
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start)); __ li(at, i);
}
// Entry with id == kMaxEntriesBranchReach - 1.
__ bind(&trampoline_jump); __ bind(&trampoline_jump);
__ BranchShort(USE_DELAY_SLOT, &done_special); trampoline_jump = Label();
__ li(at, -1); __ BranchShort(USE_DELAY_SLOT, &trampoline_jump);
__ nop();
for (int i = kMaxEntriesBranchReach ; i < count(); i++) { } else {
Label start; __ BranchShort(USE_DELAY_SLOT, &trampoline_jump); // Expose delay slot.
__ bind(&start);
DCHECK(is_int16(i));
__ BranchShort(USE_DELAY_SLOT, &done); // Expose delay slot.
__ li(at, i); // In the delay slot. __ li(at, i); // In the delay slot.
__ nop();
}
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start));
} }
DCHECK_EQ(masm()->SizeOfCodeGeneratedSince(&table_start), DCHECK_EQ(masm()->SizeOfCodeGeneratedSince(&table_start),
count() * table_entry_size_); count() * table_entry_size_);
__ bind(&done_special); __ bind(&trampoline_jump);
__ addiu(at, at, kMaxEntriesBranchReach);
__ bind(&done);
__ Push(at); __ Push(at);
} }
} }
......
...@@ -323,14 +323,14 @@ void Deoptimizer::TableEntryGenerator::Generate() { ...@@ -323,14 +323,14 @@ void Deoptimizer::TableEntryGenerator::Generate() {
// Maximum size of a table entry generated below. // Maximum size of a table entry generated below.
const int Deoptimizer::table_entry_size_ = 2 * Assembler::kInstrSize; const int Deoptimizer::table_entry_size_ = 3 * Assembler::kInstrSize;
void Deoptimizer::TableEntryGenerator::GeneratePrologue() { void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
// Create a sequence of deoptimization entries. // Create a sequence of deoptimization entries.
// Note that registers are still live when jumping to an entry. // Note that registers are still live when jumping to an entry.
Label table_start, done, done_special, trampoline_jump; Label table_start, done, trampoline_jump;
__ bind(&table_start); __ bind(&table_start);
int kMaxEntriesBranchReach = int kMaxEntriesBranchReach =
(1 << (kImm16Bits - 2)) / (table_entry_size_ / Assembler::kInstrSize); (1 << (kImm16Bits - 2)) / (table_entry_size_ / Assembler::kInstrSize);
...@@ -343,6 +343,7 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() { ...@@ -343,6 +343,7 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
DCHECK(is_int16(i)); DCHECK(is_int16(i));
__ BranchShort(USE_DELAY_SLOT, &done); // Expose delay slot. __ BranchShort(USE_DELAY_SLOT, &done); // Expose delay slot.
__ li(at, i); // In the delay slot. __ li(at, i); // In the delay slot.
__ nop();
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start)); DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start));
} }
...@@ -353,34 +354,29 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() { ...@@ -353,34 +354,29 @@ void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
__ Push(at); __ Push(at);
} else { } else {
// Uncommon case, the branch cannot reach. // Uncommon case, the branch cannot reach.
// Create mini trampoline and adjust id constants to get proper value at // Create mini trampoline to reach the end of the table
// the end of table. for (int i = 0, j = 0; i < count(); i++, j++) {
for (int i = kMaxEntriesBranchReach; i > 1; i--) {
Label start; Label start;
__ bind(&start); __ bind(&start);
DCHECK(is_int16(i)); DCHECK(is_int16(i));
__ BranchShort(USE_DELAY_SLOT, &trampoline_jump); // Expose delay slot. if (j >= kMaxEntriesBranchReach) {
__ li(at, -i); // In the delay slot. j = 0;
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start)); __ li(at, i);
}
// Entry with id == kMaxEntriesBranchReach - 1.
__ bind(&trampoline_jump); __ bind(&trampoline_jump);
__ BranchShort(USE_DELAY_SLOT, &done_special); trampoline_jump = Label();
__ li(at, -1); __ BranchShort(USE_DELAY_SLOT, &trampoline_jump);
__ nop();
for (int i = kMaxEntriesBranchReach; i < count(); i++) { } else {
Label start; __ BranchShort(USE_DELAY_SLOT, &trampoline_jump); // Expose delay slot.
__ bind(&start);
DCHECK(is_int16(i));
__ Branch(USE_DELAY_SLOT, &done); // Expose delay slot.
__ li(at, i); // In the delay slot. __ li(at, i); // In the delay slot.
__ nop();
}
DCHECK_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start));
} }
DCHECK_EQ(masm()->SizeOfCodeGeneratedSince(&table_start), DCHECK_EQ(masm()->SizeOfCodeGeneratedSince(&table_start),
count() * table_entry_size_); count() * table_entry_size_);
__ bind(&done_special); __ bind(&trampoline_jump);
__ daddiu(at, at, kMaxEntriesBranchReach);
__ bind(&done);
__ Push(at); __ Push(at);
} }
} }
......
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