diff options
author | 2017-07-10 14:13:41 -0700 | |
---|---|---|
committer | 2017-07-12 17:54:49 -0700 | |
commit | de4b08ff24c330d5b36b5c4dc8664ed4848eeca6 (patch) | |
tree | 79835478b8b631bbf006b5e023704f3cf53bda7c /runtime/dex_to_dex_decompiler.cc | |
parent | c9267c48979698a9217760c914aba13ea20b5990 (diff) |
Reduce quicken info size
Move the quicken info from using a map of <dex pc, index> to an array
of indices. Removed leb encoding since it is harmful for 16 bit
indices. The map is indexed by the dequickenable instruction index
from the start of the code item.
Numbers for a certain large app compiled with quicken filter:
dex2oat native alloc: 85345936B -> 81527072B
oat file size: 9068968B -> 8659368B
vdex file size: 90479120B -> 86321184B
Bug: 63467744
Bug: 36457259
Test: test-art-host
(cherry picked from commit 959f348acabc48efbb18c547dad6300c0f610c1c)
Change-Id: I85546d8cd409cbf96140cbdddabd7e228797b9e3
Diffstat (limited to 'runtime/dex_to_dex_decompiler.cc')
-rw-r--r-- | runtime/dex_to_dex_decompiler.cc | 100 |
1 files changed, 43 insertions, 57 deletions
diff --git a/runtime/dex_to_dex_decompiler.cc b/runtime/dex_to_dex_decompiler.cc index c15c9ec448..b82f4f74a9 100644 --- a/runtime/dex_to_dex_decompiler.cc +++ b/runtime/dex_to_dex_decompiler.cc @@ -18,9 +18,10 @@ #include "base/logging.h" #include "base/mutex.h" +#include "bytecode_utils.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" -#include "bytecode_utils.h" +#include "quicken_info.h" namespace art { namespace optimizer { @@ -31,27 +32,21 @@ class DexDecompiler { const ArrayRef<const uint8_t>& quickened_info, bool decompile_return_instruction) : code_item_(code_item), - quickened_info_ptr_(quickened_info.data()), - quickened_info_start_(quickened_info.data()), - quickened_info_end_(quickened_info.data() + quickened_info.size()), + quicken_info_(quickened_info.data()), + quicken_info_number_of_indices_(QuickenInfoTable::NumberOfIndices(quickened_info.size())), decompile_return_instruction_(decompile_return_instruction) {} bool Decompile(); private: - void DecompileInstanceFieldAccess(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode) { - uint16_t index = GetIndexAt(dex_pc); + void DecompileInstanceFieldAccess(Instruction* inst, Instruction::Code new_opcode) { + uint16_t index = NextIndex(); inst->SetOpcode(new_opcode); inst->SetVRegC_22c(index); } - void DecompileInvokeVirtual(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode, - bool is_range) { - uint16_t index = GetIndexAt(dex_pc); + void DecompileInvokeVirtual(Instruction* inst, Instruction::Code new_opcode, bool is_range) { + const uint16_t index = NextIndex(); inst->SetOpcode(new_opcode); if (is_range) { inst->SetVRegB_3rc(index); @@ -60,40 +55,32 @@ class DexDecompiler { } } - void DecompileNop(Instruction* inst, uint32_t dex_pc) { - if (quickened_info_ptr_ == quickened_info_end_) { + void DecompileNop(Instruction* inst) { + const uint16_t reference_index = NextIndex(); + if (reference_index == DexFile::kDexNoIndex16) { + // This means it was a normal nop and not a check-cast. return; } - const uint8_t* temporary_pointer = quickened_info_ptr_; - uint32_t quickened_pc = DecodeUnsignedLeb128(&temporary_pointer); - if (quickened_pc != dex_pc) { - return; - } - uint16_t reference_index = GetIndexAt(dex_pc); - uint16_t type_index = GetIndexAt(dex_pc); + const uint16_t type_index = NextIndex(); inst->SetOpcode(Instruction::CHECK_CAST); inst->SetVRegA_21c(reference_index); inst->SetVRegB_21c(type_index); } - uint16_t GetIndexAt(uint32_t dex_pc) { - // Note that as a side effect, DecodeUnsignedLeb128 update the given pointer - // to the new position in the buffer. - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint32_t quickened_pc = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint16_t index = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LE(quickened_info_ptr_, quickened_info_end_); - DCHECK_EQ(quickened_pc, dex_pc); - return index; + uint16_t NextIndex() { + DCHECK_LT(quicken_index_, quicken_info_number_of_indices_); + const uint16_t ret = quicken_info_.GetData(quicken_index_); + quicken_index_++; + return ret; } const DexFile::CodeItem& code_item_; - const uint8_t* quickened_info_ptr_; - const uint8_t* const quickened_info_start_; - const uint8_t* const quickened_info_end_; + const QuickenInfoTable quicken_info_; + const size_t quicken_info_number_of_indices_; const bool decompile_return_instruction_; + size_t quicken_index_ = 0u; + DISALLOW_COPY_AND_ASSIGN(DexDecompiler); }; @@ -103,7 +90,6 @@ bool DexDecompiler::Decompile() { // unquickening is a rare need and not performance sensitive, it is not worth the // added storage to also add the RETURN_VOID quickening in the quickened data. for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) { - uint32_t dex_pc = it.CurrentDexPc(); Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction()); switch (inst->Opcode()) { @@ -114,71 +100,71 @@ bool DexDecompiler::Decompile() { break; case Instruction::NOP: - DecompileNop(inst, dex_pc); + DecompileNop(inst); break; case Instruction::IGET_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET); + DecompileInstanceFieldAccess(inst, Instruction::IGET); break; case Instruction::IGET_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_WIDE); + DecompileInstanceFieldAccess(inst, Instruction::IGET_WIDE); break; case Instruction::IGET_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_OBJECT); + DecompileInstanceFieldAccess(inst, Instruction::IGET_OBJECT); break; case Instruction::IGET_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BOOLEAN); + DecompileInstanceFieldAccess(inst, Instruction::IGET_BOOLEAN); break; case Instruction::IGET_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BYTE); + DecompileInstanceFieldAccess(inst, Instruction::IGET_BYTE); break; case Instruction::IGET_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_CHAR); + DecompileInstanceFieldAccess(inst, Instruction::IGET_CHAR); break; case Instruction::IGET_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_SHORT); + DecompileInstanceFieldAccess(inst, Instruction::IGET_SHORT); break; case Instruction::IPUT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT); break; case Instruction::IPUT_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BOOLEAN); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_BOOLEAN); break; case Instruction::IPUT_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BYTE); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_BYTE); break; case Instruction::IPUT_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_CHAR); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_CHAR); break; case Instruction::IPUT_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_SHORT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_SHORT); break; case Instruction::IPUT_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_WIDE); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_WIDE); break; case Instruction::IPUT_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_OBJECT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_OBJECT); break; case Instruction::INVOKE_VIRTUAL_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL, false); + DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL, false); break; case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_RANGE, true); + DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL_RANGE, true); break; default: @@ -186,14 +172,14 @@ bool DexDecompiler::Decompile() { } } - if (quickened_info_ptr_ != quickened_info_end_) { - if (quickened_info_start_ == quickened_info_ptr_) { + if (quicken_index_ != quicken_info_number_of_indices_) { + if (quicken_index_ == 0) { LOG(WARNING) << "Failed to use any value in quickening info," << " potentially due to duplicate methods."; } else { LOG(FATAL) << "Failed to use all values in quickening info." - << " Actual: " << std::hex << reinterpret_cast<uintptr_t>(quickened_info_ptr_) - << " Expected: " << reinterpret_cast<uintptr_t>(quickened_info_end_); + << " Actual: " << std::hex << quicken_index_ + << " Expected: " << quicken_info_number_of_indices_; return false; } } |