Improve interpreter performance.

Bug: 8196227

This CL removes the use of DecodedInstruction to read instruction opcode and
operands. It now directly access to each operand according to instruction
format (like VRegA_11x for accessing register vA with format 11x).

It also caches some information used for instrumentation like 'this' object
and current method and add missing check about pending exception.

Change-Id: I8c03c0aea9d75068b89e3cb2c8c12383d7928281
diff --git a/src/dex_instruction-inl.h b/src/dex_instruction-inl.h
new file mode 100644
index 0000000..66fbd29
--- /dev/null
+++ b/src/dex_instruction-inl.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_DEX_INSTRUCTION_INL_H_
+#define ART_SRC_DEX_INSTRUCTION_INL_H_
+
+#include "dex_instruction.h"
+
+namespace art {
+
+//------------------------------------------------------------------------------
+// VRegA
+//------------------------------------------------------------------------------
+inline int8_t Instruction::VRegA_10t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k10t);
+  return static_cast<int8_t>(InstAA());
+}
+
+inline uint4_t Instruction::VRegA_11n() const {
+  DCHECK_EQ(FormatOf(Opcode()), k11n);
+  return InstA();
+}
+
+inline uint8_t Instruction::VRegA_11x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k11x);
+  return InstAA();
+}
+
+inline uint4_t Instruction::VRegA_12x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k12x);
+  return InstA();
+}
+
+inline int16_t Instruction::VRegA_20t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k20t);
+  return static_cast<int16_t>(Fetch16(1));
+}
+
+inline uint8_t Instruction::VRegA_21c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21c);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_21h() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21h);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_21s() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21s);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_21t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21t);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_22b() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22b);
+  return InstAA();
+}
+
+inline uint4_t Instruction::VRegA_22c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22c);
+  return InstA();
+}
+
+inline uint4_t Instruction::VRegA_22s() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22s);
+  return InstA();
+}
+
+inline uint4_t Instruction::VRegA_22t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22t);
+  return InstA();
+}
+
+inline uint8_t Instruction::VRegA_22x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22x);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_23x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k23x);
+  return InstAA();
+}
+
+inline int32_t Instruction::VRegA_30t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k30t);
+  return static_cast<int32_t>(Fetch32(1));
+}
+
+inline uint8_t Instruction::VRegA_31c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31c);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_31i() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31i);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_31t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31t);
+  return InstAA();
+}
+
+inline uint16_t Instruction::VRegA_32x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k32x);
+  return Fetch16(1);
+}
+
+inline uint4_t Instruction::VRegA_35c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k35c);
+  return InstB(); // This is labeled A in the spec.
+}
+
+inline uint8_t Instruction::VRegA_3rc() const {
+  DCHECK_EQ(FormatOf(Opcode()), k3rc);
+  return InstAA();
+}
+
+inline uint8_t Instruction::VRegA_51l() const {
+  DCHECK_EQ(FormatOf(Opcode()), k51l);
+  return InstAA();
+}
+
+//------------------------------------------------------------------------------
+// VRegB
+//------------------------------------------------------------------------------
+inline int4_t Instruction::VRegB_11n() const {
+  DCHECK_EQ(FormatOf(Opcode()), k11n);
+  return static_cast<int4_t>((InstB() << 28) >> 28);
+}
+
+inline uint4_t Instruction::VRegB_12x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k12x);
+  return InstB();
+}
+
+inline uint16_t Instruction::VRegB_21c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21c);
+  return Fetch16(1);
+}
+
+inline uint16_t Instruction::VRegB_21h() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21h);
+  return Fetch16(1);
+}
+
+inline int16_t Instruction::VRegB_21s() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21s);
+  return static_cast<int16_t>(Fetch16(1));
+}
+
+inline int16_t Instruction::VRegB_21t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k21t);
+  return static_cast<int16_t>(Fetch16(1));
+}
+
+inline uint8_t Instruction::VRegB_22b() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22b);
+  return static_cast<uint8_t>(Fetch16(1) & 0xff);
+}
+
+inline uint4_t Instruction::VRegB_22c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22c);
+  return InstB();
+}
+
+inline uint4_t Instruction::VRegB_22s() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22s);
+  return InstB();
+}
+
+inline uint4_t Instruction::VRegB_22t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22t);
+  return InstB();
+}
+
+inline uint16_t Instruction::VRegB_22x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22x);
+  return Fetch16(1);
+}
+
+inline uint8_t Instruction::VRegB_23x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k23x);
+  return static_cast<uint8_t>(Fetch16(1) & 0xff);
+}
+
+inline uint32_t Instruction::VRegB_31c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31c);
+  return Fetch32(1);
+}
+
+inline int32_t Instruction::VRegB_31i() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31i);
+  return static_cast<int32_t>(Fetch32(1));
+}
+
+inline int32_t Instruction::VRegB_31t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k31t);
+  return static_cast<int32_t>(Fetch32(1));
+}
+
+inline uint16_t Instruction::VRegB_32x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k32x);
+  return Fetch16(2);
+}
+
+inline uint16_t Instruction::VRegB_35c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k35c);
+  return Fetch16(1);
+}
+
+inline uint16_t Instruction::VRegB_3rc() const {
+  DCHECK_EQ(FormatOf(Opcode()), k3rc);
+  return Fetch16(1);
+}
+
+inline uint64_t Instruction::VRegB_51l() const {
+  DCHECK_EQ(FormatOf(Opcode()), k51l);
+  uint64_t vB_wide = Fetch32(1) | ((uint64_t) Fetch32(3) << 32);
+  return vB_wide;
+}
+
+//------------------------------------------------------------------------------
+// VRegC
+//------------------------------------------------------------------------------
+inline int8_t Instruction::VRegC_22b() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22b);
+  return static_cast<int8_t>(Fetch16(1) >> 8);
+}
+
+inline uint16_t Instruction::VRegC_22c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22c);
+  return Fetch16(1);
+}
+
+inline int16_t Instruction::VRegC_22s() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22s);
+  return static_cast<int16_t>(Fetch16(1));
+}
+
+inline int16_t Instruction::VRegC_22t() const {
+  DCHECK_EQ(FormatOf(Opcode()), k22t);
+  return static_cast<int16_t>(Fetch16(1));
+}
+
+inline uint8_t Instruction::VRegC_23x() const {
+  DCHECK_EQ(FormatOf(Opcode()), k23x);
+  return static_cast<uint8_t>(Fetch16(1) >> 8);
+}
+
+inline uint4_t Instruction::VRegC_35c() const {
+  DCHECK_EQ(FormatOf(Opcode()), k35c);
+  return static_cast<uint4_t>(Fetch16(2) & 0x0f);
+}
+
+inline uint16_t Instruction::VRegC_3rc() const {
+  DCHECK_EQ(FormatOf(Opcode()), k3rc);
+  return Fetch16(2);
+}
+
+inline void Instruction::GetArgs(uint32_t arg[5]) const {
+  DCHECK_EQ(FormatOf(Opcode()), k35c);
+
+  /*
+   * 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 = Fetch16(2);
+  uint4_t count = InstB(); // This is labeled A in the spec.
+
+  /*
+   * 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] = InstA();
+    case 4: arg[3] = (regList >> 12) & 0x0f;
+    case 3: arg[2] = (regList >> 8) & 0x0f;
+    case 2: arg[1] = (regList >> 4) & 0x0f;
+    case 1: 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;
+  }
+}
+
+} // namespace art
+
+#endif // ART_SRC_DEX_INSTRUCTION_INL_H_
diff --git a/src/dex_instruction.cc b/src/dex_instruction.cc
index 3224d77..414e78f 100644
--- a/src/dex_instruction.cc
+++ b/src/dex_instruction.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dex_instruction.h"
+#include "dex_instruction-inl.h"
 
 #include "dex_file-inl.h"
 #include "utils.h"
@@ -72,13 +72,13 @@
  * Handy macros for helping decode instructions.
  */
 #define FETCH(_offset)      (insns[(_offset)])
-#define FETCH_u4(_offset)   (fetch_u4_impl((_offset), insns))
+#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_u4, above. */
-static inline uint32_t fetch_u4_impl(uint32_t offset, const uint16_t* insns) {
+/* 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);
 }
 
@@ -150,12 +150,12 @@
       vC = FETCH(1);
       break;
     case k30t:       // op +AAAAAAAA
-      vA = FETCH_u4(1);                     // signed 32-bit value
+      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_u4(1);                     // 32-bit value
+      vB = FETCH_uint32(1);                     // 32-bit value
       break;
     case k32x:       // op vAAAA, vBBBB
       vA = FETCH(1);
@@ -163,7 +163,7 @@
       break;
     case k31i:       // op vAA, #+BBBBBBBB
       vA = INST_AA(insn);
-      vB = FETCH_u4(1);                     // signed 32-bit value
+      vB = FETCH_uint32(1);                     // signed 32-bit value
       break;
     case k35c:       // op {vC, vD, vE, vF, vG}, thing@BBBB
       {
@@ -213,7 +213,7 @@
         break;
     case k51l:       // op vAA, #+BBBBBBBBBBBBBBBB
       vA = INST_AA(insn);
-      vB_wide = FETCH_u4(1) | ((uint64_t) FETCH_u4(3) << 32);
+      vB_wide = FETCH_uint32(1) | ((uint64_t) FETCH_uint32(3) << 32);
       break;
     default:
       LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
diff --git a/src/dex_instruction.h b/src/dex_instruction.h
index 3921212..45c93ef 100644
--- a/src/dex_instruction.h
+++ b/src/dex_instruction.h
@@ -21,6 +21,9 @@
 #include "base/macros.h"
 #include "globals.h"
 
+typedef uint8_t uint4_t;
+typedef int8_t int4_t;
+
 namespace art {
 
 class DexFile;
@@ -176,6 +179,64 @@
     return kInstructionNames[opcode];
   }
 
+  // VRegA
+  int8_t VRegA_10t() const;
+  uint4_t VRegA_11n() const;
+  uint8_t VRegA_11x() const;
+  uint4_t VRegA_12x() const;
+  int16_t VRegA_20t() const;
+  uint8_t VRegA_21c() const;
+  uint8_t VRegA_21h() const;
+  uint8_t VRegA_21s() const;
+  uint8_t VRegA_21t() const;
+  uint8_t VRegA_22b() const;
+  uint4_t VRegA_22c() const;
+  uint4_t VRegA_22s() const;
+  uint4_t VRegA_22t() const;
+  uint8_t VRegA_22x() const;
+  uint8_t VRegA_23x() const;
+  int32_t VRegA_30t() const;
+  uint8_t VRegA_31c() const;
+  uint8_t VRegA_31i() const;
+  uint8_t VRegA_31t() const;
+  uint16_t VRegA_32x() const;
+  uint4_t VRegA_35c() const;
+  uint8_t VRegA_3rc() const;
+  uint8_t VRegA_51l() const;
+
+  // VRegB
+  int4_t VRegB_11n() const;
+  uint4_t VRegB_12x() const;
+  uint16_t VRegB_21c() const;
+  uint16_t VRegB_21h() const;
+  int16_t VRegB_21s() const;
+  int16_t VRegB_21t() const;
+  uint8_t VRegB_22b() const;
+  uint4_t VRegB_22c() const;
+  uint4_t VRegB_22s() const;
+  uint4_t VRegB_22t() const;
+  uint16_t VRegB_22x() const;
+  uint8_t VRegB_23x() const;
+  uint32_t VRegB_31c() const;
+  int32_t VRegB_31i() const;
+  int32_t VRegB_31t() const;
+  uint16_t VRegB_32x() const;
+  uint16_t VRegB_35c() const;
+  uint16_t VRegB_3rc() const;
+  uint64_t VRegB_51l() const; // vB_wide
+
+  // VRegC
+  int8_t VRegC_22b() const;
+  uint16_t VRegC_22c() const;
+  int16_t VRegC_22s() const;
+  int16_t VRegC_22t() const;
+  uint8_t VRegC_23x() const;
+  uint4_t VRegC_35c() const;
+  uint16_t VRegC_3rc() const;
+
+  // Fills the given array with the 'arg' array of the instruction.
+  void GetArgs(uint32_t args[5]) const;
+
   // Returns the opcode field of the instruction.
   Code Opcode() const {
     const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
@@ -267,6 +328,27 @@
  private:
   size_t SizeInCodeUnitsComplexOpcode() const;
 
+  uint16_t Fetch16(size_t offset) const {
+    const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
+    return insns[offset];
+  }
+
+  uint32_t Fetch32(size_t offset) const {
+    return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
+  }
+
+  uint4_t InstA() const {
+    return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f);
+  }
+
+  uint4_t InstB() const {
+    return static_cast<uint4_t>(Fetch16(0) >> 12);
+  }
+
+  uint8_t InstAA() const {
+    return static_cast<uint8_t>(Fetch16(0) >> 8);
+  }
+
   static const char* const kInstructionNames[];
   static Format const kInstructionFormats[];
   static int const kInstructionFlags[];
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 9f48e78..a3768c7 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -22,7 +22,7 @@
 #include "class_linker-inl.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
-#include "dex_instruction.h"
+#include "dex_instruction-inl.h"
 #include "gc/card_table-inl.h"
 #include "invoke_arg_array_builder.h"
 #include "nth_caller_visitor.h"
@@ -384,19 +384,20 @@
 }
 
 static void DoInvoke(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame,
-                     const DecodedInstruction& dec_insn, InvokeType type, bool is_range,
+                     const Instruction* inst, InvokeType type, bool is_range,
                      JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
   Object* receiver;
   if (type == kStatic) {
     receiver = NULL;
   } else {
-    receiver = shadow_frame.GetVRegReference(dec_insn.vC);
+    receiver = shadow_frame.GetVRegReference(vregC);
   }
-  uint32_t method_idx = dec_insn.vB;
+  uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   AbstractMethod* target_method = FindMethodFromCode(method_idx, receiver,
-                                                     shadow_frame.GetMethod(), self, true,
-                                                     type);
+                                                     shadow_frame.GetMethod(),
+                                                     self, true, type);
   if (UNLIKELY(target_method == NULL)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
@@ -435,9 +436,13 @@
 
   size_t arg_offset = (receiver == NULL) ? 0 : 1;
   const char* shorty = mh.GetShorty();
+  uint32_t arg[5];
+  if (!is_range) {
+    inst->GetArgs(arg);
+  }
   for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
     DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
-    size_t arg_pos = is_range ? dec_insn.vC + arg_offset : dec_insn.arg[arg_offset];
+    size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
     switch (shorty[shorty_pos + 1]) {
       case 'L': {
         Object* o = shadow_frame.GetVRegReference(arg_pos);
@@ -467,98 +472,117 @@
 }
 
 static void DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
-                       const DecodedInstruction& dec_insn, FindFieldType find_type,
+                       const Instruction* inst, FindFieldType find_type,
                        Primitive::Type field_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
-  uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
+  uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
   Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
                                find_type, Primitive::FieldSize(field_type));
-  if (LIKELY(f != NULL)) {
-    Object* obj;
-    if (is_static) {
-      obj = f->GetDeclaringClass();
-    } else {
-      obj = shadow_frame.GetVRegReference(dec_insn.vB);
-      if (UNLIKELY(obj == NULL)) {
-        ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
-        return;
-      }
+  if (UNLIKELY(f == NULL)) {
+    CHECK(self->IsExceptionPending());
+    return;
+  }
+  Object* obj;
+  if (is_static) {
+    obj = f->GetDeclaringClass();
+  } else {
+    obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
+      return;
     }
-    switch (field_type) {
-      case Primitive::kPrimBoolean:
-        shadow_frame.SetVReg(dec_insn.vA, f->GetBoolean(obj));
-        break;
-      case Primitive::kPrimByte:
-        shadow_frame.SetVReg(dec_insn.vA, f->GetByte(obj));
-        break;
-      case Primitive::kPrimChar:
-        shadow_frame.SetVReg(dec_insn.vA, f->GetChar(obj));
-        break;
-      case Primitive::kPrimShort:
-        shadow_frame.SetVReg(dec_insn.vA, f->GetShort(obj));
-        break;
-      case Primitive::kPrimInt:
-        shadow_frame.SetVReg(dec_insn.vA, f->GetInt(obj));
-        break;
-      case Primitive::kPrimLong:
-        shadow_frame.SetVRegLong(dec_insn.vA, f->GetLong(obj));
-        break;
-      case Primitive::kPrimNot:
-        shadow_frame.SetVRegReference(dec_insn.vA, f->GetObject(obj));
-        break;
-      default:
-        LOG(FATAL) << "Unreachable: " << field_type;
-    }
+  }
+  uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
+  switch (field_type) {
+    case Primitive::kPrimBoolean:
+      shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
+      break;
+    case Primitive::kPrimByte:
+      shadow_frame.SetVReg(vregA, f->GetByte(obj));
+      break;
+    case Primitive::kPrimChar:
+      shadow_frame.SetVReg(vregA, f->GetChar(obj));
+      break;
+    case Primitive::kPrimShort:
+      shadow_frame.SetVReg(vregA, f->GetShort(obj));
+      break;
+    case Primitive::kPrimInt:
+      shadow_frame.SetVReg(vregA, f->GetInt(obj));
+      break;
+    case Primitive::kPrimLong:
+      shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
+      break;
+    case Primitive::kPrimNot:
+      shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
+      break;
+    default:
+      LOG(FATAL) << "Unreachable: " << field_type;
   }
 }
 
 static void DoFieldPut(Thread* self, ShadowFrame& shadow_frame,
-                       const DecodedInstruction& dec_insn, FindFieldType find_type,
+                       const Instruction* inst, FindFieldType find_type,
                        Primitive::Type field_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
-  uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
+  uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
   Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
                                find_type, Primitive::FieldSize(field_type));
-  if (LIKELY(f != NULL)) {
-    Object* obj;
-    if (is_static) {
-      obj = f->GetDeclaringClass();
-    } else {
-      obj = shadow_frame.GetVRegReference(dec_insn.vB);
-      if (UNLIKELY(obj == NULL)) {
-        ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
-                                                f, false);
-        return;
-      }
-    }
-    switch (field_type) {
-      case Primitive::kPrimBoolean:
-        f->SetBoolean(obj, shadow_frame.GetVReg(dec_insn.vA));
-        break;
-      case Primitive::kPrimByte:
-        f->SetByte(obj, shadow_frame.GetVReg(dec_insn.vA));
-        break;
-      case Primitive::kPrimChar:
-        f->SetChar(obj, shadow_frame.GetVReg(dec_insn.vA));
-        break;
-      case Primitive::kPrimShort:
-        f->SetShort(obj, shadow_frame.GetVReg(dec_insn.vA));
-        break;
-      case Primitive::kPrimInt:
-        f->SetInt(obj, shadow_frame.GetVReg(dec_insn.vA));
-        break;
-      case Primitive::kPrimLong:
-        f->SetLong(obj, shadow_frame.GetVRegLong(dec_insn.vA));
-        break;
-      case Primitive::kPrimNot:
-        f->SetObj(obj, shadow_frame.GetVRegReference(dec_insn.vA));
-        break;
-      default:
-        LOG(FATAL) << "Unreachable: " << field_type;
+  if (UNLIKELY(f == NULL)) {
+    CHECK(self->IsExceptionPending());
+    return;
+  }
+  Object* obj;
+  if (is_static) {
+    obj = f->GetDeclaringClass();
+  } else {
+    obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
+                                              f, false);
+      return;
     }
   }
+  uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
+  switch (field_type) {
+    case Primitive::kPrimBoolean:
+      f->SetBoolean(obj, shadow_frame.GetVReg(vregA));
+      break;
+    case Primitive::kPrimByte:
+      f->SetByte(obj, shadow_frame.GetVReg(vregA));
+      break;
+    case Primitive::kPrimChar:
+      f->SetChar(obj, shadow_frame.GetVReg(vregA));
+      break;
+    case Primitive::kPrimShort:
+      f->SetShort(obj, shadow_frame.GetVReg(vregA));
+      break;
+    case Primitive::kPrimInt:
+      f->SetInt(obj, shadow_frame.GetVReg(vregA));
+      break;
+    case Primitive::kPrimLong:
+      f->SetLong(obj, shadow_frame.GetVRegLong(vregA));
+      break;
+    case Primitive::kPrimNot:
+      f->SetObj(obj, shadow_frame.GetVRegReference(vregA));
+      break;
+    default:
+      LOG(FATAL) << "Unreachable: " << field_type;
+  }
+}
+
+static String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx) {
+  Class* java_lang_string_class = String::GetJavaLangString();
+  if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    if (UNLIKELY(!class_linker->EnsureInitialized(java_lang_string_class,
+                                                  true, true))) {
+      DCHECK(self->IsExceptionPending());
+      return NULL;
+    }
+  }
+  return mh.ResolveString(string_idx);
 }
 
 static void DoIntDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
@@ -614,24 +638,29 @@
   }
   self->VerifyStack();
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-  const uint16_t* insns = code_item->insns_;
+  const uint16_t* const insns = code_item->insns_;
+
+  // As the 'this' object won't change during the execution of current code, we
+  // want to cache it in local variables. Nevertheless, in order to let the
+  // garbage collector access it, we store it into sirt references.
+  SirtRef<Object> this_object_ref(self, shadow_frame.GetThisObject());
+
   const Instruction* inst = Instruction::At(insns + shadow_frame.GetDexPC());
   if (inst->GetDexPc(insns) == 0) {  // We are entering the method as opposed to deoptimizing..
-    instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(), shadow_frame.GetMethod(),
-                                      0);
+    instrumentation->MethodEnterEvent(self, this_object_ref.get(),
+                                      shadow_frame.GetMethod(), 0);
   }
   while (true) {
     CheckSuspend(self);
-    uint32_t dex_pc = inst->GetDexPc(insns);
+    const uint32_t dex_pc = inst->GetDexPc(insns);
     shadow_frame.SetDexPC(dex_pc);
-    instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(), shadow_frame.GetMethod(),
-                                     dex_pc);
-    DecodedInstruction dec_insn(inst);
+    instrumentation->DexPcMovedEvent(self, this_object_ref.get(),
+                                     shadow_frame.GetMethod(), dex_pc);
     const bool kTracing = false;
     if (kTracing) {
 #define TRACE_LOG std::cerr
       TRACE_LOG << PrettyMethod(shadow_frame.GetMethod())
-                << StringPrintf("\n0x%x: ", inst->GetDexPc(insns))
+                << StringPrintf("\n0x%x: ", dex_pc)
                 << inst->DumpString(&mh.GetDexFile()) << "\n";
       for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
         uint32_t raw_value = shadow_frame.GetVReg(i);
@@ -650,133 +679,170 @@
 #undef TRACE_LOG
     }
     const Instruction* next_inst = inst->Next();
-    switch (dec_insn.opcode) {
+    switch (inst->Opcode()) {
       case Instruction::NOP:
         break;
       case Instruction::MOVE:
+        shadow_frame.SetVReg(inst->VRegA_12x(),
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
+        break;
       case Instruction::MOVE_FROM16:
+        shadow_frame.SetVReg(inst->VRegA_22x(),
+                             shadow_frame.GetVReg(inst->VRegB_22x()));
+        break;
       case Instruction::MOVE_16:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(inst->VRegA_32x(),
+                             shadow_frame.GetVReg(inst->VRegB_32x()));
         break;
       case Instruction::MOVE_WIDE:
+        shadow_frame.SetVRegLong(inst->VRegA_12x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
+        break;
       case Instruction::MOVE_WIDE_FROM16:
+        shadow_frame.SetVRegLong(inst->VRegA_22x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_22x()));
+        break;
       case Instruction::MOVE_WIDE_16:
-        shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_32x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_32x()));
         break;
       case Instruction::MOVE_OBJECT:
+        shadow_frame.SetVRegReference(inst->VRegA_12x(),
+                                      shadow_frame.GetVRegReference(inst->VRegB_12x()));
+        break;
       case Instruction::MOVE_OBJECT_FROM16:
+        shadow_frame.SetVRegReference(inst->VRegA_22x(),
+                                      shadow_frame.GetVRegReference(inst->VRegB_22x()));
+        break;
       case Instruction::MOVE_OBJECT_16:
-        shadow_frame.SetVRegReference(dec_insn.vA, shadow_frame.GetVRegReference(dec_insn.vB));
+        shadow_frame.SetVRegReference(inst->VRegA_32x(),
+                                      shadow_frame.GetVRegReference(inst->VRegB_32x()));
         break;
       case Instruction::MOVE_RESULT:
-        shadow_frame.SetVReg(dec_insn.vA, result_register.GetI());
+        shadow_frame.SetVReg(inst->VRegA_11x(), result_register.GetI());
         break;
       case Instruction::MOVE_RESULT_WIDE:
-        shadow_frame.SetVRegLong(dec_insn.vA, result_register.GetJ());
+        shadow_frame.SetVRegLong(inst->VRegA_11x(), result_register.GetJ());
         break;
       case Instruction::MOVE_RESULT_OBJECT:
-        shadow_frame.SetVRegReference(dec_insn.vA, result_register.GetL());
+        shadow_frame.SetVRegReference(inst->VRegA_11x(), result_register.GetL());
         break;
       case Instruction::MOVE_EXCEPTION: {
         Throwable* exception = self->GetException(NULL);
         self->ClearException();
-        shadow_frame.SetVRegReference(dec_insn.vA, exception);
+        shadow_frame.SetVRegReference(inst->VRegA_11x(), exception);
         break;
       }
       case Instruction::RETURN_VOID: {
         JValue result;
-        instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(),
-                                         shadow_frame.GetMethod(), shadow_frame.GetDexPC(),
-                                         result);
+        instrumentation->MethodExitEvent(self, this_object_ref.get(),
+                                         shadow_frame.GetMethod(), dex_pc, result);
         return result;
       }
       case Instruction::RETURN: {
         JValue result;
         result.SetJ(0);
-        result.SetI(shadow_frame.GetVReg(dec_insn.vA));
-        instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(),
-                                         shadow_frame.GetMethod(), shadow_frame.GetDexPC(),
-                                         result);
+        result.SetI(shadow_frame.GetVReg(inst->VRegA_11x()));
+        instrumentation->MethodExitEvent(self, this_object_ref.get(),
+                                         shadow_frame.GetMethod(), dex_pc, result);
         return result;
       }
       case Instruction::RETURN_WIDE: {
         JValue result;
-        result.SetJ(shadow_frame.GetVRegLong(dec_insn.vA));
-        instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(),
-                                         shadow_frame.GetMethod(), shadow_frame.GetDexPC(),
-                                         result);
+        result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x()));
+        instrumentation->MethodExitEvent(self, this_object_ref.get(),
+                                         shadow_frame.GetMethod(), dex_pc, result);
         return result;
       }
       case Instruction::RETURN_OBJECT: {
         JValue result;
         result.SetJ(0);
-        result.SetL(shadow_frame.GetVRegReference(dec_insn.vA));
-        instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(),
-                                         shadow_frame.GetMethod(), shadow_frame.GetDexPC(),
-                                         result);
+        result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x()));
+        instrumentation->MethodExitEvent(self, this_object_ref.get(),
+                                         shadow_frame.GetMethod(), dex_pc, result);
         return result;
       }
       case Instruction::CONST_4: {
-        int32_t val = static_cast<int32_t>(dec_insn.vB << 28) >> 28;
-        shadow_frame.SetVReg(dec_insn.vA, val);
+        uint32_t dst = inst->VRegA_11n();
+        int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28;
+        shadow_frame.SetVReg(dst, val);
         if (val == 0) {
-          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dst, NULL);
         }
         break;
       }
       case Instruction::CONST_16: {
-        int32_t val = static_cast<int16_t>(dec_insn.vB);
-        shadow_frame.SetVReg(dec_insn.vA, val);
+        uint32_t dst = inst->VRegA_21s();
+        int32_t val = static_cast<int16_t>(inst->VRegB_21s());
+        shadow_frame.SetVReg(dst, val);
         if (val == 0) {
-          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dst, NULL);
         }
         break;
       }
       case Instruction::CONST: {
-        int32_t val = dec_insn.vB;
-        shadow_frame.SetVReg(dec_insn.vA, val);
+        uint32_t dst = inst->VRegA_31i();
+        int32_t val = inst->VRegB_31i();
+        shadow_frame.SetVReg(dst, val);
         if (val == 0) {
-          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dst, NULL);
         }
         break;
       }
       case Instruction::CONST_HIGH16: {
-        int32_t val = dec_insn.vB << 16;
-        shadow_frame.SetVReg(dec_insn.vA, val);
+        uint32_t dst = inst->VRegA_21h();
+        int32_t val = inst->VRegB_21h() << 16;
+        shadow_frame.SetVReg(dst, val);
         if (val == 0) {
-          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dst, NULL);
         }
         break;
       }
       case Instruction::CONST_WIDE_16:
-        shadow_frame.SetVRegLong(dec_insn.vA, static_cast<int16_t>(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_21s(),
+                                 static_cast<int16_t>(inst->VRegB_21s()));
         break;
       case Instruction::CONST_WIDE_32:
-        shadow_frame.SetVRegLong(dec_insn.vA, static_cast<int32_t>(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_31i(),
+                                 static_cast<int32_t>(inst->VRegB_31i()));
         break;
       case Instruction::CONST_WIDE:
-        shadow_frame.SetVRegLong(dec_insn.vA, dec_insn.vB_wide);
+        shadow_frame.SetVRegLong(inst->VRegA_51l(), inst->VRegB_51l());
         break;
       case Instruction::CONST_WIDE_HIGH16:
-        shadow_frame.SetVRegLong(dec_insn.vA, static_cast<uint64_t>(dec_insn.vB) << 48);
+        shadow_frame.SetVRegLong(inst->VRegA_21h(),
+                                 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
         break;
-      case Instruction::CONST_STRING:
-      case Instruction::CONST_STRING_JUMBO: {
-        if (UNLIKELY(!String::GetJavaLangString()->IsInitialized())) {
-          Runtime::Current()->GetClassLinker()->EnsureInitialized(String::GetJavaLangString(),
-                                                                  true, true);
+      case Instruction::CONST_STRING: {
+        String* s = ResolveString(self, mh,  inst->VRegB_21c());
+        if (UNLIKELY(s == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          shadow_frame.SetVRegReference( inst->VRegA_21c(), s);
         }
-        String* s = mh.ResolveString(dec_insn.vB);
-        shadow_frame.SetVRegReference(dec_insn.vA, s);
+        break;
+      }
+      case Instruction::CONST_STRING_JUMBO: {
+        String* s = ResolveString(self, mh,  inst->VRegB_31c());
+        if (UNLIKELY(s == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          shadow_frame.SetVRegReference( inst->VRegA_31c(), s);
+        }
         break;
       }
       case Instruction::CONST_CLASS: {
-        Class* c = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
-        shadow_frame.SetVRegReference(dec_insn.vA, c);
+        Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
+                                          self, false, true);
+        if (UNLIKELY(c == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          shadow_frame.SetVRegReference(inst->VRegA_21c(), c);
+        }
         break;
       }
       case Instruction::MONITOR_ENTER: {
-        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
+        Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
         if (UNLIKELY(obj == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
         } else {
@@ -785,7 +851,7 @@
         break;
       }
       case Instruction::MONITOR_EXIT: {
-        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
+        Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
         if (UNLIKELY(obj == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
         } else {
@@ -794,11 +860,12 @@
         break;
       }
       case Instruction::CHECK_CAST: {
-        Class* c = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
+        Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
+                                          self, false, true);
         if (UNLIKELY(c == NULL)) {
           CHECK(self->IsExceptionPending());
         } else {
-          Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
+          Object* obj = shadow_frame.GetVRegReference(inst->VRegA_21c());
           if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
             ThrowClassCastException(c, obj->GetClass());
           }
@@ -806,45 +873,55 @@
         break;
       }
       case Instruction::INSTANCE_OF: {
-        Class* c = ResolveVerifyAndClinit(dec_insn.vC, shadow_frame.GetMethod(), self, false, true);
+        Class* c = ResolveVerifyAndClinit(inst->VRegC_22c(), shadow_frame.GetMethod(),
+                                          self, false, true);
         if (UNLIKELY(c == NULL)) {
           CHECK(self->IsExceptionPending());
         } else {
-          Object* obj = shadow_frame.GetVRegReference(dec_insn.vB);
-          shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
+          Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
+          shadow_frame.SetVReg(inst->VRegA_22c(), (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
         }
         break;
       }
       case Instruction::ARRAY_LENGTH:  {
-        Object* array = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* array = shadow_frame.GetVRegReference(inst->VRegB_12x());
         if (UNLIKELY(array == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        shadow_frame.SetVReg(dec_insn.vA, array->AsArray()->GetLength());
+        shadow_frame.SetVReg(inst->VRegA_12x(), array->AsArray()->GetLength());
         break;
       }
       case Instruction::NEW_INSTANCE: {
-        Object* obj = AllocObjectFromCode(dec_insn.vB, shadow_frame.GetMethod(), self, true);
-        shadow_frame.SetVRegReference(dec_insn.vA, obj);
+        Object* obj = AllocObjectFromCode(inst->VRegB_21c(), shadow_frame.GetMethod(),
+                                          self, true);
+        if (UNLIKELY(obj == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          shadow_frame.SetVRegReference(inst->VRegA_21c(), obj);
+        }
         break;
       }
       case Instruction::NEW_ARRAY: {
-        int32_t length = shadow_frame.GetVReg(dec_insn.vB);
-        Object* obj = AllocArrayFromCode(dec_insn.vC, shadow_frame.GetMethod(), length, self, true);
-        shadow_frame.SetVRegReference(dec_insn.vA, obj);
+        int32_t length = shadow_frame.GetVReg(inst->VRegB_22c());
+        Object* obj = AllocArrayFromCode(inst->VRegC_22c(), shadow_frame.GetMethod(),
+                                         length, self, true);
+        if (UNLIKELY(obj == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          shadow_frame.SetVRegReference(inst->VRegA_22c(), obj);
+        }
         break;
       }
-      case Instruction::FILLED_NEW_ARRAY:
-      case Instruction::FILLED_NEW_ARRAY_RANGE: {
-        bool is_range = (dec_insn.opcode == Instruction::FILLED_NEW_ARRAY_RANGE);
-        int32_t length = dec_insn.vA;
-        CHECK(is_range || length <= 5);
+      case Instruction::FILLED_NEW_ARRAY: {
+        const int32_t length = inst->VRegA_35c();
+        CHECK(length <= 5);
         if (UNLIKELY(length < 0)) {
           ThrowNegativeArraySizeException(length);
           break;
         }
-        Class* arrayClass = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
+        Class* arrayClass = ResolveVerifyAndClinit(inst->VRegB_35c(), shadow_frame.GetMethod(),
+                                                   self, false, true);
         if (UNLIKELY(arrayClass == NULL)) {
           CHECK(self->IsExceptionPending());
           break;
@@ -864,117 +941,111 @@
           break;
         }
         Object* newArray = Array::Alloc(self, arrayClass, length);
-        if (newArray != NULL) {
+        if (UNLIKELY(newArray == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          uint32_t arg[5];
+          inst->GetArgs(arg);
+          const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
           for (int32_t i = 0; i < length; ++i) {
-            if (is_range) {
-              if (componentClass->IsPrimitiveInt()) {
-                newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(dec_insn.vC + i));
-              } else {
-                newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(dec_insn.vC + i));
-              }
+            if (is_primitive_int_component) {
+              newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(arg[i]));
             } else {
-              if (componentClass->IsPrimitiveInt()) {
-                newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(dec_insn.arg[i]));
-              } else {
-                newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(dec_insn.arg[i]));
-              }
+              newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(arg[i]));
             }
           }
         }
         result_register.SetL(newArray);
         break;
       }
-      case Instruction::CMPL_FLOAT: {
-        float val1 = shadow_frame.GetVRegFloat(dec_insn.vB);
-        float val2 = shadow_frame.GetVRegFloat(dec_insn.vC);
-        int32_t result;
-        if (val1 == val2) {
-          result = 0;
-        } else if (val1 > val2) {
-          result = 1;
-        } else {
-          result = -1;
+      case Instruction::FILLED_NEW_ARRAY_RANGE: {
+        int32_t length = inst->VRegA_3rc();
+        if (UNLIKELY(length < 0)) {
+          ThrowNegativeArraySizeException(length);
+          break;
         }
-        shadow_frame.SetVReg(dec_insn.vA, result);
+        Class* arrayClass = ResolveVerifyAndClinit(inst->VRegB_3rc(), shadow_frame.GetMethod(),
+                                                   self, false, true);
+        if (UNLIKELY(arrayClass == NULL)) {
+          CHECK(self->IsExceptionPending());
+          break;
+        }
+        CHECK(arrayClass->IsArrayClass());
+        Class* componentClass = arrayClass->GetComponentType();
+        if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
+          if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
+            ThrowRuntimeException("Bad filled array request for type %s",
+                                  PrettyDescriptor(componentClass).c_str());
+          } else {
+            self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
+                                     "Ljava/lang/InternalError;",
+                                     "Found type %s; filled-new-array not implemented for anything but \'int\'",
+                                     PrettyDescriptor(componentClass).c_str());
+          }
+          break;
+        }
+        Object* newArray = Array::Alloc(self, arrayClass, length);
+        if (UNLIKELY(newArray == NULL)) {
+          CHECK(self->IsExceptionPending());
+        } else {
+          uint32_t vregC = inst->VRegC_3rc();
+          const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
+          for (int32_t i = 0; i < length; ++i) {
+            if (is_primitive_int_component) {
+              newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(vregC + i));
+            } else {
+              newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(vregC + i));
+            }
+          }
+        }
+        result_register.SetL(newArray);
         break;
       }
-      case Instruction::CMPG_FLOAT: {
-        float val1 = shadow_frame.GetVRegFloat(dec_insn.vB);
-        float val2 = shadow_frame.GetVRegFloat(dec_insn.vC);
-        int32_t result;
-        if (val1 == val2) {
-          result = 0;
-        } else if (val1 < val2) {
-          result = -1;
-        } else {
-          result = 1;
+      case Instruction::FILL_ARRAY_DATA: {
+        Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t());
+        if (UNLIKELY(obj == NULL)) {
+          ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
+          break;
         }
-        shadow_frame.SetVReg(dec_insn.vA, result);
-        break;
-      }
-      case Instruction::CMPL_DOUBLE: {
-        double val1 = shadow_frame.GetVRegDouble(dec_insn.vB);
-        double val2 = shadow_frame.GetVRegDouble(dec_insn.vC);
-        int32_t result;
-        if (val1 == val2) {
-          result = 0;
-        } else if (val1 > val2) {
-          result = 1;
-        } else {
-          result = -1;
+        Array* array = obj->AsArray();
+        DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
+        const Instruction::ArrayDataPayload* payload =
+            reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + dex_pc + inst->VRegB_31t());
+        if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
+          self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
+                                   "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                                   "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                                   array->GetLength(), payload->element_count);
+          break;
         }
-        shadow_frame.SetVReg(dec_insn.vA, result);
-        break;
-      }
-
-      case Instruction::CMPG_DOUBLE: {
-        double val1 = shadow_frame.GetVRegDouble(dec_insn.vB);
-        double val2 = shadow_frame.GetVRegDouble(dec_insn.vC);
-        int32_t result;
-        if (val1 == val2) {
-          result = 0;
-        } else if (val1 < val2) {
-          result = -1;
-        } else {
-          result = 1;
-        }
-        shadow_frame.SetVReg(dec_insn.vA, result);
-        break;
-      }
-      case Instruction::CMP_LONG: {
-        int64_t val1 = shadow_frame.GetVRegLong(dec_insn.vB);
-        int64_t val2 = shadow_frame.GetVRegLong(dec_insn.vC);
-        int32_t result;
-        if (val1 > val2) {
-          result = 1;
-        } else if (val1 == val2) {
-          result = 0;
-        } else {
-          result = -1;
-        }
-        shadow_frame.SetVReg(dec_insn.vA, result);
+        uint32_t size_in_bytes = payload->element_count * payload->element_width;
+        memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
         break;
       }
       case Instruction::THROW: {
-        Object* exception = shadow_frame.GetVRegReference(dec_insn.vA);
-        if (exception == NULL) {
+        Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x());
+        if (UNLIKELY(exception == NULL)) {
           ThrowNullPointerException(NULL, "throw with null exception");
         } else {
           self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
         }
         break;
       }
-      case Instruction::GOTO:
-      case Instruction::GOTO_16:
+      case Instruction::GOTO: {
+        next_inst = Instruction::At(insns + dex_pc + inst->VRegA_10t());
+        break;
+      }
+      case Instruction::GOTO_16: {
+        next_inst = Instruction::At(insns + dex_pc + inst->VRegA_20t());
+        break;
+      }
       case Instruction::GOTO_32: {
-        uint32_t dex_pc = inst->GetDexPc(insns);
-        next_inst = Instruction::At(insns + dex_pc + dec_insn.vA);
+        next_inst = Instruction::At(insns + dex_pc + inst->VRegA_30t());
         break;
       }
       case Instruction::PACKED_SWITCH: {
-        uint32_t dex_pc = inst->GetDexPc(insns);
-        const uint16_t* switch_data = insns + dex_pc + dec_insn.vB;
-        int32_t test_val = shadow_frame.GetVReg(dec_insn.vA);
+        const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
+        int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
         CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
         uint16_t size = switch_data[1];
         CHECK_GT(size, 0);
@@ -990,9 +1061,8 @@
         break;
       }
       case Instruction::SPARSE_SWITCH: {
-        uint32_t dex_pc = inst->GetDexPc(insns);
-        const uint16_t* switch_data = insns + dex_pc + dec_insn.vB;
-        int32_t test_val = shadow_frame.GetVReg(dec_insn.vA);
+        const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
+        int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
         CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
         uint16_t size = switch_data[1];
         CHECK_GT(size, 0);
@@ -1016,818 +1086,998 @@
         }
         break;
       }
-      case Instruction::FILL_ARRAY_DATA: {
-        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
-        if (UNLIKELY(obj == NULL)) {
-          ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-          break;
+      case Instruction::CMPL_FLOAT: {
+        float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
+        float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
+        int32_t result;
+        // TODO: we should not test float equality like this. Reorder comparisons
+        // or use a different comparison mechanism.
+        if (val1 == val2) {
+          result = 0;
+        } else if (val1 > val2) {
+          result = 1;
+        } else {
+          result = -1;
         }
-        Array* array = obj->AsArray();
-        DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-        uint32_t dex_pc = inst->GetDexPc(insns);
-        const Instruction::ArrayDataPayload* payload =
-            reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + dex_pc + dec_insn.vB);
-        if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-          self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
-                                   "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                                   "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                                   array->GetLength(), payload->element_count);
-          break;
+        shadow_frame.SetVReg(inst->VRegA_23x(), result);
+        break;
+      }
+      case Instruction::CMPG_FLOAT: {
+        float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
+        float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
+        int32_t result;
+        // TODO: we should not test float equality like this. Reorder comparisons
+        // or use a different comparison mechanism.
+        if (val1 == val2) {
+          result = 0;
+        } else if (val1 < val2) {
+          result = -1;
+        } else {
+          result = 1;
         }
-        uint32_t size_in_bytes = payload->element_count * payload->element_width;
-        memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+        shadow_frame.SetVReg(inst->VRegA_23x(), result);
+        break;
+      }
+      case Instruction::CMPL_DOUBLE: {
+        double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
+        double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
+        int32_t result;
+        // TODO: we should not test double equality like this. Reorder comparisons
+        // or use a different comparison mechanism.
+        if (val1 == val2) {
+          result = 0;
+        } else if (val1 > val2) {
+          result = 1;
+        } else {
+          result = -1;
+        }
+        shadow_frame.SetVReg(inst->VRegA_23x(), result);
+        break;
+      }
+
+      case Instruction::CMPG_DOUBLE: {
+        double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
+        double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
+        int32_t result;
+        // TODO: we should not test double equality like this. Reorder comparisons
+        // or use a different comparison mechanism.
+        if (val1 == val2) {
+          result = 0;
+        } else if (val1 < val2) {
+          result = -1;
+        } else {
+          result = 1;
+        }
+        shadow_frame.SetVReg(inst->VRegA_23x(), result);
+        break;
+      }
+      case Instruction::CMP_LONG: {
+        int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
+        int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
+        int32_t result;
+        if (val1 > val2) {
+          result = 1;
+        } else if (val1 == val2) {
+          result = 0;
+        } else {
+          result = -1;
+        }
+        shadow_frame.SetVReg(inst->VRegA_23x(), result);
         break;
       }
       case Instruction::IF_EQ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) == shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) == shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_NE: {
-        if (shadow_frame.GetVReg(dec_insn.vA) != shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) != shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_LT: {
-        if (shadow_frame.GetVReg(dec_insn.vA) < shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) < shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_GE: {
-        if (shadow_frame.GetVReg(dec_insn.vA) >= shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) >= shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_GT: {
-        if (shadow_frame.GetVReg(dec_insn.vA) > shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) > shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_LE: {
-        if (shadow_frame.GetVReg(dec_insn.vA) <= shadow_frame.GetVReg(dec_insn.vB)) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
+        if (shadow_frame.GetVReg(inst->VRegA_22t()) <= shadow_frame.GetVReg(inst->VRegB_22t())) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
         }
         break;
       }
       case Instruction::IF_EQZ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) == 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) == 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::IF_NEZ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) != 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) != 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::IF_LTZ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) < 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) < 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::IF_GEZ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) >= 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) >= 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::IF_GTZ: {
-        if (shadow_frame.GetVReg(dec_insn.vA) > 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) > 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::IF_LEZ:  {
-        if (shadow_frame.GetVReg(dec_insn.vA) <= 0) {
-          uint32_t dex_pc = inst->GetDexPc(insns);
-          next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
+        if (shadow_frame.GetVReg(inst->VRegA_21t()) <= 0) {
+          next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
         }
         break;
       }
       case Instruction::AGET_BOOLEAN: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->AsBooleanArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVReg(inst->VRegA_23x(), a->AsBooleanArray()->Get(index));
         break;
       }
       case Instruction::AGET_BYTE: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->AsByteArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVReg(inst->VRegA_23x(), a->AsByteArray()->Get(index));
         break;
       }
       case Instruction::AGET_CHAR: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->AsCharArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVReg(inst->VRegA_23x(), a->AsCharArray()->Get(index));
         break;
       }
       case Instruction::AGET_SHORT: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->AsShortArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVReg(inst->VRegA_23x(), a->AsShortArray()->Get(index));
         break;
       }
       case Instruction::AGET: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->AsIntArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVReg(inst->VRegA_23x(), a->AsIntArray()->Get(index));
         break;
       }
       case Instruction::AGET_WIDE:  {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVRegLong(dec_insn.vA, a->AsLongArray()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVRegLong(inst->VRegA_23x(), a->AsLongArray()->Get(index));
         break;
       }
       case Instruction::AGET_OBJECT: {
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVRegReference(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
+        shadow_frame.SetVRegReference(inst->VRegA_23x(), a->AsObjectArray<Object>()->Get(index));
         break;
       }
       case Instruction::APUT_BOOLEAN: {
-        uint8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsBooleanArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_BYTE: {
-        int8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        int8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsByteArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_CHAR: {
-        uint16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsCharArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_SHORT: {
-        int16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        int16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsShortArray()->Set(index, val);
         break;
       }
       case Instruction::APUT: {
-        int32_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        int32_t val = shadow_frame.GetVReg(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsIntArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_WIDE: {
-        int64_t val = shadow_frame.GetVRegLong(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsLongArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_OBJECT: {
-        Object* val = shadow_frame.GetVRegReference(dec_insn.vA);
-        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
           break;
         }
-        int32_t index = shadow_frame.GetVReg(dec_insn.vC);
+        Object* val = shadow_frame.GetVRegReference(inst->VRegA_23x());
+        int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
         a->AsObjectArray<Object>()->Set(index, val);
         break;
       }
       case Instruction::IGET_BOOLEAN:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimBoolean);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimBoolean);
         break;
       case Instruction::IGET_BYTE:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimByte);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimByte);
         break;
       case Instruction::IGET_CHAR:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimChar);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimChar);
         break;
       case Instruction::IGET_SHORT:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimShort);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimShort);
         break;
       case Instruction::IGET:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimInt);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimInt);
         break;
       case Instruction::IGET_WIDE:
-        DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimLong);
+        DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimLong);
         break;
       case Instruction::IGET_OBJECT:
-        DoFieldGet(self, shadow_frame, dec_insn, InstanceObjectRead, Primitive::kPrimNot);
+        DoFieldGet(self, shadow_frame, inst, InstanceObjectRead, Primitive::kPrimNot);
         break;
       case Instruction::SGET_BOOLEAN:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimBoolean);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimBoolean);
         break;
       case Instruction::SGET_BYTE:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimByte);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimByte);
         break;
       case Instruction::SGET_CHAR:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimChar);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimChar);
         break;
       case Instruction::SGET_SHORT:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimShort);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimShort);
         break;
       case Instruction::SGET:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimInt);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimInt);
         break;
       case Instruction::SGET_WIDE:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimLong);
+        DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimLong);
         break;
       case Instruction::SGET_OBJECT:
-        DoFieldGet(self, shadow_frame, dec_insn, StaticObjectRead, Primitive::kPrimNot);
+        DoFieldGet(self, shadow_frame, inst, StaticObjectRead, Primitive::kPrimNot);
         break;
       case Instruction::IPUT_BOOLEAN:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimBoolean);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimBoolean);
         break;
       case Instruction::IPUT_BYTE:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimByte);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimByte);
         break;
       case Instruction::IPUT_CHAR:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimChar);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimChar);
         break;
       case Instruction::IPUT_SHORT:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimShort);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimShort);
         break;
       case Instruction::IPUT:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimInt);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimInt);
         break;
       case Instruction::IPUT_WIDE:
-        DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimLong);
+        DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimLong);
         break;
       case Instruction::IPUT_OBJECT:
-        DoFieldPut(self, shadow_frame, dec_insn, InstanceObjectWrite, Primitive::kPrimNot);
+        DoFieldPut(self, shadow_frame, inst, InstanceObjectWrite, Primitive::kPrimNot);
         break;
       case Instruction::SPUT_BOOLEAN:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimBoolean);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimBoolean);
         break;
       case Instruction::SPUT_BYTE:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimByte);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimByte);
         break;
       case Instruction::SPUT_CHAR:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimChar);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimChar);
         break;
       case Instruction::SPUT_SHORT:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimShort);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimShort);
         break;
       case Instruction::SPUT:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimInt);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimInt);
         break;
       case Instruction::SPUT_WIDE:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimLong);
+        DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimLong);
         break;
       case Instruction::SPUT_OBJECT:
-        DoFieldPut(self, shadow_frame, dec_insn, StaticObjectWrite, Primitive::kPrimNot);
+        DoFieldPut(self, shadow_frame, inst, StaticObjectWrite, Primitive::kPrimNot);
         break;
       case Instruction::INVOKE_VIRTUAL:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kVirtual, false, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kVirtual, false, &result_register);
         break;
       case Instruction::INVOKE_VIRTUAL_RANGE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kVirtual, true, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kVirtual, true, &result_register);
         break;
       case Instruction::INVOKE_SUPER:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kSuper, false, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kSuper, false, &result_register);
         break;
       case Instruction::INVOKE_SUPER_RANGE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kSuper, true, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kSuper, true, &result_register);
         break;
       case Instruction::INVOKE_DIRECT:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kDirect, false, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kDirect, false, &result_register);
         break;
       case Instruction::INVOKE_DIRECT_RANGE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kDirect, true, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kDirect, true, &result_register);
         break;
       case Instruction::INVOKE_INTERFACE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kInterface, false, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kInterface, false, &result_register);
         break;
       case Instruction::INVOKE_INTERFACE_RANGE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kInterface, true, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kInterface, true, &result_register);
         break;
       case Instruction::INVOKE_STATIC:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kStatic, false, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kStatic, false, &result_register);
         break;
       case Instruction::INVOKE_STATIC_RANGE:
-        DoInvoke(self, mh, shadow_frame, dec_insn, kStatic, true, &result_register);
+        DoInvoke(self, mh, shadow_frame, inst, kStatic, true, &result_register);
         break;
       case Instruction::NEG_INT:
-        shadow_frame.SetVReg(dec_insn.vA, -shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(inst->VRegA_12x(), -shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
       case Instruction::NOT_INT:
-        shadow_frame.SetVReg(dec_insn.vA, ~shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(inst->VRegA_12x(), ~shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
       case Instruction::NEG_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, -shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_12x(), -shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
       case Instruction::NOT_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, ~shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_12x(), ~shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
       case Instruction::NEG_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA, -shadow_frame.GetVRegFloat(dec_insn.vB));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(), -shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
       case Instruction::NEG_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA, -shadow_frame.GetVRegDouble(dec_insn.vB));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(), -shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
       case Instruction::INT_TO_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVRegLong(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
       case Instruction::INT_TO_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
       case Instruction::INT_TO_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
       case Instruction::LONG_TO_INT:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVReg(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
       case Instruction::LONG_TO_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
       case Instruction::LONG_TO_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
       case Instruction::FLOAT_TO_INT: {
-        float val = shadow_frame.GetVRegFloat(dec_insn.vB);
+        uint32_t dst = inst->VRegA_12x();
+        float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
         if (val != val) {
-          shadow_frame.SetVReg(dec_insn.vA, 0);
+          shadow_frame.SetVReg(dst, 0);
         } else if (val > static_cast<float>(kMaxInt)) {
-          shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
+          shadow_frame.SetVReg(dst, kMaxInt);
         } else if (val < static_cast<float>(kMinInt)) {
-          shadow_frame.SetVReg(dec_insn.vA, kMinInt);
+          shadow_frame.SetVReg(dst, kMinInt);
         } else {
-          shadow_frame.SetVReg(dec_insn.vA, val);
+          shadow_frame.SetVReg(dst, val);
         }
         break;
       }
       case Instruction::FLOAT_TO_LONG: {
-        float val = shadow_frame.GetVRegFloat(dec_insn.vB);
+        uint32_t dst = inst->VRegA_12x();
+        float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
         if (val != val) {
-          shadow_frame.SetVRegLong(dec_insn.vA, 0);
+          shadow_frame.SetVRegLong(dst, 0);
         } else if (val > static_cast<float>(kMaxLong)) {
-          shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
+          shadow_frame.SetVRegLong(dst, kMaxLong);
         } else if (val < static_cast<float>(kMinLong)) {
-          shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
+          shadow_frame.SetVRegLong(dst, kMinLong);
         } else {
-          shadow_frame.SetVRegLong(dec_insn.vA, val);
+          shadow_frame.SetVRegLong(dst, val);
         }
         break;
       }
       case Instruction::FLOAT_TO_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegFloat(dec_insn.vB));
+        shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
       case Instruction::DOUBLE_TO_INT: {
-        double val = shadow_frame.GetVRegDouble(dec_insn.vB);
+        uint32_t dst = inst->VRegA_12x();
+        double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
         if (val != val) {
-          shadow_frame.SetVReg(dec_insn.vA, 0);
+          shadow_frame.SetVReg(dst, 0);
         } else if (val > static_cast<double>(kMaxInt)) {
-          shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
+          shadow_frame.SetVReg(dst, kMaxInt);
         } else if (val < static_cast<double>(kMinInt)) {
-          shadow_frame.SetVReg(dec_insn.vA, kMinInt);
+          shadow_frame.SetVReg(dst, kMinInt);
         } else {
-          shadow_frame.SetVReg(dec_insn.vA, val);
+          shadow_frame.SetVReg(dst, val);
         }
         break;
       }
       case Instruction::DOUBLE_TO_LONG: {
-        double val = shadow_frame.GetVRegDouble(dec_insn.vB);
+        uint32_t dst = inst->VRegA_12x();
+        double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
         if (val != val) {
-          shadow_frame.SetVRegLong(dec_insn.vA, 0);
+          shadow_frame.SetVRegLong(dst, 0);
         } else if (val > static_cast<double>(kMaxLong)) {
-          shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
+          shadow_frame.SetVRegLong(dst, kMaxLong);
         } else if (val < static_cast<double>(kMinLong)) {
-          shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
+          shadow_frame.SetVRegLong(dst, kMinLong);
         } else {
-          shadow_frame.SetVRegLong(dec_insn.vA, val);
+          shadow_frame.SetVRegLong(dst, val);
         }
         break;
       }
       case Instruction::DOUBLE_TO_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVRegDouble(dec_insn.vB));
+        shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
       case Instruction::INT_TO_BYTE:
-        shadow_frame.SetVReg(dec_insn.vA, static_cast<int8_t>(shadow_frame.GetVReg(dec_insn.vB)));
+        shadow_frame.SetVReg(inst->VRegA_12x(),
+                             static_cast<int8_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
         break;
       case Instruction::INT_TO_CHAR:
-        shadow_frame.SetVReg(dec_insn.vA, static_cast<uint16_t>(shadow_frame.GetVReg(dec_insn.vB)));
+        shadow_frame.SetVReg(inst->VRegA_12x(),
+                             static_cast<uint16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
         break;
       case Instruction::INT_TO_SHORT:
-        shadow_frame.SetVReg(dec_insn.vA, static_cast<int16_t>(shadow_frame.GetVReg(dec_insn.vB)));
+        shadow_frame.SetVReg(inst->VRegA_12x(),
+                             static_cast<int16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
         break;
       case Instruction::ADD_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) + shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) +
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::SUB_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) - shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) -
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::MUL_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) * shadow_frame.GetVReg(dec_insn.vC));
-        break;
-      case Instruction::REM_INT:
-        DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
-                       shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) *
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::DIV_INT:
-        DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
-                    shadow_frame.GetVReg(dec_insn.vC));
+        DoIntDivide(self, shadow_frame, inst->VRegA_23x(),
+                    shadow_frame.GetVReg(inst->VRegB_23x()),
+                    shadow_frame.GetVReg(inst->VRegC_23x()));
+        break;
+      case Instruction::REM_INT:
+        DoIntRemainder(self, shadow_frame, inst->VRegA_23x(),
+                       shadow_frame.GetVReg(inst->VRegB_23x()),
+                       shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::SHL_INT:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) <<
-                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) <<
+                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
         break;
       case Instruction::SHR_INT:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >>
-                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) >>
+                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
         break;
       case Instruction::USHR_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
-                             (shadow_frame.GetVReg(dec_insn.vC) & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
+                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
         break;
       case Instruction::AND_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) & shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) &
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::OR_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) | shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) |
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::XOR_INT:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vB) ^ shadow_frame.GetVReg(dec_insn.vC));
+        shadow_frame.SetVReg(inst->VRegA_23x(),
+                             shadow_frame.GetVReg(inst->VRegB_23x()) ^
+                             shadow_frame.GetVReg(inst->VRegC_23x()));
         break;
       case Instruction::ADD_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) +
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) +
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::SUB_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) -
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) -
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::MUL_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) *
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) *
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::DIV_LONG:
-        DoLongDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB),
-                    shadow_frame.GetVRegLong(dec_insn.vC));
+        DoLongDivide(self, shadow_frame, inst->VRegA_23x(),
+                     shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                    shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::REM_LONG:
-        DoLongRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB),
-                        shadow_frame.GetVRegLong(dec_insn.vC));
+        DoLongRemainder(self, shadow_frame, inst->VRegA_23x(),
+                        shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                        shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::AND_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) &
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::OR_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) |
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::XOR_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) ^
-                                 shadow_frame.GetVRegLong(dec_insn.vC));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
+                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
         break;
       case Instruction::SHL_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) <<
-                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
+                                 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
         break;
       case Instruction::SHR_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vB) >>
-                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
+                                 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
         break;
       case Instruction::USHR_LONG:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vB)) >>
-                                 (shadow_frame.GetVReg(dec_insn.vC) & 0x3f));
+        shadow_frame.SetVRegLong(inst->VRegA_23x(),
+                                 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
+                                 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
         break;
       case Instruction::ADD_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vB) +
-                                  shadow_frame.GetVRegFloat(dec_insn.vC));
+        shadow_frame.SetVRegFloat(inst->VRegA_23x(),
+                                  shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
+                                  shadow_frame.GetVRegFloat(inst->VRegC_23x()));
         break;
       case Instruction::SUB_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vB) -
-                                  shadow_frame.GetVRegFloat(dec_insn.vC));
+        shadow_frame.SetVRegFloat(inst->VRegA_23x(),
+                                  shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
+                                  shadow_frame.GetVRegFloat(inst->VRegC_23x()));
         break;
       case Instruction::MUL_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vB) *
-                                  shadow_frame.GetVRegFloat(dec_insn.vC));
+        shadow_frame.SetVRegFloat(inst->VRegA_23x(),
+                                  shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
+                                  shadow_frame.GetVRegFloat(inst->VRegC_23x()));
         break;
       case Instruction::DIV_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vB) /
-                                  shadow_frame.GetVRegFloat(dec_insn.vC));
+        shadow_frame.SetVRegFloat(inst->VRegA_23x(),
+                                  shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
+                                  shadow_frame.GetVRegFloat(inst->VRegC_23x()));
         break;
       case Instruction::REM_FLOAT:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  fmodf(shadow_frame.GetVRegFloat(dec_insn.vB),
-                                        shadow_frame.GetVRegFloat(dec_insn.vC)));
+        shadow_frame.SetVRegFloat(inst->VRegA_23x(),
+                                  fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
+                                        shadow_frame.GetVRegFloat(inst->VRegC_23x())));
         break;
       case Instruction::ADD_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vB) +
-                                   shadow_frame.GetVRegDouble(dec_insn.vC));
+        shadow_frame.SetVRegDouble(inst->VRegA_23x(),
+                                   shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
+                                   shadow_frame.GetVRegDouble(inst->VRegC_23x()));
         break;
       case Instruction::SUB_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vB) -
-                                   shadow_frame.GetVRegDouble(dec_insn.vC));
+        shadow_frame.SetVRegDouble(inst->VRegA_23x(),
+                                   shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
+                                   shadow_frame.GetVRegDouble(inst->VRegC_23x()));
         break;
       case Instruction::MUL_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vB) *
-                                   shadow_frame.GetVRegDouble(dec_insn.vC));
+        shadow_frame.SetVRegDouble(inst->VRegA_23x(),
+                                   shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
+                                   shadow_frame.GetVRegDouble(inst->VRegC_23x()));
         break;
       case Instruction::DIV_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vB) /
-                                   shadow_frame.GetVRegDouble(dec_insn.vC));
+        shadow_frame.SetVRegDouble(inst->VRegA_23x(),
+                                   shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
+                                   shadow_frame.GetVRegDouble(inst->VRegC_23x()));
         break;
       case Instruction::REM_DOUBLE:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   fmod(shadow_frame.GetVRegDouble(dec_insn.vB),
-                                        shadow_frame.GetVRegDouble(dec_insn.vC)));
+        shadow_frame.SetVRegDouble(inst->VRegA_23x(),
+                                   fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
+                                        shadow_frame.GetVRegDouble(inst->VRegC_23x())));
         break;
-      case Instruction::ADD_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) + shadow_frame.GetVReg(dec_insn.vB));
+      case Instruction::ADD_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) +
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::SUB_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) - shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::SUB_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) -
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::MUL_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) * shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::MUL_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) *
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::REM_INT_2ADDR:
-        DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA),
-                       shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::REM_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        DoIntRemainder(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
+                       shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::SHL_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA) <<
-                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
+      }
+      case Instruction::SHL_INT_2ADDR:{
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) <<
+                             (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
         break;
-      case Instruction::SHR_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA) >>
-                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
+      }
+      case Instruction::SHR_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) >>
+                             (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
         break;
-      case Instruction::USHR_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vA)) >>
-                             (shadow_frame.GetVReg(dec_insn.vB) & 0x1f));
+      }
+      case Instruction::USHR_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
+                             (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
         break;
-      case Instruction::AND_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) & shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::AND_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) &
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::OR_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) | shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::OR_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) |
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::XOR_INT_2ADDR:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             shadow_frame.GetVReg(dec_insn.vA) ^ shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::XOR_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVReg(vregA,
+                             shadow_frame.GetVReg(vregA) ^
+                             shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::DIV_INT_2ADDR:
-        DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA),
-                    shadow_frame.GetVReg(dec_insn.vB));
+      }
+      case Instruction::DIV_INT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
+                    shadow_frame.GetVReg(inst->VRegB_12x()));
         break;
-      case Instruction::ADD_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) +
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::ADD_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) +
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::SUB_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) -
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::SUB_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) -
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::MUL_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) *
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::MUL_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) *
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::DIV_LONG_2ADDR:
-        DoLongDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vA),
-                    shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::DIV_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        DoLongDivide(self, shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
+                    shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::REM_LONG_2ADDR:
-        DoLongRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vA),
-                        shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::REM_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        DoLongRemainder(self, shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
+                        shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::AND_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) &
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::AND_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) &
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::OR_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) |
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::OR_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) |
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::XOR_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) ^
-                                 shadow_frame.GetVRegLong(dec_insn.vB));
+      }
+      case Instruction::XOR_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) ^
+                                 shadow_frame.GetVRegLong(inst->VRegB_12x()));
         break;
-      case Instruction::SHL_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) <<
-                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
+      }
+      case Instruction::SHL_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) <<
+                                 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
         break;
-      case Instruction::SHR_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 shadow_frame.GetVRegLong(dec_insn.vA) >>
-                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
+      }
+      case Instruction::SHR_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 shadow_frame.GetVRegLong(vregA) >>
+                                 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
         break;
-      case Instruction::USHR_LONG_2ADDR:
-        shadow_frame.SetVRegLong(dec_insn.vA,
-                                 static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vA)) >>
-                                 (shadow_frame.GetVReg(dec_insn.vB) & 0x3f));
+      }
+      case Instruction::USHR_LONG_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegLong(vregA,
+                                 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
+                                 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
         break;
-      case Instruction::ADD_FLOAT_2ADDR:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vA) +
-                                  shadow_frame.GetVRegFloat(dec_insn.vB));
+      }
+      case Instruction::ADD_FLOAT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegFloat(vregA,
+                                  shadow_frame.GetVRegFloat(vregA) +
+                                  shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
-      case Instruction::SUB_FLOAT_2ADDR:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vA) -
-                                  shadow_frame.GetVRegFloat(dec_insn.vB));
+      }
+      case Instruction::SUB_FLOAT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegFloat(vregA,
+                                  shadow_frame.GetVRegFloat(vregA) -
+                                  shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
-      case Instruction::MUL_FLOAT_2ADDR:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vA) *
-                                  shadow_frame.GetVRegFloat(dec_insn.vB));
+      }
+      case Instruction::MUL_FLOAT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegFloat(vregA,
+                                  shadow_frame.GetVRegFloat(vregA) *
+                                  shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
-      case Instruction::DIV_FLOAT_2ADDR:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  shadow_frame.GetVRegFloat(dec_insn.vA) /
-                                  shadow_frame.GetVRegFloat(dec_insn.vB));
+      }
+      case Instruction::DIV_FLOAT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegFloat(vregA,
+                                  shadow_frame.GetVRegFloat(vregA) /
+                                  shadow_frame.GetVRegFloat(inst->VRegB_12x()));
         break;
-      case Instruction::REM_FLOAT_2ADDR:
-        shadow_frame.SetVRegFloat(dec_insn.vA,
-                                  fmodf(shadow_frame.GetVRegFloat(dec_insn.vA),
-                                        shadow_frame.GetVRegFloat(dec_insn.vB)));
+      }
+      case Instruction::REM_FLOAT_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegFloat(vregA,
+                                  fmodf(shadow_frame.GetVRegFloat(vregA),
+                                        shadow_frame.GetVRegFloat(inst->VRegB_12x())));
         break;
-      case Instruction::ADD_DOUBLE_2ADDR:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vA) +
-                                   shadow_frame.GetVRegDouble(dec_insn.vB));
+      }
+      case Instruction::ADD_DOUBLE_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegDouble(vregA,
+                                   shadow_frame.GetVRegDouble(vregA) +
+                                   shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
-      case Instruction::SUB_DOUBLE_2ADDR:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vA) -
-                                   shadow_frame.GetVRegDouble(dec_insn.vB));
+      }
+      case Instruction::SUB_DOUBLE_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegDouble(vregA,
+                                   shadow_frame.GetVRegDouble(vregA) -
+                                   shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
-      case Instruction::MUL_DOUBLE_2ADDR:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vA) *
-                                   shadow_frame.GetVRegDouble(dec_insn.vB));
+      }
+      case Instruction::MUL_DOUBLE_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegDouble(vregA,
+                                   shadow_frame.GetVRegDouble(vregA) *
+                                   shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
-      case Instruction::DIV_DOUBLE_2ADDR:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   shadow_frame.GetVRegDouble(dec_insn.vA) /
-                                   shadow_frame.GetVRegDouble(dec_insn.vB));
+      }
+      case Instruction::DIV_DOUBLE_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegDouble(vregA,
+                                   shadow_frame.GetVRegDouble(vregA) /
+                                   shadow_frame.GetVRegDouble(inst->VRegB_12x()));
         break;
-      case Instruction::REM_DOUBLE_2ADDR:
-        shadow_frame.SetVRegDouble(dec_insn.vA,
-                                   fmod(shadow_frame.GetVRegDouble(dec_insn.vA),
-                                        shadow_frame.GetVRegDouble(dec_insn.vB)));
+      }
+      case Instruction::REM_DOUBLE_2ADDR: {
+        uint32_t vregA = inst->VRegA_12x();
+        shadow_frame.SetVRegDouble(vregA,
+                                   fmod(shadow_frame.GetVRegDouble(vregA),
+                                        shadow_frame.GetVRegDouble(inst->VRegB_12x())));
         break;
+      }
       case Instruction::ADD_INT_LIT16:
-      case Instruction::ADD_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) + dec_insn.vC);
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             shadow_frame.GetVReg(inst->VRegB_22s()) +
+                             inst->VRegC_22s());
         break;
       case Instruction::RSUB_INT:
-      case Instruction::RSUB_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, dec_insn.vC - shadow_frame.GetVReg(dec_insn.vB));
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             inst->VRegC_22s() -
+                             shadow_frame.GetVReg(inst->VRegB_22s()));
         break;
       case Instruction::MUL_INT_LIT16:
-      case Instruction::MUL_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) * dec_insn.vC);
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             shadow_frame.GetVReg(inst->VRegB_22s()) *
+                             inst->VRegC_22s());
         break;
       case Instruction::DIV_INT_LIT16:
-      case Instruction::DIV_INT_LIT8:
-        DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
-                    dec_insn.vC);
+        DoIntDivide(self, shadow_frame, inst->VRegA_22s(),
+                    shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
         break;
       case Instruction::REM_INT_LIT16:
-      case Instruction::REM_INT_LIT8:
-        DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
-                       dec_insn.vC);
+        DoIntRemainder(self, shadow_frame, inst->VRegA_22s(),
+                       shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
         break;
       case Instruction::AND_INT_LIT16:
-      case Instruction::AND_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) & dec_insn.vC);
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             shadow_frame.GetVReg(inst->VRegB_22s()) &
+                             inst->VRegC_22s());
         break;
       case Instruction::OR_INT_LIT16:
-      case Instruction::OR_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) | dec_insn.vC);
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             shadow_frame.GetVReg(inst->VRegB_22s()) |
+                             inst->VRegC_22s());
         break;
       case Instruction::XOR_INT_LIT16:
+        shadow_frame.SetVReg(inst->VRegA_22s(),
+                             shadow_frame.GetVReg(inst->VRegB_22s()) ^
+                             inst->VRegC_22s());
+        break;
+      case Instruction::ADD_INT_LIT8:
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) +
+                             inst->VRegC_22b());
+        break;
+      case Instruction::RSUB_INT_LIT8:
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             inst->VRegC_22b() -
+                             shadow_frame.GetVReg(inst->VRegB_22b()));
+        break;
+      case Instruction::MUL_INT_LIT8:
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) *
+                             inst->VRegC_22b());
+        break;
+      case Instruction::DIV_INT_LIT8:
+        DoIntDivide(self, shadow_frame, inst->VRegA_22b(),
+                    shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
+        break;
+      case Instruction::REM_INT_LIT8:
+        DoIntRemainder(self, shadow_frame, inst->VRegA_22b(),
+                       shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
+        break;
+      case Instruction::AND_INT_LIT8:
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) &
+                             inst->VRegC_22b());
+        break;
+      case Instruction::OR_INT_LIT8:
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) |
+                             inst->VRegC_22b());
+        break;
       case Instruction::XOR_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) ^ dec_insn.vC);
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) ^
+                             inst->VRegC_22b());
         break;
       case Instruction::SHL_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) <<
-                             (dec_insn.vC & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) <<
+                             (inst->VRegC_22b() & 0x1f));
         break;
       case Instruction::SHR_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >>
-                             (dec_insn.vC & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             shadow_frame.GetVReg(inst->VRegB_22b()) >>
+                             (inst->VRegC_22b() & 0x1f));
         break;
       case Instruction::USHR_INT_LIT8:
-        shadow_frame.SetVReg(dec_insn.vA,
-                             static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
-                             (dec_insn.vC & 0x1f));
+        shadow_frame.SetVReg(inst->VRegA_22b(),
+                             static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
+                             (inst->VRegC_22b() & 0x1f));
         break;
       default:
         LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile());
@@ -1837,18 +2087,17 @@
       self->VerifyStack();
       ThrowLocation throw_location;
       mirror::Throwable* exception = self->GetException(&throw_location);
-      uint32_t found_dex_pc =
-          shadow_frame.GetMethod()->FindCatchBlock(exception->GetClass(), inst->GetDexPc(insns));
+      uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock(exception->GetClass(), dex_pc);
       if (found_dex_pc == DexFile::kDexNoIndex) {
         JValue result;
         result.SetJ(0);
-        instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
-                                           shadow_frame.GetMethod(), shadow_frame.GetDexPC());
+        instrumentation->MethodUnwindEvent(self, this_object_ref.get(),
+                                           shadow_frame.GetMethod(), dex_pc);
         return result;  // Handler in caller.
       } else {
-        Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self, throw_location,
-                                                                       shadow_frame.GetMethod(),
-                                                                       found_dex_pc, exception);
+        instrumentation->ExceptionCaughtEvent(self, throw_location,
+                                              shadow_frame.GetMethod(),
+                                              found_dex_pc, exception);
         next_inst = Instruction::At(insns + found_dex_pc);
       }
     }
@@ -1895,10 +2144,12 @@
     CHECK(receiver != NULL);
     shadow_frame->SetVRegReference(cur_reg, receiver);
     ++cur_reg;
-  } else if (!method->GetDeclaringClass()->IsInitializing()) {
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
-                                                                 true, true)) {
-      DCHECK(Thread::Current()->IsExceptionPending());
+  } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(),
+                                                  true, true))) {
+      CHECK(self->IsExceptionPending());
+      self->PopShadowFrame();
       return;
     }
     CHECK(method->GetDeclaringClass()->IsInitializing());
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index d9b369b..b096431 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -163,7 +163,7 @@
     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
     return NULL;  // Failure.
   } else {
-    if (resolved_field->IsStatic() != is_static) {
+    if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
       ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
       return NULL;
     }
diff --git a/src/stack.h b/src/stack.h
index 8e597b2..d6ff9c6 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -126,11 +126,13 @@
   }
 
   int64_t GetVRegLong(size_t i) const {
+    DCHECK_LT(i, NumberOfVRegs());
     const uint32_t* vreg = &vregs_[i];
     return *reinterpret_cast<const int64_t*>(vreg);
   }
 
   double GetVRegDouble(size_t i) const {
+    DCHECK_LT(i, NumberOfVRegs());
     const uint32_t* vreg = &vregs_[i];
     return *reinterpret_cast<const double*>(vreg);
   }
@@ -163,11 +165,13 @@
   }
 
   void SetVRegLong(size_t i, int64_t val) {
+    DCHECK_LT(i, NumberOfVRegs());
     uint32_t* vreg = &vregs_[i];
     *reinterpret_cast<int64_t*>(vreg) = val;
   }
 
   void SetVRegDouble(size_t i, double val) {
+    DCHECK_LT(i, NumberOfVRegs());
     uint32_t* vreg = &vregs_[i];
     *reinterpret_cast<double*>(vreg) = val;
   }