Use LIRSlowPath for throwing div by zero exception.

Get rid of launchpads for throwing div by zero exception and
use LIRSlowPath instead. Add a CallRuntimeHelper that takes no
argument for the runtime function.

Bug: 13170824
Change-Id: I7e0563e736c6f92bd63e3fbdfe3a777ad333e338
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 6c8c85d..38d37b0 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -324,7 +324,6 @@
 
 enum ThrowKind {
   kThrowNullPointer,
-  kThrowDivZero,
   kThrowArrayBounds,
   kThrowConstantArrayBounds,
   kThrowNoSuchMethod,
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 1abb91d..c80297b 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -917,7 +917,7 @@
   RegStorage t_reg = AllocTemp();
   NewLIR4(kThumb2OrrRRRs, t_reg.GetReg(), reg.GetLowReg(), reg.GetHighReg(), 0);
   FreeTemp(t_reg);
-  GenCheck(kCondEq, kThrowDivZero);
+  AddDivZeroSlowPath(kCondEq);
 }
 
 // Test suspend flag, return target of taken suspend branch
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index a3fb420..4522379 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -42,17 +42,6 @@
   barrier->u.m.def_mask = ENCODE_ALL;
 }
 
-// TODO: need to do some work to split out targets with
-// condition codes and those without
-LIR* Mir2Lir::GenCheck(ConditionCode c_code, ThrowKind kind) {
-  DCHECK_NE(cu_->instruction_set, kMips);
-  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_);
-  LIR* branch = OpCondBranch(c_code, tgt);
-  // Remember branch target - will process later
-  throw_launchpads_.Insert(tgt);
-  return branch;
-}
-
 LIR* Mir2Lir::GenImmedCheck(ConditionCode c_code, RegStorage reg, int imm_val, ThrowKind kind) {
   LIR* tgt;
   LIR* branch;
@@ -69,6 +58,38 @@
   return branch;
 }
 
+void Mir2Lir::AddDivZeroSlowPath(ConditionCode c_code) {
+  LIR* branch = OpCondBranch(c_code, nullptr);
+  AddDivZeroCheckSlowPath(branch);
+}
+
+void Mir2Lir::AddDivZeroSlowPath(ConditionCode c_code, RegStorage reg, int imm_val) {
+  LIR* branch;
+  if (c_code == kCondAl) {
+    branch = OpUnconditionalBranch(nullptr);
+  } else {
+    branch = OpCmpImmBranch(c_code, reg, imm_val, nullptr);
+  }
+  AddDivZeroCheckSlowPath(branch);
+}
+
+void Mir2Lir::AddDivZeroCheckSlowPath(LIR* branch) {
+  class DivZeroCheckSlowPath : public Mir2Lir::LIRSlowPath {
+   public:
+    DivZeroCheckSlowPath(Mir2Lir* m2l, LIR* branch)
+        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch) {
+    }
+
+    void Compile() {
+      m2l_->ResetRegPool();
+      m2l_->ResetDefTracking();
+      GenerateTargetLabel();
+      m2l_->CallRuntimeHelper(QUICK_ENTRYPOINT_OFFSET(4, pThrowDivZero), true);
+    }
+  };
+
+  AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch));
+}
 
 /* Perform null-check on a register.  */
 LIR* Mir2Lir::GenNullCheck(RegStorage m_reg, int opt_flags) {
@@ -689,9 +710,6 @@
         }
         func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds);
         break;
-      case kThrowDivZero:
-        func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowDivZero);
-        break;
       case kThrowNoSuchMethod:
         OpRegCopy(TargetReg(kArg0), RegStorage::Solo32(v1));
         func_offset =
@@ -1533,7 +1551,7 @@
       rl_src1 = LoadValue(rl_src1, kCoreReg);
       rl_src2 = LoadValue(rl_src2, kCoreReg);
       if (check_zero) {
-          GenImmedCheck(kCondEq, rl_src2.reg, 0, kThrowDivZero);
+          AddDivZeroSlowPath(kCondEq, rl_src2.reg, 0);
       }
       rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
       done = true;
@@ -1544,7 +1562,7 @@
         rl_src1 = LoadValue(rl_src1, kCoreReg);
         rl_src2 = LoadValue(rl_src2, kCoreReg);
         if (check_zero) {
-            GenImmedCheck(kCondEq, rl_src2.reg, 0, kThrowDivZero);
+            AddDivZeroSlowPath(kCondEq, rl_src2.reg, 0);
         }
         rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
         done = true;
@@ -1559,7 +1577,7 @@
       RegStorage r_tgt = CallHelperSetup(func_offset);
       LoadValueDirectFixed(rl_src1, TargetReg(kArg0));
       if (check_zero) {
-        GenImmedCheck(kCondEq, TargetReg(kArg1), 0, kThrowDivZero);
+        AddDivZeroSlowPath(kCondEq, TargetReg(kArg1), 0);
       }
       // NOTE: callout here is not a safepoint.
       CallHelper(r_tgt, func_offset, false /* not a safepoint */);
@@ -1784,7 +1802,7 @@
     case Instruction::REM_INT_LIT8:
     case Instruction::REM_INT_LIT16: {
       if (lit == 0) {
-        GenImmedCheck(kCondAl, RegStorage::InvalidReg(), 0, kThrowDivZero);
+        AddDivZeroSlowPath(kCondAl, RegStorage::InvalidReg(), 0);
         return;
       }
       if ((opcode == Instruction::DIV_INT) ||
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 396a709..d827568 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -87,6 +87,12 @@
   return call_inst;
 }
 
+void Mir2Lir::CallRuntimeHelper(ThreadOffset<4> helper_offset, bool safepoint_pc) {
+  RegStorage r_tgt = CallHelperSetup(helper_offset);
+  ClobberCallerSave();
+  CallHelper(r_tgt, helper_offset, safepoint_pc);
+}
+
 void Mir2Lir::CallRuntimeHelperImm(ThreadOffset<4> helper_offset, int arg0, bool safepoint_pc) {
   RegStorage r_tgt = CallHelperSetup(helper_offset);
   LoadConstant(TargetReg(kArg0), arg0);
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 5fe96d2..0492fdb 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -346,7 +346,7 @@
   DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
   RegStorage t_reg = AllocTemp();
   OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
-  GenImmedCheck(kCondEq, t_reg, 0, kThrowDivZero);
+  AddDivZeroSlowPath(kCondEq, t_reg, 0);
   FreeTemp(t_reg);
 }
 
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 35f948e..6dbeb34 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -562,7 +562,8 @@
     void HandleThrowLaunchPads();
     void HandleSlowPaths();
     void GenBarrier();
-    LIR* GenCheck(ConditionCode c_code, ThrowKind kind);
+    void AddDivZeroSlowPath(ConditionCode c_code);
+    void AddDivZeroSlowPath(ConditionCode c_code, RegStorage reg, int imm_val);
     void MarkPossibleNullPointerException(int opt_flags);
     void MarkPossibleStackOverflowException();
     void ForceImplicitNullCheck(RegStorage reg, int opt_flags);
@@ -619,6 +620,7 @@
     LIR* CallHelper(RegStorage r_tgt, ThreadOffset<4> helper_offset, bool safepoint_pc,
                     bool use_link = true);
     RegStorage CallHelperSetup(ThreadOffset<4> helper_offset);
+    void CallRuntimeHelper(ThreadOffset<4> helper_offset, bool safepoint_pc);
     void CallRuntimeHelperImm(ThreadOffset<4> helper_offset, int arg0, bool safepoint_pc);
     void CallRuntimeHelperReg(ThreadOffset<4> helper_offset, RegStorage arg0, bool safepoint_pc);
     void CallRuntimeHelperRegLocation(ThreadOffset<4> helper_offset, RegLocation arg0,
@@ -1220,6 +1222,7 @@
      */
     bool GenSpecialIdentity(MIR* mir, const InlineMethod& special);
 
+    void AddDivZeroCheckSlowPath(LIR* branch);
 
   public:
     // TODO: add accessors for these.
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index c1d1e01..a5f3b61 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -629,7 +629,7 @@
 
   if (check_zero) {
     // Handle division by zero case.
-    GenImmedCheck(kCondEq, rs_r1, 0, kThrowDivZero);
+    AddDivZeroSlowPath(kCondEq, rs_r1, 0);
   }
 
   // Have to catch 0x80000000/-1 case, or we will get an exception!
@@ -885,7 +885,7 @@
   OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
 
   // In case of zero, throw ArithmeticException.
-  GenCheck(kCondEq, kThrowDivZero);
+  AddDivZeroSlowPath(kCondEq);
 
   // The temp is no longer needed so free it at this time.
   FreeTemp(t_reg);