Use LIRSlowPath for throwing NPE.

Get rid of launchpads for throwing NPE and use LIRSlowPath instead.
Also clean up some code of using LIRSlowPath for checking div
by zero.

Bug: 13170824

Change-Id: I0c20a49c39feff3eb1f147755e557d9bc0ff15bb
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 38d37b0..8a88d61 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -323,7 +323,6 @@
 std::ostream& operator<<(std::ostream& os, const X86ConditionCode& kind);
 
 enum ThrowKind {
-  kThrowNullPointer,
   kThrowArrayBounds,
   kThrowConstantArrayBounds,
   kThrowNoSuchMethod,
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 13fa635..b0bc11d 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -131,7 +131,7 @@
     RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
     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 GenDivZeroCheck(RegStorage reg);
+    void GenDivZeroCheckWide(RegStorage reg);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 8b4171d..c876b3a 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -911,12 +911,12 @@
   }
 }
 
-void ArmMir2Lir::GenDivZeroCheck(RegStorage reg) {
+void ArmMir2Lir::GenDivZeroCheckWide(RegStorage reg) {
   DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
   RegStorage t_reg = AllocTemp();
   NewLIR4(kThumb2OrrRRRs, t_reg.GetReg(), reg.GetLowReg(), reg.GetHighReg(), 0);
   FreeTemp(t_reg);
-  AddDivZeroSlowPath(kCondEq);
+  GenDivZeroCheck(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 4522379..0d938d9 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -58,18 +58,18 @@
   return branch;
 }
 
-void Mir2Lir::AddDivZeroSlowPath(ConditionCode c_code) {
+void Mir2Lir::GenDivZeroException() {
+  LIR* branch = OpUnconditionalBranch(nullptr);
+  AddDivZeroCheckSlowPath(branch);
+}
+
+void Mir2Lir::GenDivZeroCheck(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);
-  }
+void Mir2Lir::GenDivZeroCheck(RegStorage reg) {
+  LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
   AddDivZeroCheckSlowPath(branch);
 }
 
@@ -80,7 +80,7 @@
         : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch) {
     }
 
-    void Compile() {
+    void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
       GenerateTargetLabel();
@@ -91,6 +91,26 @@
   AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch));
 }
 
+LIR* Mir2Lir::GenNullCheck(RegStorage reg) {
+  class NullCheckSlowPath : public Mir2Lir::LIRSlowPath {
+   public:
+    NullCheckSlowPath(Mir2Lir* m2l, LIR* branch)
+        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch) {
+    }
+
+    void Compile() OVERRIDE {
+      m2l_->ResetRegPool();
+      m2l_->ResetDefTracking();
+      GenerateTargetLabel();
+      m2l_->CallRuntimeHelper(QUICK_ENTRYPOINT_OFFSET(4, pThrowNullPointer), true);
+    }
+  };
+
+  LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
+  AddSlowPath(new (arena_) NullCheckSlowPath(this, branch));
+  return branch;
+}
+
 /* Perform null-check on a register.  */
 LIR* Mir2Lir::GenNullCheck(RegStorage m_reg, int opt_flags) {
   if (Runtime::Current()->ExplicitNullChecks()) {
@@ -104,7 +124,7 @@
   if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
     return NULL;
   }
-  return GenImmedCheck(kCondEq, m_reg, 0, kThrowNullPointer);
+  return GenNullCheck(m_reg);
 }
 
 void Mir2Lir::MarkPossibleNullPointerException(int opt_flags) {
@@ -658,9 +678,6 @@
     int v2 = lab->operands[3];
     const bool target_x86 = cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64;
     switch (lab->operands[0]) {
-      case kThrowNullPointer:
-        func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowNullPointer);
-        break;
       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) {
@@ -1551,7 +1568,7 @@
       rl_src1 = LoadValue(rl_src1, kCoreReg);
       rl_src2 = LoadValue(rl_src2, kCoreReg);
       if (check_zero) {
-          AddDivZeroSlowPath(kCondEq, rl_src2.reg, 0);
+          GenDivZeroCheck(rl_src2.reg);
       }
       rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
       done = true;
@@ -1562,7 +1579,7 @@
         rl_src1 = LoadValue(rl_src1, kCoreReg);
         rl_src2 = LoadValue(rl_src2, kCoreReg);
         if (check_zero) {
-            AddDivZeroSlowPath(kCondEq, rl_src2.reg, 0);
+            GenDivZeroCheck(rl_src2.reg);
         }
         rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
         done = true;
@@ -1577,7 +1594,7 @@
       RegStorage r_tgt = CallHelperSetup(func_offset);
       LoadValueDirectFixed(rl_src1, TargetReg(kArg0));
       if (check_zero) {
-        AddDivZeroSlowPath(kCondEq, TargetReg(kArg1), 0);
+        GenDivZeroCheck(TargetReg(kArg1));
       }
       // NOTE: callout here is not a safepoint.
       CallHelper(r_tgt, func_offset, false /* not a safepoint */);
@@ -1802,7 +1819,7 @@
     case Instruction::REM_INT_LIT8:
     case Instruction::REM_INT_LIT16: {
       if (lit == 0) {
-        AddDivZeroSlowPath(kCondAl, RegStorage::InvalidReg(), 0);
+        GenDivZeroException();
         return;
       }
       if ((opcode == Instruction::DIV_INT) ||
@@ -1976,7 +1993,7 @@
       RegStorage r_tmp2 = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
       LoadValueDirectWideFixed(rl_src2, r_tmp2);
       RegStorage r_tgt = CallHelperSetup(func_offset);
-      GenDivZeroCheck(RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3)));
+      GenDivZeroCheckWide(RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3)));
       LoadValueDirectWideFixed(rl_src1, r_tmp1);
       // NOTE: callout here is not a safepoint
       CallHelper(r_tgt, func_offset, false /* not safepoint */);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index d827568..4aae16d 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1496,7 +1496,7 @@
         ((cu_->disable_opt & (1 << kNullCheckElimination)) != 0 ||
          (info->opt_flags & MIR_IGNORE_NULL_CHECK) == 0))  {
       RegLocation rl_obj = LoadValue(info->args[0], kCoreReg);
-      GenImmedCheck(kCondEq, rl_obj.reg, 0, kThrowNullPointer);
+      GenNullCheck(rl_obj.reg);
     }
     return;
   }
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 5089111..40641d6 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -131,7 +131,7 @@
     RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
     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 GenDivZeroCheck(RegStorage reg);
+    void GenDivZeroCheckWide(RegStorage reg);
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc
index 0492fdb..ac0847f 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -342,11 +342,11 @@
   }
 }
 
-void MipsMir2Lir::GenDivZeroCheck(RegStorage reg) {
+void MipsMir2Lir::GenDivZeroCheckWide(RegStorage reg) {
   DCHECK(reg.IsPair());   // TODO: support k64BitSolo.
   RegStorage t_reg = AllocTemp();
   OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
-  AddDivZeroSlowPath(kCondEq, t_reg, 0);
+  GenDivZeroCheck(kCondEq);
   FreeTemp(t_reg);
 }
 
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 6dbeb34..65910e9 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -562,8 +562,12 @@
     void HandleThrowLaunchPads();
     void HandleSlowPaths();
     void GenBarrier();
-    void AddDivZeroSlowPath(ConditionCode c_code);
-    void AddDivZeroSlowPath(ConditionCode c_code, RegStorage reg, int imm_val);
+    void GenDivZeroException();
+    // c_code holds condition code that's generated from testing divisor against 0.
+    void GenDivZeroCheck(ConditionCode c_code);
+    // reg holds divisor.
+    void GenDivZeroCheck(RegStorage reg);
+    LIR* GenNullCheck(RegStorage reg);
     void MarkPossibleNullPointerException(int opt_flags);
     void MarkPossibleStackOverflowException();
     void ForceImplicitNullCheck(RegStorage reg, int opt_flags);
@@ -960,10 +964,9 @@
      * @brief Used for generating code that throws ArithmeticException if both registers are zero.
      * @details This is used for generating DivideByZero checks when divisor is held in two
      *  separate registers.
-     * @param reg_lo The register holding the lower 32-bits.
-     * @param reg_hi The register holding the upper 32-bits.
+     * @param reg The register holding the pair of 32-bit values.
      */
-    virtual void GenDivZeroCheck(RegStorage reg) = 0;
+    virtual void GenDivZeroCheckWide(RegStorage reg) = 0;
 
     virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) = 0;
     virtual void GenExitSequence() = 0;
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index af2a140..0b9823d 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -135,7 +135,7 @@
     RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
     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 GenDivZeroCheck(RegStorage reg);
+    void GenDivZeroCheckWide(RegStorage reg);
     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 a5f3b61..4ffb9a4 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.
-    AddDivZeroSlowPath(kCondEq, rs_r1, 0);
+    GenDivZeroCheck(rs_r1);
   }
 
   // Have to catch 0x80000000/-1 case, or we will get an exception!
@@ -876,7 +876,7 @@
   }
 }
 
-void X86Mir2Lir::GenDivZeroCheck(RegStorage reg) {
+void X86Mir2Lir::GenDivZeroCheckWide(RegStorage reg) {
   DCHECK(reg.IsPair());  // TODO: allow 64BitSolo.
   // We are not supposed to clobber the incoming storage, so allocate a temporary.
   RegStorage t_reg = AllocTemp();
@@ -885,7 +885,7 @@
   OpRegRegReg(kOpOr, t_reg, reg.GetLow(), reg.GetHigh());
 
   // In case of zero, throw ArithmeticException.
-  AddDivZeroSlowPath(kCondEq);
+  GenDivZeroCheck(kCondEq);
 
   // The temp is no longer needed so free it at this time.
   FreeTemp(t_reg);