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 |