Revert "[codegen] Reduce size of safepoint table fields"

This reverts commit f68242bcb0.

Reason for revert: UBSan error: https://logs.chromium.org/logs/v8/buildbucket/cr-buildbucket/8828943333104509889/+/u/build/compile/stdout

Original change's description:
> [codegen] Reduce size of safepoint table fields
>
> Code objects are often small and do not use the full integer range of PC
> offsets and deoptimization indexes. Reducing the size of these fields to
> the required size per table reduces the overall size of safepoint tables
> by roughly 25%.
>
> R=​jkummerow@chromium.org
>
> Bug: v8:12401
> Change-Id: Ie6889a70782f5510436a1d05d31d17aac0bfec6e
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3306556
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Commit-Queue: Clemens Backes <clemensb@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#78216}

Bug: v8:12401
Change-Id: I53b574558305ac25fa8f38a843c98f653af201ba
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3312488
Auto-Submit: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#78217}
This commit is contained in:
Clemens Backes 2021-12-02 16:04:29 +00:00 committed by V8 LUCI CQ
parent f68242bcb0
commit 4f34cd833b
2 changed files with 41 additions and 79 deletions

View File

@ -80,7 +80,7 @@ void SafepointTable::Print(std::ostream& os) const {
for (int index = 0; index < length_; index++) {
SafepointEntry entry = GetEntry(index);
os << reinterpret_cast<const void*>(instruction_start_ + entry.pc()) << " "
<< std::setw(6) << std::hex << entry.pc() << std::dec;
<< std::setw(6) << std::hex << entry.pc();
if (!entry.tagged_slots().empty()) {
os << " slots (sp->fp): ";
@ -163,47 +163,21 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
assembler->RecordComment(";;; Safepoint table.");
offset_ = assembler->pc_offset();
// Compute the required sizes of the fields.
int used_register_indexes = 0;
int max_pc = 0;
STATIC_ASSERT(SafepointEntry::kNoDeoptIndex == -1);
int max_deopt_index = SafepointEntry::kNoDeoptIndex;
for (const EntryBuilder& entry : entries_) {
used_register_indexes |= entry.register_indexes;
max_pc = std::max(max_pc, std::max(entry.pc, entry.trampoline));
max_deopt_index = std::max(max_deopt_index, entry.deopt_index);
}
// Derive the bytes and bools for the entry configuration from the values.
auto value_to_bytes = [](int value) {
if (value == 0) return 0;
for (int bytes = 1;; ++bytes) {
DCHECK_GE(4, bytes);
int shifted_value = (value << (32 - 8 * bytes)) >> (32 - 8 * bytes);
if (shifted_value == value) return bytes;
}
};
bool has_deopt_data = max_deopt_index != SafepointEntry::kNoDeoptIndex;
int register_indexes_size = value_to_bytes(used_register_indexes);
int pc_size = value_to_bytes(max_pc);
int deopt_index_size = value_to_bytes(max_deopt_index);
// Compute the number of bytes for tagged slots per safepoint entry.
int tagged_slots_bytes =
(tagged_slots_size + kBitsPerByte - 1) / kBitsPerByte;
// Add a CHECK to ensure we never overflow the space in the bitfield, even for
// huge functions which might not be covered by tests.
CHECK(SafepointTable::RegisterIndexesSizeField::is_valid(
register_indexes_size) &&
SafepointTable::PcSizeField::is_valid(pc_size) &&
SafepointTable::DeoptIndexSizeField::is_valid(deopt_index_size) &&
SafepointTable::TaggedSlotsBytesField::is_valid(tagged_slots_bytes));
RoundUp(tagged_slots_size, kBitsPerByte) >> kBitsPerByteLog2;
bool has_deopt_data =
std::any_of(entries_.begin(), entries_.end(), [](auto& entry) {
return entry.deopt_index != SafepointEntry::kNoDeoptIndex;
});
bool has_register_indexes =
std::any_of(entries_.begin(), entries_.end(),
[](auto& entry) { return entry.register_indexes != 0; });
uint32_t entry_configuration =
SafepointTable::TaggedSlotsBytesField::encode(tagged_slots_bytes) |
SafepointTable::HasDeoptDataField::encode(has_deopt_data) |
SafepointTable::RegisterIndexesSizeField::encode(register_indexes_size) |
SafepointTable::PcSizeField::encode(pc_size) |
SafepointTable::DeoptIndexSizeField::encode(deopt_index_size) |
SafepointTable::TaggedSlotsBytesField::encode(tagged_slots_bytes);
SafepointTable::HasRegisterIndexesField::encode(has_register_indexes);
// Emit the table header.
STATIC_ASSERT(SafepointTable::kLengthOffset == 0 * kIntSize);
@ -213,19 +187,16 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
assembler->dd(length);
assembler->dd(entry_configuration);
auto emit_bytes = [assembler](int value, int bytes) {
for (int b = bytes - 1; b >= 0; --b) {
assembler->db(value >> (8 * b));
}
};
// Emit entries, sorted by pc offsets.
for (const EntryBuilder& entry : entries_) {
emit_bytes(entry.pc, pc_size);
assembler->dd(entry.pc);
if (has_deopt_data) {
emit_bytes(entry.deopt_index, deopt_index_size);
emit_bytes(entry.trampoline, pc_size);
assembler->dd(entry.deopt_index);
assembler->dd(entry.trampoline);
}
if (has_register_indexes) {
assembler->dd(entry.register_indexes);
}
emit_bytes(entry.register_indexes, register_indexes_size);
}
// Emit bitmaps of tagged stack slots.

View File

@ -109,15 +109,20 @@ class SafepointTable {
Address entry_ptr =
safepoint_table_address_ + kHeaderSize + index * entry_size();
int pc = read_bytes(&entry_ptr, pc_size());
int pc = base::Memory<int>(entry_ptr);
entry_ptr += kPcSize;
int deopt_index = SafepointEntry::kNoDeoptIndex;
int trampoline_pc = SafepointEntry::kNoTrampolinePC;
if (has_deopt_data()) {
deopt_index = read_bytes(&entry_ptr, deopt_index_size());
trampoline_pc = read_bytes(&entry_ptr, pc_size());
deopt_index = base::Memory<int>(entry_ptr);
trampoline_pc = base::Memory<int>(entry_ptr + kIntSize);
entry_ptr += kDeoptDataSize;
}
int tagged_register_indexes = 0;
if (has_register_indexes()) {
tagged_register_indexes = base::Memory<int>(entry_ptr);
entry_ptr += kRegisterIndexesSize;
}
int tagged_register_indexes =
read_bytes(&entry_ptr, register_indexes_size());
// Entry bits start after the the vector of entries (thus the pc offset of
// the non-existing entry after the last one).
@ -142,20 +147,21 @@ class SafepointTable {
static constexpr int kEntryConfigurationOffset = kLengthOffset + kIntSize;
static constexpr int kHeaderSize = kEntryConfigurationOffset + kUInt32Size;
using HasDeoptDataField = base::BitField<bool, 0, 1>;
using RegisterIndexesSizeField = HasDeoptDataField::Next<int, 3>;
using PcSizeField = RegisterIndexesSizeField::Next<int, 3>;
using DeoptIndexSizeField = PcSizeField::Next<int, 3>;
// In 22 bits, we can encode up to 4M bytes, corresponding to 32M frame slots,
// which is 128MB on 32-bit and 256MB on 64-bit systems. The stack size is
// limited to a bit below 1MB anyway (see FLAG_stack_size).
using TaggedSlotsBytesField = DeoptIndexSizeField::Next<int, 22>;
// An entry consists of the pc, plus optional deopt data (deopt index and
// trampoline PC), plus optional register indexes.
static constexpr int kPcSize = kIntSize;
static constexpr int kDeoptDataSize = 2 * kIntSize;
static constexpr int kRegisterIndexesSize = kIntSize;
using TaggedSlotsBytesField = base::BitField<int, 0, 30>;
using HasDeoptDataField = TaggedSlotsBytesField::Next<bool, 1>;
using HasRegisterIndexesField = HasDeoptDataField::Next<bool, 1>;
SafepointTable(Address instruction_start, Address safepoint_table_address);
int entry_size() const {
int deopt_data_size = has_deopt_data() ? pc_size() + deopt_index_size() : 0;
return pc_size() + deopt_data_size + register_indexes_size();
return kPcSize + (has_deopt_data() ? kDeoptDataSize : 0) +
(has_register_indexes() ? kRegisterIndexesSize : 0);
}
int tagged_slots_bytes() const {
@ -164,23 +170,8 @@ class SafepointTable {
bool has_deopt_data() const {
return HasDeoptDataField::decode(entry_configuration_);
}
int pc_size() const { return PcSizeField::decode(entry_configuration_); }
int deopt_index_size() const {
return DeoptIndexSizeField::decode(entry_configuration_);
}
int register_indexes_size() const {
return RegisterIndexesSizeField::decode(entry_configuration_);
}
static int read_bytes(Address* ptr, int bytes) {
if (bytes == 0) return 0;
// Sign-extend the first byte.
int result = *reinterpret_cast<int8_t*>(*ptr);
for (int b = 1; b < bytes; ++b) {
result = result << 8 | *reinterpret_cast<uint8_t*>(*ptr + b);
}
*ptr += bytes;
return result;
bool has_register_indexes() const {
return HasRegisterIndexesField::decode(entry_configuration_);
}
DISALLOW_GARBAGE_COLLECTION(no_gc_)