Revert "Revert "Use LIRSlowPath for throwing ArrayOutOfBoundsException.""

This adds back using LIRSlowPath for ArrayIndexOutOfBoundsException.
And fix the host test crash.

Change-Id: Idbb602f4bb2c5ce59233feb480a0ff1b216e4887
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 4ffb9a4..84325b4 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -891,6 +891,86 @@
   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, int32_t 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();
+
+      RegStorage new_index = index_;
+      // Move index out of kArg1, either directly to kArg0, or to kArg2.
+      if (index_.GetReg() == m2l_->TargetReg(kArg1).GetReg()) {
+        if (array_base_.GetReg() == m2l_->TargetReg(kArg0).GetReg()) {
+          m2l_->OpRegCopy(m2l_->TargetReg(kArg2), index_);
+          new_index = m2l_->TargetReg(kArg2);
+        } else {
+          m2l_->OpRegCopy(m2l_->TargetReg(kArg0), index_);
+          new_index = m2l_->TargetReg(kArg0);
+        }
+      }
+      // Load array length to kArg1.
+      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
+      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
+                                    new_index, m2l_->TargetReg(kArg1), true);
+    }
+
+   private:
+    const RegStorage index_;
+    const RegStorage array_base_;
+    const int32_t 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(int32_t index,
+                                     RegStorage array_base,
+                                     int32_t len_offset) {
+  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
+   public:
+    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch,
+                             int32_t index, RegStorage array_base, int32_t 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 kArg1.
+      m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
+      m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
+      m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
+                                    m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+    }
+
+   private:
+    const int32_t index_;
+    const RegStorage array_base_;
+    const int32_t 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);
@@ -1348,10 +1428,9 @@
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
-                       constant_index_value, kThrowConstantArrayBounds);
+      GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset);
     } else {
-      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
+      GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset);
     }
   }
   rl_result = EvalLoc(rl_dest, reg_class, true);
@@ -1400,10 +1479,9 @@
 
   if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
     if (constant_index) {
-      GenMemImmedCheck(kCondLs, rl_array.reg, len_offset,
-                       constant_index_value, kThrowConstantArrayBounds);
+      GenArrayBoundsCheck(constant_index_value, rl_array.reg, len_offset);
     } else {
-      GenRegMemCheck(kCondUge, rl_index.reg, rl_array.reg, len_offset, kThrowArrayBounds);
+      GenArrayBoundsCheck(rl_index.reg, rl_array.reg, len_offset);
     }
   }
   if ((size == kLong) || (size == kDouble)) {