| Index: src/compiler/greedy-allocator.cc
 | 
| diff --git a/src/compiler/greedy-allocator.cc b/src/compiler/greedy-allocator.cc
 | 
| index 444130aa1ea806e2647d7d375f4395384e6e5528..d6f48a2716e2be223b05c46c526dcbc4ca5a7a79 100644
 | 
| --- a/src/compiler/greedy-allocator.cc
 | 
| +++ b/src/compiler/greedy-allocator.cc
 | 
| @@ -390,9 +390,94 @@ void GreedyAllocator::SpillRangeAsLastResort(LiveRange* range) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +LiveRange* GreedyAllocator::GetRemainderAfterSplittingAroundFirstCall(
 | 
| +    LiveRange* range) {
 | 
| +  LiveRange* ret = range;
 | 
| +  for (UseInterval* interval = range->first_interval(); interval != nullptr;
 | 
| +       interval = interval->next()) {
 | 
| +    LifetimePosition start = interval->start();
 | 
| +    LifetimePosition end = interval->end();
 | 
| +    // If the interval starts at instruction end, then the first instruction
 | 
| +    // in the interval is the next one.
 | 
| +    int first_full_instruction = (start.IsGapPosition() || start.IsStart())
 | 
| +                                     ? start.ToInstructionIndex()
 | 
| +                                     : start.ToInstructionIndex() + 1;
 | 
| +    // If the interval ends in a gap or at instruction start, then the last
 | 
| +    // instruction is the previous one.
 | 
| +    int last_full_instruction = (end.IsGapPosition() || end.IsStart())
 | 
| +                                    ? end.ToInstructionIndex() - 1
 | 
| +                                    : end.ToInstructionIndex();
 | 
| +
 | 
| +    for (int instruction_index = first_full_instruction;
 | 
| +         instruction_index <= last_full_instruction; ++instruction_index) {
 | 
| +      if (!code()->InstructionAt(instruction_index)->IsCall()) continue;
 | 
| +
 | 
| +      LifetimePosition before =
 | 
| +          GetSplitPositionForInstruction(range, instruction_index);
 | 
| +      LiveRange* second_part =
 | 
| +          before.IsValid() ? Split(range, data(), before) : range;
 | 
| +
 | 
| +      if (range != second_part) scheduler().Schedule(range);
 | 
| +
 | 
| +      LifetimePosition after =
 | 
| +          FindSplitPositionAfterCall(second_part, instruction_index);
 | 
| +
 | 
| +      if (after.IsValid()) {
 | 
| +        ret = Split(second_part, data(), after);
 | 
| +      } else {
 | 
| +        ret = nullptr;
 | 
| +      }
 | 
| +      Spill(second_part);
 | 
| +      return ret;
 | 
| +    }
 | 
| +  }
 | 
| +  return ret;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +bool GreedyAllocator::TrySplitAroundCalls(LiveRange* range) {
 | 
| +  bool modified = false;
 | 
| +
 | 
| +  while (range != nullptr) {
 | 
| +    LiveRange* remainder = GetRemainderAfterSplittingAroundFirstCall(range);
 | 
| +    // If we performed no modification, we're done.
 | 
| +    if (remainder == range) {
 | 
| +      break;
 | 
| +    }
 | 
| +    // We performed a modification.
 | 
| +    modified = true;
 | 
| +    range = remainder;
 | 
| +  }
 | 
| +  // If we have a remainder and we made modifications, it means the remainder
 | 
| +  // has no calls and we should schedule it for further processing. If we made
 | 
| +  // no modifications, we will just return false, because we want the algorithm
 | 
| +  // to make progress by trying some other heuristic.
 | 
| +  if (modified && range != nullptr) {
 | 
| +    DCHECK(!range->spilled());
 | 
| +    DCHECK(!range->HasRegisterAssigned());
 | 
| +    scheduler().Schedule(range);
 | 
| +  }
 | 
| +  return modified;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LifetimePosition GreedyAllocator::FindSplitPositionAfterCall(
 | 
| +    const LiveRange* range, int call_index) {
 | 
| +  LifetimePosition after_call =
 | 
| +      Max(range->Start(),
 | 
| +          LifetimePosition::GapFromInstructionIndex(call_index + 1));
 | 
| +  UsePosition* next_use = range->NextRegisterPosition(after_call);
 | 
| +  if (!next_use) return LifetimePosition::Invalid();
 | 
| +
 | 
| +  LifetimePosition split_pos = FindOptimalSplitPos(after_call, next_use->pos());
 | 
| +  split_pos =
 | 
| +      GetSplitPositionForInstruction(range, split_pos.ToInstructionIndex());
 | 
| +  return split_pos;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
 | 
| -  // TODO(mtrofin): replace the call below with the entry point selecting
 | 
| -  // heuristics, once they exist, out of which GLRSP is the last one.
 | 
| +  if (TrySplitAroundCalls(range)) return;
 | 
|    auto pos = GetLastResortSplitPosition(range, code());
 | 
|    if (pos.IsValid()) {
 | 
|      LiveRange* tail = Split(range, data(), pos);
 | 
| 
 |