Chromium Code Reviews| Index: runtime/vm/flow_graph_allocator.cc |
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc |
| index 66e7ee7ba7e7bb072c10bcd8b84aee18b756ed7f..69fc5c619d249789208d38832a74a46306a61c7d 100644 |
| --- a/runtime/vm/flow_graph_allocator.cc |
| +++ b/runtime/vm/flow_graph_allocator.cc |
| @@ -311,6 +311,23 @@ void LiveRange::AddUse(intptr_t pos, Location* location_slot) { |
| } |
| +void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { |
| + SafepointPosition* safepoint = new SafepointPosition(pos, locs); |
| + |
| + if (first_safepoint_ == NULL) { |
| + ASSERT(last_safepoint_ == NULL); |
| + first_safepoint_ = last_safepoint_ = safepoint; |
| + } else { |
| + ASSERT(last_safepoint_ != NULL); |
| + // We assume that safepoints list is sorted by position and that |
| + // safepoints are added in this order. |
| + ASSERT(last_safepoint_->pos() < pos); |
| + last_safepoint_->set_next(safepoint); |
| + last_safepoint_ = safepoint; |
| + } |
| +} |
| + |
| + |
| void LiveRange::AddHintedUse(intptr_t pos, |
| Location* location_slot, |
| Location* hint) { |
| @@ -519,6 +536,8 @@ void FlowGraphAllocator::BuildLiveRanges() { |
| spill_slots_.Add(range->End()); |
| } |
| + AssignSafepoints(range); |
| + |
| range->finger()->Initialize(range); |
| UsePosition* use = range->finger()->FirstRegisterBeneficialUse( |
| graph_entry->start_pos()); |
| @@ -658,6 +677,7 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { |
| // All phi resolution moves are connected. Phi's live range is |
| // complete. |
| + AssignSafepoints(range); |
| AddToUnallocated(range); |
| move_idx++; |
| @@ -812,9 +832,6 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| // [--) |
| // |
| // The stack bitmap describes the position i. |
| - Safepoint safepoint = { pos, locs->stack_bitmap() }; |
| - safepoints_.Add(safepoint); |
| - |
| for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
| BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), |
| pos, |
| @@ -837,6 +854,10 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| #endif |
| } |
| + if (locs->contains_call()) { |
| + safepoints_.Add(current); |
| + } |
| + |
| Definition* def = current->AsDefinition(); |
| if (def == NULL) { |
| ASSERT(locs->out().IsInvalid()); |
| @@ -937,6 +958,7 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| range->AddUse(pos, out); |
| } |
| + AssignSafepoints(range); |
| AddToUnallocated(range); |
| } |
| @@ -1204,6 +1226,34 @@ LiveRange* LiveRange::MakeTemp(intptr_t pos, Location* location_slot) { |
| } |
| +template<typename PositionType> |
|
srdjan
2012/08/15 00:12:03
I think this kind of code sharing makes code less
Vyacheslav Egorov (Google)
2012/08/15 13:08:07
I keep in mind that we try to avoid using template
|
| +PositionType* SplitListOfPositions(PositionType** head, |
| + intptr_t split_pos, |
| + bool split_at_start) { |
| + PositionType* last_before_split = NULL; |
| + PositionType* pos = *head; |
| + if (split_at_start) { |
| + while ((pos != NULL) && (pos->pos() < split_pos)) { |
| + last_before_split = pos; |
| + pos = pos->next(); |
| + } |
| + } else { |
| + while ((pos != NULL) && (pos->pos() <= split_pos)) { |
| + last_before_split = pos; |
| + pos = pos->next(); |
| + } |
| + } |
| + |
| + if (last_before_split == NULL) { |
| + *head = NULL; |
| + } else { |
| + last_before_split->set_next(NULL); |
| + } |
| + |
| + return pos; |
| +} |
| + |
| + |
| LiveRange* LiveRange::SplitAt(intptr_t split_pos) { |
| if (Start() == split_pos) return this; |
| @@ -1240,26 +1290,11 @@ LiveRange* LiveRange::SplitAt(intptr_t split_pos) { |
| ASSERT(last_before_split->end() <= split_pos); |
| ASSERT(split_pos <= first_after_split->start()); |
| - UsePosition* last_use_before_split = NULL; |
| - UsePosition* use = uses_; |
| - if (split_at_start) { |
| - while ((use != NULL) && (use->pos() < split_pos)) { |
| - last_use_before_split = use; |
| - use = use->next(); |
| - } |
| - } else { |
| - while ((use != NULL) && (use->pos() <= split_pos)) { |
| - last_use_before_split = use; |
| - use = use->next(); |
| - } |
| - } |
| - UsePosition* first_use_after_split = use; |
| + UsePosition* first_use_after_split = |
| + SplitListOfPositions(&uses_, split_pos, split_at_start); |
| - if (last_use_before_split == NULL) { |
| - uses_ = NULL; |
| - } else { |
| - last_use_before_split->set_next(NULL); |
| - } |
| + SafepointPosition* first_safepoint_after_split = |
| + SplitListOfPositions(&first_safepoint_, split_pos, split_at_start); |
| UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? |
| first_after_split : last_use_interval_; |
| @@ -1267,6 +1302,7 @@ LiveRange* LiveRange::SplitAt(intptr_t split_pos) { |
| first_use_after_split, |
| first_after_split, |
| last_use_interval, |
| + first_safepoint_after_split, |
| next_sibling_); |
| TRACE_ALLOC(OS::Print(" split sibling [%d, %d)\n", |
| @@ -1371,30 +1407,17 @@ void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| } |
| -bool LiveRange::Contains(intptr_t pos) const { |
| - const LiveRange* current = this; |
| - while (current != NULL) { |
| - UseInterval* interval = current->first_use_interval_; |
| - while (interval != NULL) { |
| - if (interval->Contains(pos)) return true; |
| - interval = interval->next(); |
| - } |
| - current = current->next_sibling_; |
| - } |
| - return false; |
| -} |
| - |
| - |
| void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { |
| intptr_t stack_index = range->spill_slot().stack_index(); |
| ASSERT(stack_index >= 0); |
| - for (intptr_t i = 0; i < safepoints_.length(); ++i) { |
| - if (range->Contains(safepoints_[i].position)) { |
| - TRACE_ALLOC(OS::Print(" marking S[%d] in stack bitmap at %d\n", |
| - stack_index, |
| - safepoints_[i].position)); |
| - safepoints_[i].stack_bitmap->Set(stack_index, true); |
| + |
| + while (range != NULL) { |
| + for (SafepointPosition* safepoint = range->first_safepoint(); |
| + safepoint != NULL; |
| + safepoint = safepoint->next()) { |
| + safepoint->locs()->stack_bitmap()->Set(stack_index, true); |
| } |
| + range = range->next_sibling(); |
| } |
| } |
| @@ -1703,6 +1726,15 @@ void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { |
| for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
| ConvertUseTo(use, loc); |
| } |
| + |
| + if (range->assigned_location().IsRegister()) { |
| + Register reg = range->assigned_location().reg(); |
| + for (SafepointPosition* safepoint = range->first_safepoint(); |
| + safepoint != NULL; |
| + safepoint = safepoint->next()) { |
| + safepoint->locs()->live_registers()->Add(reg); |
| + } |
| + } |
| } |
| @@ -1732,6 +1764,33 @@ static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { |
| } |
| +bool LiveRange::Contains(intptr_t pos) const { |
| + if (!CanCover(pos)) return false; |
| + |
| + for (UseInterval* interval = first_use_interval_; |
| + interval != NULL; |
| + interval = interval->next()) { |
| + if (interval->Contains(pos)) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| + |
| +void FlowGraphAllocator::AssignSafepoints(LiveRange* range) { |
| + for (intptr_t i = safepoints_.length() - 1; i >= 0; i--) { |
| + Instruction* instr = safepoints_[i]; |
| + |
| + const intptr_t pos = instr->lifetime_position(); |
| + if (range->End() <= pos) break; |
| + |
| + if (range->Contains(pos)) range->AddSafepoint(pos, instr->locs()); |
| + } |
| +} |
| + |
| + |
| void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { |
| range->finger()->Initialize(range); |