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 class RegisterAllocatorGreedy FINAL : public RegisterAllocator { | |
685 public: | |
686 explicit RegisterAllocatorGreedy(const RegisterConfiguration* config, | |
687 Zone* local_zone, Frame* frame, | |
688 InstructionSequence* code, | |
689 const char* debug_name = nullptr); | |
690 | |
691 void AllocateGeneralRegisters() override; | |
692 void AllocateDoubleRegisters() override; | |
693 | |
694 private: | |
695 void AllocateRegisters(RegisterKind mode); | |
696 class RegisterAllocationInfo { | |
dcarney
2015/04/17 07:22:45
make ZoneObject
Mircea Trofin
2015/04/17 19:23:33
Done.
| |
697 public: | |
698 explicit RegisterAllocationInfo(Zone* zone) : _storage(zone) {} | |
dcarney
2015/04/17 07:22:46
this class doesn't need to be in the header.
also
Mircea Trofin
2015/04/17 19:23:34
Done.
| |
699 | |
700 bool find(UseInterval* query, LiveRange*& result) { | |
dcarney
2015/04/17 07:22:46
here and all over the place: functions in v8 start
Mircea Trofin
2015/04/17 19:23:34
Done.
| |
701 ZoneSplayTree<Config>::Locator locator; | |
702 bool ret = _storage.Find(GetKey(query), &locator); | |
703 if (ret) result = locator.value(); | |
704 return ret; | |
705 } | |
706 | |
707 bool insert(LiveRange* range) { | |
708 auto* interval = range->first_interval(); | |
709 while (interval) { | |
710 if (!insert(interval, range)) return false; | |
711 interval = interval->next(); | |
712 } | |
713 return true; | |
714 } | |
715 | |
716 bool remove(UseInterval* key) { return _storage.Remove(GetKey(key)); } | |
717 | |
718 bool remove(LiveRange* range) { | |
719 bool ret = false; | |
720 auto* segment = range->first_interval(); | |
721 while (segment) { | |
722 ret |= remove(segment); | |
723 segment = segment->next(); | |
724 } | |
725 return ret; | |
726 } | |
727 int isEmpty() { return _storage.is_empty(); } | |
728 | |
729 private: | |
730 struct Config { | |
731 typedef std::pair<int, int> Key; | |
732 typedef LiveRange* Value; | |
733 static const Key kNoKey; | |
734 static Value NoValue() { return nullptr; } | |
735 static int Compare(const Key& a, const Key& b) { | |
736 if (a.second <= b.first) return -1; | |
737 if (a.first >= b.second) return 1; | |
738 return 0; | |
739 } | |
740 }; | |
741 | |
742 Config::Key GetKey(UseInterval* interval) { | |
743 if (!interval) return std::make_pair(0, 0); | |
744 return std::make_pair(interval->start().Value(), interval->end().Value()); | |
745 } | |
746 bool insert(UseInterval* interval, LiveRange* range) { | |
747 ZoneSplayTree<Config>::Locator locator; | |
748 bool ret = _storage.Insert(GetKey(interval), &locator); | |
749 if (ret) locator.set_value(range); | |
750 return ret; | |
751 } | |
752 | |
753 ZoneSplayTree<Config> _storage; | |
dcarney
2015/04/17 07:22:45
in v8 this must be called storage_
Mircea Trofin
2015/04/17 19:23:34
Done.
| |
754 }; | |
dcarney
2015/04/17 07:22:45
the chromium style guide was DISALLOW_COPY_AND_ASS
Mircea Trofin
2015/04/17 19:23:33
Done.
| |
755 | |
756 typedef std::priority_queue<std::pair<unsigned, LiveRange*>> PQueue; | |
757 | |
758 unsigned GetLiveRangeSize(LiveRange* range); | |
759 void Enqueue(LiveRange* range); | |
760 | |
761 void Evict(LiveRange* range); | |
762 float CalculateSpillWeight(LiveRange* range); | |
763 float CalculateMaxSpillWeight(ZoneSet<LiveRange*> ranges); | |
dcarney
2015/04/17 07:22:46
you want ZoneSet<LiveRange*>* here to avoid epic l
Mircea Trofin
2015/04/17 19:23:34
Good catch, thanks! It was meant to be ZoneSet<Liv
| |
764 | |
765 | |
766 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>& conflicting); | |
dcarney
2015/04/17 07:22:45
ZoneSet<LiveRange*>* here as well, only const ref
Mircea Trofin
2015/04/17 19:23:34
Done.
| |
767 bool TryAllocatePhysicalRegister(unsigned regId, LiveRange* range, | |
768 ZoneSet<LiveRange*>& conflicting); | |
769 bool HandleSpillOperands(LiveRange* range); | |
770 bool AllocateBlockedRange(LiveRange*, ZoneSet<LiveRange*>&); | |
771 | |
772 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | |
773 LifetimePosition until, LifetimePosition end); | |
774 void AssignRangeToRegister(unsigned regId, LiveRange* range); | |
775 PQueue queue_; | |
776 ZoneVector<RegisterAllocationInfo*> allocations_; | |
777 DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorGreedy); | |
664 }; | 778 }; |
665 | 779 |
666 } // namespace compiler | 780 } // namespace compiler |
667 } // namespace internal | 781 } // namespace internal |
668 } // namespace v8 | 782 } // namespace v8 |
669 | 783 |
670 #endif // V8_REGISTER_ALLOCATOR_H_ | 784 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |