Move DecodedInstruction into MIR.

Change-Id: I188dc7fef4f4033361c78daf2015b869242191c6
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 651fa66..2f17e08 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -880,7 +880,7 @@
 
   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 @@
 
 /* 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 @@
 
 /* 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 @@
                                                               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 6857edb..30d0bc3 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 @@
 /*
  * 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 @@
 }
 
 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 5997e5b..b926503 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -254,7 +254,15 @@
    * 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 @@
   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 72c46cc..9f15cd4 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -49,7 +49,7 @@
 
     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 1efdd38..b0aa63b 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -409,7 +409,7 @@
       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 207b0b6..ad9491f 100644
--- a/runtime/dex_instruction-inl.h
+++ b/runtime/dex_instruction-inl.h
@@ -24,6 +24,68 @@
 //------------------------------------------------------------------------------
 // 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 @@
 //------------------------------------------------------------------------------
 // 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 @@
 //------------------------------------------------------------------------------
 // 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 @@
   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 7546245..0494f22 100644
--- a/runtime/dex_instruction.cc
+++ b/runtime/dex_instruction.cc
@@ -70,121 +70,6 @@
 #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 @@
   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 @@
       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 4352c4a..560e5ff 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -151,8 +151,7 @@
     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 @@
   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 @@
   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::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 5660508..da3e8ea 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -85,7 +85,7 @@
     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 @@
   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 8bd8dba..d8fc277 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/runtime/quick/inline_method_analyser.cc
@@ -174,26 +174,24 @@
     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 91170f0..03ceed3 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -649,54 +649,53 @@
 }
 
 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 @@
     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::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 @@
   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 @@
   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 @@
       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];