| 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 void MergeDisjointIntervals(UseInterval* other); | 405 void MergeDisjointIntervals(UseInterval* other); |
| 406 | 406 |
| 407 ZoneVector<LiveRange*> live_ranges_; | 407 ZoneVector<LiveRange*> live_ranges_; |
| 408 UseInterval* use_interval_; | 408 UseInterval* use_interval_; |
| 409 LifetimePosition end_position_; | 409 LifetimePosition end_position_; |
| 410 | 410 |
| 411 DISALLOW_COPY_AND_ASSIGN(SpillRange); | 411 DISALLOW_COPY_AND_ASSIGN(SpillRange); |
| 412 }; | 412 }; |
| 413 | 413 |
| 414 | 414 |
| 415 class RegisterAllocator FINAL : public ZoneObject { | 415 class RegisterAllocator : public ZoneObject { |
| 416 public: | 416 public: |
| 417 explicit RegisterAllocator(const RegisterConfiguration* config, | 417 explicit RegisterAllocator(const RegisterConfiguration* config, |
| 418 Zone* local_zone, Frame* frame, | 418 Zone* local_zone, Frame* frame, |
| 419 InstructionSequence* code, | 419 InstructionSequence* code, |
| 420 const char* debug_name = nullptr); | 420 const char* debug_name = nullptr); |
| 421 | 421 |
| 422 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; } | 422 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; } |
| 423 const ZoneVector<LiveRange*>& fixed_live_ranges() const { | 423 const ZoneVector<LiveRange*>& fixed_live_ranges() const { |
| 424 return fixed_live_ranges_; | 424 return fixed_live_ranges_; |
| 425 } | 425 } |
| 426 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { | 426 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const { |
| 427 return fixed_double_live_ranges_; | 427 return fixed_double_live_ranges_; |
| 428 } | 428 } |
| 429 InstructionSequence* code() const { return code_; } | 429 InstructionSequence* code() const { return code_; } |
| 430 // This zone is for datastructures only needed during register allocation. | 430 // This zone is for datastructures only needed during register allocation. |
| 431 Zone* local_zone() const { return local_zone_; } | 431 Zone* local_zone() const { return local_zone_; } |
| 432 | 432 |
| 433 // Phase 1 : insert moves to account for fixed register operands. | 433 // Phase 1 : insert moves to account for fixed register operands. |
| 434 void MeetRegisterConstraints(); | 434 void MeetRegisterConstraints(); |
| 435 | 435 |
| 436 // Phase 2: deconstruct SSA by inserting moves in successors and the headers | 436 // Phase 2: deconstruct SSA by inserting moves in successors and the headers |
| 437 // of blocks containing phis. | 437 // of blocks containing phis. |
| 438 void ResolvePhis(); | 438 void ResolvePhis(); |
| 439 | 439 |
| 440 // Phase 3: compute liveness of all virtual register. | 440 // Phase 3: compute liveness of all virtual register. |
| 441 void BuildLiveRanges(); | 441 void BuildLiveRanges(); |
| 442 bool ExistsUseWithoutDefinition(); | 442 bool ExistsUseWithoutDefinition(); |
| 443 | 443 |
| 444 // Phase 4: compute register assignments. | 444 // Phase 4: compute register assignments. |
| 445 void AllocateGeneralRegisters(); | 445 virtual void AllocateGeneralRegisters() = 0; |
| 446 void AllocateDoubleRegisters(); | 446 virtual void AllocateDoubleRegisters() = 0; |
| 447 | 447 |
| 448 // Phase 5: assign spill splots. | 448 // Phase 5: assign spill splots. |
| 449 void AssignSpillSlots(); | 449 void AssignSpillSlots(); |
| 450 | 450 |
| 451 // Phase 6: commit assignment. | 451 // Phase 6: commit assignment. |
| 452 void CommitAssignment(); | 452 void CommitAssignment(); |
| 453 | 453 |
| 454 // Phase 7: compute values for pointer maps. | 454 // Phase 7: compute values for pointer maps. |
| 455 void PopulateReferenceMaps(); | 455 void PopulateReferenceMaps(); |
| 456 | 456 |
| 457 // Phase 8: reconnect split ranges with moves. | 457 // Phase 8: reconnect split ranges with moves. |
| 458 void ConnectRanges(); | 458 void ConnectRanges(); |
| 459 | 459 |
| 460 // Phase 9: insert moves to connect ranges across basic blocks. | 460 // Phase 9: insert moves to connect ranges across basic blocks. |
| 461 void ResolveControlFlow(); | 461 void ResolveControlFlow(); |
| 462 | 462 |
| 463 private: | 463 protected: |
| 464 int GetVirtualRegister() { return code()->NextVirtualRegister(); } | 464 virtual ~RegisterAllocator() {} |
| 465 class PhiMapValue : public ZoneObject { |
| 466 public: |
| 467 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone) |
| 468 : phi(phi), block(block), incoming_moves(zone) { |
| 469 incoming_moves.reserve(phi->operands().size()); |
| 470 } |
| 471 PhiInstruction* const phi; |
| 472 const InstructionBlock* const block; |
| 473 ZoneVector<MoveOperands*> incoming_moves; |
| 474 }; |
| 475 typedef ZoneMap<int, PhiMapValue*> PhiMap; |
| 476 PhiMap& phi_map() { return phi_map_; } |
| 465 | 477 |
| 478 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } |
| 479 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } |
| 480 ZoneVector<LiveRange*>& fixed_double_live_ranges() { |
| 481 return fixed_double_live_ranges_; |
| 482 } |
| 483 |
| 484 BitVector* assigned_registers() const { return assigned_registers_; } |
| 485 BitVector* assigned_double_registers() const { |
| 486 return assigned_double_registers_; |
| 487 } |
| 488 |
| 489 Frame* frame() const { return frame_; } |
| 490 const char* debug_name() const { return debug_name_; } |
| 491 const RegisterConfiguration* config() const { return config_; } |
| 492 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } |
| 493 |
| 494 // This zone is for InstructionOperands and moves that live beyond register |
| 495 // allocation. |
| 496 Zone* code_zone() const { return code()->zone(); } |
| 497 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } |
| 498 // Creates a new live range. |
| 499 LiveRange* NewLiveRange(int index); |
| 500 |
| 501 LiveRange* LiveRangeFor(int index); |
| 502 LiveRange* LiveRangeFor(InstructionOperand* operand); |
| 503 LiveRange* FixedLiveRangeFor(int index); |
| 504 LiveRange* FixedDoubleLiveRangeFor(int index); |
| 505 static int FixedLiveRangeID(int index) { return -index - 1; } |
| 506 int FixedDoubleLiveRangeID(int index); |
| 507 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); |
| 508 |
| 509 // Helper methods for building intervals. |
| 510 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, |
| 511 bool is_tagged); |
| 512 |
| 513 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, |
| 514 const InstructionOperand& from, |
| 515 const InstructionOperand& to); |
| 466 // Checks whether the value of a given virtual register is a reference. | 516 // Checks whether the value of a given virtual register is a reference. |
| 467 // TODO(titzer): rename this to IsReference. | 517 // TODO(titzer): rename this to IsReference. |
| 468 bool HasTaggedValue(int virtual_register) const; | 518 bool HasTaggedValue(int virtual_register) const; |
| 469 | 519 |
| 520 bool IsBlockBoundary(LifetimePosition pos); |
| 521 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
| 522 |
| 523 // Return the block which contains give lifetime position. |
| 524 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); |
| 525 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); |
| 526 void Spill(LiveRange* range); |
| 527 |
| 528 // Live range splitting helpers. |
| 529 // Split the given range at the given position. |
| 530 // If range starts at or after the given position then the |
| 531 // original range is returned. |
| 532 // Otherwise returns the live range that starts at pos and contains |
| 533 // all uses from the original range that follow pos. Uses at pos will |
| 534 // still be owned by the original range after splitting. |
| 535 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); |
| 536 |
| 537 // Split the given range in a position from the interval [start, end]. |
| 538 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, |
| 539 LifetimePosition end); |
| 540 |
| 541 // Find a lifetime position in the interval [start, end] which |
| 542 // is optimal for splitting: it is either header of the outermost |
| 543 // loop covered by this interval or the latest possible position. |
| 544 LifetimePosition FindOptimalSplitPos(LifetimePosition start, |
| 545 LifetimePosition end); |
| 546 |
| 547 |
| 548 private: |
| 549 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); |
| 550 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); |
| 551 void ProcessInstructions(const InstructionBlock* block, BitVector* live); |
| 552 Instruction* GetLastInstruction(const InstructionBlock* block); |
| 553 void Define(LifetimePosition position, InstructionOperand* operand, |
| 554 InstructionOperand* hint); |
| 555 int GetVirtualRegister() { return code()->NextVirtualRegister(); } |
| 556 void Use(LifetimePosition block_start, LifetimePosition position, |
| 557 InstructionOperand* operand, InstructionOperand* hint); |
| 470 // Returns the register kind required by the given virtual register. | 558 // Returns the register kind required by the given virtual register. |
| 471 RegisterKind RequiredRegisterKind(int virtual_register) const; | 559 RegisterKind RequiredRegisterKind(int virtual_register) const; |
| 472 | 560 |
| 473 // Creates a new live range. | 561 bool IsOutputRegisterOf(Instruction* instr, int index); |
| 474 LiveRange* NewLiveRange(int index); | 562 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); |
| 475 | 563 |
| 476 // This zone is for InstructionOperands and moves that live beyond register | 564 void ResolvePhis(const InstructionBlock* block); |
| 477 // allocation. | 565 void MeetRegisterConstraints(const InstructionBlock* block); |
| 478 Zone* code_zone() const { return code()->zone(); } | 566 void MeetConstraintsBefore(int index); |
| 567 void MeetConstraintsAfter(int index); |
| 568 void MeetRegisterConstraintsForLastInstructionInBlock( |
| 569 const InstructionBlock* block); |
| 479 | 570 |
| 480 BitVector* assigned_registers() { return assigned_registers_; } | 571 // Helper methods for resolving control flow. |
| 481 BitVector* assigned_double_registers() { return assigned_double_registers_; } | 572 void ResolveControlFlow(const InstructionBlock* block, |
| 573 const InstructionOperand& cur_op, |
| 574 const InstructionBlock* pred, |
| 575 const InstructionOperand& pred_op); |
| 576 bool SafePointsAreInOrder() const; |
| 482 | 577 |
| 578 // Liveness analysis support. |
| 579 BitVector* ComputeLiveOut(const InstructionBlock* block); |
| 580 |
| 581 Zone* const local_zone_; |
| 582 Frame* const frame_; |
| 583 InstructionSequence* const code_; |
| 584 const char* const debug_name_; |
| 585 const RegisterConfiguration* config_; |
| 586 PhiMap phi_map_; |
| 587 |
| 588 // Liveness analysis results. |
| 589 ZoneVector<LiveRange*> live_ranges_; |
| 590 |
| 591 // Lists of live ranges. |
| 592 ZoneVector<LiveRange*> fixed_live_ranges_; |
| 593 ZoneVector<LiveRange*> fixed_double_live_ranges_; |
| 594 ZoneVector<SpillRange*> spill_ranges_; |
| 595 |
| 596 // During liveness analysis keep a mapping from block id to live_in sets |
| 597 // for blocks already analyzed. |
| 598 ZoneVector<BitVector*> live_in_sets_; |
| 599 |
| 600 BitVector* assigned_registers_; |
| 601 BitVector* assigned_double_registers_; |
| 602 }; |
| 603 |
| 604 |
| 605 class RegisterAllocatorLinear FINAL : public RegisterAllocator { |
| 606 public: |
| 607 explicit RegisterAllocatorLinear(const RegisterConfiguration* config, |
| 608 Zone* local_zone, Frame* frame, |
| 609 InstructionSequence* code, |
| 610 const char* debug_name = nullptr); |
| 611 void AllocateGeneralRegisters() override; |
| 612 void AllocateDoubleRegisters() override; |
| 613 |
| 614 private: |
| 483 #ifdef DEBUG | 615 #ifdef DEBUG |
| 484 void Verify() const; | 616 void Verify() const; |
| 485 #endif | 617 #endif |
| 486 | 618 |
| 487 void AllocateRegisters(); | 619 void AllocateRegisters(); |
| 488 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | |
| 489 bool SafePointsAreInOrder() const; | |
| 490 | |
| 491 // Liveness analysis support. | |
| 492 BitVector* ComputeLiveOut(const InstructionBlock* block); | |
| 493 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); | |
| 494 bool IsOutputRegisterOf(Instruction* instr, int index); | |
| 495 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); | |
| 496 void ProcessInstructions(const InstructionBlock* block, BitVector* live); | |
| 497 void MeetRegisterConstraints(const InstructionBlock* block); | |
| 498 void MeetConstraintsBefore(int index); | |
| 499 void MeetConstraintsAfter(int index); | |
| 500 void MeetRegisterConstraintsForLastInstructionInBlock( | |
| 501 const InstructionBlock* block); | |
| 502 void ResolvePhis(const InstructionBlock* block); | |
| 503 | |
| 504 // Helper methods for building intervals. | |
| 505 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, | |
| 506 bool is_tagged); | |
| 507 LiveRange* LiveRangeFor(InstructionOperand* operand); | |
| 508 void Define(LifetimePosition position, InstructionOperand* operand, | |
| 509 InstructionOperand* hint); | |
| 510 void Use(LifetimePosition block_start, LifetimePosition position, | |
| 511 InstructionOperand* operand, InstructionOperand* hint); | |
| 512 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, | |
| 513 const InstructionOperand& from, | |
| 514 const InstructionOperand& to); | |
| 515 | 620 |
| 516 // Helper methods for updating the life range lists. | 621 // Helper methods for updating the life range lists. |
| 517 void AddToActive(LiveRange* range); | 622 void AddToActive(LiveRange* range); |
| 518 void AddToInactive(LiveRange* range); | 623 void AddToInactive(LiveRange* range); |
| 519 void AddToUnhandledSorted(LiveRange* range); | 624 void AddToUnhandledSorted(LiveRange* range); |
| 520 void AddToUnhandledUnsorted(LiveRange* range); | 625 void AddToUnhandledUnsorted(LiveRange* range); |
| 521 void SortUnhandled(); | 626 void SortUnhandled(); |
| 522 bool UnhandledIsSorted(); | 627 bool UnhandledIsSorted(); |
| 523 void ActiveToHandled(LiveRange* range); | 628 void ActiveToHandled(LiveRange* range); |
| 524 void ActiveToInactive(LiveRange* range); | 629 void ActiveToInactive(LiveRange* range); |
| 525 void InactiveToHandled(LiveRange* range); | 630 void InactiveToHandled(LiveRange* range); |
| 526 void InactiveToActive(LiveRange* range); | 631 void InactiveToActive(LiveRange* range); |
| 527 | 632 |
| 528 // Helper methods for allocating registers. | 633 // Helper methods for allocating registers. |
| 529 bool TryReuseSpillForPhi(LiveRange* range); | 634 bool TryReuseSpillForPhi(LiveRange* range); |
| 530 bool TryAllocateFreeReg(LiveRange* range); | 635 bool TryAllocateFreeReg(LiveRange* range); |
| 531 void AllocateBlockedReg(LiveRange* range); | 636 void AllocateBlockedReg(LiveRange* range); |
| 532 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); | |
| 533 | |
| 534 // Live range splitting helpers. | |
| 535 | |
| 536 // Split the given range at the given position. | |
| 537 // If range starts at or after the given position then the | |
| 538 // original range is returned. | |
| 539 // Otherwise returns the live range that starts at pos and contains | |
| 540 // all uses from the original range that follow pos. Uses at pos will | |
| 541 // still be owned by the original range after splitting. | |
| 542 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); | |
| 543 | |
| 544 // Split the given range in a position from the interval [start, end]. | |
| 545 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, | |
| 546 LifetimePosition end); | |
| 547 | |
| 548 // Find a lifetime position in the interval [start, end] which | |
| 549 // is optimal for splitting: it is either header of the outermost | |
| 550 // loop covered by this interval or the latest possible position. | |
| 551 LifetimePosition FindOptimalSplitPos(LifetimePosition start, | |
| 552 LifetimePosition end); | |
| 553 | 637 |
| 554 // Spill the given life range after position pos. | 638 // Spill the given life range after position pos. |
| 555 void SpillAfter(LiveRange* range, LifetimePosition pos); | 639 void SpillAfter(LiveRange* range, LifetimePosition pos); |
| 556 | 640 |
| 557 // Spill the given life range after position [start] and up to position [end]. | 641 // Spill the given life range after position [start] and up to position [end]. |
| 558 void SpillBetween(LiveRange* range, LifetimePosition start, | 642 void SpillBetween(LiveRange* range, LifetimePosition start, |
| 559 LifetimePosition end); | 643 LifetimePosition end); |
| 560 | 644 |
| 561 // Spill the given life range after position [start] and up to position [end]. | 645 // Spill the given life range after position [start] and up to position [end]. |
| 562 // Range is guaranteed to be spilled at least until position [until]. | 646 // Range is guaranteed to be spilled at least until position [until]. |
| 563 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 647 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
| 564 LifetimePosition until, LifetimePosition end); | 648 LifetimePosition until, LifetimePosition end); |
| 565 | 649 |
| 566 void SplitAndSpillIntersecting(LiveRange* range); | 650 void SplitAndSpillIntersecting(LiveRange* range); |
| 567 | 651 |
| 568 // If we are trying to spill a range inside the loop try to | 652 // If we are trying to spill a range inside the loop try to |
| 569 // hoist spill position out to the point just before the loop. | 653 // hoist spill position out to the point just before the loop. |
| 570 LifetimePosition FindOptimalSpillingPos(LiveRange* range, | 654 LifetimePosition FindOptimalSpillingPos(LiveRange* range, |
| 571 LifetimePosition pos); | 655 LifetimePosition pos); |
| 572 | 656 |
| 573 void Spill(LiveRange* range); | |
| 574 bool IsBlockBoundary(LifetimePosition pos); | |
| 575 | |
| 576 // Helper methods for resolving control flow. | |
| 577 void ResolveControlFlow(const InstructionBlock* block, | |
| 578 const InstructionOperand& cur_op, | |
| 579 const InstructionBlock* pred, | |
| 580 const InstructionOperand& pred_op); | |
| 581 | |
| 582 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); | |
| 583 | |
| 584 // Return the block which contains give lifetime position. | |
| 585 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); | |
| 586 | |
| 587 // Helper methods for the fixed registers. | 657 // Helper methods for the fixed registers. |
| 588 int RegisterCount() const; | 658 int RegisterCount() const; |
| 589 static int FixedLiveRangeID(int index) { return -index - 1; } | |
| 590 int FixedDoubleLiveRangeID(int index); | |
| 591 LiveRange* FixedLiveRangeFor(int index); | |
| 592 LiveRange* FixedDoubleLiveRangeFor(int index); | |
| 593 LiveRange* LiveRangeFor(int index); | |
| 594 Instruction* GetLastInstruction(const InstructionBlock* block); | |
| 595 | 659 |
| 596 const char* RegisterName(int allocation_index); | 660 const char* RegisterName(int allocation_index); |
| 597 | |
| 598 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | |
| 599 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); | |
| 600 | |
| 601 Frame* frame() const { return frame_; } | |
| 602 const char* debug_name() const { return debug_name_; } | |
| 603 const RegisterConfiguration* config() const { return config_; } | |
| 604 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } | |
| 605 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } | |
| 606 ZoneVector<LiveRange*>& fixed_double_live_ranges() { | |
| 607 return fixed_double_live_ranges_; | |
| 608 } | |
| 609 ZoneVector<LiveRange*>& unhandled_live_ranges() { | 661 ZoneVector<LiveRange*>& unhandled_live_ranges() { |
| 610 return unhandled_live_ranges_; | 662 return unhandled_live_ranges_; |
| 611 } | 663 } |
| 612 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } | 664 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } |
| 613 ZoneVector<LiveRange*>& inactive_live_ranges() { | 665 ZoneVector<LiveRange*>& inactive_live_ranges() { |
| 614 return inactive_live_ranges_; | 666 return inactive_live_ranges_; |
| 615 } | 667 } |
| 616 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } | |
| 617 | 668 |
| 618 class PhiMapValue : public ZoneObject { | |
| 619 public: | |
| 620 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone) | |
| 621 : phi(phi), block(block), incoming_moves(zone) { | |
| 622 incoming_moves.reserve(phi->operands().size()); | |
| 623 } | |
| 624 PhiInstruction* const phi; | |
| 625 const InstructionBlock* const block; | |
| 626 ZoneVector<MoveOperands*> incoming_moves; | |
| 627 }; | |
| 628 typedef ZoneMap<int, PhiMapValue*> PhiMap; | |
| 629 | 669 |
| 630 Zone* const local_zone_; | |
| 631 Frame* const frame_; | |
| 632 InstructionSequence* const code_; | |
| 633 const char* const debug_name_; | |
| 634 | |
| 635 const RegisterConfiguration* config_; | |
| 636 PhiMap phi_map_; | |
| 637 | |
| 638 // During liveness analysis keep a mapping from block id to live_in sets | |
| 639 // for blocks already analyzed. | |
| 640 ZoneVector<BitVector*> live_in_sets_; | |
| 641 | |
| 642 // Liveness analysis results. | |
| 643 ZoneVector<LiveRange*> live_ranges_; | |
| 644 | |
| 645 // Lists of live ranges | |
| 646 ZoneVector<LiveRange*> fixed_live_ranges_; | |
| 647 ZoneVector<LiveRange*> fixed_double_live_ranges_; | |
| 648 ZoneVector<LiveRange*> unhandled_live_ranges_; | 670 ZoneVector<LiveRange*> unhandled_live_ranges_; |
| 649 ZoneVector<LiveRange*> active_live_ranges_; | 671 ZoneVector<LiveRange*> active_live_ranges_; |
| 650 ZoneVector<LiveRange*> inactive_live_ranges_; | 672 ZoneVector<LiveRange*> inactive_live_ranges_; |
| 651 ZoneVector<SpillRange*> spill_ranges_; | |
| 652 | 673 |
| 653 RegisterKind mode_; | 674 RegisterKind mode_; |
| 654 int num_registers_; | 675 int num_registers_; |
| 655 | 676 |
| 656 BitVector* assigned_registers_; | |
| 657 BitVector* assigned_double_registers_; | |
| 658 | |
| 659 #ifdef DEBUG | 677 #ifdef DEBUG |
| 660 LifetimePosition allocation_finger_; | 678 LifetimePosition allocation_finger_; |
| 661 #endif | 679 #endif |
| 662 | 680 |
| 663 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 681 DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorLinear); |
| 682 }; |
| 683 |
| 684 |
| 685 class RegisterAllocationInfo; |
| 686 |
| 687 |
| 688 class RegisterAllocatorGreedy FINAL : public RegisterAllocator { |
| 689 public: |
| 690 explicit RegisterAllocatorGreedy(const RegisterConfiguration* config, |
| 691 Zone* local_zone, Frame* frame, |
| 692 InstructionSequence* code, |
| 693 const char* debug_name = nullptr); |
| 694 |
| 695 void AllocateGeneralRegisters() override; |
| 696 void AllocateDoubleRegisters() override; |
| 697 |
| 698 private: |
| 699 void AllocateRegisters(RegisterKind mode); |
| 700 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; |
| 701 |
| 702 unsigned GetLiveRangeSize(LiveRange* range); |
| 703 void Enqueue(LiveRange* range); |
| 704 |
| 705 void Evict(LiveRange* range); |
| 706 float CalculateSpillWeight(LiveRange* range); |
| 707 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); |
| 708 |
| 709 |
| 710 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); |
| 711 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, |
| 712 ZoneSet<LiveRange*>* conflicting); |
| 713 bool HandleSpillOperands(LiveRange* range); |
| 714 bool AllocateBlockedRange(LiveRange*, const ZoneSet<LiveRange*>&); |
| 715 |
| 716 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
| 717 LifetimePosition until, LifetimePosition end); |
| 718 void AssignRangeToRegister(unsigned regId, LiveRange* range); |
| 719 |
| 720 ZoneVector<RegisterAllocationInfo*> allocations_; |
| 721 PQueue queue_; |
| 722 DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorGreedy); |
| 664 }; | 723 }; |
| 665 | 724 |
| 666 } // namespace compiler | 725 } // namespace compiler |
| 667 } // namespace internal | 726 } // namespace internal |
| 668 } // namespace v8 | 727 } // namespace v8 |
| 669 | 728 |
| 670 #endif // V8_REGISTER_ALLOCATOR_H_ | 729 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |