| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_REGISTER_ALLOCATOR_H_ | 5 #ifndef V8_REGISTER_ALLOCATOR_H_ |
| 6 #define V8_REGISTER_ALLOCATOR_H_ | 6 #define V8_REGISTER_ALLOCATOR_H_ |
| 7 | 7 |
| 8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
| 9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
| 10 | 10 |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 const ZoneVector<LiveRange*>& fixed_live_ranges() const { | 437 const ZoneVector<LiveRange*>& fixed_live_ranges() const { |
| 438 return fixed_live_ranges_; | 438 return fixed_live_ranges_; |
| 439 } | 439 } |
| 440 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } | 440 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } |
| 441 ZoneVector<LiveRange*>& fixed_double_live_ranges() { | 441 ZoneVector<LiveRange*>& fixed_double_live_ranges() { |
| 442 return fixed_double_live_ranges_; | 442 return fixed_double_live_ranges_; |
| 443 } | 443 } |
| 444 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { | 444 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { |
| 445 return fixed_double_live_ranges_; | 445 return fixed_double_live_ranges_; |
| 446 } | 446 } |
| 447 const ZoneVector<BitVector*>& live_in_sets() const { return live_in_sets_; } | |
| 448 ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } | 447 ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; } |
| 449 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } | 448 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } |
| 450 const ZoneVector<SpillRange*>& spill_ranges() const { return spill_ranges_; } | |
| 451 InstructionSequence* code() const { return code_; } | 449 InstructionSequence* code() const { return code_; } |
| 452 // This zone is for datastructures only needed during register allocation | 450 // This zone is for datastructures only needed during register allocation |
| 453 // phases. | 451 // phases. |
| 454 Zone* allocation_zone() const { return allocation_zone_; } | 452 Zone* allocation_zone() const { return allocation_zone_; } |
| 455 // This zone is for InstructionOperands and moves that live beyond register | 453 // This zone is for InstructionOperands and moves that live beyond register |
| 456 // allocation. | 454 // allocation. |
| 457 Zone* code_zone() const { return code()->zone(); } | 455 Zone* code_zone() const { return code()->zone(); } |
| 458 const PhiMap& phi_map() const { return phi_map_; } | 456 const PhiMap& phi_map() const { return phi_map_; } |
| 459 PhiMap& phi_map() { return phi_map_; } | 457 PhiMap& phi_map() { return phi_map_; } |
| 460 Frame* frame() const { return frame_; } | 458 Frame* frame() const { return frame_; } |
| 461 const char* debug_name() const { return debug_name_; } | 459 const char* debug_name() const { return debug_name_; } |
| 462 const RegisterConfiguration* config() const { return config_; } | 460 const RegisterConfiguration* config() const { return config_; } |
| 463 | 461 |
| 464 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); | 462 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); |
| 465 LiveRange* LiveRangeFor(int index); | 463 LiveRange* LiveRangeFor(int index); |
| 466 Instruction* InstructionAt(int index) const { | |
| 467 return code()->InstructionAt(index); | |
| 468 } | |
| 469 | 464 |
| 470 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); | 465 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); |
| 471 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); | 466 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); |
| 472 | 467 |
| 473 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, | 468 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, |
| 474 const InstructionOperand& from, | 469 const InstructionOperand& from, |
| 475 const InstructionOperand& to); | 470 const InstructionOperand& to); |
| 476 | 471 |
| 477 bool IsReference(int virtual_register) const { | 472 bool IsReference(int virtual_register) const { |
| 478 return code()->IsReference(virtual_register); | 473 return code()->IsReference(virtual_register); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 495 ZoneVector<LiveRange*> fixed_live_ranges_; | 490 ZoneVector<LiveRange*> fixed_live_ranges_; |
| 496 ZoneVector<LiveRange*> fixed_double_live_ranges_; | 491 ZoneVector<LiveRange*> fixed_double_live_ranges_; |
| 497 ZoneVector<SpillRange*> spill_ranges_; | 492 ZoneVector<SpillRange*> spill_ranges_; |
| 498 BitVector* assigned_registers_; | 493 BitVector* assigned_registers_; |
| 499 BitVector* assigned_double_registers_; | 494 BitVector* assigned_double_registers_; |
| 500 | 495 |
| 501 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); | 496 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); |
| 502 }; | 497 }; |
| 503 | 498 |
| 504 | 499 |
| 505 class LiveRangeBuilder final : public ZoneObject { | 500 class ConstraintBuilder final : public ZoneObject { |
| 506 public: | 501 public: |
| 507 explicit LiveRangeBuilder(RegisterAllocationData* data); | 502 explicit ConstraintBuilder(RegisterAllocationData* data); |
| 508 | 503 |
| 509 // Phase 1 : insert moves to account for fixed register operands. | 504 // Phase 1 : insert moves to account for fixed register operands. |
| 510 void MeetRegisterConstraints(); | 505 void MeetRegisterConstraints(); |
| 511 | 506 |
| 512 // Phase 2: deconstruct SSA by inserting moves in successors and the headers | 507 // Phase 2: deconstruct SSA by inserting moves in successors and the headers |
| 513 // of blocks containing phis. | 508 // of blocks containing phis. |
| 514 void ResolvePhis(); | 509 void ResolvePhis(); |
| 515 | 510 |
| 511 private: |
| 512 RegisterAllocationData* data() const { return data_; } |
| 513 InstructionSequence* code() const { return data()->code(); } |
| 514 Zone* allocation_zone() const { return data()->allocation_zone(); } |
| 515 |
| 516 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } |
| 517 bool IsReference(int virtual_register) const { |
| 518 return data()->IsReference(virtual_register); |
| 519 } |
| 520 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
| 521 |
| 522 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
| 523 bool is_tagged); |
| 524 void MeetRegisterConstraints(const InstructionBlock* block); |
| 525 void MeetConstraintsBefore(int index); |
| 526 void MeetConstraintsAfter(int index); |
| 527 void MeetRegisterConstraintsForLastInstructionInBlock( |
| 528 const InstructionBlock* block); |
| 529 void ResolvePhis(const InstructionBlock* block); |
| 530 |
| 531 RegisterAllocationData* const data_; |
| 532 |
| 533 DISALLOW_COPY_AND_ASSIGN(ConstraintBuilder); |
| 534 }; |
| 535 |
| 536 |
| 537 class LiveRangeBuilder final : public ZoneObject { |
| 538 public: |
| 539 explicit LiveRangeBuilder(RegisterAllocationData* data); |
| 540 |
| 516 // Phase 3: compute liveness of all virtual register. | 541 // Phase 3: compute liveness of all virtual register. |
| 517 void BuildLiveRanges(); | 542 void BuildLiveRanges(); |
| 518 | 543 |
| 519 private: | 544 private: |
| 520 RegisterAllocationData* data() const { return data_; } | 545 RegisterAllocationData* data() const { return data_; } |
| 521 InstructionSequence* code() const { return data()->code(); } | 546 InstructionSequence* code() const { return data()->code(); } |
| 522 Zone* allocation_zone() const { return data()->allocation_zone(); } | 547 Zone* allocation_zone() const { return data()->allocation_zone(); } |
| 523 Zone* code_zone() const { return code()->zone(); } | 548 Zone* code_zone() const { return code()->zone(); } |
| 524 const RegisterConfiguration* config() const { return data()->config(); } | 549 const RegisterConfiguration* config() const { return data()->config(); } |
| 525 ZoneVector<BitVector*>& live_in_sets() const { | 550 ZoneVector<BitVector*>& live_in_sets() const { |
| 526 return data()->live_in_sets(); | 551 return data()->live_in_sets(); |
| 527 } | 552 } |
| 528 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); } | |
| 529 ZoneVector<LiveRange*>& fixed_live_ranges() { | |
| 530 return data()->fixed_live_ranges(); | |
| 531 } | |
| 532 ZoneVector<LiveRange*>& fixed_double_live_ranges() { | |
| 533 return data()->fixed_double_live_ranges(); | |
| 534 } | |
| 535 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); } | |
| 536 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); } | |
| 537 | 553 |
| 538 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | 554 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
| 539 bool IsReference(int virtual_register) const { | |
| 540 return data()->IsReference(virtual_register); | |
| 541 } | |
| 542 | 555 |
| 543 void Verify() const; | 556 void Verify() const; |
| 544 | 557 |
| 545 // Liveness analysis support. | 558 // Liveness analysis support. |
| 546 BitVector* ComputeLiveOut(const InstructionBlock* block); | 559 BitVector* ComputeLiveOut(const InstructionBlock* block); |
| 547 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | 560 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
| 548 bool IsOutputRegisterOf(Instruction* instr, int index); | 561 bool IsOutputRegisterOf(Instruction* instr, int index); |
| 549 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); | 562 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); |
| 550 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | 563 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
| 551 void MeetRegisterConstraints(const InstructionBlock* block); | |
| 552 void MeetConstraintsBefore(int index); | |
| 553 void MeetConstraintsAfter(int index); | |
| 554 void MeetRegisterConstraintsForLastInstructionInBlock( | |
| 555 const InstructionBlock* block); | |
| 556 void ResolvePhis(const InstructionBlock* block); | |
| 557 | 564 |
| 558 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | |
| 559 static int FixedLiveRangeID(int index) { return -index - 1; } | 565 static int FixedLiveRangeID(int index) { return -index - 1; } |
| 560 int FixedDoubleLiveRangeID(int index); | 566 int FixedDoubleLiveRangeID(int index); |
| 561 LiveRange* FixedLiveRangeFor(int index); | 567 LiveRange* FixedLiveRangeFor(int index); |
| 562 LiveRange* FixedDoubleLiveRangeFor(int index); | 568 LiveRange* FixedDoubleLiveRangeFor(int index); |
| 563 Instruction* GetLastInstruction(const InstructionBlock* block); | |
| 564 | 569 |
| 565 // Returns the register kind required by the given virtual register. | 570 // Returns the register kind required by the given virtual register. |
| 566 RegisterKind RequiredRegisterKind(int virtual_register) const; | 571 RegisterKind RequiredRegisterKind(int virtual_register) const; |
| 567 | 572 |
| 568 // Helper methods for building intervals. | 573 // Helper methods for building intervals. |
| 569 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | |
| 570 bool is_tagged); | |
| 571 LiveRange* LiveRangeFor(InstructionOperand* operand); | 574 LiveRange* LiveRangeFor(InstructionOperand* operand); |
| 572 void Define(LifetimePosition position, InstructionOperand* operand, | 575 void Define(LifetimePosition position, InstructionOperand* operand, |
| 573 InstructionOperand* hint); | 576 InstructionOperand* hint); |
| 574 void Use(LifetimePosition block_start, LifetimePosition position, | 577 void Use(LifetimePosition block_start, LifetimePosition position, |
| 575 InstructionOperand* operand, InstructionOperand* hint); | 578 InstructionOperand* operand, InstructionOperand* hint); |
| 576 | 579 |
| 577 RegisterAllocationData* const data_; | 580 RegisterAllocationData* const data_; |
| 578 | 581 |
| 579 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); | 582 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); |
| 580 }; | 583 }; |
| 581 | 584 |
| 582 | 585 |
| 583 class LinearScanAllocator final : public ZoneObject { | 586 class LinearScanAllocator final : public ZoneObject { |
| 584 public: | 587 public: |
| 585 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, | 588 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, |
| 586 Zone* local_zone); | 589 Zone* local_zone); |
| 587 | 590 |
| 588 // Phase 4: compute register assignments. | 591 // Phase 4: compute register assignments. |
| 589 void AllocateRegisters(); | 592 void AllocateRegisters(); |
| 590 | 593 |
| 591 private: | 594 private: |
| 592 RegisterAllocationData* data() const { return data_; } | 595 RegisterAllocationData* data() const { return data_; } |
| 593 InstructionSequence* code() const { return data()->code(); } | 596 InstructionSequence* code() const { return data()->code(); } |
| 594 Zone* allocation_zone() const { return data()->allocation_zone(); } | 597 Zone* allocation_zone() const { return data()->allocation_zone(); } |
| 595 Zone* code_zone() const { return code()->zone(); } | |
| 596 const RegisterConfiguration* config() const { return data()->config(); } | |
| 597 int num_registers() const { return num_registers_; } | 598 int num_registers() const { return num_registers_; } |
| 598 const char* RegisterName(int allocation_index) const; | 599 const char* RegisterName(int allocation_index) const; |
| 599 | 600 |
| 600 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); } | |
| 601 ZoneVector<LiveRange*>& unhandled_live_ranges() { | 601 ZoneVector<LiveRange*>& unhandled_live_ranges() { |
| 602 return unhandled_live_ranges_; | 602 return unhandled_live_ranges_; |
| 603 } | 603 } |
| 604 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } | 604 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } |
| 605 ZoneVector<LiveRange*>& inactive_live_ranges() { | 605 ZoneVector<LiveRange*>& inactive_live_ranges() { |
| 606 return inactive_live_ranges_; | 606 return inactive_live_ranges_; |
| 607 } | 607 } |
| 608 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); } | |
| 609 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); } | |
| 610 | 608 |
| 611 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | |
| 612 bool IsReference(int virtual_register) const { | |
| 613 return data()->IsReference(virtual_register); | |
| 614 } | |
| 615 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | 609 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
| 616 | 610 |
| 617 // Helper methods for updating the life range lists. | 611 // Helper methods for updating the life range lists. |
| 618 void AddToActive(LiveRange* range); | 612 void AddToActive(LiveRange* range); |
| 619 void AddToInactive(LiveRange* range); | 613 void AddToInactive(LiveRange* range); |
| 620 void AddToUnhandledSorted(LiveRange* range); | 614 void AddToUnhandledSorted(LiveRange* range); |
| 621 void AddToUnhandledUnsorted(LiveRange* range); | 615 void AddToUnhandledUnsorted(LiveRange* range); |
| 622 void SortUnhandled(); | 616 void SortUnhandled(); |
| 623 bool UnhandledIsSorted(); | 617 bool UnhandledIsSorted(); |
| 624 void ActiveToHandled(LiveRange* range); | 618 void ActiveToHandled(LiveRange* range); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 | 702 |
| 709 | 703 |
| 710 class ReferenceMapPopulator final : public ZoneObject { | 704 class ReferenceMapPopulator final : public ZoneObject { |
| 711 public: | 705 public: |
| 712 explicit ReferenceMapPopulator(RegisterAllocationData* data); | 706 explicit ReferenceMapPopulator(RegisterAllocationData* data); |
| 713 | 707 |
| 714 // Phase 7: compute values for pointer maps. | 708 // Phase 7: compute values for pointer maps. |
| 715 void PopulateReferenceMaps(); | 709 void PopulateReferenceMaps(); |
| 716 | 710 |
| 717 private: | 711 private: |
| 712 RegisterAllocationData* data() const { return data_; } |
| 713 |
| 718 bool SafePointsAreInOrder() const; | 714 bool SafePointsAreInOrder() const; |
| 719 | 715 |
| 720 bool IsReference(int virtual_register) const { | |
| 721 return data()->IsReference(virtual_register); | |
| 722 } | |
| 723 | |
| 724 RegisterAllocationData* data() const { return data_; } | |
| 725 | |
| 726 RegisterAllocationData* const data_; | 716 RegisterAllocationData* const data_; |
| 727 | 717 |
| 728 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator); | 718 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator); |
| 729 }; | 719 }; |
| 730 | 720 |
| 731 | 721 |
| 732 class LiveRangeConnector final : public ZoneObject { | 722 class LiveRangeConnector final : public ZoneObject { |
| 733 public: | 723 public: |
| 734 explicit LiveRangeConnector(RegisterAllocationData* data); | 724 explicit LiveRangeConnector(RegisterAllocationData* data); |
| 735 | 725 |
| 736 // Phase 8: reconnect split ranges with moves. | 726 // Phase 8: reconnect split ranges with moves. |
| 737 void ConnectRanges(Zone* local_zone); | 727 void ConnectRanges(Zone* local_zone); |
| 738 | 728 |
| 739 // Phase 9: insert moves to connect ranges across basic blocks. | 729 // Phase 9: insert moves to connect ranges across basic blocks. |
| 740 void ResolveControlFlow(Zone* local_zone); | 730 void ResolveControlFlow(Zone* local_zone); |
| 741 | 731 |
| 742 private: | 732 private: |
| 733 RegisterAllocationData* data() const { return data_; } |
| 734 InstructionSequence* code() const { return data()->code(); } |
| 735 Zone* code_zone() const { return code()->zone(); } |
| 736 |
| 743 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | 737 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
| 744 void ResolveControlFlow(const InstructionBlock* block, | 738 void ResolveControlFlow(const InstructionBlock* block, |
| 745 const InstructionOperand& cur_op, | 739 const InstructionOperand& cur_op, |
| 746 const InstructionBlock* pred, | 740 const InstructionBlock* pred, |
| 747 const InstructionOperand& pred_op); | 741 const InstructionOperand& pred_op); |
| 748 InstructionSequence* code() const { return data()->code(); } | |
| 749 Zone* code_zone() const { return code()->zone(); } | |
| 750 RegisterAllocationData* data() const { return data_; } | |
| 751 | 742 |
| 752 RegisterAllocationData* const data_; | 743 RegisterAllocationData* const data_; |
| 753 | 744 |
| 754 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 745 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
| 755 }; | 746 }; |
| 756 | 747 |
| 757 } // namespace compiler | 748 } // namespace compiler |
| 758 } // namespace internal | 749 } // namespace internal |
| 759 } // namespace v8 | 750 } // namespace v8 |
| 760 | 751 |
| 761 #endif // V8_REGISTER_ALLOCATOR_H_ | 752 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |