summaryrefslogtreecommitdiff
path: root/runtime/dex_to_dex_decompiler.cc
diff options
context:
space:
mode:
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;
}
}