| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ | 5 #ifndef RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 6 #define RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ | 6 #define RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "vm/flow_graph.h" | 8 #include "vm/flow_graph.h" |
| 9 #include "vm/growable_array.h" | 9 #include "vm/growable_array.h" |
| 10 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 class AllocationFinger; | 14 class AllocationFinger; |
| 15 class BlockInfo; | 15 class BlockInfo; |
| 16 class FlowGraph; | 16 class FlowGraph; |
| 17 class LiveRange; | 17 class LiveRange; |
| 18 class UseInterval; | 18 class UseInterval; |
| 19 class UsePosition; | 19 class UsePosition; |
| 20 | 20 |
| 21 | |
| 22 class ReachingDefs : public ValueObject { | 21 class ReachingDefs : public ValueObject { |
| 23 public: | 22 public: |
| 24 explicit ReachingDefs(const FlowGraph& flow_graph) | 23 explicit ReachingDefs(const FlowGraph& flow_graph) |
| 25 : flow_graph_(flow_graph), phis_(10) {} | 24 : flow_graph_(flow_graph), phis_(10) {} |
| 26 | 25 |
| 27 BitVector* Get(PhiInstr* phi); | 26 BitVector* Get(PhiInstr* phi); |
| 28 | 27 |
| 29 private: | 28 private: |
| 30 void AddPhi(PhiInstr* phi); | 29 void AddPhi(PhiInstr* phi); |
| 31 void Compute(); | 30 void Compute(); |
| 32 | 31 |
| 33 const FlowGraph& flow_graph_; | 32 const FlowGraph& flow_graph_; |
| 34 GrowableArray<PhiInstr*> phis_; | 33 GrowableArray<PhiInstr*> phis_; |
| 35 }; | 34 }; |
| 36 | 35 |
| 37 | |
| 38 class SSALivenessAnalysis : public LivenessAnalysis { | 36 class SSALivenessAnalysis : public LivenessAnalysis { |
| 39 public: | 37 public: |
| 40 explicit SSALivenessAnalysis(const FlowGraph& flow_graph) | 38 explicit SSALivenessAnalysis(const FlowGraph& flow_graph) |
| 41 : LivenessAnalysis(flow_graph.max_virtual_register_number(), | 39 : LivenessAnalysis(flow_graph.max_virtual_register_number(), |
| 42 flow_graph.postorder()), | 40 flow_graph.postorder()), |
| 43 graph_entry_(flow_graph.graph_entry()) {} | 41 graph_entry_(flow_graph.graph_entry()) {} |
| 44 | 42 |
| 45 private: | 43 private: |
| 46 // Compute initial values for live-out, kill and live-in sets. | 44 // Compute initial values for live-out, kill and live-in sets. |
| 47 virtual void ComputeInitialSets(); | 45 virtual void ComputeInitialSets(); |
| 48 | 46 |
| 49 GraphEntryInstr* graph_entry_; | 47 GraphEntryInstr* graph_entry_; |
| 50 }; | 48 }; |
| 51 | 49 |
| 52 | |
| 53 class FlowGraphAllocator : public ValueObject { | 50 class FlowGraphAllocator : public ValueObject { |
| 54 public: | 51 public: |
| 55 // Number of stack slots needed for a fpu register spill slot. | 52 // Number of stack slots needed for a fpu register spill slot. |
| 56 static const intptr_t kDoubleSpillFactor = kDoubleSize / kWordSize; | 53 static const intptr_t kDoubleSpillFactor = kDoubleSize / kWordSize; |
| 57 | 54 |
| 58 explicit FlowGraphAllocator(const FlowGraph& flow_graph, | 55 explicit FlowGraphAllocator(const FlowGraph& flow_graph, |
| 59 bool intrinsic_mode = false); | 56 bool intrinsic_mode = false); |
| 60 | 57 |
| 61 void AllocateRegisters(); | 58 void AllocateRegisters(); |
| 62 | 59 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 | 143 |
| 147 // Find all safepoints that are covered by this live range. | 144 // Find all safepoints that are covered by this live range. |
| 148 void AssignSafepoints(Definition* defn, LiveRange* range); | 145 void AssignSafepoints(Definition* defn, LiveRange* range); |
| 149 | 146 |
| 150 void PrepareForAllocation(Location::Kind register_kind, | 147 void PrepareForAllocation(Location::Kind register_kind, |
| 151 intptr_t number_of_registers, | 148 intptr_t number_of_registers, |
| 152 const GrowableArray<LiveRange*>& unallocated, | 149 const GrowableArray<LiveRange*>& unallocated, |
| 153 LiveRange** blocking_ranges, | 150 LiveRange** blocking_ranges, |
| 154 bool* blocked_registers); | 151 bool* blocked_registers); |
| 155 | 152 |
| 156 | |
| 157 // Process live ranges sorted by their start and assign registers | 153 // Process live ranges sorted by their start and assign registers |
| 158 // to them | 154 // to them |
| 159 void AllocateUnallocatedRanges(); | 155 void AllocateUnallocatedRanges(); |
| 160 void AdvanceActiveIntervals(const intptr_t start); | 156 void AdvanceActiveIntervals(const intptr_t start); |
| 161 | 157 |
| 162 // Connect split siblings over non-linear control flow edges. | 158 // Connect split siblings over non-linear control flow edges. |
| 163 void ResolveControlFlow(); | 159 void ResolveControlFlow(); |
| 164 void ConnectSplitSiblings(LiveRange* range, | 160 void ConnectSplitSiblings(LiveRange* range, |
| 165 BlockEntryInstr* source_block, | 161 BlockEntryInstr* source_block, |
| 166 BlockEntryInstr* target_block); | 162 BlockEntryInstr* target_block); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 | 300 |
| 305 // Per register lists of allocated live ranges. Contain only those | 301 // Per register lists of allocated live ranges. Contain only those |
| 306 // ranges that can be affected by future allocation decisions. | 302 // ranges that can be affected by future allocation decisions. |
| 307 // Those live ranges that end before the start of the current live range are | 303 // Those live ranges that end before the start of the current live range are |
| 308 // removed from the list and will not be affected. | 304 // removed from the list and will not be affected. |
| 309 // The length of both arrays is 'number_of_registers_' | 305 // The length of both arrays is 'number_of_registers_' |
| 310 GrowableArray<ZoneGrowableArray<LiveRange*>*> registers_; | 306 GrowableArray<ZoneGrowableArray<LiveRange*>*> registers_; |
| 311 | 307 |
| 312 GrowableArray<bool> blocked_registers_; | 308 GrowableArray<bool> blocked_registers_; |
| 313 | 309 |
| 314 | |
| 315 // Worklist for register allocator. Always maintained sorted according | 310 // Worklist for register allocator. Always maintained sorted according |
| 316 // to ShouldBeAllocatedBefore predicate. | 311 // to ShouldBeAllocatedBefore predicate. |
| 317 GrowableArray<LiveRange*> unallocated_; | 312 GrowableArray<LiveRange*> unallocated_; |
| 318 | 313 |
| 319 // List of used spill slots. Contains positions after which spill slots | 314 // List of used spill slots. Contains positions after which spill slots |
| 320 // become free and can be reused for allocation. | 315 // become free and can be reused for allocation. |
| 321 GrowableArray<intptr_t> spill_slots_; | 316 GrowableArray<intptr_t> spill_slots_; |
| 322 | 317 |
| 323 // For every used spill slot contains a flag determines whether it is | 318 // For every used spill slot contains a flag determines whether it is |
| 324 // QuadSpillSlot to ensure that indexes of quad and double spill slots | 319 // QuadSpillSlot to ensure that indexes of quad and double spill slots |
| 325 // are disjoint. | 320 // are disjoint. |
| 326 GrowableArray<bool> quad_spill_slots_; | 321 GrowableArray<bool> quad_spill_slots_; |
| 327 | 322 |
| 328 // Track whether a spill slot is expected to hold a tagged or untagged value. | 323 // Track whether a spill slot is expected to hold a tagged or untagged value. |
| 329 // This is used to keep tagged and untagged spill slots disjoint. See bug | 324 // This is used to keep tagged and untagged spill slots disjoint. See bug |
| 330 // #18955 for details. | 325 // #18955 for details. |
| 331 GrowableArray<bool> untagged_spill_slots_; | 326 GrowableArray<bool> untagged_spill_slots_; |
| 332 | 327 |
| 333 intptr_t cpu_spill_slot_count_; | 328 intptr_t cpu_spill_slot_count_; |
| 334 | 329 |
| 335 const bool intrinsic_mode_; | 330 const bool intrinsic_mode_; |
| 336 | 331 |
| 337 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); | 332 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator); |
| 338 }; | 333 }; |
| 339 | 334 |
| 340 | |
| 341 // Additional information about a block that is not contained in a | 335 // Additional information about a block that is not contained in a |
| 342 // block entry. | 336 // block entry. |
| 343 class BlockInfo : public ZoneAllocated { | 337 class BlockInfo : public ZoneAllocated { |
| 344 public: | 338 public: |
| 345 explicit BlockInfo(BlockEntryInstr* entry) | 339 explicit BlockInfo(BlockEntryInstr* entry) |
| 346 : entry_(entry), | 340 : entry_(entry), |
| 347 loop_(NULL), | 341 loop_(NULL), |
| 348 is_loop_header_(false), | 342 is_loop_header_(false), |
| 349 backedge_interference_(NULL) {} | 343 backedge_interference_(NULL) {} |
| 350 | 344 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 bool is_loop_header_; | 387 bool is_loop_header_; |
| 394 | 388 |
| 395 BlockEntryInstr* last_block_; | 389 BlockEntryInstr* last_block_; |
| 396 intptr_t loop_id_; | 390 intptr_t loop_id_; |
| 397 | 391 |
| 398 BitVector* backedge_interference_; | 392 BitVector* backedge_interference_; |
| 399 | 393 |
| 400 DISALLOW_COPY_AND_ASSIGN(BlockInfo); | 394 DISALLOW_COPY_AND_ASSIGN(BlockInfo); |
| 401 }; | 395 }; |
| 402 | 396 |
| 403 | |
| 404 // UsePosition represents a single use of an SSA value by some instruction. | 397 // UsePosition represents a single use of an SSA value by some instruction. |
| 405 // It points to a location slot which either tells register allocator | 398 // It points to a location slot which either tells register allocator |
| 406 // where instruction expects the value (if slot contains a fixed location) or | 399 // where instruction expects the value (if slot contains a fixed location) or |
| 407 // asks register allocator to allocate storage (register or spill slot) for | 400 // asks register allocator to allocate storage (register or spill slot) for |
| 408 // this use with certain properties (if slot contains an unallocated location). | 401 // this use with certain properties (if slot contains an unallocated location). |
| 409 class UsePosition : public ZoneAllocated { | 402 class UsePosition : public ZoneAllocated { |
| 410 public: | 403 public: |
| 411 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) | 404 UsePosition(intptr_t pos, UsePosition* next, Location* location_slot) |
| 412 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { | 405 : pos_(pos), location_slot_(location_slot), hint_(NULL), next_(next) { |
| 413 ASSERT(location_slot != NULL); | 406 ASSERT(location_slot != NULL); |
| 414 } | 407 } |
| 415 | 408 |
| 416 Location* location_slot() const { return location_slot_; } | 409 Location* location_slot() const { return location_slot_; } |
| 417 void set_location_slot(Location* location_slot) { | 410 void set_location_slot(Location* location_slot) { |
| 418 location_slot_ = location_slot; | 411 location_slot_ = location_slot; |
| 419 } | 412 } |
| 420 | 413 |
| 421 Location hint() const { | 414 Location hint() const { |
| 422 ASSERT(HasHint()); | 415 ASSERT(HasHint()); |
| 423 return *hint_; | 416 return *hint_; |
| 424 } | 417 } |
| 425 | 418 |
| 426 void set_hint(Location* hint) { hint_ = hint; } | 419 void set_hint(Location* hint) { hint_ = hint; } |
| 427 | 420 |
| 428 bool HasHint() const { return (hint_ != NULL) && !hint_->IsUnallocated(); } | 421 bool HasHint() const { return (hint_ != NULL) && !hint_->IsUnallocated(); } |
| 429 | 422 |
| 430 | |
| 431 void set_next(UsePosition* next) { next_ = next; } | 423 void set_next(UsePosition* next) { next_ = next; } |
| 432 UsePosition* next() const { return next_; } | 424 UsePosition* next() const { return next_; } |
| 433 | 425 |
| 434 intptr_t pos() const { return pos_; } | 426 intptr_t pos() const { return pos_; } |
| 435 | 427 |
| 436 private: | 428 private: |
| 437 const intptr_t pos_; | 429 const intptr_t pos_; |
| 438 Location* location_slot_; | 430 Location* location_slot_; |
| 439 Location* hint_; | 431 Location* hint_; |
| 440 UsePosition* next_; | 432 UsePosition* next_; |
| 441 | 433 |
| 442 DISALLOW_COPY_AND_ASSIGN(UsePosition); | 434 DISALLOW_COPY_AND_ASSIGN(UsePosition); |
| 443 }; | 435 }; |
| 444 | 436 |
| 445 | |
| 446 // UseInterval represents a holeless half open interval of liveness for a given | 437 // UseInterval represents a holeless half open interval of liveness for a given |
| 447 // SSA value: [start, end) in terms of lifetime positions that | 438 // SSA value: [start, end) in terms of lifetime positions that |
| 448 // NumberInstructions assigns to instructions. Register allocator has to keep | 439 // NumberInstructions assigns to instructions. Register allocator has to keep |
| 449 // a value live in the register or in a spill slot from start position and until | 440 // a value live in the register or in a spill slot from start position and until |
| 450 // the end position. The interval can cover zero or more uses. | 441 // the end position. The interval can cover zero or more uses. |
| 451 // Note: currently all uses of the same SSA value are linked together into a | 442 // Note: currently all uses of the same SSA value are linked together into a |
| 452 // single list (and not split between UseIntervals). | 443 // single list (and not split between UseIntervals). |
| 453 class UseInterval : public ZoneAllocated { | 444 class UseInterval : public ZoneAllocated { |
| 454 public: | 445 public: |
| 455 UseInterval(intptr_t start, intptr_t end, UseInterval* next) | 446 UseInterval(intptr_t start, intptr_t end, UseInterval* next) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 472 private: | 463 private: |
| 473 friend class LiveRange; | 464 friend class LiveRange; |
| 474 | 465 |
| 475 intptr_t start_; | 466 intptr_t start_; |
| 476 intptr_t end_; | 467 intptr_t end_; |
| 477 UseInterval* next_; | 468 UseInterval* next_; |
| 478 | 469 |
| 479 DISALLOW_COPY_AND_ASSIGN(UseInterval); | 470 DISALLOW_COPY_AND_ASSIGN(UseInterval); |
| 480 }; | 471 }; |
| 481 | 472 |
| 482 | |
| 483 // AllocationFinger is used to keep track of currently active position | 473 // AllocationFinger is used to keep track of currently active position |
| 484 // for the register allocator and cache lookup results. | 474 // for the register allocator and cache lookup results. |
| 485 class AllocationFinger : public ValueObject { | 475 class AllocationFinger : public ValueObject { |
| 486 public: | 476 public: |
| 487 AllocationFinger() | 477 AllocationFinger() |
| 488 : first_pending_use_interval_(NULL), | 478 : first_pending_use_interval_(NULL), |
| 489 first_register_use_(NULL), | 479 first_register_use_(NULL), |
| 490 first_register_beneficial_use_(NULL), | 480 first_register_beneficial_use_(NULL), |
| 491 first_hinted_use_(NULL) {} | 481 first_hinted_use_(NULL) {} |
| 492 | 482 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 505 | 495 |
| 506 private: | 496 private: |
| 507 UseInterval* first_pending_use_interval_; | 497 UseInterval* first_pending_use_interval_; |
| 508 UsePosition* first_register_use_; | 498 UsePosition* first_register_use_; |
| 509 UsePosition* first_register_beneficial_use_; | 499 UsePosition* first_register_beneficial_use_; |
| 510 UsePosition* first_hinted_use_; | 500 UsePosition* first_hinted_use_; |
| 511 | 501 |
| 512 DISALLOW_COPY_AND_ASSIGN(AllocationFinger); | 502 DISALLOW_COPY_AND_ASSIGN(AllocationFinger); |
| 513 }; | 503 }; |
| 514 | 504 |
| 515 | |
| 516 class SafepointPosition : public ZoneAllocated { | 505 class SafepointPosition : public ZoneAllocated { |
| 517 public: | 506 public: |
| 518 SafepointPosition(intptr_t pos, LocationSummary* locs) | 507 SafepointPosition(intptr_t pos, LocationSummary* locs) |
| 519 : pos_(pos), locs_(locs), next_(NULL) {} | 508 : pos_(pos), locs_(locs), next_(NULL) {} |
| 520 | 509 |
| 521 void set_next(SafepointPosition* next) { next_ = next; } | 510 void set_next(SafepointPosition* next) { next_ = next; } |
| 522 SafepointPosition* next() const { return next_; } | 511 SafepointPosition* next() const { return next_; } |
| 523 | 512 |
| 524 intptr_t pos() const { return pos_; } | 513 intptr_t pos() const { return pos_; } |
| 525 | 514 |
| 526 LocationSummary* locs() const { return locs_; } | 515 LocationSummary* locs() const { return locs_; } |
| 527 | 516 |
| 528 private: | 517 private: |
| 529 const intptr_t pos_; | 518 const intptr_t pos_; |
| 530 LocationSummary* const locs_; | 519 LocationSummary* const locs_; |
| 531 | 520 |
| 532 SafepointPosition* next_; | 521 SafepointPosition* next_; |
| 533 }; | 522 }; |
| 534 | 523 |
| 535 | |
| 536 // LiveRange represents a sequence of UseIntervals for a given SSA value. | 524 // LiveRange represents a sequence of UseIntervals for a given SSA value. |
| 537 class LiveRange : public ZoneAllocated { | 525 class LiveRange : public ZoneAllocated { |
| 538 public: | 526 public: |
| 539 explicit LiveRange(intptr_t vreg, Representation rep) | 527 explicit LiveRange(intptr_t vreg, Representation rep) |
| 540 : vreg_(vreg), | 528 : vreg_(vreg), |
| 541 representation_(rep), | 529 representation_(rep), |
| 542 assigned_location_(), | 530 assigned_location_(), |
| 543 spill_slot_(), | 531 spill_slot_(), |
| 544 uses_(NULL), | 532 uses_(NULL), |
| 545 first_use_interval_(NULL), | 533 first_use_interval_(NULL), |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 LiveRange* next_sibling_; | 639 LiveRange* next_sibling_; |
| 652 | 640 |
| 653 intptr_t has_only_any_uses_in_loops_; | 641 intptr_t has_only_any_uses_in_loops_; |
| 654 bool is_loop_phi_; | 642 bool is_loop_phi_; |
| 655 | 643 |
| 656 AllocationFinger finger_; | 644 AllocationFinger finger_; |
| 657 | 645 |
| 658 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 646 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
| 659 }; | 647 }; |
| 660 | 648 |
| 661 | |
| 662 } // namespace dart | 649 } // namespace dart |
| 663 | 650 |
| 664 #endif // RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ | 651 #endif // RUNTIME_VM_FLOW_GRAPH_ALLOCATOR_H_ |
| OLD | NEW |