current_stack_map_ = BitTableBuilder<StackMap>::Entry();
current_stack_map_[StackMap::kKind] = static_cast<uint32_t>(kind);
current_stack_map_[StackMap::kPackedNativePc] =
StackMap::PackNativePc(native_pc_offset, instruction_set_);
current_stack_map_[StackMap::kDexPc] = dex_pc; if (stack_maps_.size() > 0) { // Check that non-catch stack maps are sorted by pc. // Catch stack maps are at the end and may be unordered. if (stack_maps_.back()[StackMap::kKind] == StackMap::Kind::Catch) {
DCHECK(current_stack_map_[StackMap::kKind] == StackMap::Kind::Catch);
} elseif (current_stack_map_[StackMap::kKind] != StackMap::Kind::Catch) {
DCHECK_LE(stack_maps_.back()[StackMap::kPackedNativePc],
current_stack_map_[StackMap::kPackedNativePc]);
}
} if (register_mask != 0) {
uint32_t shift = LeastSignificantBit(register_mask);
BitTableBuilder<RegisterMask>::Entry entry;
entry[RegisterMask::kValue] = register_mask >> shift;
entry[RegisterMask::kShift] = shift;
current_stack_map_[StackMap::kRegisterMaskIndex] = register_masks_.Dedup(&entry);
} // The compiler assumes the bit vector will be read during PrepareForFillIn(), // and it might modify the data before that. Therefore, just store the pointer. // See ClearSpillSlotsFromLoopPhisInStackMap in code_generator.h.
lazy_stack_masks_.push_back(stack_mask);
current_inline_infos_.clear();
current_dex_registers_.clear();
expected_num_dex_registers_ = needs_vreg_info ? num_dex_registers_ : 0u;
if (kVerifyStackMaps) {
size_t stack_map_index = stack_maps_.size(); // Create lambda method, which will be executed at the very end to verify data. // Parameters and local variables will be captured(stored) by the lambda "[=]".
dchecks_.emplace_back([=, this](const CodeInfo& code_info) { // The `native_pc_offset` may have been overridden using `SetStackMapNativePcOffset(.)`.
uint32_t final_native_pc_offset = GetStackMapNativePcOffset(stack_map_index); if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) {
StackMap stack_map = code_info.GetStackMapForNativePcOffset(final_native_pc_offset,
instruction_set_);
CHECK_EQ(stack_map.Row(), stack_map_index);
} elseif (kind == StackMap::Kind::Catch) {
StackMap stack_map = code_info.GetCatchStackMapForDexPc(
ArrayRef<const uint32_t>(dex_pc_list_for_catch_verification));
CHECK_EQ(stack_map.Row(), stack_map_index);
}
StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
CHECK_EQ(stack_map.GetNativePcOffset(instruction_set_), final_native_pc_offset);
CHECK_EQ(stack_map.GetKind(), static_cast<uint32_t>(kind));
CHECK_EQ(stack_map.GetDexPc(), dex_pc);
CHECK_EQ(code_info.GetRegisterMaskOf(stack_map), register_mask);
BitMemoryRegion seen_stack_mask = code_info.GetStackMaskOf(stack_map);
CHECK_GE(seen_stack_mask.size_in_bits(), stack_mask ? stack_mask->GetNumberOfBits() : 0); for (size_t b = 0; b < seen_stack_mask.size_in_bits(); b++) {
CHECK_EQ(seen_stack_mask.LoadBit(b), stack_mask != nullptr && stack_mask->IsBitSet(b));
}
});
}
}
// Create delta-compressed dex register map based on the current list of DexRegisterLocations. // All dex registers for a stack map are concatenated - inlined registers are just appended. void StackMapStream::CreateDexRegisterMap() { // These are fields rather than local variables so that we can reuse the reserved memory.
temp_dex_register_mask_.ClearAllBits();
temp_dex_register_map_.clear();
// Ensure that the arrays that hold previous state are big enough to be safely indexed below. if (previous_dex_registers_.size() < current_dex_registers_.size()) {
previous_dex_registers_.resize(current_dex_registers_.size(), DexRegisterLocation::None());
dex_register_timestamp_.resize(current_dex_registers_.size(), 0u);
}
// Set bit in the mask for each register that has been changed since the previous stack map. // Modified registers are stored in the catalogue and the catalogue index added to the list. for (size_t i = 0; i < current_dex_registers_.size(); i++) {
DexRegisterLocation reg = current_dex_registers_[i]; // Distance is difference between this index and the index of last modification.
uint32_t distance = stack_maps_.size() - dex_register_timestamp_[i]; if (previous_dex_registers_[i] != reg || distance > kMaxDexRegisterMapSearchDistance) {
BitTableBuilder<DexRegisterInfo>::Entry entry;
entry[DexRegisterInfo::kKind] = static_cast<uint32_t>(reg.GetKind());
entry[DexRegisterInfo::kPackedValue] =
DexRegisterInfo::PackValue(reg.GetKind(), reg.GetValue());
uint32_t index = reg.IsLive() ? dex_register_catalog_.Dedup(&entry) : kNoValue;
temp_dex_register_mask_.SetBit(i);
temp_dex_register_map_.push_back({index});
previous_dex_registers_[i] = reg;
dex_register_timestamp_[i] = stack_maps_.size();
}
}
// Set the mask and map for the current StackMap (which includes inlined registers). if (temp_dex_register_mask_.GetNumberOfBits() != 0) {
current_stack_map_[StackMap::kDexRegisterMaskIndex] =
dex_register_masks_.Dedup(temp_dex_register_mask_.GetRawStorage(),
temp_dex_register_mask_.GetNumberOfBits());
} if (!current_dex_registers_.empty()) {
current_stack_map_[StackMap::kDexRegisterMapIndex] =
dex_register_maps_.Dedup(temp_dex_register_map_.data(),
temp_dex_register_map_.size());
}
if (kVerifyStackMaps) {
size_t stack_map_index = stack_maps_.size(); // We need to make copy of the current registers for later (when the check is run). auto expected_dex_registers = std::make_shared<dchecked_vector<DexRegisterLocation>>(
current_dex_registers_.begin(), current_dex_registers_.end());
dchecks_.emplace_back([=](const CodeInfo& code_info) {
StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
uint32_t expected_reg = 0; for (DexRegisterLocation reg : code_info.GetDexRegisterMapOf(stack_map)) {
CHECK_EQ((*expected_dex_registers)[expected_reg++], reg);
} for (InlineInfo inline_info : code_info.GetInlineInfosOf(stack_map)) {
DexRegisterMap map = code_info.GetInlineDexRegisterMapOf(stack_map, inline_info); for (DexRegisterLocation reg : map) {
CHECK_EQ((*expected_dex_registers)[expected_reg++], reg);
}
}
CHECK_EQ(expected_reg, expected_dex_registers->size());
});
}
}
uint32_t bit_table_flags = 0;
ForEachBitTable([&bit_table_flags](size_t i, auto bit_table) { if (bit_table->size() != 0) { // Record which bit-tables are stored.
bit_table_flags |= 1 << i;
}
});
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.