Optimize branch instructions in interpreter.

This CL cleans up branch instructions handling by optimizing instruction
displacement with an offset by changing the way we compute the next
instruction. On ARM, it saves at least 3 instructions for GOTO and 4
instructions for IF-XX/Z.

This CL also transforms the Instruction::At CHECK into a DCHECK. This improves
the compiled code when computing next instruction.

Change-Id: I901699201012d2dbbaef4d9158cc97b63bfbbe84
diff --git a/src/dex_instruction-inl.h b/src/dex_instruction-inl.h
index 519b3cf..b426e66 100644
--- a/src/dex_instruction-inl.h
+++ b/src/dex_instruction-inl.h
@@ -21,13 +21,6 @@
 
 namespace art {
 
-inline const Instruction* Instruction::Next_51l() const {
-  DCHECK_EQ(FormatOf(Opcode()), k51l);
-  size_t current_size_in_bytes = 5 * sizeof(uint16_t);
-  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
-  return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
-}
-
 //------------------------------------------------------------------------------
 // VRegA
 //------------------------------------------------------------------------------
diff --git a/src/dex_instruction.h b/src/dex_instruction.h
index ae469d0..adaada7 100644
--- a/src/dex_instruction.h
+++ b/src/dex_instruction.h
@@ -162,39 +162,45 @@
     }
   }
 
+  // Reads an instruction out of the stream at the specified address.
+  static const Instruction* At(const uint16_t* code) {
+    DCHECK(code != NULL);
+    return reinterpret_cast<const Instruction*>(code);
+  }
+
+  // Reads an instruction out of the stream from the current address plus an offset.
+  const Instruction* RelativeAt(int32_t offset) const {
+    return At(reinterpret_cast<const uint16_t*>(this) + offset);
+  }
+
   // Returns a pointer to the next instruction in the stream.
   const Instruction* Next() const {
-    size_t current_size_in_bytes = SizeInCodeUnits() * sizeof(uint16_t);
-    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
-    return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
+    return RelativeAt(SizeInCodeUnits());
   }
 
   // Returns a pointer to the instruction after this 1xx instruction in the stream.
   const Instruction* Next_1xx() const {
     DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
-    size_t current_size_in_bytes = 1 * sizeof(uint16_t);
-    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
-    return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
+    return RelativeAt(1);
   }
 
   // Returns a pointer to the instruction after this 2xx instruction in the stream.
   const Instruction* Next_2xx() const {
     DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
-    size_t current_size_in_bytes = 2 * sizeof(uint16_t);
-    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
-    return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
+    return RelativeAt(2);
   }
 
   // Returns a pointer to the instruction after this 3xx instruction in the stream.
   const Instruction* Next_3xx() const {
     DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
-    size_t current_size_in_bytes = 3 * sizeof(uint16_t);
-    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
-    return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
+    return RelativeAt(3);
   }
 
   // Returns a pointer to the instruction after this 51l instruction in the stream.
-  const Instruction* Next_51l() const;
+  const Instruction* Next_51l() const {
+    DCHECK(FormatOf(Opcode()) == k51l);
+    return RelativeAt(5);
+  }
 
   // Returns the name of this instruction's opcode.
   const char* Name() const {
@@ -272,12 +278,6 @@
     return static_cast<Code>(opcode);
   }
 
-  // Reads an instruction out of the stream at the specified address.
-  static const Instruction* At(const uint16_t* code) {
-    CHECK(code != NULL);
-    return reinterpret_cast<const Instruction*>(code);
-  }
-
   // Returns the format of the given opcode.
   static Format FormatOf(Code opcode) {
     return kInstructionFormats[opcode];
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 2e87dfd..705e265 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -1202,22 +1202,22 @@
       }
       case Instruction::GOTO: {
         PREAMBLE();
-        inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_10t());
+        inst = inst->RelativeAt(inst->VRegA_10t());
         break;
       }
       case Instruction::GOTO_16: {
         PREAMBLE();
-        inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_20t());
+        inst = inst->RelativeAt(inst->VRegA_20t());
         break;
       }
       case Instruction::GOTO_32: {
         PREAMBLE();
-        inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_30t());
+        inst = inst->RelativeAt(inst->VRegA_30t());
         break;
       }
       case Instruction::PACKED_SWITCH: {
         PREAMBLE();
-        const uint16_t* switch_data = insns + inst->GetDexPc(insns) + inst->VRegB_31t();
+        const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
         int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
         DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
         uint16_t size = switch_data[1];
@@ -1229,7 +1229,7 @@
         DCHECK(IsAligned<4>(targets));
         int32_t index = test_val - first_key;
         if (index >= 0 && index < size) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + targets[index]);
+          inst = inst->RelativeAt(targets[index]);
         } else {
           inst = inst->Next_3xx();
         }
@@ -1237,8 +1237,7 @@
       }
       case Instruction::SPARSE_SWITCH: {
         PREAMBLE();
-        uint32_t dex_pc = inst->GetDexPc(insns);
-        const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
+        const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + 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];
@@ -1249,6 +1248,7 @@
         CHECK(IsAligned<4>(entries));
         int lo = 0;
         int hi = size - 1;
+        const Instruction* current_inst = inst;
         inst = inst->Next_3xx();
         while (lo <= hi) {
           int mid = (lo + hi) / 2;
@@ -1258,7 +1258,7 @@
           } else if (test_val > foundVal) {
             lo = mid + 1;
           } else {
-            inst = Instruction::At(insns + dex_pc + entries[mid]);
+            inst = current_inst->RelativeAt(entries[mid]);
             break;
           }
         }
@@ -1348,7 +1348,7 @@
       case Instruction::IF_EQ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) == shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1357,7 +1357,7 @@
       case Instruction::IF_NE: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) != shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1366,7 +1366,7 @@
       case Instruction::IF_LT: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) < shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1375,7 +1375,7 @@
       case Instruction::IF_GE: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) >= shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1384,7 +1384,7 @@
       case Instruction::IF_GT: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) > shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1393,7 +1393,7 @@
       case Instruction::IF_LE: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_22t()) <= shadow_frame.GetVReg(inst->VRegB_22t())) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+          inst = inst->RelativeAt(inst->VRegC_22t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1402,7 +1402,7 @@
       case Instruction::IF_EQZ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) == 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1411,7 +1411,7 @@
       case Instruction::IF_NEZ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) != 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1420,7 +1420,7 @@
       case Instruction::IF_LTZ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) < 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1429,7 +1429,7 @@
       case Instruction::IF_GEZ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) >= 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1438,7 +1438,7 @@
       case Instruction::IF_GTZ: {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) > 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -1447,7 +1447,7 @@
       case Instruction::IF_LEZ:  {
         PREAMBLE();
         if (shadow_frame.GetVReg(inst->VRegA_21t()) <= 0) {
-          inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+          inst = inst->RelativeAt(inst->VRegB_21t());
         } else {
           inst = inst->Next_2xx();
         }
@@ -2305,6 +2305,14 @@
         inst = inst->Next_1xx();
         break;
       }
+      case Instruction::DIV_INT_2ADDR: {
+        PREAMBLE();
+        uint32_t vregA = inst->VRegA_12x();
+        DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
+                    shadow_frame.GetVReg(inst->VRegB_12x()));
+        inst = inst->Next_1xx();
+        break;
+      }
       case Instruction::REM_INT_2ADDR: {
         PREAMBLE();
         uint32_t vregA = inst->VRegA_12x();
@@ -2367,14 +2375,6 @@
         inst = inst->Next_1xx();
         break;
       }
-      case Instruction::DIV_INT_2ADDR: {
-        PREAMBLE();
-        uint32_t vregA = inst->VRegA_12x();
-        DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
-                    shadow_frame.GetVReg(inst->VRegB_12x()));
-        inst = inst->Next_1xx();
-        break;
-      }
       case Instruction::ADD_LONG_2ADDR: {
         PREAMBLE();
         uint32_t vregA = inst->VRegA_12x();