| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_FLOW_GRAPH_ALLOCATOR_H_ | 5 #ifndef VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 6 #define VM_FLOW_GRAPH_ALLOCATOR_H_ | 6 #define VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 | 10 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 LiveRange* MakeLiveRangeForTemporary(); | 87 LiveRange* MakeLiveRangeForTemporary(); |
| 88 | 88 |
| 89 // Visit instructions in the postorder and build live ranges for | 89 // Visit instructions in the postorder and build live ranges for |
| 90 // all SSA values. | 90 // all SSA values. |
| 91 void BuildLiveRanges(); | 91 void BuildLiveRanges(); |
| 92 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); | 92 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block); |
| 93 void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current); | 93 void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current); |
| 94 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); | 94 void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr); |
| 95 void ConnectIncomingPhiMoves(BlockEntryInstr* block); | 95 void ConnectIncomingPhiMoves(BlockEntryInstr* block); |
| 96 void BlockLocation(Location loc, intptr_t from, intptr_t to); | 96 void BlockLocation(Location loc, intptr_t from, intptr_t to); |
| 97 void BlockRegisterLocation(Location loc, |
| 98 intptr_t from, |
| 99 intptr_t to, |
| 100 bool* blocked_registers, |
| 101 LiveRange** blocking_ranges); |
| 102 |
| 103 intptr_t NumberOfRegisters() const { return number_of_registers_; } |
| 97 | 104 |
| 98 // Find all safepoints that are covered by this live range. | 105 // Find all safepoints that are covered by this live range. |
| 99 void AssignSafepoints(LiveRange* range); | 106 void AssignSafepoints(LiveRange* range); |
| 100 | 107 |
| 108 void PrepareForAllocation(Location::Kind register_kind, |
| 109 intptr_t number_of_registers, |
| 110 const GrowableArray<LiveRange*>& unallocated, |
| 111 LiveRange** blocking_ranges, |
| 112 bool* blocked_registers); |
| 113 |
| 114 |
| 101 // Process live ranges sorted by their start and assign registers | 115 // Process live ranges sorted by their start and assign registers |
| 102 // to them | 116 // to them |
| 103 void AllocateCPURegisters(); | 117 void AllocateUnallocatedRanges(); |
| 104 void AdvanceActiveIntervals(const intptr_t start); | 118 void AdvanceActiveIntervals(const intptr_t start); |
| 105 | 119 |
| 106 // Connect split siblings over non-linear control flow edges. | 120 // Connect split siblings over non-linear control flow edges. |
| 107 void ResolveControlFlow(); | 121 void ResolveControlFlow(); |
| 108 void ConnectSplitSiblings(LiveRange* range, | 122 void ConnectSplitSiblings(LiveRange* range, |
| 109 BlockEntryInstr* source_block, | 123 BlockEntryInstr* source_block, |
| 110 BlockEntryInstr* target_block); | 124 BlockEntryInstr* target_block); |
| 111 | 125 |
| 112 | 126 |
| 113 // Update location slot corresponding to the use with location allocated for | 127 // Update location slot corresponding to the use with location allocated for |
| 114 // the use's live range. | 128 // the use's live range. |
| 115 void ConvertUseTo(UsePosition* use, Location loc); | 129 void ConvertUseTo(UsePosition* use, Location loc); |
| 116 void ConvertAllUses(LiveRange* range); | 130 void ConvertAllUses(LiveRange* range); |
| 117 | 131 |
| 118 // Add live range to the list of unallocated live ranges to be processed | 132 // Add live range to the list of unallocated live ranges to be processed |
| 119 // by the allocator. | 133 // by the allocator. |
| 120 void AddToUnallocated(LiveRange* range); | 134 void AddToUnallocated(LiveRange* range); |
| 135 void CompleteRange(LiveRange* range, Location::Kind kind); |
| 121 #if defined(DEBUG) | 136 #if defined(DEBUG) |
| 122 bool UnallocatedIsSorted(); | 137 bool UnallocatedIsSorted(); |
| 123 #endif | 138 #endif |
| 124 | 139 |
| 125 // Try to find a free register for an unallocated live range. | 140 // Try to find a free register for an unallocated live range. |
| 126 bool AllocateFreeRegister(LiveRange* unallocated); | 141 bool AllocateFreeRegister(LiveRange* unallocated); |
| 127 | 142 |
| 128 // Try to find a register that can be used by a given live range. | 143 // Try to find a register that can be used by a given live range. |
| 129 // If all registers are occupied consider evicting interference for | 144 // If all registers are occupied consider evicting interference for |
| 130 // a register that is going to be used as far from the start of | 145 // a register that is going to be used as far from the start of |
| 131 // the unallocated live range as possible. | 146 // the unallocated live range as possible. |
| 132 void AllocateAnyRegister(LiveRange* unallocated); | 147 void AllocateAnyRegister(LiveRange* unallocated); |
| 133 | 148 |
| 134 // Assign selected non-free register to an unallocated live range and | 149 // Assign selected non-free register to an unallocated live range and |
| 135 // evict any interference that can be evicted by splitting and spilling | 150 // evict any interference that can be evicted by splitting and spilling |
| 136 // parts of interfering live ranges. Place non-spilled parts into | 151 // parts of interfering live ranges. Place non-spilled parts into |
| 137 // the list of unallocated ranges. | 152 // the list of unallocated ranges. |
| 138 void AssignNonFreeRegister(LiveRange* unallocated, Register reg); | 153 void AssignNonFreeRegister(LiveRange* unallocated, intptr_t reg); |
| 139 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); | 154 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated); |
| 140 void RemoveEvicted(Register reg, intptr_t first_evicted); | 155 void RemoveEvicted(intptr_t reg, intptr_t first_evicted); |
| 141 | 156 |
| 142 // Find first intersection between unallocated live range and | 157 // Find first intersection between unallocated live range and |
| 143 // live ranges currently allocated to the given register. | 158 // live ranges currently allocated to the given register. |
| 144 intptr_t FirstIntersectionWithAllocated(Register reg, | 159 intptr_t FirstIntersectionWithAllocated(intptr_t reg, |
| 145 LiveRange* unallocated); | 160 LiveRange* unallocated); |
| 146 | 161 |
| 147 bool UpdateFreeUntil(Register reg, | 162 bool UpdateFreeUntil(intptr_t reg, |
| 148 LiveRange* unallocated, | 163 LiveRange* unallocated, |
| 149 intptr_t* cur_free_until, | 164 intptr_t* cur_free_until, |
| 150 intptr_t* cur_blocked_at); | 165 intptr_t* cur_blocked_at); |
| 151 | 166 |
| 152 // Split given live range in an optimal position between given positions. | 167 // Split given live range in an optimal position between given positions. |
| 153 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); | 168 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to); |
| 154 | 169 |
| 155 // Find a spill slot that can be used by the given live range. | 170 // Find a spill slot that can be used by the given live range. |
| 156 void AllocateSpillSlotFor(LiveRange* range); | 171 void AllocateSpillSlotFor(LiveRange* range); |
| 157 | 172 |
| 158 // Allocate the given live range to a spill slot. | 173 // Allocate the given live range to a spill slot. |
| 159 void Spill(LiveRange* range); | 174 void Spill(LiveRange* range); |
| 160 | 175 |
| 161 // Spill the given live range from the given position onwards. | 176 // Spill the given live range from the given position onwards. |
| 162 void SpillAfter(LiveRange* range, intptr_t from); | 177 void SpillAfter(LiveRange* range, intptr_t from); |
| 163 | 178 |
| 164 // Spill the given live range from the given position until some | 179 // Spill the given live range from the given position until some |
| 165 // position preceding the to position. | 180 // position preceding the to position. |
| 166 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); | 181 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to); |
| 167 | 182 |
| 168 // Mark the live range as a live object pointer at all safepoints | 183 // Mark the live range as a live object pointer at all safepoints |
| 169 // contained in the range. | 184 // contained in the range. |
| 170 void MarkAsObjectAtSafepoints(LiveRange* range); | 185 void MarkAsObjectAtSafepoints(LiveRange* range); |
| 171 | 186 |
| 172 MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from); | 187 MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from); |
| 173 | 188 |
| 189 Location MakeRegisterLocation(intptr_t reg) { |
| 190 return Location::MachineRegisterLocation(register_kind_, reg); |
| 191 } |
| 192 |
| 174 void PrintLiveRanges(); | 193 void PrintLiveRanges(); |
| 175 | 194 |
| 176 const FlowGraph& flow_graph_; | 195 const FlowGraph& flow_graph_; |
| 177 const GrowableArray<BlockEntryInstr*>& block_order_; | 196 const GrowableArray<BlockEntryInstr*>& block_order_; |
| 178 const GrowableArray<BlockEntryInstr*>& postorder_; | 197 const GrowableArray<BlockEntryInstr*>& postorder_; |
| 179 | 198 |
| 180 // Mapping between lifetime positions and instructions. | 199 // Mapping between lifetime positions and instructions. |
| 181 GrowableArray<Instruction*> instructions_; | 200 GrowableArray<Instruction*> instructions_; |
| 182 | 201 |
| 183 // Mapping between lifetime positions and blocks containing them. | 202 // Mapping between lifetime positions and blocks containing them. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 197 // that are used by this block or its successors. | 216 // that are used by this block or its successors. |
| 198 GrowableArray<BitVector*> live_in_; | 217 GrowableArray<BitVector*> live_in_; |
| 199 | 218 |
| 200 // Number of virtual registers. Currently equal to the number of | 219 // Number of virtual registers. Currently equal to the number of |
| 201 // SSA values. | 220 // SSA values. |
| 202 const intptr_t vreg_count_; | 221 const intptr_t vreg_count_; |
| 203 | 222 |
| 204 // LiveRanges corresponding to SSA values. | 223 // LiveRanges corresponding to SSA values. |
| 205 GrowableArray<LiveRange*> live_ranges_; | 224 GrowableArray<LiveRange*> live_ranges_; |
| 206 | 225 |
| 207 // Worklist for register allocator. Always maintained sorted according | 226 GrowableArray<LiveRange*> unallocated_cpu_; |
| 208 // to ShouldBeAllocatedBefore predicate. | 227 GrowableArray<LiveRange*> unallocated_xmm_; |
| 209 GrowableArray<LiveRange*> unallocated_; | 228 |
| 229 LiveRange* cpu_regs_[kNumberOfCpuRegisters]; |
| 230 LiveRange* xmm_regs_[kNumberOfXmmRegisters]; |
| 231 |
| 232 bool blocked_cpu_registers_[kNumberOfCpuRegisters]; |
| 233 bool blocked_xmm_registers_[kNumberOfXmmRegisters]; |
| 210 | 234 |
| 211 #if defined(DEBUG) | 235 #if defined(DEBUG) |
| 212 GrowableArray<LiveRange*> temporaries_; | 236 GrowableArray<LiveRange*> temporaries_; |
| 213 #endif | 237 #endif |
| 214 | 238 |
| 215 // List of spilled live ranges. | 239 // List of spilled live ranges. |
| 216 GrowableArray<LiveRange*> spilled_; | 240 GrowableArray<LiveRange*> spilled_; |
| 217 | 241 |
| 218 // List of instructions containing calls. | 242 // List of instructions containing calls. |
| 219 GrowableArray<Instruction*> safepoints_; | 243 GrowableArray<Instruction*> safepoints_; |
| 220 | 244 |
| 245 Location::Kind register_kind_; |
| 246 |
| 247 intptr_t number_of_registers_; |
| 248 |
| 221 // Per register lists of allocated live ranges. Contain only those | 249 // Per register lists of allocated live ranges. Contain only those |
| 222 // ranges that can be affected by future allocation decisions. | 250 // ranges that can be affected by future allocation decisions. |
| 223 // Those live ranges that end before the start of the current live range are | 251 // Those live ranges that end before the start of the current live range are |
| 224 // removed from the list and will not be affected. | 252 // removed from the list and will not be affected. |
| 225 GrowableArray<LiveRange*> cpu_regs_[kNumberOfCpuRegisters]; | 253 GrowableArray<LiveRange*> registers_[kNumberOfCpuRegisters]; |
| 254 |
| 255 bool blocked_registers_[kNumberOfCpuRegisters]; |
| 256 |
| 257 |
| 258 // Worklist for register allocator. Always maintained sorted according |
| 259 // to ShouldBeAllocatedBefore predicate. |
| 260 GrowableArray<LiveRange*> unallocated_; |
| 226 | 261 |
| 227 // List of used spill slots. Contains positions after which spill slots | 262 // List of used spill slots. Contains positions after which spill slots |
| 228 // become free and can be reused for allocation. | 263 // become free and can be reused for allocation. |
| 229 GrowableArray<intptr_t> spill_slots_; | 264 GrowableArray<intptr_t> spill_slots_; |
| 265 intptr_t cpu_spill_slot_count_; |
| 230 | 266 |
| 231 bool blocked_cpu_regs_[kNumberOfCpuRegisters]; | |
| 232 | 267 |
| 233 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); | 268 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); |
| 234 }; | 269 }; |
| 235 | 270 |
| 236 | 271 |
| 237 // Additional information about a block that is not contained in a | 272 // Additional information about a block that is not contained in a |
| 238 // block entry. | 273 // block entry. |
| 239 class BlockInfo : public ZoneAllocated { | 274 class BlockInfo : public ZoneAllocated { |
| 240 public: | 275 public: |
| 241 explicit BlockInfo(BlockEntryInstr* entry) | 276 explicit BlockInfo(BlockEntryInstr* entry) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 268 | 303 |
| 269 | 304 |
| 270 // UsePosition represents a single use of an SSA value by some instruction. | 305 // UsePosition represents a single use of an SSA value by some instruction. |
| 271 // It points to a location slot which either tells register allocator | 306 // It points to a location slot which either tells register allocator |
| 272 // where instruction expects the value (if slot contains a fixed location) or | 307 // where instruction expects the value (if slot contains a fixed location) or |
| 273 // asks register allocator to allocate storage (register or spill slot) for | 308 // asks register allocator to allocate storage (register or spill slot) for |
| 274 // this use with certain properties (if slot contains an unallocated location). | 309 // this use with certain properties (if slot contains an unallocated location). |
| 275 class UsePosition : public ZoneAllocated { | 310 class UsePosition : public ZoneAllocated { |
| 276 public: | 311 public: |
| 277 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) | 312 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) |
| 278 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { } | 313 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { |
| 314 ASSERT(location_slot != NULL); |
| 315 } |
| 279 | 316 |
| 280 Location* location_slot() const { return location_slot_; } | 317 Location* location_slot() const { return location_slot_; } |
| 281 void set_location_slot(Location* location_slot) { | 318 void set_location_slot(Location* location_slot) { |
| 282 location_slot_ = location_slot; | 319 location_slot_ = location_slot; |
| 283 } | 320 } |
| 284 | 321 |
| 285 Location hint() const { | 322 Location hint() const { |
| 286 ASSERT(HasHint()); | 323 ASSERT(HasHint()); |
| 287 return *hint_; | 324 return *hint_; |
| 288 } | 325 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 | 543 |
| 507 AllocationFinger finger_; | 544 AllocationFinger finger_; |
| 508 | 545 |
| 509 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 546 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 510 }; | 547 }; |
| 511 | 548 |
| 512 | 549 |
| 513 } // namespace dart | 550 } // namespace dart |
| 514 | 551 |
| 515 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ | 552 #endif // VM_FLOW_GRAPH_ALLOCATOR_H_ |
| OLD | NEW |