CodeInfo CodeInfo::DecodeGcMasksOnly(const OatQuickMethodHeader* header) {
CodeInfo code_info(header->GetOptimizedCodeInfoPtr());
CodeInfo copy; // Copy to dead-code-eliminate all fields that we do not need.
copy.stack_maps_ = code_info.stack_maps_;
copy.register_masks_ = code_info.register_masks_;
copy.stack_masks_ = code_info.stack_masks_; return copy;
}
CodeInfo CodeInfo::DecodeInlineInfoOnly(const OatQuickMethodHeader* header) {
CodeInfo code_info(header->GetOptimizedCodeInfoPtr());
CodeInfo copy; // Copy to dead-code-eliminate all fields that we do not need.
copy.number_of_dex_registers_ = code_info.number_of_dex_registers_;
copy.stack_maps_ = code_info.stack_maps_;
copy.inline_infos_ = code_info.inline_infos_;
copy.method_infos_ = code_info.method_infos_; return copy;
}
StackMap CodeInfo::GetStackMapForNativePcOffset(uintptr_t pc, InstructionSet isa) const {
uint32_t packed_pc = StackMap::PackNativePc(pc, isa); // Binary search. All catch stack maps are stored separately at the end. auto it = std::partition_point(
stack_maps_.begin(),
stack_maps_.end(),
[packed_pc](const StackMap& sm) { return sm.GetPackedNativePc() < packed_pc && sm.GetKind() != StackMap::Kind::Catch;
}); // Start at the lower bound and iterate over all stack maps with the given native pc. for (; it != stack_maps_.end() && (*it).GetNativePcOffset(isa) == pc; ++it) {
StackMap::Kind kind = static_cast<StackMap::Kind>((*it).GetKind()); if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) { return *it;
}
} return stack_maps_.GetInvalidRow();
}
// Scan backward to determine dex register locations at given stack map. // All registers for a stack map are combined - inlined registers are just appended, // therefore 'first_dex_register' allows us to select a sub-range to decode. void CodeInfo::DecodeDexRegisterMap(uint32_t stack_map_index,
uint32_t first_dex_register, /*out*/ DexRegisterMap* map) const { // Count remaining work so we know when we have finished.
uint32_t remaining_registers = map->size();
// Keep scanning backwards and collect the most recent location of each register. for (int32_t s = stack_map_index; s >= 0 && remaining_registers != 0; s--) {
StackMap stack_map = GetStackMapAt(s);
DCHECK_LE(stack_map_index - s, kMaxDexRegisterMapSearchDistance) << "Unbounded search";
// The mask specifies which registers where modified in this stack map. // NB: the mask can be shorter than expected if trailing zero bits were removed.
uint32_t mask_index = stack_map.GetDexRegisterMaskIndex(); if (mask_index == StackMap::kNoValue) { continue; // Nothing changed at this stack map.
}
BitMemoryRegion mask = dex_register_masks_.GetBitMemoryRegion</*kColumn=*/0>(mask_index); if (mask.size_in_bits() <= first_dex_register) { continue; // Nothing changed after the first register we are interested in.
}
// The map stores one catalogue index per each modified register location.
uint32_t map_index = stack_map.GetDexRegisterMapIndex();
DCHECK_NE(map_index, StackMap::kNoValue);
// Skip initial registers which we are not interested in (to get to inlined registers).
map_index += mask.PopCount(0, first_dex_register);
mask = mask.Subregion(first_dex_register, mask.size_in_bits() - first_dex_register);
// Update registers that we see for first time (i.e. most recent value).
DexRegisterLocation* regs = map->data(); const uint32_t end = std::min<uint32_t>(map->size(), mask.size_in_bits()); const size_t kNumBits = BitSizeOf<uint32_t>(); for (uint32_t reg = 0; reg < end; reg += kNumBits) { // Process the mask in chunks of kNumBits for performance.
uint32_t bits = mask.LoadBits(reg, std::min<uint32_t>(end - reg, kNumBits)); while (bits != 0) {
uint32_t bit = CTZ(bits); if (regs[reg + bit].GetKind() == DexRegisterLocation::Kind::kInvalid) {
regs[reg + bit] =
GetDexRegisterCatalogEntry(dex_register_maps_.Get</*kColumn=*/0>(map_index));
remaining_registers--;
}
map_index++;
bits ^= 1u << bit; // Clear the bit.
}
}
}
// Set any remaining registers to None (which is the default state at first stack map). if (remaining_registers != 0) {
DexRegisterLocation* regs = map->data(); for (uint32_t r = 0; r < map->size(); r++) { if (regs[r].GetKind() == DexRegisterLocation::Kind::kInvalid) {
regs[r] = DexRegisterLocation::None();
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.