Commit 253d93e1 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add an implicit default safepoint

Allow calls to not specify a safepoint. When we look up the safepoint
for such a location, we return a default safepoint which just has the
stack slots and no deopt info or pushed registers. This is different to
the TF safepoint elision, which tries to find the _next_ safepoint for a
PC. This allows us to let most calls not specify a safepoint at all, at
the cost of not being able to deduplicate safepoints anymore.

Bug: v8:7700
Change-Id: Ia119f56f40b5af426e0daa521801e6386b28ddb0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3770106Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81958}
parent 2eb73988
......@@ -40,38 +40,37 @@ MaglevSafepointTable::MaglevSafepointTable(Address instruction_start,
num_untagged_slots_(base::Memory<uint32_t>(safepoint_table_address +
kNumUntaggedSlotsOffset)) {}
int MaglevSafepointTable::find_return_pc(int pc_offset) {
for (int i = 0; i < length(); i++) {
MaglevSafepointEntry entry = GetEntry(i);
if (entry.trampoline_pc() == pc_offset || entry.pc() == pc_offset) {
return entry.pc();
}
}
UNREACHABLE();
}
MaglevSafepointEntry MaglevSafepointTable::FindEntry(Address pc) const {
int pc_offset = static_cast<int>(pc - instruction_start_);
// Check if the PC is pointing at a trampoline.
if (has_deopt_data()) {
int candidate = -1;
for (int i = 0; i < length_; ++i) {
MaglevSafepointEntry entry = GetEntry(i);
int trampoline_pc = GetEntry(i).trampoline_pc();
if (trampoline_pc != -1 && trampoline_pc <= pc_offset) candidate = i;
if (trampoline_pc != -1 && trampoline_pc == pc_offset) return entry;
if (trampoline_pc > pc_offset) break;
}
if (candidate != -1) return GetEntry(candidate);
}
// Try to find an exact pc match.
for (int i = 0; i < length_; ++i) {
MaglevSafepointEntry entry = GetEntry(i);
if (i == length_ - 1 || GetEntry(i + 1).pc() > pc_offset) {
DCHECK_LE(entry.pc(), pc_offset);
if (entry.pc() == pc_offset) {
return entry;
}
}
UNREACHABLE();
// Return a default entry which has no deopt data and no pushed registers.
// This allows us to elide emitting entries for trivial calls.
int deopt_index = MaglevSafepointEntry::kNoDeoptIndex;
int trampoline_pc = MaglevSafepointEntry::kNoTrampolinePC;
uint8_t num_pushed_registers = 0;
int tagged_register_indexes = 0;
return MaglevSafepointEntry(pc_offset, deopt_index, num_tagged_slots_,
num_untagged_slots_, num_pushed_registers,
tagged_register_indexes, trampoline_pc);
}
void MaglevSafepointTable::Print(std::ostream& os) const {
......@@ -147,8 +146,6 @@ void MaglevSafepointTableBuilder::Emit(Assembler* assembler) {
}
#endif // DEBUG
RemoveDuplicates();
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
// We cannot emit a const pool within the safepoint table.
Assembler::BlockConstPoolScope block_const_pool(assembler);
......@@ -237,35 +234,5 @@ void MaglevSafepointTableBuilder::Emit(Assembler* assembler) {
}
}
void MaglevSafepointTableBuilder::RemoveDuplicates() {
// Remove any duplicate entries, i.e. succeeding entries that are identical
// except for the PC. During lookup, we will find the first entry whose PC is
// not larger than the PC at hand, and find the first non-duplicate.
if (entries_.size() < 2) return;
auto is_identical_except_for_pc = [](const EntryBuilder& entry1,
const EntryBuilder& entry2) {
if (entry1.deopt_index != entry2.deopt_index) return false;
DCHECK_EQ(entry1.trampoline, entry2.trampoline);
return entry1.num_pushed_registers == entry2.num_pushed_registers &&
entry1.tagged_register_indexes == entry2.tagged_register_indexes;
};
auto remaining_it = entries_.begin();
size_t remaining = 0;
for (auto it = entries_.begin(), end = entries_.end(); it != end;
++remaining_it, ++remaining) {
if (remaining_it != it) *remaining_it = *it;
// Merge identical entries.
do {
++it;
} while (it != end && is_identical_except_for_pc(*it, *remaining_it));
}
entries_.Rewind(remaining);
}
} // namespace internal
} // namespace v8
......@@ -74,8 +74,6 @@ class MaglevSafepointTable {
int byte_size() const { return kHeaderSize + length_ * entry_size(); }
int find_return_pc(int pc_offset);
MaglevSafepointEntry GetEntry(int index) const {
DCHECK_GT(length_, index);
Address entry_ptr =
......@@ -230,9 +228,6 @@ class MaglevSafepointTableBuilder : public SafepointTableBuilderBase {
int deopt_index);
private:
// Remove consecutive identical entries.
void RemoveDuplicates();
const uint32_t num_tagged_slots_;
const uint32_t num_untagged_slots_;
ZoneChunkList<EntryBuilder> entries_;
......
......@@ -127,9 +127,6 @@ class MaglevCodeGeneratingNodeProcessor {
__ subq(rsp,
Immediate(graph->untagged_stack_slots() * kSystemPointerSize));
}
// Define a single safepoint at the end of the code object.
safepoint_table_builder()->DefineSafepoint(masm());
}
void PostProcessGraph(MaglevCompilationInfo*, Graph*) {}
......
......@@ -130,6 +130,8 @@ class SaveRegisterStateForCall {
}
MaglevSafepointTableBuilder::Safepoint DefineSafepoint() {
// TODO(leszeks): Avoid emitting safepoints when there are no registers to
// save.
auto safepoint = code_gen_state->safepoint_table_builder()->DefineSafepoint(
code_gen_state->masm());
int pushed_reg_index = 0;
......@@ -842,8 +844,6 @@ void CreateFunctionContext::GenerateCode(MaglevCodeGenState* code_gen_state,
__ Move(D::GetRegisterParameter(D::kSlots), Immediate(slot_count()));
// TODO(leszeks): Consider inlining this allocation.
__ CallBuiltin(Builtin::kFastNewFunctionContextFunction);
code_gen_state->safepoint_table_builder()->DefineSafepoint(
code_gen_state->masm());
}
void CreateFunctionContext::PrintParams(
std::ostream& os, MaglevGraphLabeller* graph_labeller) const {
......
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