[codegen] Avoid unused fields in safepoint table
Many safepoint tables do not contain any deoptimization info and/or no callee-saved registers. Do not emit empty fields for all entries in this case. This often shrinks the size of the encoded safepoint table by more than 50%. Drive-by cleanups: - Rename fields of the safepoint table entries to clarify their meaning ("tagged slots" instead of "bits", "tagged register indexes" instead of "register bits"). - Include the PC in the decoded {SafepointEntry} to make it the single source of truth. R=jkummerow@chromium.org Bug: v8:12401 Change-Id: If5c24a688a434842ed3b6427f5f1f3ea9232173a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3289173 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#78021}
This commit is contained in:
parent
9a13c49fd4
commit
0580829fb5
@ -20,29 +20,28 @@ namespace internal {
|
||||
|
||||
SafepointTable::SafepointTable(Isolate* isolate, Address pc, Code code)
|
||||
: SafepointTable(code.InstructionStart(isolate, pc),
|
||||
code.SafepointTableAddress(), true) {}
|
||||
code.SafepointTableAddress()) {}
|
||||
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
SafepointTable::SafepointTable(const wasm::WasmCode* code)
|
||||
: SafepointTable(code->instruction_start(),
|
||||
code->instruction_start() + code->safepoint_table_offset(),
|
||||
false) {}
|
||||
: SafepointTable(
|
||||
code->instruction_start(),
|
||||
code->instruction_start() + code->safepoint_table_offset()) {}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
SafepointTable::SafepointTable(Address instruction_start,
|
||||
Address safepoint_table_address, bool has_deopt)
|
||||
Address safepoint_table_address)
|
||||
: instruction_start_(instruction_start),
|
||||
has_deopt_(has_deopt),
|
||||
safepoint_table_address_(safepoint_table_address),
|
||||
length_(ReadLength(safepoint_table_address)),
|
||||
entry_size_(ReadEntrySize(safepoint_table_address)) {}
|
||||
length_(base::Memory<int>(safepoint_table_address + kLengthOffset)),
|
||||
entry_configuration_(base::Memory<uint32_t>(safepoint_table_address +
|
||||
kEntryConfigurationOffset)) {}
|
||||
|
||||
int SafepointTable::find_return_pc(int pc_offset) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (GetTrampolinePcOffset(i) == static_cast<int>(pc_offset)) {
|
||||
return GetPcOffset(i);
|
||||
} else if (GetPcOffset(i) == pc_offset) {
|
||||
return pc_offset;
|
||||
SafepointEntry entry = GetEntry(i);
|
||||
if (entry.trampoline_pc() == pc_offset || entry.pc() == pc_offset) {
|
||||
return entry.pc();
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
@ -54,27 +53,21 @@ SafepointEntry SafepointTable::FindEntry(Address pc) const {
|
||||
DCHECK_NE(kMaxUInt32, pc_offset);
|
||||
CHECK_LT(0, length_);
|
||||
// A single entry with pc == -1 covers all call sites in the function.
|
||||
if (length_ == 1 && GetPcOffset(0) == -1) return GetEntry(0);
|
||||
if (length_ == 1 && GetEntry(0).pc() == -1) return GetEntry(0);
|
||||
for (int i = 0; i < length_; i++) {
|
||||
// TODO(kasperl): Replace the linear search with binary search.
|
||||
if (GetPcOffset(i) == pc_offset ||
|
||||
(has_deopt_ &&
|
||||
GetTrampolinePcOffset(i) == static_cast<int>(pc_offset))) {
|
||||
return GetEntry(i);
|
||||
SafepointEntry entry = GetEntry(i);
|
||||
if (entry.pc() == pc_offset || entry.trampoline_pc() == pc_offset) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void SafepointTable::PrintEntry(int index, std::ostream& os) const {
|
||||
disasm::NameConverter converter;
|
||||
SafepointEntry entry = GetEntry(index);
|
||||
uint8_t* bits = entry.bits();
|
||||
|
||||
// Print the stack slot bits.
|
||||
for (int i = 0; i < entry_size_; ++i) {
|
||||
for (uint8_t bits : GetEntry(index).tagged_slots()) {
|
||||
for (int bit = 0; bit < kBitsPerByte; ++bit) {
|
||||
os << ((bits[i] & (1 << bit)) ? "1" : "0");
|
||||
os << ((bits >> bit) & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,7 +93,7 @@ int SafepointTableBuilder::UpdateDeoptimizationInfo(int pc, int trampoline,
|
||||
return index;
|
||||
}
|
||||
|
||||
void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
|
||||
void SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
|
||||
#ifdef DEBUG
|
||||
int last_pc = -1;
|
||||
int last_trampoline = -1;
|
||||
@ -121,7 +114,7 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
|
||||
#endif // DEBUG
|
||||
|
||||
RemoveDuplicates();
|
||||
TrimEntries(&bits_per_entry);
|
||||
TrimEntries(&tagged_slots_size);
|
||||
|
||||
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
|
||||
// We cannot emit a const pool within the safepoint table.
|
||||
@ -133,56 +126,58 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
|
||||
assembler->RecordComment(";;; Safepoint table.");
|
||||
offset_ = assembler->pc_offset();
|
||||
|
||||
// Compute the number of bytes per safepoint entry.
|
||||
int bytes_per_entry =
|
||||
RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
|
||||
// Compute the number of bytes for tagged slots per safepoint entry.
|
||||
int 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::HasRegisterIndexesField::encode(has_register_indexes);
|
||||
|
||||
// Emit the table header.
|
||||
STATIC_ASSERT(SafepointTable::kLengthOffset == 0 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kEntrySizeOffset == 1 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kEntryConfigurationOffset == 1 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kHeaderSize == 2 * kIntSize);
|
||||
int length = static_cast<int>(entries_.size());
|
||||
assembler->dd(length);
|
||||
assembler->dd(bytes_per_entry);
|
||||
assembler->dd(entry_configuration);
|
||||
|
||||
// Emit sorted table of pc offsets together with additional info (i.e. the
|
||||
// deoptimization index or arguments count) and trampoline offsets.
|
||||
STATIC_ASSERT(SafepointTable::kPcOffset == 0 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kEncodedInfoOffset == 1 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kTrampolinePcOffset == 2 * kIntSize);
|
||||
STATIC_ASSERT(SafepointTable::kFixedEntrySize == 3 * kIntSize);
|
||||
// Emit entries, sorted by pc offsets.
|
||||
for (const EntryBuilder& entry : entries_) {
|
||||
assembler->dd(entry.pc);
|
||||
if (entry.register_indexes) {
|
||||
// We emit the register indexes in the same bits as the deopt_index.
|
||||
// Register indexes and deopt_index should not exist at the same time.
|
||||
DCHECK_EQ(entry.deopt_index, SafepointEntry::kNoDeoptIndex);
|
||||
assembler->dd(entry.register_indexes);
|
||||
} else {
|
||||
if (has_deopt_data) {
|
||||
assembler->dd(entry.deopt_index);
|
||||
assembler->dd(entry.trampoline);
|
||||
}
|
||||
if (has_register_indexes) {
|
||||
assembler->dd(entry.register_indexes);
|
||||
}
|
||||
assembler->dd(entry.trampoline);
|
||||
}
|
||||
|
||||
// Emit table of bitmaps.
|
||||
ZoneVector<uint8_t> bits(bytes_per_entry, 0, zone_);
|
||||
// Emit bitmaps of tagged stack slots.
|
||||
ZoneVector<uint8_t> bits(tagged_slots_bytes, 0, zone_);
|
||||
for (const EntryBuilder& entry : entries_) {
|
||||
ZoneChunkList<int>* indexes = entry.stack_indexes;
|
||||
std::fill(bits.begin(), bits.end(), 0);
|
||||
|
||||
// Run through the indexes and build a bitmap.
|
||||
for (int idx : *indexes) {
|
||||
DCHECK_GT(bits_per_entry, idx);
|
||||
int index = bits_per_entry - 1 - idx;
|
||||
for (int idx : *entry.stack_indexes) {
|
||||
DCHECK_GT(tagged_slots_size, idx);
|
||||
int index = tagged_slots_size - 1 - idx;
|
||||
int byte_index = index >> kBitsPerByteLog2;
|
||||
int bit_index = index & (kBitsPerByte - 1);
|
||||
bits[byte_index] |= (1U << bit_index);
|
||||
bits[byte_index] |= (1u << bit_index);
|
||||
}
|
||||
|
||||
// Emit the bitmap for the current entry.
|
||||
for (int k = 0; k < bytes_per_entry; k++) {
|
||||
assembler->db(bits[k]);
|
||||
}
|
||||
for (uint8_t byte : bits) assembler->db(byte);
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,13 +219,13 @@ void SafepointTableBuilder::RemoveDuplicates() {
|
||||
}
|
||||
}
|
||||
|
||||
void SafepointTableBuilder::TrimEntries(int* bits_per_entry) {
|
||||
int min_index = *bits_per_entry;
|
||||
void SafepointTableBuilder::TrimEntries(int* tagged_slots_size) {
|
||||
int min_index = *tagged_slots_size;
|
||||
if (min_index == 0) return; // Early exit: nothing to trim.
|
||||
|
||||
for (auto& entry : entries_) {
|
||||
for (int idx : *entry.stack_indexes) {
|
||||
DCHECK_GT(*bits_per_entry, idx); // Validity check.
|
||||
DCHECK_GT(*tagged_slots_size, idx); // Validity check.
|
||||
if (idx >= min_index) continue;
|
||||
if (idx == 0) return; // Early exit: nothing to trim.
|
||||
min_index = idx;
|
||||
@ -238,7 +233,7 @@ void SafepointTableBuilder::TrimEntries(int* bits_per_entry) {
|
||||
}
|
||||
|
||||
DCHECK_LT(0, min_index);
|
||||
*bits_per_entry -= min_index;
|
||||
*tagged_slots_size -= min_index;
|
||||
for (auto& entry : entries_) {
|
||||
for (int& idx : *entry.stack_indexes) {
|
||||
idx -= min_index;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_CODEGEN_SAFEPOINT_TABLE_H_
|
||||
#define V8_CODEGEN_SAFEPOINT_TABLE_H_
|
||||
|
||||
#include "src/base/bit-field.h"
|
||||
#include "src/base/iterator.h"
|
||||
#include "src/base/memory.h"
|
||||
#include "src/common/assert-scope.h"
|
||||
@ -27,66 +28,59 @@ class SafepointEntry {
|
||||
|
||||
SafepointEntry() = default;
|
||||
|
||||
SafepointEntry(int deopt_index, uint8_t* bits, uint8_t* bits_end,
|
||||
int trampoline_pc)
|
||||
: deopt_index_(deopt_index),
|
||||
bits_(bits),
|
||||
bits_end_(bits_end),
|
||||
SafepointEntry(int pc, int deopt_index, uint32_t tagged_register_indexes,
|
||||
base::Vector<uint8_t> tagged_slots, int trampoline_pc)
|
||||
: pc_(pc),
|
||||
deopt_index_(deopt_index),
|
||||
tagged_register_indexes_(tagged_register_indexes),
|
||||
tagged_slots_(tagged_slots),
|
||||
trampoline_pc_(trampoline_pc) {
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
bool is_valid() const { return bits_ != nullptr; }
|
||||
bool is_valid() const { return tagged_slots_.begin() != nullptr; }
|
||||
|
||||
bool Equals(const SafepointEntry& other) const {
|
||||
return deopt_index_ == other.deopt_index_ && bits_ == other.bits_;
|
||||
bool operator==(const SafepointEntry& other) const {
|
||||
return pc_ == other.pc_ && deopt_index_ == other.deopt_index_ &&
|
||||
tagged_register_indexes_ == other.tagged_register_indexes_ &&
|
||||
tagged_slots_ == other.tagged_slots_ &&
|
||||
trampoline_pc_ == other.trampoline_pc_;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
deopt_index_ = kNoDeoptIndex;
|
||||
bits_ = nullptr;
|
||||
bits_end_ = nullptr;
|
||||
*this = SafepointEntry{};
|
||||
DCHECK(!is_valid());
|
||||
}
|
||||
|
||||
int trampoline_pc() { return trampoline_pc_; }
|
||||
int pc() const { return pc_; }
|
||||
|
||||
int deoptimization_index() const {
|
||||
DCHECK(is_valid() && has_deoptimization_index());
|
||||
return deopt_index_;
|
||||
}
|
||||
|
||||
uint32_t register_bits() const {
|
||||
// The register bits use the same field as the deopt_index_.
|
||||
DCHECK(is_valid());
|
||||
return deopt_index_;
|
||||
}
|
||||
|
||||
bool has_register_bits() const {
|
||||
// The register bits use the same field as the deopt_index_.
|
||||
DCHECK(is_valid());
|
||||
return deopt_index_ != kNoDeoptIndex;
|
||||
}
|
||||
int trampoline_pc() const { return trampoline_pc_; }
|
||||
|
||||
bool has_deoptimization_index() const {
|
||||
DCHECK(is_valid());
|
||||
return deopt_index_ != kNoDeoptIndex;
|
||||
}
|
||||
|
||||
uint8_t* bits() const {
|
||||
int deoptimization_index() const {
|
||||
DCHECK(is_valid() && has_deoptimization_index());
|
||||
return deopt_index_;
|
||||
}
|
||||
|
||||
uint32_t tagged_register_indexes() const {
|
||||
DCHECK(is_valid());
|
||||
return bits_;
|
||||
return tagged_register_indexes_;
|
||||
}
|
||||
|
||||
base::iterator_range<uint8_t*> iterate_bits() const {
|
||||
return base::make_iterator_range(bits_, bits_end_);
|
||||
base::Vector<const uint8_t> tagged_slots() const {
|
||||
DCHECK(is_valid());
|
||||
return tagged_slots_;
|
||||
}
|
||||
|
||||
size_t entry_size() const { return bits_end_ - bits_; }
|
||||
|
||||
private:
|
||||
int pc_ = -1;
|
||||
int deopt_index_ = kNoDeoptIndex;
|
||||
uint8_t* bits_ = nullptr;
|
||||
uint8_t* bits_end_ = nullptr;
|
||||
uint32_t tagged_register_indexes_ = 0;
|
||||
base::Vector<uint8_t> tagged_slots_;
|
||||
int trampoline_pc_ = kNoTrampolinePC;
|
||||
};
|
||||
|
||||
@ -102,32 +96,44 @@ class SafepointTable {
|
||||
SafepointTable(const SafepointTable&) = delete;
|
||||
SafepointTable& operator=(const SafepointTable&) = delete;
|
||||
|
||||
int size() const {
|
||||
return kHeaderSize + (length_ * (kFixedEntrySize + entry_size_));
|
||||
}
|
||||
int length() const { return length_; }
|
||||
int entry_size() const { return entry_size_; }
|
||||
|
||||
int GetPcOffset(int index) const {
|
||||
DCHECK_GT(length_, index);
|
||||
return base::Memory<int>(GetPcOffsetLocation(index));
|
||||
}
|
||||
|
||||
int GetTrampolinePcOffset(int index) const {
|
||||
DCHECK_GT(length_, index);
|
||||
return base::Memory<int>(GetTrampolineLocation(index));
|
||||
int byte_size() const {
|
||||
return kHeaderSize + length_ * (entry_size() + tagged_slots_bytes());
|
||||
}
|
||||
|
||||
int find_return_pc(int pc_offset);
|
||||
|
||||
SafepointEntry GetEntry(int index) const {
|
||||
DCHECK_GT(length_, index);
|
||||
int deopt_index = base::Memory<int>(GetEncodedInfoLocation(index));
|
||||
uint8_t* bits = &base::Memory<uint8_t>(entries() + (index * entry_size_));
|
||||
int trampoline_pc = has_deopt_
|
||||
? base::Memory<int>(GetTrampolineLocation(index))
|
||||
: SafepointEntry::kNoTrampolinePC;
|
||||
return SafepointEntry(deopt_index, bits, bits + entry_size_, trampoline_pc);
|
||||
Address entry_ptr =
|
||||
safepoint_table_address_ + kHeaderSize + index * entry_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 = 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;
|
||||
}
|
||||
|
||||
// Entry bits start after the the vector of entries (thus the pc offset of
|
||||
// the non-existing entry after the last one).
|
||||
uint8_t* tagged_slots_start = reinterpret_cast<uint8_t*>(
|
||||
safepoint_table_address_ + kHeaderSize + length_ * entry_size());
|
||||
base::Vector<uint8_t> tagged_slots(
|
||||
tagged_slots_start + index * tagged_slots_bytes(),
|
||||
tagged_slots_bytes());
|
||||
|
||||
return SafepointEntry(pc, deopt_index, tagged_register_indexes,
|
||||
tagged_slots, trampoline_pc);
|
||||
}
|
||||
|
||||
// Returns the entry for the given pc.
|
||||
@ -136,54 +142,46 @@ class SafepointTable {
|
||||
void PrintEntry(int index, std::ostream& os) const;
|
||||
|
||||
private:
|
||||
SafepointTable(Address instruction_start, Address safepoint_table_address,
|
||||
bool has_deopt);
|
||||
|
||||
static const uint8_t kNoRegisters = 0xFF;
|
||||
|
||||
// Layout information.
|
||||
static const int kLengthOffset = 0;
|
||||
static const int kEntrySizeOffset = kLengthOffset + kIntSize;
|
||||
static const int kHeaderSize = kEntrySizeOffset + kIntSize;
|
||||
static const int kPcOffset = 0;
|
||||
static const int kEncodedInfoOffset = kPcOffset + kIntSize;
|
||||
static const int kTrampolinePcOffset = kEncodedInfoOffset + kIntSize;
|
||||
static const int kFixedEntrySize = kTrampolinePcOffset + kIntSize;
|
||||
static constexpr int kLengthOffset = 0;
|
||||
static constexpr int kEntryConfigurationOffset = kLengthOffset + kIntSize;
|
||||
static constexpr int kHeaderSize = kEntryConfigurationOffset + kUInt32Size;
|
||||
|
||||
static int ReadLength(Address table) {
|
||||
return base::Memory<int>(table + kLengthOffset);
|
||||
}
|
||||
static int ReadEntrySize(Address table) {
|
||||
return base::Memory<int>(table + kEntrySizeOffset);
|
||||
}
|
||||
Address pc_and_deoptimization_indexes() const {
|
||||
return safepoint_table_address_ + kHeaderSize;
|
||||
}
|
||||
Address entries() const {
|
||||
return safepoint_table_address_ + kHeaderSize + (length_ * kFixedEntrySize);
|
||||
// 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 {
|
||||
return kPcSize + (has_deopt_data() ? kDeoptDataSize : 0) +
|
||||
(has_register_indexes() ? kRegisterIndexesSize : 0);
|
||||
}
|
||||
|
||||
Address GetPcOffsetLocation(int index) const {
|
||||
return pc_and_deoptimization_indexes() + (index * kFixedEntrySize);
|
||||
int tagged_slots_bytes() const {
|
||||
return TaggedSlotsBytesField::decode(entry_configuration_);
|
||||
}
|
||||
|
||||
Address GetEncodedInfoLocation(int index) const {
|
||||
return GetPcOffsetLocation(index) + kEncodedInfoOffset;
|
||||
bool has_deopt_data() const {
|
||||
return HasDeoptDataField::decode(entry_configuration_);
|
||||
}
|
||||
|
||||
Address GetTrampolineLocation(int index) const {
|
||||
return GetPcOffsetLocation(index) + kTrampolinePcOffset;
|
||||
bool has_register_indexes() const {
|
||||
return HasRegisterIndexesField::decode(entry_configuration_);
|
||||
}
|
||||
|
||||
DISALLOW_GARBAGE_COLLECTION(no_gc_)
|
||||
|
||||
const Address instruction_start_;
|
||||
const bool has_deopt_;
|
||||
|
||||
// Safepoint table layout.
|
||||
const Address safepoint_table_address_;
|
||||
const int length_;
|
||||
const int entry_size_;
|
||||
const uint32_t entry_configuration_;
|
||||
|
||||
friend class SafepointTableBuilder;
|
||||
friend class SafepointEntry;
|
||||
@ -265,7 +263,7 @@ class SafepointTableBuilder {
|
||||
|
||||
int offset_ = -1;
|
||||
|
||||
Zone* zone_;
|
||||
Zone* const zone_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -995,8 +995,8 @@ void CommonFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
entry->code.GetSafepointEntry(isolate(), inner_pointer);
|
||||
DCHECK(entry->safepoint_entry.is_valid());
|
||||
} else {
|
||||
DCHECK(entry->safepoint_entry.Equals(
|
||||
entry->code.GetSafepointEntry(isolate(), inner_pointer)));
|
||||
DCHECK_EQ(entry->safepoint_entry,
|
||||
entry->code.GetSafepointEntry(isolate(), inner_pointer));
|
||||
}
|
||||
|
||||
code = entry->code;
|
||||
@ -1090,10 +1090,10 @@ void CommonFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
|
||||
// Visit pointer spill slots and locals.
|
||||
DCHECK_GE((stack_slots + kBitsPerByte) / kBitsPerByte,
|
||||
safepoint_entry.entry_size());
|
||||
safepoint_entry.tagged_slots().size());
|
||||
int slot_offset = 0;
|
||||
PtrComprCageBase cage_base(isolate());
|
||||
for (uint8_t bits : safepoint_entry.iterate_bits()) {
|
||||
for (uint8_t bits : safepoint_entry.tagged_slots()) {
|
||||
while (bits) {
|
||||
int bit = base::bits::CountTrailingZeros(bits);
|
||||
bits &= ~(1 << bit);
|
||||
@ -2042,12 +2042,11 @@ void WasmDebugBreakFrame::Iterate(RootVisitor* v) const {
|
||||
DCHECK(code);
|
||||
SafepointTable table(code);
|
||||
SafepointEntry safepoint_entry = table.FindEntry(caller_pc());
|
||||
if (!safepoint_entry.has_register_bits()) return;
|
||||
uint32_t register_bits = safepoint_entry.register_bits();
|
||||
uint32_t tagged_register_indexes = safepoint_entry.tagged_register_indexes();
|
||||
|
||||
while (register_bits != 0) {
|
||||
int reg_code = base::bits::CountTrailingZeros(register_bits);
|
||||
register_bits &= ~(1 << reg_code);
|
||||
while (tagged_register_indexes != 0) {
|
||||
int reg_code = base::bits::CountTrailingZeros(tagged_register_indexes);
|
||||
tagged_register_indexes &= ~(1 << reg_code);
|
||||
FullObjectSlot spill_slot(&Memory<Address>(
|
||||
fp() +
|
||||
WasmDebugBreakFrameConstants::GetPushedGpRegisterOffset(reg_code)));
|
||||
|
@ -585,18 +585,16 @@ void Code::Disassemble(const char* name, std::ostream& os, Isolate* isolate,
|
||||
|
||||
if (has_safepoint_info()) {
|
||||
SafepointTable table(isolate, current_pc, *this);
|
||||
os << "Safepoints (size = " << table.size() << ")\n";
|
||||
os << "Safepoints (entries = " << table.length()
|
||||
<< ", byte size = " << table.byte_size() << ")\n";
|
||||
for (int i = 0; i < table.length(); i++) {
|
||||
int pc_offset = table.GetPcOffset(i);
|
||||
os << reinterpret_cast<const void*>(InstructionStart() + pc_offset)
|
||||
<< " ";
|
||||
os << std::setw(6) << std::hex << pc_offset << " " << std::setw(4);
|
||||
int trampoline_pc = table.GetTrampolinePcOffset(i);
|
||||
print_pc(os, trampoline_pc);
|
||||
SafepointEntry entry = table.GetEntry(i);
|
||||
os << reinterpret_cast<const void*>(InstructionStart() + entry.pc())
|
||||
<< " " << std::setw(6) << std::hex << entry.pc() << " ";
|
||||
print_pc(os, entry.trampoline_pc());
|
||||
os << std::dec << " ";
|
||||
table.PrintEntry(i, os);
|
||||
os << " (sp -> fp) ";
|
||||
SafepointEntry entry = table.GetEntry(i);
|
||||
if (entry.has_deoptimization_index()) {
|
||||
os << std::setw(6) << entry.deoptimization_index();
|
||||
} else {
|
||||
@ -610,8 +608,9 @@ void Code::Disassemble(const char* name, std::ostream& os, Isolate* isolate,
|
||||
if (has_handler_table()) {
|
||||
HandlerTable table(*this);
|
||||
os << "Handler Table (size = " << table.NumberOfReturnEntries() << ")\n";
|
||||
if (CodeKindIsOptimizedJSFunction(kind()))
|
||||
if (CodeKindIsOptimizedJSFunction(kind())) {
|
||||
table.HandlerTableReturnPrint(os);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
|
@ -436,20 +436,21 @@ void WasmCode::Disassemble(const char* name, std::ostream& os,
|
||||
|
||||
if (safepoint_table_offset_ > 0) {
|
||||
SafepointTable table(this);
|
||||
os << "Safepoints (size = " << table.size() << ")\n";
|
||||
// TODO(clemensb): Unify with printing in code.cc.
|
||||
os << "Safepoints (entries = " << table.length()
|
||||
<< ", byte size = " << table.byte_size() << ")\n";
|
||||
for (int i = 0; i < table.length(); i++) {
|
||||
int pc_offset = table.GetPcOffset(i);
|
||||
os << reinterpret_cast<const void*>(instruction_start() + pc_offset);
|
||||
os << std::setw(6) << std::hex << pc_offset << " " << std::dec;
|
||||
SafepointEntry entry = table.GetEntry(i);
|
||||
os << reinterpret_cast<const void*>(instruction_start() + entry.pc())
|
||||
<< " " << std::setw(6) << std::hex << entry.pc() << " ";
|
||||
table.PrintEntry(i, os);
|
||||
os << " (sp -> fp)";
|
||||
SafepointEntry entry = table.GetEntry(i);
|
||||
if (entry.trampoline_pc() != SafepointEntry::kNoTrampolinePC) {
|
||||
os << " trampoline: " << std::hex << entry.trampoline_pc() << std::dec;
|
||||
}
|
||||
if (entry.has_register_bits()) {
|
||||
if (entry.tagged_register_indexes() != 0) {
|
||||
os << " registers: ";
|
||||
uint32_t register_bits = entry.register_bits();
|
||||
uint32_t register_bits = entry.tagged_register_indexes();
|
||||
int bits = 32 - base::bits::CountLeadingZeros32(register_bits);
|
||||
for (int j = bits - 1; j >= 0; --j) {
|
||||
os << ((register_bits >> j) & 1);
|
||||
|
Loading…
Reference in New Issue
Block a user