Move oatdump to use code item accessor
Bug: 63756964
Test: test-art-host
Test: clean-oat-host && dump-oat-boot
Change-Id: I26dae94761ae38d44ccaa372a468013a9a13ce3d
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index b20fa90..8334a62 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -36,6 +36,7 @@
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "class_linker.h"
+#include "code_item_accessors-inl.h"
#include "compiled_method.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
@@ -994,14 +995,15 @@
if (code_item == nullptr) {
return;
}
+ CodeItemInstructionAccessor instructions(&dex_file, code_item);
- const uint16_t* code_ptr = code_item->insns_;
// If we inserted a new dex code item pointer, add to total code bytes.
+ const uint16_t* code_ptr = instructions.Insns();
if (dex_code_item_ptrs_.insert(code_ptr).second) {
- dex_code_bytes_ += code_item->insns_size_in_code_units_ * sizeof(code_ptr[0]);
+ dex_code_bytes_ += instructions.InsnsSizeInCodeUnits() * sizeof(code_ptr[0]);
}
- for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+ for (const DexInstructionPcPair& inst : instructions) {
switch (inst->Opcode()) {
case Instruction::CONST_STRING: {
const dex::StringIndex string_index(inst->VRegB_21c());
@@ -1266,11 +1268,17 @@
bool DumpOatMethod(VariableIndentationOutputStream* vios,
const DexFile::ClassDef& class_def,
uint32_t class_method_index,
- const OatFile::OatClass& oat_class, const DexFile& dex_file,
- uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
- uint32_t method_access_flags, bool* addr_found) {
+ const OatFile::OatClass& oat_class,
+ const DexFile& dex_file,
+ uint32_t dex_method_idx,
+ const DexFile::CodeItem* code_item,
+ uint32_t method_access_flags,
+ bool* addr_found) {
bool success = true;
+ CodeItemDataAccessor code_item_accessor(CodeItemDataAccessor::CreateNullable(&dex_file,
+ code_item));
+
// TODO: Support regex
std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
if (method_name.find(options_.method_filter_) == std::string::npos) {
@@ -1281,7 +1289,9 @@
vios->Stream() << StringPrintf("%d: %s (dex_method_idx=%d)\n",
class_method_index, pretty_method.c_str(),
dex_method_idx);
- if (options_.list_methods_) return success;
+ if (options_.list_methods_) {
+ return success;
+ }
uint32_t oat_method_offsets_offset = oat_class.GetOatMethodOffsetsOffset(class_method_index);
const OatMethodOffsets* oat_method_offsets = oat_class.GetOatMethodOffsets(class_method_index);
@@ -1302,7 +1312,12 @@
{
vios->Stream() << "DEX CODE:\n";
ScopedIndentation indent2(vios);
- DumpDexCode(vios->Stream(), dex_file, code_item);
+ if (code_item_accessor.HasCodeItem()) {
+ for (const DexInstructionPcPair& inst : code_item_accessor) {
+ vios->Stream() << StringPrintf("0x%04x: ", inst.DexPc()) << inst->DumpHexLE(5)
+ << StringPrintf("\t| %s\n", inst->DumpString(&dex_file).c_str());
+ }
+ }
}
std::unique_ptr<StackHandleScope<1>> hs;
@@ -1373,7 +1388,7 @@
vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);
size_t vmap_table_offset_limit =
- (kIsVdexEnabled && IsMethodGeneratedByDexToDexCompiler(oat_method, code_item))
+ (kIsVdexEnabled && IsMethodGeneratedByDexToDexCompiler(oat_method, code_item_accessor))
? oat_file_.GetVdexFile()->Size()
: method_header->GetCode() - oat_file_.Begin();
if (vmap_table_offset >= vmap_table_offset_limit) {
@@ -1385,7 +1400,7 @@
oat_method.GetVmapTableOffsetOffset());
success = false;
} else if (options_.dump_vmap_) {
- DumpVmapData(vios, oat_method, code_item);
+ DumpVmapData(vios, oat_method, code_item_accessor);
}
}
{
@@ -1406,7 +1421,7 @@
// after it is dumped, but useful for understanding quick
// code, so dumped here.
ScopedIndentation indent2(vios);
- DumpVregLocations(vios->Stream(), oat_method, code_item);
+ DumpVregLocations(vios->Stream(), oat_method, code_item_accessor);
}
{
vios->Stream() << "CODE: ";
@@ -1448,7 +1463,7 @@
success = false;
if (options_.disassemble_code_) {
if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
- DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
+ DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
}
}
} else if (code_size > kMaxCodeSize) {
@@ -1461,11 +1476,11 @@
success = false;
if (options_.disassemble_code_) {
if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
- DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
+ DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
}
}
} else if (options_.disassemble_code_) {
- DumpCode(vios, oat_method, code_item, !success, 0);
+ DumpCode(vios, oat_method, code_item_accessor, !success, 0);
}
}
}
@@ -1499,18 +1514,18 @@
// Display data stored at the the vmap offset of an oat method.
void DumpVmapData(VariableIndentationOutputStream* vios,
const OatFile::OatMethod& oat_method,
- const DexFile::CodeItem* code_item) {
- if (IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
+ const CodeItemDataAccessor& code_item_accessor) {
+ if (IsMethodGeneratedByOptimizingCompiler(oat_method, code_item_accessor)) {
// The optimizing compiler outputs its CodeInfo data in the vmap table.
const void* raw_code_info = oat_method.GetVmapTable();
if (raw_code_info != nullptr) {
CodeInfo code_info(raw_code_info);
- DCHECK(code_item != nullptr);
+ DCHECK(code_item_accessor.HasCodeItem());
ScopedIndentation indent1(vios);
MethodInfo method_info = oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo();
- DumpCodeInfo(vios, code_info, oat_method, *code_item, method_info);
+ DumpCodeInfo(vios, code_info, oat_method, code_item_accessor, method_info);
}
- } else if (IsMethodGeneratedByDexToDexCompiler(oat_method, code_item)) {
+ } else if (IsMethodGeneratedByDexToDexCompiler(oat_method, code_item_accessor)) {
// We don't encode the size in the table, so just emit that we have quickened
// information.
ScopedIndentation indent(vios);
@@ -1524,11 +1539,11 @@
void DumpCodeInfo(VariableIndentationOutputStream* vios,
const CodeInfo& code_info,
const OatFile::OatMethod& oat_method,
- const DexFile::CodeItem& code_item,
+ const CodeItemDataAccessor& code_item_accessor,
const MethodInfo& method_info) {
code_info.Dump(vios,
oat_method.GetCodeOffset(),
- code_item.registers_size_,
+ code_item_accessor.RegistersSize(),
options_.dump_code_info_stack_maps_,
instruction_set_,
method_info);
@@ -1539,7 +1554,7 @@
return static_cast<size_t>(InstructionSetPointerSize(isa)) + out_num * sizeof(uint32_t);
}
- static uint32_t GetVRegOffsetFromQuickCode(const DexFile::CodeItem* code_item,
+ static uint32_t GetVRegOffsetFromQuickCode(const CodeItemDataAccessor& code_item_accessor,
uint32_t core_spills,
uint32_t fp_spills,
size_t frame_size,
@@ -1557,8 +1572,8 @@
int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa)
+ POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa)
+ sizeof(uint32_t); // Filler.
- int num_regs = code_item->registers_size_ - code_item->ins_size_;
- int temp_threshold = code_item->registers_size_;
+ int num_regs = code_item_accessor.RegistersSize() - code_item_accessor.InsSize();
+ int temp_threshold = code_item_accessor.RegistersSize();
const int max_num_special_temps = 1;
if (reg == temp_threshold) {
// The current method pointer corresponds to special location on stack.
@@ -1568,7 +1583,7 @@
* Special temporaries may have custom locations and the logic above deals with that.
* However, non-special temporaries are placed relative to the outs.
*/
- int temps_start = code_item->outs_size_ * sizeof(uint32_t)
+ int temps_start = code_item_accessor.OutsSize() * sizeof(uint32_t)
+ static_cast<size_t>(pointer_size) /* art method */;
int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t);
return temps_start + relative_offset;
@@ -1583,12 +1598,12 @@
}
void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
- const DexFile::CodeItem* code_item) {
- if (code_item != nullptr) {
- size_t num_locals_ins = code_item->registers_size_;
- size_t num_ins = code_item->ins_size_;
+ const CodeItemDataAccessor& code_item_accessor) {
+ if (code_item_accessor.HasCodeItem()) {
+ size_t num_locals_ins = code_item_accessor.RegistersSize();
+ size_t num_ins = code_item_accessor.InsSize();
size_t num_locals = num_locals_ins - num_ins;
- size_t num_outs = code_item->outs_size_;
+ size_t num_outs = code_item_accessor.OutsSize();
os << "vr_stack_locations:";
for (size_t reg = 0; reg <= num_locals_ins; reg++) {
@@ -1601,7 +1616,7 @@
os << "\n\tlocals:";
}
- uint32_t offset = GetVRegOffsetFromQuickCode(code_item,
+ uint32_t offset = GetVRegOffsetFromQuickCode(code_item_accessor,
oat_method.GetCoreSpillMask(),
oat_method.GetFpSpillMask(),
oat_method.GetFrameSizeInBytes(),
@@ -1623,37 +1638,30 @@
}
}
- void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
- if (code_item != nullptr) {
- for (const DexInstructionPcPair& inst : code_item->Instructions()) {
- os << StringPrintf("0x%04x: ", inst.DexPc()) << inst->DumpHexLE(5)
- << StringPrintf("\t| %s\n", inst->DumpString(&dex_file).c_str());
- }
- }
- }
-
// Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
// the optimizing compiler?
- static bool IsMethodGeneratedByOptimizingCompiler(const OatFile::OatMethod& oat_method,
- const DexFile::CodeItem* code_item) {
+ static bool IsMethodGeneratedByOptimizingCompiler(
+ const OatFile::OatMethod& oat_method,
+ const CodeItemDataAccessor& code_item_accessor) {
// If the native GC map is null and the Dex `code_item` is not
// null, then this method has been compiled with the optimizing
// compiler.
return oat_method.GetQuickCode() != nullptr &&
oat_method.GetVmapTable() != nullptr &&
- code_item != nullptr;
+ code_item_accessor.HasCodeItem();
}
// Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
// the dextodex compiler?
- static bool IsMethodGeneratedByDexToDexCompiler(const OatFile::OatMethod& oat_method,
- const DexFile::CodeItem* code_item) {
+ static bool IsMethodGeneratedByDexToDexCompiler(
+ const OatFile::OatMethod& oat_method,
+ const CodeItemDataAccessor& code_item_accessor) {
// If the quick code is null, the Dex `code_item` is not
// null, and the vmap table is not null, then this method has been compiled
// with the dextodex compiler.
return oat_method.GetQuickCode() == nullptr &&
oat_method.GetVmapTable() != nullptr &&
- code_item != nullptr;
+ code_item_accessor.HasCodeItem();
}
verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
@@ -1770,7 +1778,8 @@
};
void DumpCode(VariableIndentationOutputStream* vios,
- const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item,
+ const OatFile::OatMethod& oat_method,
+ const CodeItemDataAccessor& code_item_accessor,
bool bad_input, size_t code_size) {
const void* quick_code = oat_method.GetQuickCode();
@@ -1780,7 +1789,8 @@
if (code_size == 0 || quick_code == nullptr) {
vios->Stream() << "NO CODE!\n";
return;
- } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
+ } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method,
+ code_item_accessor)) {
// The optimizing compiler outputs its CodeInfo data in the vmap table.
StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_);
MethodInfo method_info(oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo());
@@ -1835,7 +1845,8 @@
kBitsPerByte * location_catalog_bytes);
// Dex register bytes.
const size_t dex_register_bytes =
- helper.GetCodeInfo().GetDexRegisterMapsSize(encoding, code_item->registers_size_);
+ helper.GetCodeInfo().GetDexRegisterMapsSize(encoding,
+ code_item_accessor.RegistersSize());
stats_.AddBits(
Stats::kByteKindCodeInfoDexRegisterMap,
kBitsPerByte * dex_register_bytes);
@@ -1874,7 +1885,7 @@
helper.GetEncoding(),
method_info,
oat_method.GetCodeOffset(),
- code_item->registers_size_,
+ code_item_accessor.RegistersSize(),
instruction_set_);
do {
helper.Next();
@@ -2502,8 +2513,8 @@
}
}
} else {
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
+ CodeItemDataAccessor code_item_accessor(method);
+ size_t dex_instruction_bytes = code_item_accessor.InsnsSizeInCodeUnits() * 2;
stats_.dex_instruction_bytes += dex_instruction_bytes;
bool first_occurrence;
diff --git a/runtime/code_item_accessors-inl.h b/runtime/code_item_accessors-inl.h
index 61b5175..2c5bc2e 100644
--- a/runtime/code_item_accessors-inl.h
+++ b/runtime/code_item_accessors-inl.h
@@ -113,18 +113,23 @@
inline CodeItemDataAccessor::CodeItemDataAccessor(ArtMethod* method)
: CodeItemDataAccessor(method->GetDexFile(), method->GetCodeItem()) {}
-inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(ArtMethod* method) {
- DCHECK(method != nullptr);
+inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(
+ const DexFile* dex_file,
+ const DexFile::CodeItem* code_item) {
CodeItemDataAccessor ret;
- const DexFile::CodeItem* code_item = method->GetCodeItem();
if (code_item != nullptr) {
- ret.Init(method->GetDexFile(), code_item);
+ ret.Init(dex_file, code_item);
} else {
DCHECK(!ret.HasCodeItem()) << "Should be null initialized";
}
return ret;
}
+inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(ArtMethod* method) {
+ DCHECK(method != nullptr);
+ return CreateNullable(method->GetDexFile(), method->GetCodeItem());
+}
+
} // namespace art
#endif // ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
diff --git a/runtime/code_item_accessors.h b/runtime/code_item_accessors.h
index fcece3e..fdc8ac5 100644
--- a/runtime/code_item_accessors.h
+++ b/runtime/code_item_accessors.h
@@ -102,6 +102,9 @@
ALWAYS_INLINE static CodeItemDataAccessor CreateNullable(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
+ ALWAYS_INLINE static CodeItemDataAccessor CreateNullable(const DexFile* dex_file,
+ const DexFile::CodeItem* code_item);
+
protected:
CodeItemDataAccessor() = default;