Use LIRSlowPath for throwing ArrayOutOfBoundsException.

Get rid of launchpads for throwing ArrayOutOfBoundsException
and use LIRSlowPath instead.

Bug: 13170824
Change-Id: I0e27f7a261a6a7fb5c0645e6113a957e098f699e
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 4ffb9a4..e45e7a8 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -891,6 +891,78 @@
   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);
@@ -1348,10 +1420,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 +1471,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)) {