summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-05-02 15:27:29 -0700
committerIan Rogers <irogers@google.com>2014-05-02 15:35:19 -0700
commit29a2648821ea4d0b5d3aecb9f835822fdfe6faa1 (patch)
tree2eb972b2b006e4d2842c8cf6a1d6631f90a39249
parentdbb8727b0b3ae73e84fb8db55e051336d6222add (diff)
downloadandroid_art-29a2648821ea4d0b5d3aecb9f835822fdfe6faa1.tar.gz
android_art-29a2648821ea4d0b5d3aecb9f835822fdfe6faa1.tar.bz2
android_art-29a2648821ea4d0b5d3aecb9f835822fdfe6faa1.zip
Move DecodedInstruction into MIR.
Change-Id: I188dc7fef4f4033361c78daf2015b869242191c6
-rw-r--r--compiler/dex/mir_dataflow.cc8
-rw-r--r--compiler/dex/mir_graph.cc19
-rw-r--r--compiler/dex/mir_graph.h12
-rw-r--r--compiler/dex/mir_optimization.cc2
-rw-r--r--compiler/optimizing/builder.cc2
-rw-r--r--runtime/dex_instruction-inl.h156
-rw-r--r--runtime/dex_instruction.cc256
-rw-r--r--runtime/dex_instruction.h30
-rw-r--r--runtime/interpreter/interpreter_common.cc4
-rw-r--r--runtime/quick/inline_method_analyser.cc16
-rw-r--r--runtime/verifier/method_verifier.cc46
11 files changed, 226 insertions, 325 deletions
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 651fa66b9d..2f17e08974 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -880,7 +880,7 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) {
for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
uint64_t df_attributes = GetDataFlowAttributes(mir);
- DecodedInstruction *d_insn = &mir->dalvikInsn;
+ MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
if (df_attributes & DF_HAS_USES) {
if (df_attributes & DF_UA) {
@@ -949,7 +949,7 @@ void MIRGraph::HandleSSADef(int* defs, int dalvik_reg, int reg_index) {
/* Look up new SSA names for format_35c instructions */
void MIRGraph::DataFlowSSAFormat35C(MIR* mir) {
- DecodedInstruction *d_insn = &mir->dalvikInsn;
+ MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
int num_uses = d_insn->vA;
int i;
@@ -967,7 +967,7 @@ void MIRGraph::DataFlowSSAFormat35C(MIR* mir) {
/* Look up new SSA names for format_3rc instructions */
void MIRGraph::DataFlowSSAFormat3RC(MIR* mir) {
- DecodedInstruction *d_insn = &mir->dalvikInsn;
+ MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
int num_uses = d_insn->vA;
int i;
@@ -1064,7 +1064,7 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) {
kArenaAllocDFInfo));
}
- DecodedInstruction *d_insn = &mir->dalvikInsn;
+ MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
if (df_attributes & DF_HAS_USES) {
num_uses = 0;
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 6857edbbe7..30d0bc3d0a 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -21,6 +21,7 @@
#include "base/stl_util.h"
#include "compiler_internals.h"
#include "dex_file-inl.h"
+#include "dex_instruction-inl.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/quick/dex_file_method_inliner.h"
#include "leb128.h"
@@ -106,11 +107,17 @@ MIRGraph::~MIRGraph() {
/*
* Parse an instruction, return the length of the instruction
*/
-int MIRGraph::ParseInsn(const uint16_t* code_ptr, DecodedInstruction* decoded_instruction) {
- const Instruction* instruction = Instruction::At(code_ptr);
- *decoded_instruction = DecodedInstruction(instruction);
-
- return instruction->SizeInCodeUnits();
+int MIRGraph::ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction) {
+ const Instruction* inst = Instruction::At(code_ptr);
+ decoded_instruction->opcode = inst->Opcode();
+ decoded_instruction->vA = inst->HasVRegA() ? inst->VRegA() : 0;
+ decoded_instruction->vB = inst->HasVRegB() ? inst->VRegB() : 0;
+ decoded_instruction->vB_wide = inst->HasWideVRegB() ? inst->WideVRegB() : 0;
+ decoded_instruction->vC = inst->HasVRegC() ? inst->VRegC() : 0;
+ if (inst->HasVarArgs()) {
+ inst->GetVarArgs(decoded_instruction->arg);
+ }
+ return inst->SizeInCodeUnits();
}
@@ -935,7 +942,7 @@ MIR* BasicBlock::GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current) {
}
char* MIRGraph::GetDalvikDisassembly(const MIR* mir) {
- DecodedInstruction insn = mir->dalvikInsn;
+ MIR::DecodedInstruction insn = mir->dalvikInsn;
std::string str;
int flags = 0;
int opcode = insn.opcode;
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 5997e5b5bd..b926503557 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -254,7 +254,15 @@ struct MIR {
* additional fields on as-needed basis. Question: how to support MIR Pseudo-ops; probably
* need to carry aux data pointer.
*/
- DecodedInstruction dalvikInsn;
+ struct DecodedInstruction {
+ uint32_t vA;
+ uint32_t vB;
+ uint64_t vB_wide; /* for k51l */
+ uint32_t vC;
+ uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
+ Instruction::Code opcode;
+ } dalvikInsn;
+
uint16_t width; // Note: width can include switch table or fill array data.
NarrowDexOffset offset; // Offset of the instruction in code units.
uint16_t optimization_flags;
@@ -884,7 +892,7 @@ class MIRGraph {
void CompilerInitializeSSAConversion();
bool DoSSAConversion(BasicBlock* bb);
bool InvokeUsesMethodStar(MIR* mir);
- int ParseInsn(const uint16_t* code_ptr, DecodedInstruction* decoded_instruction);
+ int ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction);
bool ContentIsInsn(const uint16_t* code_ptr);
BasicBlock* SplitBlock(DexOffset code_offset, BasicBlock* orig_block,
BasicBlock** immed_pred_block_p);
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 72c46cc975..9f15cd4c3b 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -49,7 +49,7 @@ void MIRGraph::DoConstantPropagation(BasicBlock* bb) {
uint64_t df_attributes = GetDataFlowAttributes(mir);
- DecodedInstruction *d_insn = &mir->dalvikInsn;
+ MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
if (!(df_attributes & DF_HAS_DEFS)) continue;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 1efdd389d8..b0aa63bb3e 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -409,7 +409,7 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_
uint32_t method_idx = instruction.VRegB_35c();
uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
uint32_t args[5];
- instruction.GetArgs(args);
+ instruction.GetVarArgs(args);
if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
return false;
}
diff --git a/runtime/dex_instruction-inl.h b/runtime/dex_instruction-inl.h
index 207b0b6795..ad9491fda6 100644
--- a/runtime/dex_instruction-inl.h
+++ b/runtime/dex_instruction-inl.h
@@ -24,6 +24,68 @@ namespace art {
//------------------------------------------------------------------------------
// VRegA
//------------------------------------------------------------------------------
+inline bool Instruction::HasVRegA() const {
+ switch (FormatOf(Opcode())) {
+ case k10t: return true;
+ case k10x: return true;
+ case k11n: return true;
+ case k11x: return true;
+ case k12x: return true;
+ case k20t: return true;
+ case k21c: return true;
+ case k21h: return true;
+ case k21s: return true;
+ case k21t: return true;
+ case k22b: return true;
+ case k22c: return true;
+ case k22s: return true;
+ case k22t: return true;
+ case k22x: return true;
+ case k23x: return true;
+ case k30t: return true;
+ case k31c: return true;
+ case k31i: return true;
+ case k31t: return true;
+ case k32x: return true;
+ case k35c: return true;
+ case k3rc: return true;
+ case k51l: return true;
+ default: return false;
+ }
+}
+
+inline int32_t Instruction::VRegA() const {
+ switch (FormatOf(Opcode())) {
+ case k10t: return VRegA_10t();
+ case k10x: return VRegA_10x();
+ case k11n: return VRegA_11n();
+ case k11x: return VRegA_11x();
+ case k12x: return VRegA_12x();
+ case k20t: return VRegA_20t();
+ case k21c: return VRegA_21c();
+ case k21h: return VRegA_21h();
+ case k21s: return VRegA_21s();
+ case k21t: return VRegA_21t();
+ case k22b: return VRegA_22b();
+ case k22c: return VRegA_22c();
+ case k22s: return VRegA_22s();
+ case k22t: return VRegA_22t();
+ case k22x: return VRegA_22x();
+ case k23x: return VRegA_23x();
+ case k30t: return VRegA_30t();
+ case k31c: return VRegA_31c();
+ case k31i: return VRegA_31i();
+ case k31t: return VRegA_31t();
+ case k32x: return VRegA_32x();
+ case k35c: return VRegA_35c();
+ case k3rc: return VRegA_3rc();
+ case k51l: return VRegA_51l();
+ default:
+ LOG(FATAL) << "Tried to access vA of instruction " << Name() << " which has no A operand.";
+ exit(EXIT_FAILURE);
+ }
+}
+
inline int8_t Instruction::VRegA_10t(uint16_t inst_data) const {
DCHECK_EQ(FormatOf(Opcode()), k10t);
return static_cast<int8_t>(InstAA(inst_data));
@@ -147,6 +209,66 @@ inline uint8_t Instruction::VRegA_51l(uint16_t inst_data) const {
//------------------------------------------------------------------------------
// VRegB
//------------------------------------------------------------------------------
+inline bool Instruction::HasVRegB() const {
+ switch (FormatOf(Opcode())) {
+ case k11n: return true;
+ case k12x: return true;
+ case k21c: return true;
+ case k21h: return true;
+ case k21s: return true;
+ case k21t: return true;
+ case k22b: return true;
+ case k22c: return true;
+ case k22s: return true;
+ case k22t: return true;
+ case k22x: return true;
+ case k23x: return true;
+ case k31c: return true;
+ case k31i: return true;
+ case k31t: return true;
+ case k32x: return true;
+ case k35c: return true;
+ case k3rc: return true;
+ case k51l: return true;
+ default: return false;
+ }
+}
+
+inline bool Instruction::HasWideVRegB() const {
+ return FormatOf(Opcode()) == k51l;
+}
+
+inline int32_t Instruction::VRegB() const {
+ switch (FormatOf(Opcode())) {
+ case k11n: return VRegB_11n();
+ case k12x: return VRegB_12x();
+ case k21c: return VRegB_21c();
+ case k21h: return VRegB_21h();
+ case k21s: return VRegB_21s();
+ case k21t: return VRegB_21t();
+ case k22b: return VRegB_22b();
+ case k22c: return VRegB_22c();
+ case k22s: return VRegB_22s();
+ case k22t: return VRegB_22t();
+ case k22x: return VRegB_22x();
+ case k23x: return VRegB_23x();
+ case k31c: return VRegB_31c();
+ case k31i: return VRegB_31i();
+ case k31t: return VRegB_31t();
+ case k32x: return VRegB_32x();
+ case k35c: return VRegB_35c();
+ case k3rc: return VRegB_3rc();
+ case k51l: return VRegB_51l();
+ default:
+ LOG(FATAL) << "Tried to access vB of instruction " << Name() << " which has no B operand.";
+ exit(EXIT_FAILURE);
+ }
+}
+
+inline uint64_t Instruction::WideVRegB() const {
+ return VRegB_51l();
+}
+
inline int4_t Instruction::VRegB_11n(uint16_t inst_data) const {
DCHECK_EQ(FormatOf(Opcode()), k11n);
return static_cast<int4_t>((InstB(inst_data) << 28) >> 28);
@@ -246,6 +368,34 @@ inline uint64_t Instruction::VRegB_51l() const {
//------------------------------------------------------------------------------
// VRegC
//------------------------------------------------------------------------------
+inline bool Instruction::HasVRegC() const {
+ switch (FormatOf(Opcode())) {
+ case k22b: return true;
+ case k22c: return true;
+ case k22s: return true;
+ case k22t: return true;
+ case k23x: return true;
+ case k35c: return true;
+ case k3rc: return true;
+ default: return false;
+ }
+}
+
+inline int32_t Instruction::VRegC() const {
+ switch (FormatOf(Opcode())) {
+ case k22b: return VRegC_22b();
+ case k22c: return VRegC_22c();
+ case k22s: return VRegC_22s();
+ case k22t: return VRegC_22t();
+ case k23x: return VRegC_23x();
+ case k35c: return VRegC_35c();
+ case k3rc: return VRegC_3rc();
+ default:
+ LOG(FATAL) << "Tried to access vC of instruction " << Name() << " which has no C operand.";
+ exit(EXIT_FAILURE);
+ }
+}
+
inline int8_t Instruction::VRegC_22b() const {
DCHECK_EQ(FormatOf(Opcode()), k22b);
return static_cast<int8_t>(Fetch16(1) >> 8);
@@ -281,7 +431,11 @@ inline uint16_t Instruction::VRegC_3rc() const {
return Fetch16(2);
}
-inline void Instruction::GetArgs(uint32_t arg[5], uint16_t inst_data) const {
+inline bool Instruction::HasVarArgs() const {
+ return FormatOf(Opcode()) == k35c;
+}
+
+inline void Instruction::GetVarArgs(uint32_t arg[5], uint16_t inst_data) const {
DCHECK_EQ(FormatOf(Opcode()), k35c);
/*
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc
index 754624538d..0494f22886 100644
--- a/runtime/dex_instruction.cc
+++ b/runtime/dex_instruction.cc
@@ -70,121 +70,6 @@ int const Instruction::kInstructionSizeInCodeUnits[] = {
#undef INSTRUCTION_SIZE
};
-/*
- * Handy macros for helping decode instructions.
- */
-#define FETCH(_offset) (insns[(_offset)])
-#define FETCH_uint32(_offset) (fetch_uint32_impl((_offset), insns))
-#define INST_A(_insn) (((uint16_t)(_insn) >> 8) & 0x0f)
-#define INST_B(_insn) ((uint16_t)(_insn) >> 12)
-#define INST_AA(_insn) ((_insn) >> 8)
-
-/* Helper for FETCH_uint32, above. */
-static inline uint32_t fetch_uint32_impl(uint32_t offset, const uint16_t* insns) {
- return insns[offset] | ((uint32_t) insns[offset+1] << 16);
-}
-
-
-bool Instruction::HasVRegC() const {
- switch (FormatOf(Opcode())) {
- case k23x: return true;
- case k35c: return true;
- case k3rc: return true;
- default: return false;
- }
-}
-
-bool Instruction::HasVRegB() const {
- switch (FormatOf(Opcode())) {
- case k12x: return true;
- case k22b: return true;
- case k22c: return true;
- case k22s: return true;
- case k22t: return true;
- case k22x: return true;
- case k23x: return true;
- case k32x: return true;
- default: return false;
- }
-}
-
-bool Instruction::HasVRegA() const {
- switch (FormatOf(Opcode())) {
- case k11n: return true;
- case k11x: return true;
- case k12x: return true;
- case k21c: return true;
- case k21h: return true;
- case k21s: return true;
- case k21t: return true;
- case k22b: return true;
- case k22c: return true;
- case k22s: return true;
- case k22t: return true;
- case k22x: return true;
- case k23x: return true;
- case k31c: return true;
- case k31i: return true;
- case k31t: return true;
- case k32x: return true;
- case k51l: return true;
- default: return false;
- }
-}
-
-int32_t Instruction::VRegC() const {
- switch (FormatOf(Opcode())) {
- case k23x: return VRegC_23x();
- case k35c: return VRegC_35c();
- case k3rc: return VRegC_3rc();
- default: LOG(FATAL) << "Tried to access vC of instruction " << Name() <<
- " which has no C operand.";
- }
- return -1;
-}
-
-int32_t Instruction::VRegB() const {
- switch (FormatOf(Opcode())) {
- case k12x: return VRegB_12x();
- case k22b: return VRegB_22b();
- case k22c: return VRegB_22c();
- case k22s: return VRegB_22s();
- case k22t: return VRegB_22t();
- case k22x: return VRegB_22x();
- case k23x: return VRegB_23x();
- case k32x: return VRegB_32x();
- default: LOG(FATAL) << "Tried to access vB of instruction " << Name() <<
- " which has no B operand.";
- }
- return -1;
-}
-
-int32_t Instruction::VRegA() const {
- switch (FormatOf(Opcode())) {
- case k11n: return VRegA_11n();
- case k11x: return VRegA_11x();
- case k12x: return VRegA_12x();
- case k21c: return VRegA_21c();
- case k21h: return VRegA_21h();
- case k21s: return VRegA_21s();
- case k21t: return VRegA_21t();
- case k22b: return VRegA_22b();
- case k22c: return VRegA_22c();
- case k22s: return VRegA_22s();
- case k22t: return VRegA_22t();
- case k22x: return VRegA_22x();
- case k23x: return VRegA_23x();
- case k31c: return VRegA_31c();
- case k31i: return VRegA_31i();
- case k31t: return VRegA_31t();
- case k32x: return VRegA_32x();
- case k51l: return VRegA_51l();
- default: LOG(FATAL) << "Tried to access vA of instruction " << Name() <<
- " which has no A operand.";
- }
- return -1;
-}
-
int32_t Instruction::GetTargetOffset() const {
switch (FormatOf(Opcode())) {
// Cases for conditional branches follow.
@@ -207,145 +92,6 @@ bool Instruction::CanFlowThrough() const {
return FlagsOf(opcode) & Instruction::kContinue;
}
-void Instruction::Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const {
- const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
- uint16_t insn = *insns;
- Code opcode = static_cast<Code>(insn & 0xFF);
-
- switch (FormatOf(opcode)) {
- case k10x: // op
- /* nothing to do; copy the AA bits out for the verifier */
- vA = INST_AA(insn);
- break;
- case k12x: // op vA, vB
- vA = INST_A(insn);
- vB = INST_B(insn);
- break;
- case k11n: // op vA, #+B
- vA = INST_A(insn);
- vB = (int32_t) (INST_B(insn) << 28) >> 28; // sign extend 4-bit value
- break;
- case k11x: // op vAA
- vA = INST_AA(insn);
- break;
- case k10t: // op +AA
- vA = (int8_t) INST_AA(insn); // sign-extend 8-bit value
- break;
- case k20t: // op +AAAA
- vA = (int16_t) FETCH(1); // sign-extend 16-bit value
- break;
- case k21c: // op vAA, thing@BBBB
- case k22x: // op vAA, vBBBB
- vA = INST_AA(insn);
- vB = FETCH(1);
- break;
- case k21s: // op vAA, #+BBBB
- case k21t: // op vAA, +BBBB
- vA = INST_AA(insn);
- vB = (int16_t) FETCH(1); // sign-extend 16-bit value
- break;
- case k21h: // op vAA, #+BBBB0000[00000000]
- vA = INST_AA(insn);
- /*
- * The value should be treated as right-zero-extended, but we don't
- * actually do that here. Among other things, we don't know if it's
- * the top bits of a 32- or 64-bit value.
- */
- vB = FETCH(1);
- break;
- case k23x: // op vAA, vBB, vCC
- vA = INST_AA(insn);
- vB = FETCH(1) & 0xff;
- vC = FETCH(1) >> 8;
- break;
- case k22b: // op vAA, vBB, #+CC
- vA = INST_AA(insn);
- vB = FETCH(1) & 0xff;
- vC = (int8_t) (FETCH(1) >> 8); // sign-extend 8-bit value
- break;
- case k22s: // op vA, vB, #+CCCC
- case k22t: // op vA, vB, +CCCC
- vA = INST_A(insn);
- vB = INST_B(insn);
- vC = (int16_t) FETCH(1); // sign-extend 16-bit value
- break;
- case k22c: // op vA, vB, thing@CCCC
- vA = INST_A(insn);
- vB = INST_B(insn);
- vC = FETCH(1);
- break;
- case k30t: // op +AAAAAAAA
- vA = FETCH_uint32(1); // signed 32-bit value
- break;
- case k31t: // op vAA, +BBBBBBBB
- case k31c: // op vAA, string@BBBBBBBB
- vA = INST_AA(insn);
- vB = FETCH_uint32(1); // 32-bit value
- break;
- case k32x: // op vAAAA, vBBBB
- vA = FETCH(1);
- vB = FETCH(2);
- break;
- case k31i: // op vAA, #+BBBBBBBB
- vA = INST_AA(insn);
- vB = FETCH_uint32(1); // signed 32-bit value
- break;
- case k35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
- {
- /*
- * Note that the fields mentioned in the spec don't appear in
- * their "usual" positions here compared to most formats. This
- * was done so that the field names for the argument count and
- * reference index match between this format and the corresponding
- * range formats (3rc and friends).
- *
- * Bottom line: The argument count is always in vA, and the
- * method constant (or equivalent) is always in vB.
- */
- uint16_t regList;
- int count;
-
- vA = INST_B(insn); // This is labeled A in the spec.
- vB = FETCH(1);
- regList = FETCH(2);
-
- count = vA;
-
- /*
- * Copy the argument registers into the arg[] array, and
- * also copy the first argument (if any) into vC. (The
- * DecodedInstruction structure doesn't have separate
- * fields for {vD, vE, vF, vG}, so there's no need to make
- * copies of those.) Note that cases 5..2 fall through.
- */
- switch (count) {
- case 5: arg[4] = INST_A(insn);
- case 4: arg[3] = (regList >> 12) & 0x0f;
- case 3: arg[2] = (regList >> 8) & 0x0f;
- case 2: arg[1] = (regList >> 4) & 0x0f;
- case 1: vC = arg[0] = regList & 0x0f; break;
- case 0: break; // Valid, but no need to do anything.
- default:
- LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
- return;
- }
- }
- break;
- case k3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
- vA = INST_AA(insn);
- vB = FETCH(1);
- vC = FETCH(2);
- break;
- case k51l: // op vAA, #+BBBBBBBBBBBBBBBB
- vA = INST_AA(insn);
- vB_wide = FETCH_uint32(1) | ((uint64_t) FETCH_uint32(3) << 32);
- break;
- default:
- LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
- return;
- }
-}
-
size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
// Handle special NOP encoded variable length sequences.
@@ -549,7 +295,7 @@ std::string Instruction::DumpString(const DexFile* file) const {
break;
case k35c: {
uint32_t arg[5];
- GetArgs(arg);
+ GetVarArgs(arg);
switch (Opcode()) {
case FILLED_NEW_ARRAY:
{
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index 4352c4add0..560e5ff8c2 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -151,8 +151,7 @@ class Instruction {
kVerifyError = 0x80000,
};
- // Decodes this instruction, populating its arguments.
- void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
+ static constexpr uint32_t kMaxVarArgRegs = 5;
// Returns the size (in 2 byte code units) of this instruction.
size_t SizeInCodeUnits() const {
@@ -313,6 +312,9 @@ class Instruction {
bool HasVRegB() const;
int32_t VRegB() const;
+ bool HasWideVRegB() const;
+ uint64_t WideVRegB() const;
+
int4_t VRegB_11n() const {
return VRegB_11n(Fetch16(0));
}
@@ -365,9 +367,10 @@ class Instruction {
uint16_t VRegC_3rc() const;
// Fills the given array with the 'arg' array of the instruction.
- void GetArgs(uint32_t args[5], uint16_t inst_data) const;
- void GetArgs(uint32_t args[5]) const {
- return GetArgs(args, Fetch16(0));
+ bool HasVarArgs() const;
+ void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
+ void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
+ return GetVarArgs(args, Fetch16(0));
}
// Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
@@ -549,23 +552,6 @@ std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
-/*
- * Holds the contents of a decoded instruction.
- */
-struct DecodedInstruction {
- uint32_t vA;
- uint32_t vB;
- uint64_t vB_wide; /* for k51l */
- uint32_t vC;
- uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
- Instruction::Code opcode;
-
- explicit DecodedInstruction(const Instruction* inst) {
- inst->Decode(vA, vB, vB_wide, vC, arg);
- opcode = inst->Opcode();
- }
-};
-
} // namespace art
#endif // ART_RUNTIME_DEX_INSTRUCTION_H_
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 566050896b..da3e8ea095 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -85,7 +85,7 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
if (is_range) {
vregC = inst->VRegC_3rc();
} else {
- inst->GetArgs(arg, inst_data);
+ inst->GetVarArgs(arg, inst_data);
}
// Handle receiver apart since it's not part of the shorty.
@@ -224,7 +224,7 @@ bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
if (is_range) {
vregC = inst->VRegC_3rc();
} else {
- inst->GetArgs(arg);
+ inst->GetVarArgs(arg);
}
const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
for (int32_t i = 0; i < length; ++i) {
diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc
index 8bd8dbab73..d8fc2776d9 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/runtime/quick/inline_method_analyser.cc
@@ -174,26 +174,24 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item
return false;
}
- uint32_t return_reg = return_instruction->VRegA_11x();
+ int32_t return_reg = return_instruction->VRegA_11x();
DCHECK_LT(return_reg, code_item->registers_size_);
- uint32_t vA, vB, dummy;
- uint64_t dummy_wide;
- instruction->Decode(vA, vB, dummy_wide, dummy, nullptr);
+ int32_t const_value = instruction->VRegB();
if (instruction->Opcode() == Instruction::CONST_HIGH16) {
- vB <<= 16;
+ const_value <<= 16;
}
- DCHECK_LT(vA, code_item->registers_size_);
- if (vA != return_reg) {
+ DCHECK_LT(instruction->VRegA(), code_item->registers_size_);
+ if (instruction->VRegA() != return_reg) {
return false; // Not returning the value set by const?
}
- if (return_opcode == Instruction::RETURN_OBJECT && vB != 0) {
+ if (return_opcode == Instruction::RETURN_OBJECT && const_value != 0) {
return false; // Returning non-null reference constant?
}
if (result != nullptr) {
result->opcode = kInlineOpNonWideConst;
result->flags = kInlineSpecial;
- result->d.data = static_cast<uint64_t>(vB);
+ result->d.data = static_cast<uint64_t>(const_value);
}
return true;
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 91170f0e83..03ceed357c 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -649,54 +649,53 @@ bool MethodVerifier::VerifyInstructions() {
}
bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_offset) {
- DecodedInstruction dec_insn(inst);
bool result = true;
switch (inst->GetVerifyTypeArgumentA()) {
case Instruction::kVerifyRegA:
- result = result && CheckRegisterIndex(dec_insn.vA);
+ result = result && CheckRegisterIndex(inst->VRegA());
break;
case Instruction::kVerifyRegAWide:
- result = result && CheckWideRegisterIndex(dec_insn.vA);
+ result = result && CheckWideRegisterIndex(inst->VRegA());
break;
}
switch (inst->GetVerifyTypeArgumentB()) {
case Instruction::kVerifyRegB:
- result = result && CheckRegisterIndex(dec_insn.vB);
+ result = result && CheckRegisterIndex(inst->VRegB());
break;
case Instruction::kVerifyRegBField:
- result = result && CheckFieldIndex(dec_insn.vB);
+ result = result && CheckFieldIndex(inst->VRegB());
break;
case Instruction::kVerifyRegBMethod:
- result = result && CheckMethodIndex(dec_insn.vB);
+ result = result && CheckMethodIndex(inst->VRegB());
break;
case Instruction::kVerifyRegBNewInstance:
- result = result && CheckNewInstance(dec_insn.vB);
+ result = result && CheckNewInstance(inst->VRegB());
break;
case Instruction::kVerifyRegBString:
- result = result && CheckStringIndex(dec_insn.vB);
+ result = result && CheckStringIndex(inst->VRegB());
break;
case Instruction::kVerifyRegBType:
- result = result && CheckTypeIndex(dec_insn.vB);
+ result = result && CheckTypeIndex(inst->VRegB());
break;
case Instruction::kVerifyRegBWide:
- result = result && CheckWideRegisterIndex(dec_insn.vB);
+ result = result && CheckWideRegisterIndex(inst->VRegB());
break;
}
switch (inst->GetVerifyTypeArgumentC()) {
case Instruction::kVerifyRegC:
- result = result && CheckRegisterIndex(dec_insn.vC);
+ result = result && CheckRegisterIndex(inst->VRegC());
break;
case Instruction::kVerifyRegCField:
- result = result && CheckFieldIndex(dec_insn.vC);
+ result = result && CheckFieldIndex(inst->VRegC());
break;
case Instruction::kVerifyRegCNewArray:
- result = result && CheckNewArray(dec_insn.vC);
+ result = result && CheckNewArray(inst->VRegC());
break;
case Instruction::kVerifyRegCType:
- result = result && CheckTypeIndex(dec_insn.vC);
+ result = result && CheckTypeIndex(inst->VRegC());
break;
case Instruction::kVerifyRegCWide:
- result = result && CheckWideRegisterIndex(dec_insn.vC);
+ result = result && CheckWideRegisterIndex(inst->VRegC());
break;
}
switch (inst->GetVerifyExtraFlags()) {
@@ -709,11 +708,14 @@ bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_of
case Instruction::kVerifySwitchTargets:
result = result && CheckSwitchTargets(code_offset);
break;
- case Instruction::kVerifyVarArg:
- result = result && CheckVarArgRegs(dec_insn.vA, dec_insn.arg);
+ case Instruction::kVerifyVarArg: {
+ uint32_t args[Instruction::kMaxVarArgRegs];
+ inst->GetVarArgs(args);
+ result = result && CheckVarArgRegs(inst->VRegA(), args);
break;
+ }
case Instruction::kVerifyVarArgRange:
- result = result && CheckVarArgRangeRegs(dec_insn.vA, dec_insn.vC);
+ result = result && CheckVarArgRangeRegs(inst->VRegA(), inst->VRegC());
break;
case Instruction::kVerifyError:
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected opcode " << inst->Name();
@@ -1009,7 +1011,7 @@ bool MethodVerifier::CheckSwitchTargets(uint32_t cur_offset) {
}
bool MethodVerifier::CheckVarArgRegs(uint32_t vA, uint32_t arg[]) {
- if (vA > 5) {
+ if (vA > Instruction::kMaxVarArgRegs) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid arg count (" << vA << ") in non-range invoke)";
return false;
}
@@ -3075,7 +3077,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst,
size_t params_size = params == NULL ? 0 : params->Size();
uint32_t arg[5];
if (!is_range) {
- inst->GetArgs(arg);
+ inst->GetVarArgs(arg);
}
for (size_t param_index = 0; param_index < params_size; param_index++) {
if (actual_args >= expected_args) {
@@ -3189,7 +3191,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instructio
size_t params_size = params == NULL ? 0 : params->Size();
uint32_t arg[5];
if (!is_range) {
- inst->GetArgs(arg);
+ inst->GetVarArgs(arg);
}
size_t actual_args = 1;
for (size_t param_index = 0; param_index < params_size; param_index++) {
@@ -3255,7 +3257,7 @@ void MethodVerifier::VerifyNewArray(const Instruction* inst, bool is_filled, boo
uint32_t arg_count = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
uint32_t arg[5];
if (!is_range) {
- inst->GetArgs(arg);
+ inst->GetVarArgs(arg);
}
for (size_t ui = 0; ui < arg_count; ui++) {
uint32_t get_reg = is_range ? inst->VRegC_3rc() + ui : arg[ui];