Optimize instruction data fetch in interpreter.

The computed goto implementation prevents the compiler from detecting we are
loading the first 16 bits of instruction twice: first one to get the opcode and
second one to fetch first instruction's operand(s) like vA and vB.

We now load the 16 bits into a local variable and decode opcode and operands
from this variable. And do the same in the switch-based implementation for
consistency.

The performance improvement is 5% in average on benchmark applications suite.

Also remove unused "Thread* self" parameter from DoIGetQuick and DoIPutQuick.

Bug: 10703860
Change-Id: I83026ed6e78f642ac3dcdc6edbb6056fe012005f
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index 13b0f1c..e8db3bc 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -217,44 +217,122 @@
   // VRegA
   bool HasVRegA() const;
   int32_t VRegA() const;
-  int8_t VRegA_10t() const;
-  uint8_t VRegA_10x() const;
-  uint4_t VRegA_11n() const;
-  uint8_t VRegA_11x() const;
-  uint4_t VRegA_12x() const;
+
+  int8_t VRegA_10t() const {
+    return VRegA_10t(Fetch16(0));
+  }
+  uint8_t VRegA_10x() const {
+    return VRegA_10x(Fetch16(0));
+  }
+  uint4_t VRegA_11n() const {
+    return VRegA_11n(Fetch16(0));
+  }
+  uint8_t VRegA_11x() const {
+    return VRegA_11x(Fetch16(0));
+  }
+  uint4_t VRegA_12x() const {
+    return VRegA_12x(Fetch16(0));
+  }
   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;
+  uint8_t VRegA_21c() const {
+    return VRegA_21c(Fetch16(0));
+  }
+  uint8_t VRegA_21h() const {
+    return VRegA_21h(Fetch16(0));
+  }
+  uint8_t VRegA_21s() const {
+    return VRegA_21s(Fetch16(0));
+  }
+  uint8_t VRegA_21t() const {
+    return VRegA_21t(Fetch16(0));
+  }
+  uint8_t VRegA_22b() const {
+    return VRegA_22b(Fetch16(0));
+  }
+  uint4_t VRegA_22c() const {
+    return VRegA_22c(Fetch16(0));
+  }
+  uint4_t VRegA_22s() const {
+    return VRegA_22s(Fetch16(0));
+  }
+  uint4_t VRegA_22t() const {
+    return VRegA_22t(Fetch16(0));
+  }
+  uint8_t VRegA_22x() const {
+    return VRegA_22x(Fetch16(0));
+  }
+  uint8_t VRegA_23x() const {
+    return VRegA_23x(Fetch16(0));
+  }
   int32_t VRegA_30t() const;
-  uint8_t VRegA_31c() const;
-  uint8_t VRegA_31i() const;
-  uint8_t VRegA_31t() const;
+  uint8_t VRegA_31c() const {
+    return VRegA_31c(Fetch16(0));
+  }
+  uint8_t VRegA_31i() const {
+    return VRegA_31i(Fetch16(0));
+  }
+  uint8_t VRegA_31t() const {
+    return VRegA_31t(Fetch16(0));
+  }
   uint16_t VRegA_32x() const;
-  uint4_t VRegA_35c() const;
-  uint8_t VRegA_3rc() const;
-  uint8_t VRegA_51l() const;
+  uint4_t VRegA_35c() const {
+    return VRegA_35c(Fetch16(0));
+  }
+  uint8_t VRegA_3rc() const {
+    return VRegA_3rc(Fetch16(0));
+  }
+  uint8_t VRegA_51l() const {
+    return VRegA_51l(Fetch16(0));
+  }
+
+  // The following methods return the vA operand for various instruction formats. The "inst_data"
+  // parameter holds the first 16 bits of instruction which the returned value is decoded from.
+  int8_t VRegA_10t(uint16_t inst_data) const;
+  uint8_t VRegA_10x(uint16_t inst_data) const;
+  uint4_t VRegA_11n(uint16_t inst_data) const;
+  uint8_t VRegA_11x(uint16_t inst_data) const;
+  uint4_t VRegA_12x(uint16_t inst_data) const;
+  uint8_t VRegA_21c(uint16_t inst_data) const;
+  uint8_t VRegA_21h(uint16_t inst_data) const;
+  uint8_t VRegA_21s(uint16_t inst_data) const;
+  uint8_t VRegA_21t(uint16_t inst_data) const;
+  uint8_t VRegA_22b(uint16_t inst_data) const;
+  uint4_t VRegA_22c(uint16_t inst_data) const;
+  uint4_t VRegA_22s(uint16_t inst_data) const;
+  uint4_t VRegA_22t(uint16_t inst_data) const;
+  uint8_t VRegA_22x(uint16_t inst_data) const;
+  uint8_t VRegA_23x(uint16_t inst_data) const;
+  uint8_t VRegA_31c(uint16_t inst_data) const;
+  uint8_t VRegA_31i(uint16_t inst_data) const;
+  uint8_t VRegA_31t(uint16_t inst_data) const;
+  uint4_t VRegA_35c(uint16_t inst_data) const;
+  uint8_t VRegA_3rc(uint16_t inst_data) const;
+  uint8_t VRegA_51l(uint16_t inst_data) const;
 
   // VRegB
   bool HasVRegB() const;
   int32_t VRegB() const;
-  int4_t VRegB_11n() const;
-  uint4_t VRegB_12x() const;
+
+  int4_t VRegB_11n() const {
+    return VRegB_11n(Fetch16(0));
+  }
+  uint4_t VRegB_12x() const {
+    return VRegB_12x(Fetch16(0));
+  }
   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;
+  uint4_t VRegB_22c() const {
+    return VRegB_22c(Fetch16(0));
+  }
+  uint4_t VRegB_22s() const {
+    return VRegB_22s(Fetch16(0));
+  }
+  uint4_t VRegB_22t() const {
+    return VRegB_22t(Fetch16(0));
+  }
   uint16_t VRegB_22x() const;
   uint8_t VRegB_23x() const;
   uint32_t VRegB_31c() const;
@@ -265,9 +343,19 @@
   uint16_t VRegB_3rc() const;
   uint64_t VRegB_51l() const;  // vB_wide
 
+  // The following methods return the vB operand for all instruction formats where it is encoded in
+  // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
+  // value is decoded from it.
+  int4_t VRegB_11n(uint16_t inst_data) const;
+  uint4_t VRegB_12x(uint16_t inst_data) const;
+  uint4_t VRegB_22c(uint16_t inst_data) const;
+  uint4_t VRegB_22s(uint16_t inst_data) const;
+  uint4_t VRegB_22t(uint16_t inst_data) const;
+
   // VRegC
   bool HasVRegC() const;
   int32_t VRegC() const;
+
   int8_t VRegC_22b() const;
   uint16_t VRegC_22c() const;
   int16_t VRegC_22s() const;
@@ -279,9 +367,16 @@
   // 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.
+  // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
+  // 16 bits of instruction.
+  Code Opcode(uint16_t inst_data) const {
+    DCHECK_EQ(inst_data, Fetch16(0));
+    return static_cast<Code>(inst_data & 0xFF);
+  }
+
+  // Returns the opcode field of the instruction from the first 16 bits of instruction.
   Code Opcode() const {
-    return static_cast<Code>(Fetch16(0) & 0xFF);
+    return Opcode(Fetch16(0));
   }
 
   void SetOpcode(Code opcode) {
@@ -395,28 +490,43 @@
   // Dump code_units worth of this instruction, padding to code_units for shorter instructions
   std::string DumpHex(size_t code_units) const;
 
- 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];
   }
 
+ private:
+  size_t SizeInCodeUnitsComplexOpcode() const;
+
   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);
+    return InstA(Fetch16(0));
   }
 
   uint4_t InstB() const {
-    return static_cast<uint4_t>(Fetch16(0) >> 12);
+    return InstB(Fetch16(0));
   }
 
   uint8_t InstAA() const {
-    return static_cast<uint8_t>(Fetch16(0) >> 8);
+    return InstAA(Fetch16(0));
+  }
+
+  uint4_t InstA(uint16_t inst_data) const {
+    DCHECK_EQ(inst_data, Fetch16(0));
+    return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
+  }
+
+  uint4_t InstB(uint16_t inst_data) const {
+    DCHECK_EQ(inst_data, Fetch16(0));
+    return static_cast<uint4_t>(inst_data >> 12);
+  }
+
+  uint8_t InstAA(uint16_t inst_data) const {
+    DCHECK_EQ(inst_data, Fetch16(0));
+    return static_cast<uint8_t>(inst_data >> 8);
   }
 
   static const char* const kInstructionNames[];