summaryrefslogtreecommitdiff
path: root/runtime/dex_to_dex_decompiler.cc
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2017-07-10 14:13:41 -0700
committer Mathieu Chartier <mathieuc@google.com> 2017-07-12 17:54:49 -0700
commitde4b08ff24c330d5b36b5c4dc8664ed4848eeca6 (patch)
tree79835478b8b631bbf006b5e023704f3cf53bda7c /runtime/dex_to_dex_decompiler.cc
parentc9267c48979698a9217760c914aba13ea20b5990 (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.cc100
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;
}
}