Revert "Use LIRSlowPath for throwing ArrayOutOfBoundsException."

This reverts commit 9d46314a309aff327f9913789b5f61200c162609.
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 6f4fa3a..8a88d61 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -323,6 +323,8 @@
 std::ostream& operator<<(std::ostream& os, const X86ConditionCode& kind);
 
 enum ThrowKind {
+  kThrowArrayBounds,
+  kThrowConstantArrayBounds,
   kThrowNoSuchMethod,
 };
 
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index d5b34a5..c876b3a 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -1167,9 +1167,9 @@
 
     if (needs_range_check) {
       if (constant_index) {
-        GenArrayBoundsCheck(mir_graph_->ConstantValue(rl_index), reg_len);
+        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
       } else {
-        GenArrayBoundsCheck(rl_index.reg, reg_len);
+        GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds);
       }
       FreeTemp(reg_len);
     }
@@ -1196,7 +1196,7 @@
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
     LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
@@ -1271,9 +1271,9 @@
     }
     if (needs_range_check) {
       if (constant_index) {
-        GenArrayBoundsCheck(mir_graph_->ConstantValue(rl_index), reg_len);
+        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
       } else {
-        GenArrayBoundsCheck(rl_index.reg, reg_len);
+        GenRegRegCheck(kCondLs, reg_len, rl_index.reg, kThrowArrayBounds);
       }
       FreeTemp(reg_len);
     }
@@ -1289,7 +1289,7 @@
     OpRegRegImm(kOpAdd, reg_ptr, rl_array.reg, data_offset);
     rl_src = LoadValue(rl_src, reg_class);
     if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
     StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size);
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index bb19516..1847921 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -91,62 +91,6 @@
   AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch));
 }
 
-void Mir2Lir::GenArrayBoundsCheck(RegStorage index, RegStorage length) {
-  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
-   public:
-    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, RegStorage index, RegStorage length)
-        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
-          index_(index), length_(length) {
-    }
-
-    void Compile() OVERRIDE {
-      m2l_->ResetRegPool();
-      m2l_->ResetDefTracking();
-      GenerateTargetLabel();
-      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                    index_, length_, true);
-    }
-
-   private:
-    RegStorage index_;
-    RegStorage length_;
-  };
-
-  LIR* branch = OpCmpBranch(kCondUge, index, length, nullptr);
-  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
-}
-
-void Mir2Lir::GenArrayBoundsCheck(int index, RegStorage length) {
-  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
-   public:
-    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, int index, RegStorage length)
-        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
-          index_(index), length_(length) {
-    }
-
-    void Compile() OVERRIDE {
-      m2l_->ResetRegPool();
-      m2l_->ResetDefTracking();
-      GenerateTargetLabel();
-      // kArg0 will be used to hold the constant index.
-      if (length_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) {
-        m2l_->OpRegCopy(m2l_->TargetReg(kArg1), length_);
-        length_ = m2l_->TargetReg(kArg1);
-      }
-      m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
-      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                    m2l_->TargetReg(kArg0), length_, true);
-    }
-
-   private:
-    int index_;
-    RegStorage length_;
-  };
-
-  LIR* branch = OpCmpImmBranch(kCondLs, length, index, nullptr);
-  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
-}
-
 LIR* Mir2Lir::GenNullCheck(RegStorage reg) {
   class NullCheckSlowPath : public Mir2Lir::LIRSlowPath {
    public:
@@ -741,7 +685,58 @@
     AppendLIR(lab);
     ThreadOffset<4> func_offset(-1);
     int v1 = lab->operands[2];
+    int v2 = lab->operands[3];
+    const bool target_x86 = cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64;
     switch (lab->operands[0]) {
+      case kThrowConstantArrayBounds:  // v1 is length reg (for Arm/Mips), v2 constant index
+        // v1 holds the constant array index.  Mips/Arm uses v2 for length, x86 reloads.
+        if (target_x86) {
+          OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v1),
+                   mirror::Array::LengthOffset().Int32Value());
+        } else {
+          OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v1));
+        }
+        // Make sure the following LoadConstant doesn't mess with kArg1.
+        LockTemp(TargetReg(kArg1));
+        LoadConstant(TargetReg(kArg0), v2);
+        func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds);
+        break;
+      case kThrowArrayBounds:
+        // Move v1 (array index) to kArg0 and v2 (array length) to kArg1
+        if (v2 != TargetReg(kArg0).GetReg()) {
+          OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
+          if (target_x86) {
+            // x86 leaves the array pointer in v2, so load the array length that the handler expects
+            OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                     mirror::Array::LengthOffset().Int32Value());
+          } else {
+            OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
+          }
+        } else {
+          if (v1 == TargetReg(kArg1).GetReg()) {
+            // Swap v1 and v2, using kArg2 as a temp
+            OpRegCopy(TargetReg(kArg2), RegStorage::Solo32(v1));
+            if (target_x86) {
+              // x86 leaves the array pointer in v2; load the array length that the handler expects
+              OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                       mirror::Array::LengthOffset().Int32Value());
+            } else {
+              OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
+            }
+            OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
+          } else {
+            if (target_x86) {
+              // x86 leaves the array pointer in v2; load the array length that the handler expects
+              OpRegMem(kOpMov, TargetReg(kArg1), RegStorage::Solo32(v2),
+                       mirror::Array::LengthOffset().Int32Value());
+            } else {
+              OpRegCopy(TargetReg(kArg1), RegStorage::Solo32(v2));
+            }
+            OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
+          }
+        }
+        func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds);
+        break;
       case kThrowNoSuchMethod:
         OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
         func_offset =
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 758096b..4aae16d 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -255,27 +255,12 @@
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
 
-void Mir2Lir::CopyToArgumentRegs(RegStorage arg0, RegStorage arg1) {
-  if (arg1.GetReg() == TargetReg(kArg0).GetReg()) {
-    if (arg0.GetReg() == TargetReg(kArg1).GetReg()) {
-      // Swap kArg0 and kArg1 with kArg2 as temp.
-      OpRegCopy(TargetReg(kArg2), arg1);
-      OpRegCopy(TargetReg(kArg0), arg0);
-      OpRegCopy(TargetReg(kArg1), TargetReg(kArg2));
-    } else {
-      OpRegCopy(TargetReg(kArg1), arg1);
-      OpRegCopy(TargetReg(kArg0), arg0);
-    }
-  } else {
-    OpRegCopy(TargetReg(kArg0), arg0);
-    OpRegCopy(TargetReg(kArg1), arg1);
-  }
-}
-
 void Mir2Lir::CallRuntimeHelperRegReg(ThreadOffset<4> helper_offset, RegStorage arg0,
                                       RegStorage arg1, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  CopyToArgumentRegs(arg0, arg1);
+  DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg());  // check copy into arg0 won't clobber arg1
+  OpRegCopy(TargetReg(kArg0), arg0);
+  OpRegCopy(TargetReg(kArg1), arg1);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
 }
@@ -283,7 +268,9 @@
 void Mir2Lir::CallRuntimeHelperRegRegImm(ThreadOffset<4> helper_offset, RegStorage arg0,
                                          RegStorage arg1, int arg2, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
-  CopyToArgumentRegs(arg0, arg1);
+  DCHECK_NE(TargetReg(kArg0).GetReg(), arg1.GetReg());  // check copy into arg0 won't clobber arg1
+  OpRegCopy(TargetReg(kArg0), arg0);
+  OpRegCopy(TargetReg(kArg1), arg1);
   LoadConstant(TargetReg(kArg2), arg2);
   ClobberCallerSave();
   CallHelper(r_tgt, helper_offset, safepoint_pc);
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 2375720..60358b4 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -513,7 +513,7 @@
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
     LoadBaseDispWide(reg_ptr, 0, rl_result.reg, INVALID_SREG);
@@ -524,7 +524,7 @@
     rl_result = EvalLoc(rl_dest, reg_class, true);
 
     if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
     LoadBaseIndexed(reg_ptr, rl_index.reg, rl_result.reg, scale, size);
@@ -590,7 +590,7 @@
     rl_src = LoadValueWide(rl_src, reg_class);
 
     if (needs_range_check) {
-      GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
 
@@ -598,7 +598,7 @@
   } else {
     rl_src = LoadValue(rl_src, reg_class);
     if (needs_range_check) {
-       GenArrayBoundsCheck(rl_index.reg, reg_len);
+      GenRegRegCheck(kCondUge, rl_index.reg, reg_len, kThrowArrayBounds);
       FreeTemp(reg_len);
     }
     StoreBaseIndexed(reg_ptr, rl_index.reg, rl_src.reg, scale, size);
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index a7a3635..65910e9 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -567,8 +567,6 @@
     void GenDivZeroCheck(ConditionCode c_code);
     // reg holds divisor.
     void GenDivZeroCheck(RegStorage reg);
-    void GenArrayBoundsCheck(RegStorage index, RegStorage length);
-    void GenArrayBoundsCheck(int index, RegStorage length);
     LIR* GenNullCheck(RegStorage reg);
     void MarkPossibleNullPointerException(int opt_flags);
     void MarkPossibleStackOverflowException();
@@ -1229,10 +1227,6 @@
 
     void AddDivZeroCheckSlowPath(LIR* branch);
 
-    // Copy arg0 and arg1 to kArg0 and kArg1 safely, possibly using
-    // kArg2 as temp.
-    void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1);
-
   public:
     // TODO: add accessors for these.
     LIR* literal_list_;                        // Constants.
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 7be7c23..0b9823d 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -136,8 +136,6 @@
     RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
     void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
     void GenDivZeroCheckWide(RegStorage reg);
-    void GenArrayBoundsCheck(RegStorage index, RegStorage array_base, int len_offset);
-    void GenArrayBoundsCheck(int index, RegStorage array_base, int len_offset);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index e45e7a8..4ffb9a4 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -891,78 +891,6 @@
   FreeTemp(t_reg);
 }
 
-void X86Mir2Lir::GenArrayBoundsCheck(RegStorage index,
-                                     RegStorage array_base,
-                                     int len_offset) {
-  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
-   public:
-    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch,
-                             RegStorage index, RegStorage array_base, int len_offset)
-        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
-          index_(index), array_base_(array_base), len_offset_(len_offset) {
-    }
-
-    void Compile() OVERRIDE {
-      m2l_->ResetRegPool();
-      m2l_->ResetDefTracking();
-      GenerateTargetLabel();
-      // Load array length to array_base_.
-      m2l_->OpRegMem(kOpMov, array_base_, array_base_, len_offset_);
-      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                    index_, array_base_, true);
-    }
-
-   private:
-    RegStorage index_;
-    RegStorage array_base_;
-    int len_offset_;
-  };
-
-  OpRegMem(kOpCmp, index, array_base, len_offset);
-  LIR* branch = OpCondBranch(kCondUge, nullptr);
-  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch,
-                                                    index, array_base, len_offset));
-}
-
-void X86Mir2Lir::GenArrayBoundsCheck(int index,
-                                     RegStorage array_base,
-                                     int len_offset) {
-  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
-   public:
-    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch,
-                             int index, RegStorage array_base, int len_offset)
-        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
-          index_(index), array_base_(array_base), len_offset_(len_offset) {
-    }
-
-    void Compile() OVERRIDE {
-      m2l_->ResetRegPool();
-      m2l_->ResetDefTracking();
-      GenerateTargetLabel();
-      // kArg0 will be used to hold the constant index.
-      if (array_base_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) {
-        m2l_->OpRegCopy(m2l_->TargetReg(kArg1), array_base_);
-        array_base_ = m2l_->TargetReg(kArg1);
-      }
-      m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
-      // Load array length to kArg1.
-      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
-      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
-                                    m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
-    }
-
-   private:
-    int index_;
-    RegStorage array_base_;
-    int len_offset_;
-  };
-
-  NewLIR3(IS_SIMM8(index) ? kX86Cmp32MI8 : kX86Cmp32MI, array_base.GetReg(), len_offset, index);
-  LIR* branch = OpCondBranch(kCondLs, nullptr);
-  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch,
-                                                    index, array_base, len_offset));
-}
-
 // Test suspend flag, return target of taken suspend branch
 LIR* X86Mir2Lir::OpTestSuspend(LIR* target) {
   OpTlsCmp(Thread::ThreadFlagsOffset<4>(), 0);
@@ -1420,9 +1348,10 @@
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset);
+      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
+                       constant_index_value, kThrowConstantArrayBounds);
     } else {
-      GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset);
+      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
     }
   }
   rl_result = EvalLoc(rl_dest, reg_class, true);
@@ -1471,9 +1400,10 @@
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset);
+      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
+                       constant_index_value, kThrowConstantArrayBounds);
     } else {
-      GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset);
+      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
     }
   }
   if ((size == kLong) || (size == kDouble)) {