Merge "ART: Hot fix for an inliner issue"
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 2fbd051..a02b1da 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -1422,7 +1422,6 @@
                         : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
   }
   UsePosition* use = current->GetFirstUse();
-  SafepointPosition* safepoint_position = interval->GetFirstSafepoint();
 
   // Walk over all siblings, updating locations of use positions, and
   // connecting them when they are adjacent.
@@ -1473,11 +1472,10 @@
       InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination);
     }
 
-    for (; safepoint_position != nullptr; safepoint_position = safepoint_position->GetNext()) {
-      if (!current->Covers(safepoint_position->GetPosition())) {
-        DCHECK(next_sibling != nullptr);
-        break;
-      }
+    for (SafepointPosition* safepoint_position = current->GetFirstSafepoint();
+         safepoint_position != nullptr;
+         safepoint_position = safepoint_position->GetNext()) {
+      DCHECK(current->Covers(safepoint_position->GetPosition()));
 
       LocationSummary* locations = safepoint_position->GetLocations();
       if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
@@ -1523,7 +1521,6 @@
   } while (current != nullptr);
 
   if (kIsDebugBuild) {
-    DCHECK(safepoint_position == nullptr);
     // Following uses can only be environment uses. The location for
     // these environments will be none.
     while (use != nullptr) {
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 2b51f94..98f98a2 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -492,6 +492,15 @@
     return defined_by_;
   }
 
+  SafepointPosition* FindSafepointJustBefore(size_t position) const {
+    for (SafepointPosition* safepoint = first_safepoint_, *previous = nullptr;
+         safepoint != nullptr;
+         previous = safepoint, safepoint = safepoint->GetNext()) {
+      if (safepoint->GetPosition() >= position) return previous;
+    }
+    return last_safepoint_;
+  }
+
   /**
    * Split this interval at `position`. This interval is changed to:
    * [start ... position).
@@ -510,6 +519,19 @@
     }
 
     LiveInterval* new_interval = new (allocator_) LiveInterval(allocator_, type_);
+    SafepointPosition* new_last_safepoint = FindSafepointJustBefore(position);
+    if (new_last_safepoint == nullptr) {
+      new_interval->first_safepoint_ = first_safepoint_;
+      new_interval->last_safepoint_ = last_safepoint_;
+      first_safepoint_ = last_safepoint_ = nullptr;
+    } else if (last_safepoint_ != new_last_safepoint) {
+      new_interval->last_safepoint_ = last_safepoint_;
+      new_interval->first_safepoint_ = new_last_safepoint->GetNext();
+      DCHECK(new_interval->first_safepoint_ != nullptr);
+      last_safepoint_ = new_last_safepoint;
+      last_safepoint_->SetNext(nullptr);
+    }
+
     new_interval->next_sibling_ = next_sibling_;
     next_sibling_ = new_interval;
     new_interval->parent_ = parent_;
@@ -748,7 +770,6 @@
   }
 
   SafepointPosition* GetFirstSafepoint() const {
-    DCHECK_EQ(GetParent(), this) << "Only the first sibling lists safepoints";
     return first_safepoint_;
   }
 
@@ -822,7 +843,7 @@
   LiveRange* first_range_;
   LiveRange* last_range_;
 
-  // Safepoints where this interval is live. Only set in the parent interval.
+  // Safepoints where this interval is live.
   SafepointPosition* first_safepoint_;
   SafepointPosition* last_safepoint_;