diff --git a/src/codegen/safepoint-table.cc b/src/codegen/safepoint-table.cc index 27a8031984..f57f55663f 100644 --- a/src/codegen/safepoint-table.cc +++ b/src/codegen/safepoint-table.cc @@ -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(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. diff --git a/src/codegen/safepoint-table.h b/src/codegen/safepoint-table.h index e55a5040a5..9da83a06a6 100644 --- a/src/codegen/safepoint-table.h +++ b/src/codegen/safepoint-table.h @@ -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(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(entry_ptr); + trampoline_pc = base::Memory(entry_ptr + kIntSize); + entry_ptr += kDeoptDataSize; + } + int tagged_register_indexes = 0; + if (has_register_indexes()) { + tagged_register_indexes = base::Memory(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; - using RegisterIndexesSizeField = HasDeoptDataField::Next; - using PcSizeField = RegisterIndexesSizeField::Next; - using DeoptIndexSizeField = PcSizeField::Next; - // 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; + // 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; + using HasDeoptDataField = TaggedSlotsBytesField::Next; + using HasRegisterIndexesField = HasDeoptDataField::Next; 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(*ptr); - for (int b = 1; b < bytes; ++b) { - result = result << 8 | *reinterpret_cast(*ptr + b); - } - *ptr += bytes; - return result; + bool has_register_indexes() const { + return HasRegisterIndexesField::decode(entry_configuration_); } DISALLOW_GARBAGE_COLLECTION(no_gc_)