Rewrite suspend test check with LIRSlowPath.

Change-Id: I2dc17d079655586bfc588349c7a04afc2c6879af
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index b374ed8..9cb56cf 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -383,7 +383,7 @@
         void Compile() OVERRIDE {
           m2l_->ResetRegPool();
           m2l_->ResetDefTracking();
-          GenerateTargetLabel();
+          GenerateTargetLabel(kPseudoThrowTarget);
           if (restore_lr_) {
             m2l_->LoadWordDisp(rs_rARM_SP, sp_displace_ - 4, rs_rARM_LR);
           }
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 501e4e20..c3f9b67 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -940,7 +940,6 @@
       mir_graph_(mir_graph),
       switch_tables_(arena, 4, kGrowableArraySwitchTables),
       fill_array_data_(arena, 4, kGrowableArrayFillArrayData),
-      suspend_launchpads_(arena, 4, kGrowableArraySuspendLaunchPads),
       tempreg_info_(arena, 20, kGrowableArrayMisc),
       reginfo_map_(arena, 64, kGrowableArrayMisc),
       pointer_storage_(arena, 128, kGrowableArrayMisc),
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 313174d..70f2ba8 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -72,7 +72,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
       m2l_->CallRuntimeHelper(QUICK_ENTRYPOINT_OFFSET(4, pThrowDivZero), true);
     }
   };
@@ -91,7 +91,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
       m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
                                     index_, length_, true);
     }
@@ -116,7 +116,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
 
       m2l_->OpRegCopy(m2l_->TargetReg(kArg1), length_);
       m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
@@ -143,7 +143,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
       m2l_->CallRuntimeHelper(QUICK_ENTRYPOINT_OFFSET(4, pThrowNullPointer), true);
     }
   };
@@ -693,22 +693,6 @@
   slow_paths_.Reset();
 }
 
-void Mir2Lir::HandleSuspendLaunchPads() {
-  int num_elems = suspend_launchpads_.Size();
-  ThreadOffset<4> helper_offset = QUICK_ENTRYPOINT_OFFSET(4, pTestSuspend);
-  for (int i = 0; i < num_elems; i++) {
-    ResetRegPool();
-    ResetDefTracking();
-    LIR* lab = suspend_launchpads_.Get(i);
-    LIR* resume_lab = reinterpret_cast<LIR*>(UnwrapPointer(lab->operands[0]));
-    current_dalvik_offset_ = lab->operands[1];
-    AppendLIR(lab);
-    RegStorage r_tgt = CallHelperSetup(helper_offset);
-    CallHelper(r_tgt, helper_offset, true /* MarkSafepointPC */);
-    OpUnconditionalBranch(resume_lab);
-  }
-}
-
 void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size,
                       RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double,
                       bool is_object) {
@@ -1997,6 +1981,23 @@
   }
 }
 
+class SuspendCheckSlowPath : public Mir2Lir::LIRSlowPath {
+ public:
+  SuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont)
+      : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch, cont) {
+  }
+
+  void Compile() OVERRIDE {
+    m2l_->ResetRegPool();
+    m2l_->ResetDefTracking();
+    GenerateTargetLabel(kPseudoSuspendTarget);
+    m2l_->CallRuntimeHelper(QUICK_ENTRYPOINT_OFFSET(4, pTestSuspend), true);
+    if (cont_ != nullptr) {
+      m2l_->OpUnconditionalBranch(cont_);
+    }
+  }
+};
+
 /* Check if we need to check for pending suspend request */
 void Mir2Lir::GenSuspendTest(int opt_flags) {
   if (Runtime::Current()->ExplicitSuspendChecks()) {
@@ -2005,11 +2006,8 @@
     }
     FlushAllRegs();
     LIR* branch = OpTestSuspend(NULL);
-    LIR* ret_lab = NewLIR0(kPseudoTargetLabel);
-    LIR* target = RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, WrapPointer(ret_lab),
-                         current_dalvik_offset_);
-    branch->target = target;
-    suspend_launchpads_.Insert(target);
+    LIR* cont = NewLIR0(kPseudoTargetLabel);
+    AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, cont));
   } else {
     if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
       return;
@@ -2028,12 +2026,9 @@
       return;
     }
     OpTestSuspend(target);
-    LIR* launch_pad =
-        RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, WrapPointer(target),
-               current_dalvik_offset_);
     FlushAllRegs();
-    OpUnconditionalBranch(launch_pad);
-    suspend_launchpads_.Insert(launch_pad);
+    LIR* branch = OpUnconditionalBranch(nullptr);
+    AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, target));
   } else {
     // For the implicit suspend check, just perform the trigger
     // load and branch to the target.
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 53b6ed4..05313a9 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -44,8 +44,7 @@
     void Compile() {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      LIR* label = GenerateTargetLabel();
-      label->opcode = kPseudoIntrinsicRetry;
+      GenerateTargetLabel(kPseudoIntrinsicRetry);
       // NOTE: GenInvokeNoInline() handles MarkSafepointPC.
       m2l_->GenInvokeNoInline(info_);
       if (cont_ != nullptr) {
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index a237ac7..df13882 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -327,7 +327,7 @@
       void Compile() OVERRIDE {
         m2l_->ResetRegPool();
         m2l_->ResetDefTracking();
-        GenerateTargetLabel();
+        GenerateTargetLabel(kPseudoThrowTarget);
         // LR is offset 0 since we push in reverse order.
         m2l_->Load32Disp(rs_rMIPS_SP, 0, rs_rRA);
         m2l_->OpRegImm(kOpAdd, rs_rMIPS_SP, sp_displace_);
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index b8ab609..df7a7c1 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -1099,18 +1099,15 @@
     } while ((next_bb != NULL) && (next_bb->block_type == kDead));
   }
   HandleSlowPaths();
-
-  cu_->NewTimingSplit("Launchpads");
-  HandleSuspendLaunchPads();
 }
 
 //
 // LIR Slow Path
 //
 
-LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel() {
+LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel(int opcode) {
   m2l_->SetCurrentDexPc(current_dex_pc_);
-  LIR* target = m2l_->NewLIR0(kPseudoTargetLabel);
+  LIR* target = m2l_->NewLIR0(opcode);
   fromfast_->target = target;
   return target;
 }
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 2b6d78b..9283a29 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -325,7 +325,7 @@
       }
 
      protected:
-      LIR* GenerateTargetLabel();
+      LIR* GenerateTargetLabel(int opcode = kPseudoTargetLabel);
 
       Mir2Lir* const m2l_;
       const DexOffset current_dex_pc_;
@@ -563,7 +563,6 @@
     bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
                           RegLocation rl_src, RegLocation rl_dest, int lit);
     bool HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit);
-    void HandleSuspendLaunchPads();
     void HandleSlowPaths();
     void GenBarrier();
     void GenDivZeroException();
@@ -1277,7 +1276,6 @@
     MIRGraph* const mir_graph_;
     GrowableArray<SwitchTable*> switch_tables_;
     GrowableArray<FillArrayData*> fill_array_data_;
-    GrowableArray<LIR*> suspend_launchpads_;
     GrowableArray<RegisterInfo*> tempreg_info_;
     GrowableArray<RegisterInfo*> reginfo_map_;
     GrowableArray<void*> pointer_storage_;
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 0083109..06cc861 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -219,7 +219,7 @@
       void Compile() OVERRIDE {
         m2l_->ResetRegPool();
         m2l_->ResetDefTracking();
-        GenerateTargetLabel();
+        GenerateTargetLabel(kPseudoThrowTarget);
         m2l_->OpRegImm(kOpAdd, rs_rX86_SP, sp_displace_);
         m2l_->ClobberCallerSave();
         ThreadOffset<4> func_offset = QUICK_ENTRYPOINT_OFFSET(4, pThrowStackOverflow);
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 3bff497..96c4cbe 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -881,7 +881,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
 
       RegStorage new_index = index_;
       // Move index out of kArg1, either directly to kArg0, or to kArg2.
@@ -926,7 +926,7 @@
     void Compile() OVERRIDE {
       m2l_->ResetRegPool();
       m2l_->ResetDefTracking();
-      GenerateTargetLabel();
+      GenerateTargetLabel(kPseudoThrowTarget);
 
       // Load array length to kArg1.
       m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
diff --git a/compiler/utils/growable_array.h b/compiler/utils/growable_array.h
index 993492d..659b4f7 100644
--- a/compiler/utils/growable_array.h
+++ b/compiler/utils/growable_array.h
@@ -31,7 +31,6 @@
   kGrowableArrayDfsOrder,
   kGrowableArrayDfsPostOrder,
   kGrowableArrayDomPostOrderTraversal,
-  kGrowableArraySuspendLaunchPads,
   kGrowableArraySwitchTables,
   kGrowableArrayFillArrayData,
   kGrowableArraySuccessorBlocks,