diff options
-rw-r--r-- | compiler/dex/mir_dataflow.cc | 8 | ||||
-rw-r--r-- | compiler/dex/mir_graph.cc | 19 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 12 | ||||
-rw-r--r-- | compiler/dex/mir_optimization.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/builder.cc | 2 | ||||
-rw-r--r-- | runtime/dex_instruction-inl.h | 156 | ||||
-rw-r--r-- | runtime/dex_instruction.cc | 256 | ||||
-rw-r--r-- | runtime/dex_instruction.h | 30 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 4 | ||||
-rw-r--r-- | runtime/quick/inline_method_analyser.cc | 16 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 46 |
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]; |