Commit 1c43ad50 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[codegen] Verify safepoint entries

Verify certain properties when emitting safepoint tables:
- entries are ordered by PC,
- trampoline PCs are also in order,
- all trampoline PCs come after all regular PCs, and
- an entry with a deopt index also has a trampoline PC set.

Drive-by: Slightly simplify logic in {UpdateDeoptimizationInfo}.
Drive-by 2: Inline IsIdenticalExceptForPc into the only caller, and
further simplify the logic there.

R=jkummerow@chromium.org

Bug: v8:12401
Change-Id: I8ea41b1628dceb914191f23165c8dccb79f9204c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3289162
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77983}
parent 6fcbc0d2
......@@ -94,19 +94,38 @@ int SafepointTableBuilder::GetCodeOffset() const {
int SafepointTableBuilder::UpdateDeoptimizationInfo(int pc, int trampoline,
int start,
int deopt_index) {
DCHECK_NE(SafepointEntry::kNoTrampolinePC, trampoline);
DCHECK_NE(SafepointEntry::kNoDeoptIndex, deopt_index);
auto it = deoptimization_info_.Find(start);
DCHECK(std::any_of(it, deoptimization_info_.end(),
[pc](auto& info) { return info.pc == pc; }));
int index = start;
for (auto it = deoptimization_info_.Find(start);
it != deoptimization_info_.end(); it++, index++) {
if (it->pc == pc) {
it->trampoline = trampoline;
it->deopt_index = deopt_index;
return index;
}
}
UNREACHABLE();
while (it->pc != pc) ++it, ++index;
it->trampoline = trampoline;
it->deopt_index = deopt_index;
return index;
}
void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
#ifdef DEBUG
int last_pc = -1;
int last_trampoline = -1;
for (const DeoptimizationInfo& info : deoptimization_info_) {
// Entries are ordered by PC.
DCHECK_LT(last_pc, info.pc);
last_pc = info.pc;
// Trampoline PCs are increasing, and larger than regular PCs.
if (info.trampoline != SafepointEntry::kNoTrampolinePC) {
DCHECK_LT(last_trampoline, info.trampoline);
DCHECK_LT(deoptimization_info_.back().pc, info.trampoline);
last_trampoline = info.trampoline;
}
// An entry either has trampoline and deopt index, or none of the two.
DCHECK_EQ(info.trampoline == SafepointEntry::kNoTrampolinePC,
info.deopt_index == SafepointEntry::kNoDeoptIndex);
}
#endif // DEBUG
RemoveDuplicates();
TrimEntries(&bits_per_entry);
......@@ -184,15 +203,32 @@ void SafepointTableBuilder::RemoveDuplicates() {
// Check that all entries (1, size] are identical to entry 0.
const DeoptimizationInfo& first_info = deoptimization_info_.front();
for (auto it = deoptimization_info_.Find(1); it != deoptimization_info_.end();
it++) {
if (!IsIdenticalExceptForPc(first_info, *it)) return;
}
auto is_identical_except_for_pc = [](const DeoptimizationInfo& info1,
const DeoptimizationInfo& info2) {
if (info1.deopt_index != info2.deopt_index) return false;
DCHECK_EQ(info1.trampoline, info2.trampoline);
ZoneChunkList<int>* indexes1 = info1.stack_indexes;
ZoneChunkList<int>* indexes2 = info2.stack_indexes;
if (indexes1->size() != indexes2->size()) return false;
if (!std::equal(indexes1->begin(), indexes1->end(), indexes2->begin())) {
return false;
}
// If we get here, all entries were identical. Rewind the list to just one
// entry, and set the pc to -1.
deoptimization_info_.Rewind(1);
deoptimization_info_.front().pc = -1;
if (info1.register_indexes != info2.register_indexes) return false;
return true;
};
if (std::all_of(deoptimization_info_.Find(1), deoptimization_info_.end(),
[&](const DeoptimizationInfo& info) {
return is_identical_except_for_pc(first_info, info);
})) {
// All entries were identical. Rewind the list to just one
// entry, and set the pc to -1.
deoptimization_info_.Rewind(1);
deoptimization_info_.front().pc = -1;
}
}
void SafepointTableBuilder::TrimEntries(int* bits_per_entry) {
......@@ -217,21 +253,5 @@ void SafepointTableBuilder::TrimEntries(int* bits_per_entry) {
}
}
bool SafepointTableBuilder::IsIdenticalExceptForPc(
const DeoptimizationInfo& info1, const DeoptimizationInfo& info2) const {
if (info1.deopt_index != info2.deopt_index) return false;
ZoneChunkList<int>* indexes1 = info1.stack_indexes;
ZoneChunkList<int>* indexes2 = info2.stack_indexes;
if (indexes1->size() != indexes2->size()) return false;
if (!std::equal(indexes1->begin(), indexes1->end(), indexes2->begin())) {
return false;
}
if (info1.register_indexes != info2.register_indexes) return false;
return true;
}
} // namespace internal
} // namespace v8
......@@ -252,10 +252,6 @@ class SafepointTableBuilder {
register_indexes(0) {}
};
// Compares all fields of a {DeoptimizationInfo} except {pc} and {trampoline}.
bool IsIdenticalExceptForPc(const DeoptimizationInfo&,
const DeoptimizationInfo&) const;
// If all entries are identical, replace them by 1 entry with pc = kMaxUInt32.
void RemoveDuplicates();
......
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