LCOV - code coverage report
Current view: top level - src/compiler - register-allocator.h (source / functions) Hit Total Coverage
Test: app.info Lines: 93 96 96.9 %
Date: 2017-04-26 Functions: 3 3 100.0 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_REGISTER_ALLOCATOR_H_
       6             : #define V8_REGISTER_ALLOCATOR_H_
       7             : 
       8             : #include "src/base/compiler-specific.h"
       9             : #include "src/compiler/instruction.h"
      10             : #include "src/globals.h"
      11             : #include "src/ostreams.h"
      12             : #include "src/register-configuration.h"
      13             : #include "src/zone/zone-containers.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace compiler {
      18             : 
      19             : enum RegisterKind { GENERAL_REGISTERS, FP_REGISTERS };
      20             : 
      21             : // This class represents a single point of a InstructionOperand's lifetime. For
      22             : // each instruction there are four lifetime positions:
      23             : //
      24             : //   [[START, END], [START, END]]
      25             : //
      26             : // Where the first half position corresponds to
      27             : //
      28             : //  [GapPosition::START, GapPosition::END]
      29             : //
      30             : // and the second half position corresponds to
      31             : //
      32             : //  [Lifetime::USED_AT_START, Lifetime::USED_AT_END]
      33             : //
      34             : class LifetimePosition final {
      35             :  public:
      36             :   // Return the lifetime position that corresponds to the beginning of
      37             :   // the gap with the given index.
      38             :   static LifetimePosition GapFromInstructionIndex(int index) {
      39   148330602 :     return LifetimePosition(index * kStep);
      40             :   }
      41             :   // Return the lifetime position that corresponds to the beginning of
      42             :   // the instruction with the given index.
      43             :   static LifetimePosition InstructionFromInstructionIndex(int index) {
      44   157819898 :     return LifetimePosition(index * kStep + kHalfStep);
      45             :   }
      46             : 
      47             :   static bool ExistsGapPositionBetween(LifetimePosition pos1,
      48             :                                        LifetimePosition pos2) {
      49     1358327 :     if (pos1 > pos2) std::swap(pos1, pos2);
      50     1358327 :     LifetimePosition next(pos1.value_ + 1);
      51     1358327 :     if (next.IsGapPosition()) return next < pos2;
      52             :     return next.NextFullStart() < pos2;
      53             :   }
      54             : 
      55             :   // Returns a numeric representation of this lifetime position.
      56           0 :   int value() const { return value_; }
      57             : 
      58             :   // Returns the index of the instruction to which this lifetime position
      59             :   // corresponds.
      60             :   int ToInstructionIndex() const {
      61             :     DCHECK(IsValid());
      62   147913458 :     return value_ / kStep;
      63             :   }
      64             : 
      65             :   // Returns true if this lifetime position corresponds to a START value
      66    25325216 :   bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; }
      67             :   // Returns true if this lifetime position corresponds to an END value
      68             :   bool IsEnd() const { return (value_ & (kHalfStep - 1)) == 1; }
      69             :   // Returns true if this lifetime position corresponds to a gap START value
      70    13506442 :   bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; }
      71             : 
      72   108672691 :   bool IsGapPosition() const { return (value_ & 0x2) == 0; }
      73             :   bool IsInstructionPosition() const { return !IsGapPosition(); }
      74             : 
      75             :   // Returns the lifetime position for the current START.
      76             :   LifetimePosition Start() const {
      77             :     DCHECK(IsValid());
      78   206306988 :     return LifetimePosition(value_ & ~(kHalfStep - 1));
      79             :   }
      80             : 
      81             :   // Returns the lifetime position for the current gap START.
      82             :   LifetimePosition FullStart() const {
      83             :     DCHECK(IsValid());
      84    21579190 :     return LifetimePosition(value_ & ~(kStep - 1));
      85             :   }
      86             : 
      87             :   // Returns the lifetime position for the current END.
      88             :   LifetimePosition End() const {
      89             :     DCHECK(IsValid());
      90   132554104 :     return LifetimePosition(Start().value_ + kHalfStep / 2);
      91             :   }
      92             : 
      93             :   // Returns the lifetime position for the beginning of the next START.
      94             :   LifetimePosition NextStart() const {
      95             :     DCHECK(IsValid());
      96    27380765 :     return LifetimePosition(Start().value_ + kHalfStep);
      97             :   }
      98             : 
      99             :   // Returns the lifetime position for the beginning of the next gap START.
     100             :   LifetimePosition NextFullStart() const {
     101             :     DCHECK(IsValid());
     102    21682497 :     return LifetimePosition(FullStart().value_ + kStep);
     103             :   }
     104             : 
     105             :   // Returns the lifetime position for the beginning of the previous START.
     106             :   LifetimePosition PrevStart() const {
     107             :     DCHECK(IsValid());
     108             :     DCHECK(value_ >= kHalfStep);
     109    40732726 :     return LifetimePosition(Start().value_ - kHalfStep);
     110             :   }
     111             : 
     112             :   // Constructs the lifetime position which does not correspond to any
     113             :   // instruction.
     114   940321813 :   LifetimePosition() : value_(-1) {}
     115             : 
     116             :   // Returns true if this lifetime positions corrensponds to some
     117             :   // instruction.
     118   539524129 :   bool IsValid() const { return value_ != -1; }
     119             : 
     120             :   bool operator<(const LifetimePosition& that) const {
     121  1856536489 :     return this->value_ < that.value_;
     122             :   }
     123             : 
     124             :   bool operator<=(const LifetimePosition& that) const {
     125  1161045925 :     return this->value_ <= that.value_;
     126             :   }
     127             : 
     128             :   bool operator==(const LifetimePosition& that) const {
     129    16415314 :     return this->value_ == that.value_;
     130             :   }
     131             : 
     132             :   bool operator!=(const LifetimePosition& that) const {
     133             :     return this->value_ != that.value_;
     134             :   }
     135             : 
     136             :   bool operator>(const LifetimePosition& that) const {
     137   193018353 :     return this->value_ > that.value_;
     138             :   }
     139             : 
     140             :   bool operator>=(const LifetimePosition& that) const {
     141    25515573 :     return this->value_ >= that.value_;
     142             :   }
     143             : 
     144             :   void Print() const;
     145             : 
     146             :   static inline LifetimePosition Invalid() { return LifetimePosition(); }
     147             : 
     148             :   static inline LifetimePosition MaxPosition() {
     149             :     // We have to use this kind of getter instead of static member due to
     150             :     // crash bug in GDB.
     151             :     return LifetimePosition(kMaxInt);
     152             :   }
     153             : 
     154             :   static inline LifetimePosition FromInt(int value) {
     155             :     return LifetimePosition(value);
     156             :   }
     157             : 
     158             :  private:
     159             :   static const int kHalfStep = 2;
     160             :   static const int kStep = 2 * kHalfStep;
     161             : 
     162             :   // Code relies on kStep and kHalfStep being a power of two.
     163             :   STATIC_ASSERT(IS_POWER_OF_TWO(kHalfStep));
     164             : 
     165             :   explicit LifetimePosition(int value) : value_(value) {}
     166             : 
     167             :   int value_;
     168             : };
     169             : 
     170             : 
     171             : std::ostream& operator<<(std::ostream& os, const LifetimePosition pos);
     172             : 
     173             : 
     174             : // Representation of the non-empty interval [start,end[.
     175             : class UseInterval final : public ZoneObject {
     176             :  public:
     177             :   UseInterval(LifetimePosition start, LifetimePosition end)
     178   162061586 :       : start_(start), end_(end), next_(nullptr) {
     179             :     DCHECK(start < end);
     180             :   }
     181             : 
     182             :   LifetimePosition start() const { return start_; }
     183   157228031 :   void set_start(LifetimePosition start) { start_ = start; }
     184             :   LifetimePosition end() const { return end_; }
     185    43867470 :   void set_end(LifetimePosition end) { end_ = end; }
     186             :   UseInterval* next() const { return next_; }
     187   122802039 :   void set_next(UseInterval* next) { next_ = next; }
     188             : 
     189             :   // Split this interval at the given position without effecting the
     190             :   // live range that owns it. The interval must contain the position.
     191             :   UseInterval* SplitAt(LifetimePosition pos, Zone* zone);
     192             : 
     193             :   // If this interval intersects with other return smallest position
     194             :   // that belongs to both of them.
     195   405809769 :   LifetimePosition Intersect(const UseInterval* other) const {
     196   405809769 :     if (other->start() < start_) return other->Intersect(this);
     197   315206474 :     if (other->start() < end_) return other->start();
     198             :     return LifetimePosition::Invalid();
     199             :   }
     200             : 
     201             :   bool Contains(LifetimePosition point) const {
     202  1204615726 :     return start_ <= point && point < end_;
     203             :   }
     204             : 
     205             :   // Returns the index of the first gap covered by this interval.
     206             :   int FirstGapIndex() const {
     207             :     int ret = start_.ToInstructionIndex();
     208    45697887 :     if (start_.IsInstructionPosition()) {
     209    26859112 :       ++ret;
     210             :     }
     211             :     return ret;
     212             :   }
     213             : 
     214             :   // Returns the index of the last gap covered by this interval.
     215             :   int LastGapIndex() const {
     216             :     int ret = end_.ToInstructionIndex();
     217    37152751 :     if (end_.IsGapPosition() && end_.IsStart()) {
     218     5988988 :       --ret;
     219             :     }
     220             :     return ret;
     221             :   }
     222             : 
     223             :  private:
     224             :   LifetimePosition start_;
     225             :   LifetimePosition end_;
     226             :   UseInterval* next_;
     227             : 
     228             :   DISALLOW_COPY_AND_ASSIGN(UseInterval);
     229             : };
     230             : 
     231             : 
     232             : enum class UsePositionType : uint8_t { kAny, kRequiresRegister, kRequiresSlot };
     233             : 
     234             : 
     235             : enum class UsePositionHintType : uint8_t {
     236             :   kNone,
     237             :   kOperand,
     238             :   kUsePos,
     239             :   kPhi,
     240             :   kUnresolved
     241             : };
     242             : 
     243             : 
     244             : static const int32_t kUnassignedRegister =
     245             :     RegisterConfiguration::kMaxGeneralRegisters;
     246             : 
     247             : static_assert(kUnassignedRegister <= RegisterConfiguration::kMaxFPRegisters,
     248             :               "kUnassignedRegister too small");
     249             : 
     250             : // Representation of a use position.
     251             : class V8_EXPORT_PRIVATE UsePosition final
     252             :     : public NON_EXPORTED_BASE(ZoneObject) {
     253             :  public:
     254             :   UsePosition(LifetimePosition pos, InstructionOperand* operand, void* hint,
     255             :               UsePositionHintType hint_type);
     256             : 
     257             :   InstructionOperand* operand() const { return operand_; }
     258             :   bool HasOperand() const { return operand_ != nullptr; }
     259             : 
     260             :   bool RegisterIsBeneficial() const {
     261             :     return RegisterBeneficialField::decode(flags_);
     262             :   }
     263             :   UsePositionType type() const { return TypeField::decode(flags_); }
     264             :   void set_type(UsePositionType type, bool register_beneficial);
     265             : 
     266             :   LifetimePosition pos() const { return pos_; }
     267             : 
     268             :   UsePosition* next() const { return next_; }
     269    98335036 :   void set_next(UsePosition* next) { next_ = next; }
     270             : 
     271             :   // For hinting only.
     272             :   void set_assigned_register(int register_code) {
     273    44855572 :     flags_ = AssignedRegisterField::update(flags_, register_code);
     274             :   }
     275             : 
     276             :   UsePositionHintType hint_type() const {
     277             :     return HintTypeField::decode(flags_);
     278             :   }
     279             :   bool HasHint() const;
     280             :   bool HintRegister(int* register_code) const;
     281             :   void SetHint(UsePosition* use_pos);
     282             :   void ResolveHint(UsePosition* use_pos);
     283           0 :   bool IsResolved() const {
     284             :     return hint_type() != UsePositionHintType::kUnresolved;
     285             :   }
     286             :   static UsePositionHintType HintTypeForOperand(const InstructionOperand& op);
     287             : 
     288             :  private:
     289             :   typedef BitField<UsePositionType, 0, 2> TypeField;
     290             :   typedef BitField<UsePositionHintType, 2, 3> HintTypeField;
     291             :   typedef BitField<bool, 5, 1> RegisterBeneficialField;
     292             :   typedef BitField<int32_t, 6, 6> AssignedRegisterField;
     293             : 
     294             :   InstructionOperand* const operand_;
     295             :   void* hint_;
     296             :   UsePosition* next_;
     297             :   LifetimePosition const pos_;
     298             :   uint32_t flags_;
     299             : 
     300             :   DISALLOW_COPY_AND_ASSIGN(UsePosition);
     301             : };
     302             : 
     303             : 
     304             : class SpillRange;
     305             : class RegisterAllocationData;
     306             : class TopLevelLiveRange;
     307             : class LiveRangeGroup;
     308             : 
     309             : // Representation of SSA values' live ranges as a collection of (continuous)
     310             : // intervals over the instruction ordering.
     311             : class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
     312             :  public:
     313             :   UseInterval* first_interval() const { return first_interval_; }
     314             :   UsePosition* first_pos() const { return first_pos_; }
     315             :   TopLevelLiveRange* TopLevel() { return top_level_; }
     316             :   const TopLevelLiveRange* TopLevel() const { return top_level_; }
     317             : 
     318             :   bool IsTopLevel() const;
     319             : 
     320             :   LiveRange* next() const { return next_; }
     321             : 
     322             :   int relative_id() const { return relative_id_; }
     323             : 
     324   756980562 :   bool IsEmpty() const { return first_interval() == nullptr; }
     325             : 
     326             :   InstructionOperand GetAssignedOperand() const;
     327             : 
     328             :   MachineRepresentation representation() const {
     329             :     return RepresentationField::decode(bits_);
     330             :   }
     331             : 
     332             :   int assigned_register() const { return AssignedRegisterField::decode(bits_); }
     333   115454470 :   bool HasRegisterAssigned() const {
     334             :     return assigned_register() != kUnassignedRegister;
     335             :   }
     336             :   void set_assigned_register(int reg);
     337             :   void UnsetAssignedRegister();
     338             : 
     339             :   bool spilled() const { return SpilledField::decode(bits_); }
     340             :   void Spill();
     341             : 
     342             :   RegisterKind kind() const;
     343             : 
     344             :   // Returns use position in this live range that follows both start
     345             :   // and last processed use position.
     346             :   UsePosition* NextUsePosition(LifetimePosition start) const;
     347             : 
     348             :   // Returns use position for which register is required in this live
     349             :   // range and which follows both start and last processed use position
     350             :   UsePosition* NextRegisterPosition(LifetimePosition start) const;
     351             : 
     352             :   // Returns the first use position requiring stack slot, or nullptr.
     353             :   UsePosition* NextSlotPosition(LifetimePosition start) const;
     354             : 
     355             :   // Returns use position for which register is beneficial in this live
     356             :   // range and which follows both start and last processed use position
     357             :   UsePosition* NextUsePositionRegisterIsBeneficial(
     358             :       LifetimePosition start) const;
     359             : 
     360             :   // Returns lifetime position for which register is beneficial in this live
     361             :   // range and which follows both start and last processed use position.
     362             :   LifetimePosition NextLifetimePositionRegisterIsBeneficial(
     363             :       const LifetimePosition& start) const;
     364             : 
     365             :   // Returns use position for which register is beneficial in this live
     366             :   // range and which precedes start.
     367             :   UsePosition* PreviousUsePositionRegisterIsBeneficial(
     368             :       LifetimePosition start) const;
     369             : 
     370             :   // Can this live range be spilled at this position.
     371             :   bool CanBeSpilled(LifetimePosition pos) const;
     372             : 
     373             :   // Splitting primitive used by both splitting and splintering members.
     374             :   // Performs the split, but does not link the resulting ranges.
     375             :   // The given position must follow the start of the range.
     376             :   // All uses following the given position will be moved from this
     377             :   // live range to the result live range.
     378             :   // The current range will terminate at position, while result will start from
     379             :   // position.
     380             :   enum HintConnectionOption : bool {
     381             :     DoNotConnectHints = false,
     382             :     ConnectHints = true
     383             :   };
     384             :   UsePosition* DetachAt(LifetimePosition position, LiveRange* result,
     385             :                         Zone* zone, HintConnectionOption connect_hints);
     386             : 
     387             :   // Detaches at position, and then links the resulting ranges. Returns the
     388             :   // child, which starts at position.
     389             :   LiveRange* SplitAt(LifetimePosition position, Zone* zone);
     390             : 
     391             :   // Returns nullptr when no register is hinted, otherwise sets register_index.
     392             :   UsePosition* FirstHintPosition(int* register_index) const;
     393             :   UsePosition* FirstHintPosition() const {
     394             :     int register_index;
     395      394166 :     return FirstHintPosition(&register_index);
     396             :   }
     397             : 
     398             :   UsePosition* current_hint_position() const {
     399             :     DCHECK(current_hint_position_ == FirstHintPosition());
     400             :     return current_hint_position_;
     401             :   }
     402             : 
     403   739899047 :   LifetimePosition Start() const {
     404             :     DCHECK(!IsEmpty());
     405             :     return first_interval()->start();
     406             :   }
     407             : 
     408             :   LifetimePosition End() const {
     409             :     DCHECK(!IsEmpty());
     410             :     return last_interval_->end();
     411             :   }
     412             : 
     413             :   bool ShouldBeAllocatedBefore(const LiveRange* other) const;
     414             :   bool CanCover(LifetimePosition position) const;
     415             :   bool Covers(LifetimePosition position) const;
     416             :   LifetimePosition FirstIntersection(LiveRange* other) const;
     417             : 
     418             :   void VerifyChildStructure() const {
     419             :     VerifyIntervals();
     420           0 :     VerifyPositions();
     421             :   }
     422             : 
     423             :   void ConvertUsesToOperand(const InstructionOperand& op,
     424             :                             const InstructionOperand& spill_op);
     425             :   void SetUseHints(int register_index);
     426             :   void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
     427             : 
     428             :   void Print(const RegisterConfiguration* config, bool with_children) const;
     429             :   void Print(bool with_children) const;
     430             : 
     431             :  private:
     432             :   friend class TopLevelLiveRange;
     433             :   explicit LiveRange(int relative_id, MachineRepresentation rep,
     434             :                      TopLevelLiveRange* top_level);
     435             : 
     436             :   void UpdateParentForAllChildren(TopLevelLiveRange* new_top_level);
     437             : 
     438    64919530 :   void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); }
     439             : 
     440             :   UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
     441             :   void AdvanceLastProcessedMarker(UseInterval* to_start_of,
     442             :                                   LifetimePosition but_not_past) const;
     443             : 
     444             :   void VerifyPositions() const;
     445             :   void VerifyIntervals() const;
     446             : 
     447             :   typedef BitField<bool, 0, 1> SpilledField;
     448             :   typedef BitField<int32_t, 6, 6> AssignedRegisterField;
     449             :   typedef BitField<MachineRepresentation, 12, 8> RepresentationField;
     450             : 
     451             :   // Unique among children and splinters of the same virtual register.
     452             :   int relative_id_;
     453             :   uint32_t bits_;
     454             :   UseInterval* last_interval_;
     455             :   UseInterval* first_interval_;
     456             :   UsePosition* first_pos_;
     457             :   TopLevelLiveRange* top_level_;
     458             :   LiveRange* next_;
     459             :   // This is used as a cache, it doesn't affect correctness.
     460             :   mutable UseInterval* current_interval_;
     461             :   // This is used as a cache, it doesn't affect correctness.
     462             :   mutable UsePosition* last_processed_use_;
     463             :   // This is used as a cache, it's invalid outside of BuildLiveRanges.
     464             :   mutable UsePosition* current_hint_position_;
     465             :   // Cache the last position splintering stopped at.
     466             :   mutable UsePosition* splitting_pointer_;
     467             : 
     468             :   DISALLOW_COPY_AND_ASSIGN(LiveRange);
     469             : };
     470             : 
     471             : 
     472             : class LiveRangeGroup final : public ZoneObject {
     473             :  public:
     474             :   explicit LiveRangeGroup(Zone* zone) : ranges_(zone) {}
     475             :   ZoneVector<LiveRange*>& ranges() { return ranges_; }
     476             :   const ZoneVector<LiveRange*>& ranges() const { return ranges_; }
     477             : 
     478             :   int assigned_register() const { return assigned_register_; }
     479             :   void set_assigned_register(int reg) { assigned_register_ = reg; }
     480             : 
     481             :  private:
     482             :   ZoneVector<LiveRange*> ranges_;
     483             :   int assigned_register_;
     484             :   DISALLOW_COPY_AND_ASSIGN(LiveRangeGroup);
     485             : };
     486             : 
     487             : class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
     488             :  public:
     489             :   explicit TopLevelLiveRange(int vreg, MachineRepresentation rep);
     490             :   int spill_start_index() const { return spill_start_index_; }
     491             : 
     492     3756514 :   bool IsFixed() const { return vreg_ < 0; }
     493             : 
     494             :   bool is_phi() const { return IsPhiField::decode(bits_); }
     495     2667216 :   void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); }
     496             : 
     497             :   bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); }
     498             :   void set_is_non_loop_phi(bool value) {
     499     1333608 :     bits_ = IsNonLoopPhiField::update(bits_, value);
     500             :   }
     501             : 
     502             :   bool has_slot_use() const { return HasSlotUseField::decode(bits_); }
     503             :   void set_has_slot_use(bool value) {
     504    34855688 :     bits_ = HasSlotUseField::update(bits_, value);
     505             :   }
     506             : 
     507             :   // Add a new interval or a new use position to this live range.
     508             :   void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
     509             :   void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
     510             :   void AddUsePosition(UsePosition* pos);
     511             : 
     512             :   // Shorten the most recently added interval by setting a new start.
     513             :   void ShortenTo(LifetimePosition start);
     514             : 
     515             :   // Detaches between start and end, and attributes the resulting range to
     516             :   // result.
     517             :   // The current range is pointed to as "splintered_from". No parent/child
     518             :   // relationship is established between this and result.
     519             :   void Splinter(LifetimePosition start, LifetimePosition end, Zone* zone);
     520             : 
     521             :   // Assuming other was splintered from this range, embeds other and its
     522             :   // children as part of the children sequence of this range.
     523             :   void Merge(TopLevelLiveRange* other, Zone* zone);
     524             : 
     525             :   // Spill range management.
     526             :   void SetSpillRange(SpillRange* spill_range);
     527             :   enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange };
     528             :   void set_spill_type(SpillType value) {
     529    32144092 :     bits_ = SpillTypeField::update(bits_, value);
     530             :   }
     531             :   SpillType spill_type() const { return SpillTypeField::decode(bits_); }
     532             :   InstructionOperand* GetSpillOperand() const {
     533             :     DCHECK(spill_type() == SpillType::kSpillOperand);
     534             :     return spill_operand_;
     535             :   }
     536             : 
     537             :   SpillRange* GetAllocatedSpillRange() const {
     538             :     DCHECK(spill_type() != SpillType::kSpillOperand);
     539             :     return spill_range_;
     540             :   }
     541             : 
     542             :   SpillRange* GetSpillRange() const {
     543             :     DCHECK(spill_type() == SpillType::kSpillRange);
     544             :     return spill_range_;
     545             :   }
     546    45769660 :   bool HasNoSpillType() const {
     547             :     return spill_type() == SpillType::kNoSpillType;
     548             :   }
     549   114722750 :   bool HasSpillOperand() const {
     550             :     return spill_type() == SpillType::kSpillOperand;
     551             :   }
     552    40611997 :   bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; }
     553             : 
     554             :   AllocatedOperand GetSpillRangeOperand() const;
     555             : 
     556             :   void RecordSpillLocation(Zone* zone, int gap_index,
     557             :                            InstructionOperand* operand);
     558             :   void SetSpillOperand(InstructionOperand* operand);
     559             :   void SetSpillStartIndex(int start) {
     560    45300382 :     spill_start_index_ = Min(start, spill_start_index_);
     561             :   }
     562             : 
     563             :   void CommitSpillMoves(InstructionSequence* sequence,
     564             :                         const InstructionOperand& operand,
     565             :                         bool might_be_duplicated);
     566             : 
     567             :   // If all the children of this range are spilled in deferred blocks, and if
     568             :   // for any non-spilled child with a use position requiring a slot, that range
     569             :   // is contained in a deferred block, mark the range as
     570             :   // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition,
     571             :   // and instead let the LiveRangeConnector perform the spills within the
     572             :   // deferred blocks. If so, we insert here spills for non-spilled ranges
     573             :   // with slot use positions.
     574      630572 :   void TreatAsSpilledInDeferredBlock(Zone* zone, int total_block_count) {
     575      630572 :     spill_start_index_ = -1;
     576      630572 :     spilled_in_deferred_blocks_ = true;
     577      630572 :     spill_move_insertion_locations_ = nullptr;
     578             :     list_of_blocks_requiring_spill_operands_ =
     579      630573 :         new (zone) BitVector(total_block_count, zone);
     580      630574 :   }
     581             : 
     582             :   void CommitSpillInDeferredBlocks(RegisterAllocationData* data,
     583             :                                    const InstructionOperand& spill_operand,
     584             :                                    BitVector* necessary_spill_points);
     585             : 
     586             :   TopLevelLiveRange* splintered_from() const { return splintered_from_; }
     587             :   bool IsSplinter() const { return splintered_from_ != nullptr; }
     588             :   bool MayRequireSpillRange() const {
     589             :     DCHECK(!IsSplinter());
     590     9785227 :     return !HasSpillOperand() && spill_range_ == nullptr;
     591             :   }
     592             :   void UpdateSpillRangePostMerge(TopLevelLiveRange* merged);
     593             :   int vreg() const { return vreg_; }
     594             : 
     595             : #if DEBUG
     596             :   int debug_virt_reg() const;
     597             : #endif
     598             : 
     599             :   void Verify() const;
     600             :   void VerifyChildrenInOrder() const;
     601             : 
     602    39517935 :   int GetNextChildId() {
     603             :     return IsSplinter() ? splintered_from()->GetNextChildId()
     604    39517935 :                         : ++last_child_id_;
     605             :   }
     606             : 
     607     4165172 :   int GetChildCount() const { return last_child_id_ + 1; }
     608             : 
     609             :   bool IsSpilledOnlyInDeferredBlocks() const {
     610             :     return spilled_in_deferred_blocks_;
     611             :   }
     612             : 
     613             :   struct SpillMoveInsertionList;
     614             : 
     615             :   SpillMoveInsertionList* GetSpillMoveInsertionLocations() const {
     616             :     DCHECK(!IsSpilledOnlyInDeferredBlocks());
     617             :     return spill_move_insertion_locations_;
     618             :   }
     619             :   TopLevelLiveRange* splinter() const { return splinter_; }
     620     6571846 :   void SetSplinter(TopLevelLiveRange* splinter) {
     621             :     DCHECK_NULL(splinter_);
     622             :     DCHECK_NOT_NULL(splinter);
     623             : 
     624     3285923 :     splinter_ = splinter;
     625     3285923 :     splinter->relative_id_ = GetNextChildId();
     626             :     splinter->set_spill_type(spill_type());
     627     3285923 :     splinter->SetSplinteredFrom(this);
     628     3285963 :   }
     629             : 
     630      438463 :   void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; }
     631             :   bool has_preassigned_slot() const { return has_preassigned_slot_; }
     632             : 
     633      371989 :   void AddBlockRequiringSpillOperand(RpoNumber block_id) {
     634             :     DCHECK(IsSpilledOnlyInDeferredBlocks());
     635      371989 :     GetListOfBlocksRequiringSpillOperands()->Add(block_id.ToInt());
     636             :   }
     637             : 
     638             :   BitVector* GetListOfBlocksRequiringSpillOperands() const {
     639             :     DCHECK(IsSpilledOnlyInDeferredBlocks());
     640             :     return list_of_blocks_requiring_spill_operands_;
     641             :   }
     642             : 
     643             :  private:
     644             :   void SetSplinteredFrom(TopLevelLiveRange* splinter_parent);
     645             : 
     646             :   typedef BitField<bool, 1, 1> HasSlotUseField;
     647             :   typedef BitField<bool, 2, 1> IsPhiField;
     648             :   typedef BitField<bool, 3, 1> IsNonLoopPhiField;
     649             :   typedef BitField<SpillType, 4, 2> SpillTypeField;
     650             : 
     651             :   int vreg_;
     652             :   int last_child_id_;
     653             :   TopLevelLiveRange* splintered_from_;
     654             :   union {
     655             :     // Correct value determined by spill_type()
     656             :     InstructionOperand* spill_operand_;
     657             :     SpillRange* spill_range_;
     658             :   };
     659             : 
     660             :   union {
     661             :     SpillMoveInsertionList* spill_move_insertion_locations_;
     662             :     BitVector* list_of_blocks_requiring_spill_operands_;
     663             :   };
     664             : 
     665             :   // TODO(mtrofin): generalize spilling after definition, currently specialized
     666             :   // just for spill in a single deferred block.
     667             :   bool spilled_in_deferred_blocks_;
     668             :   int spill_start_index_;
     669             :   UsePosition* last_pos_;
     670             :   TopLevelLiveRange* splinter_;
     671             :   bool has_preassigned_slot_;
     672             : 
     673             :   DISALLOW_COPY_AND_ASSIGN(TopLevelLiveRange);
     674             : };
     675             : 
     676             : 
     677             : struct PrintableLiveRange {
     678             :   const RegisterConfiguration* register_configuration_;
     679             :   const LiveRange* range_;
     680             : };
     681             : 
     682             : 
     683             : std::ostream& operator<<(std::ostream& os,
     684             :                          const PrintableLiveRange& printable_range);
     685             : 
     686             : 
     687             : class SpillRange final : public ZoneObject {
     688             :  public:
     689             :   static const int kUnassignedSlot = -1;
     690             :   SpillRange(TopLevelLiveRange* range, Zone* zone);
     691             : 
     692             :   UseInterval* interval() const { return use_interval_; }
     693             : 
     694             :   bool IsEmpty() const { return live_ranges_.empty(); }
     695             :   bool TryMerge(SpillRange* other);
     696             :   bool HasSlot() const { return assigned_slot_ != kUnassignedSlot; }
     697             : 
     698             :   void set_assigned_slot(int index) {
     699             :     DCHECK_EQ(kUnassignedSlot, assigned_slot_);
     700     1498915 :     assigned_slot_ = index;
     701             :   }
     702             :   int assigned_slot() {
     703             :     DCHECK_NE(kUnassignedSlot, assigned_slot_);
     704             :     return assigned_slot_;
     705             :   }
     706             :   const ZoneVector<TopLevelLiveRange*>& live_ranges() const {
     707             :     return live_ranges_;
     708             :   }
     709             :   ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; }
     710             :   // Spill slots can be 4, 8, or 16 bytes wide.
     711             :   int byte_width() const { return byte_width_; }
     712             :   void Print() const;
     713             : 
     714             :  private:
     715             :   LifetimePosition End() const { return end_position_; }
     716             :   bool IsIntersectingWith(SpillRange* other) const;
     717             :   // Merge intervals, making sure the use intervals are sorted
     718             :   void MergeDisjointIntervals(UseInterval* other);
     719             : 
     720             :   ZoneVector<TopLevelLiveRange*> live_ranges_;
     721             :   UseInterval* use_interval_;
     722             :   LifetimePosition end_position_;
     723             :   int assigned_slot_;
     724             :   int byte_width_;
     725             : 
     726             :   DISALLOW_COPY_AND_ASSIGN(SpillRange);
     727             : };
     728             : 
     729             : 
     730             : class RegisterAllocationData final : public ZoneObject {
     731             :  public:
     732             :   class PhiMapValue : public ZoneObject {
     733             :    public:
     734             :     PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone);
     735             : 
     736             :     const PhiInstruction* phi() const { return phi_; }
     737             :     const InstructionBlock* block() const { return block_; }
     738             : 
     739             :     // For hinting.
     740             :     int assigned_register() const { return assigned_register_; }
     741             :     void set_assigned_register(int register_code) {
     742             :       DCHECK_EQ(assigned_register_, kUnassignedRegister);
     743     1098519 :       assigned_register_ = register_code;
     744             :     }
     745             :     void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; }
     746             : 
     747             :     void AddOperand(InstructionOperand* operand);
     748             :     void CommitAssignment(const InstructionOperand& operand);
     749             : 
     750             :    private:
     751             :     PhiInstruction* const phi_;
     752             :     const InstructionBlock* const block_;
     753             :     ZoneVector<InstructionOperand*> incoming_operands_;
     754             :     int assigned_register_;
     755             :   };
     756             :   typedef ZoneMap<int, PhiMapValue*> PhiMap;
     757             : 
     758             :   struct DelayedReference {
     759             :     ReferenceMap* map;
     760             :     InstructionOperand* operand;
     761             :   };
     762             :   typedef ZoneVector<DelayedReference> DelayedReferences;
     763             :   typedef ZoneVector<std::pair<TopLevelLiveRange*, int>>
     764             :       RangesWithPreassignedSlots;
     765             : 
     766             :   RegisterAllocationData(const RegisterConfiguration* config,
     767             :                          Zone* allocation_zone, Frame* frame,
     768             :                          InstructionSequence* code,
     769             :                          const char* debug_name = nullptr);
     770             : 
     771             :   const ZoneVector<TopLevelLiveRange*>& live_ranges() const {
     772             :     return live_ranges_;
     773             :   }
     774             :   ZoneVector<TopLevelLiveRange*>& live_ranges() { return live_ranges_; }
     775             :   const ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() const {
     776             :     return fixed_live_ranges_;
     777             :   }
     778             :   ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() {
     779             :     return fixed_live_ranges_;
     780             :   }
     781             :   ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() {
     782             :     return fixed_float_live_ranges_;
     783             :   }
     784             :   const ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() const {
     785             :     return fixed_float_live_ranges_;
     786             :   }
     787             :   ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() {
     788             :     return fixed_double_live_ranges_;
     789             :   }
     790             :   const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const {
     791             :     return fixed_double_live_ranges_;
     792             :   }
     793             :   ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() {
     794             :     return fixed_simd128_live_ranges_;
     795             :   }
     796             :   const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const {
     797             :     return fixed_simd128_live_ranges_;
     798             :   }
     799             :   ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
     800             :   ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; }
     801             :   ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
     802             :   DelayedReferences& delayed_references() { return delayed_references_; }
     803             :   InstructionSequence* code() const { return code_; }
     804             :   // This zone is for data structures only needed during register allocation
     805             :   // phases.
     806             :   Zone* allocation_zone() const { return allocation_zone_; }
     807             :   // This zone is for InstructionOperands and moves that live beyond register
     808             :   // allocation.
     809    27678023 :   Zone* code_zone() const { return code()->zone(); }
     810             :   Frame* frame() const { return frame_; }
     811             :   const char* debug_name() const { return debug_name_; }
     812             :   const RegisterConfiguration* config() const { return config_; }
     813             : 
     814             :   MachineRepresentation RepresentationFor(int virtual_register);
     815             : 
     816             :   TopLevelLiveRange* GetOrCreateLiveRangeFor(int index);
     817             :   // Creates a new live range.
     818             :   TopLevelLiveRange* NewLiveRange(int index, MachineRepresentation rep);
     819             :   TopLevelLiveRange* NextLiveRange(MachineRepresentation rep);
     820             : 
     821             :   SpillRange* AssignSpillRangeToLiveRange(TopLevelLiveRange* range);
     822             :   SpillRange* CreateSpillRangeForLiveRange(TopLevelLiveRange* range);
     823             : 
     824             :   MoveOperands* AddGapMove(int index, Instruction::GapPosition position,
     825             :                            const InstructionOperand& from,
     826             :                            const InstructionOperand& to);
     827             : 
     828    23350962 :   bool IsReference(TopLevelLiveRange* top_range) const {
     829             :     return code()->IsReference(top_range->vreg());
     830             :   }
     831             : 
     832             :   bool ExistsUseWithoutDefinition();
     833             :   bool RangesDefinedInDeferredStayInDeferred();
     834             : 
     835             :   void MarkAllocated(MachineRepresentation rep, int index);
     836             : 
     837             :   PhiMapValue* InitializePhiMap(const InstructionBlock* block,
     838             :                                 PhiInstruction* phi);
     839             :   PhiMapValue* GetPhiMapValueFor(TopLevelLiveRange* top_range);
     840             :   PhiMapValue* GetPhiMapValueFor(int virtual_register);
     841             :   bool IsBlockBoundary(LifetimePosition pos) const;
     842             : 
     843             :   RangesWithPreassignedSlots& preassigned_slot_ranges() {
     844             :     return preassigned_slot_ranges_;
     845             :   }
     846             : 
     847             :  private:
     848             :   int GetNextLiveRangeId();
     849             : 
     850             :   Zone* const allocation_zone_;
     851             :   Frame* const frame_;
     852             :   InstructionSequence* const code_;
     853             :   const char* const debug_name_;
     854             :   const RegisterConfiguration* const config_;
     855             :   PhiMap phi_map_;
     856             :   ZoneVector<BitVector*> live_in_sets_;
     857             :   ZoneVector<BitVector*> live_out_sets_;
     858             :   ZoneVector<TopLevelLiveRange*> live_ranges_;
     859             :   ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
     860             :   ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
     861             :   ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_;
     862             :   ZoneVector<TopLevelLiveRange*> fixed_simd128_live_ranges_;
     863             :   ZoneVector<SpillRange*> spill_ranges_;
     864             :   DelayedReferences delayed_references_;
     865             :   BitVector* assigned_registers_;
     866             :   BitVector* assigned_double_registers_;
     867             :   int virtual_register_count_;
     868             :   RangesWithPreassignedSlots preassigned_slot_ranges_;
     869             : 
     870             :   DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData);
     871             : };
     872             : 
     873             : 
     874             : class ConstraintBuilder final : public ZoneObject {
     875             :  public:
     876             :   explicit ConstraintBuilder(RegisterAllocationData* data);
     877             : 
     878             :   // Phase 1 : insert moves to account for fixed register operands.
     879             :   void MeetRegisterConstraints();
     880             : 
     881             :   // Phase 2: deconstruct SSA by inserting moves in successors and the headers
     882             :   // of blocks containing phis.
     883             :   void ResolvePhis();
     884             : 
     885             :  private:
     886   195830656 :   RegisterAllocationData* data() const { return data_; }
     887   119329120 :   InstructionSequence* code() const { return data()->code(); }
     888    12892291 :   Zone* allocation_zone() const { return data()->allocation_zone(); }
     889             : 
     890             :   InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos,
     891             :                                     bool is_tagged);
     892             :   void MeetRegisterConstraints(const InstructionBlock* block);
     893             :   void MeetConstraintsBefore(int index);
     894             :   void MeetConstraintsAfter(int index);
     895             :   void MeetRegisterConstraintsForLastInstructionInBlock(
     896             :       const InstructionBlock* block);
     897             :   void ResolvePhis(const InstructionBlock* block);
     898             : 
     899             :   RegisterAllocationData* const data_;
     900             : 
     901             :   DISALLOW_COPY_AND_ASSIGN(ConstraintBuilder);
     902             : };
     903             : 
     904             : 
     905             : class LiveRangeBuilder final : public ZoneObject {
     906             :  public:
     907             :   explicit LiveRangeBuilder(RegisterAllocationData* data, Zone* local_zone);
     908             : 
     909             :   // Phase 3: compute liveness of all virtual register.
     910             :   void BuildLiveRanges();
     911             :   static BitVector* ComputeLiveOut(const InstructionBlock* block,
     912             :                                    RegisterAllocationData* data);
     913             : 
     914             :  private:
     915             :   RegisterAllocationData* data() const { return data_; }
     916    54311362 :   InstructionSequence* code() const { return data()->code(); }
     917   309159790 :   Zone* allocation_zone() const { return data()->allocation_zone(); }
     918             :   Zone* code_zone() const { return code()->zone(); }
     919   108003539 :   const RegisterConfiguration* config() const { return data()->config(); }
     920    13372566 :   ZoneVector<BitVector*>& live_in_sets() const {
     921             :     return data()->live_in_sets();
     922             :   }
     923             : 
     924             :   // Verification.
     925             :   void Verify() const;
     926             :   bool IntervalStartsAtBlockBoundary(const UseInterval* interval) const;
     927             :   bool IntervalPredecessorsCoveredByRange(const UseInterval* interval,
     928             :                                           const TopLevelLiveRange* range) const;
     929             :   bool NextIntervalStartsInDifferentBlocks(const UseInterval* interval) const;
     930             : 
     931             :   // Liveness analysis support.
     932             :   void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out);
     933             :   void ProcessInstructions(const InstructionBlock* block, BitVector* live);
     934             :   void ProcessPhis(const InstructionBlock* block, BitVector* live);
     935             :   void ProcessLoopHeader(const InstructionBlock* block, BitVector* live);
     936             : 
     937     7985320 :   static int FixedLiveRangeID(int index) { return -index - 1; }
     938             :   int FixedFPLiveRangeID(int index, MachineRepresentation rep);
     939             :   TopLevelLiveRange* FixedLiveRangeFor(int index);
     940             :   TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep);
     941             : 
     942             :   void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos);
     943             :   void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos);
     944             : 
     945             :   UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand,
     946             :                               void* hint, UsePositionHintType hint_type);
     947             :   UsePosition* NewUsePosition(LifetimePosition pos) {
     948     1364005 :     return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone);
     949             :   }
     950             :   TopLevelLiveRange* LiveRangeFor(InstructionOperand* operand);
     951             :   // Helper methods for building intervals.
     952             :   UsePosition* Define(LifetimePosition position, InstructionOperand* operand,
     953             :                       void* hint, UsePositionHintType hint_type);
     954             :   void Define(LifetimePosition position, InstructionOperand* operand) {
     955    14264762 :     Define(position, operand, nullptr, UsePositionHintType::kNone);
     956             :   }
     957             :   UsePosition* Use(LifetimePosition block_start, LifetimePosition position,
     958             :                    InstructionOperand* operand, void* hint,
     959             :                    UsePositionHintType hint_type);
     960             :   void Use(LifetimePosition block_start, LifetimePosition position,
     961             :            InstructionOperand* operand) {
     962    46743552 :     Use(block_start, position, operand, nullptr, UsePositionHintType::kNone);
     963             :   }
     964             : 
     965             :   RegisterAllocationData* const data_;
     966             :   ZoneMap<InstructionOperand*, UsePosition*> phi_hints_;
     967             : 
     968             :   DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder);
     969             : };
     970             : 
     971             : 
     972             : class RegisterAllocator : public ZoneObject {
     973             :  public:
     974             :   RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
     975             : 
     976             :  protected:
     977             :   RegisterAllocationData* data() const { return data_; }
     978    18671137 :   InstructionSequence* code() const { return data()->code(); }
     979             :   RegisterKind mode() const { return mode_; }
     980             :   int num_registers() const { return num_registers_; }
     981             :   int num_allocatable_registers() const { return num_allocatable_registers_; }
     982             :   const int* allocatable_register_codes() const {
     983             :     return allocatable_register_codes_;
     984             :   }
     985             :   // Returns true iff. we must check float register aliasing.
     986             :   bool check_fp_aliasing() const { return check_fp_aliasing_; }
     987             : 
     988             :   // TODO(mtrofin): explain why splitting in gap START is always OK.
     989             :   LifetimePosition GetSplitPositionForInstruction(const LiveRange* range,
     990             :                                                   int instruction_index);
     991             : 
     992    13797748 :   Zone* allocation_zone() const { return data()->allocation_zone(); }
     993             : 
     994             :   // Find the optimal split for ranges defined by a memory operand, e.g.
     995             :   // constants or function parameters passed on the stack.
     996             :   void SplitAndSpillRangesDefinedByMemoryOperand();
     997             : 
     998             :   // Split the given range at the given position.
     999             :   // If range starts at or after the given position then the
    1000             :   // original range is returned.
    1001             :   // Otherwise returns the live range that starts at pos and contains
    1002             :   // all uses from the original range that follow pos. Uses at pos will
    1003             :   // still be owned by the original range after splitting.
    1004             :   LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos);
    1005             : 
    1006   102324937 :   bool CanProcessRange(LiveRange* range) const {
    1007   397564623 :     return range != nullptr && !range->IsEmpty() && range->kind() == mode();
    1008             :   }
    1009             : 
    1010             : 
    1011             :   // Split the given range in a position from the interval [start, end].
    1012             :   LiveRange* SplitBetween(LiveRange* range, LifetimePosition start,
    1013             :                           LifetimePosition end);
    1014             : 
    1015             :   // Find a lifetime position in the interval [start, end] which
    1016             :   // is optimal for splitting: it is either header of the outermost
    1017             :   // loop covered by this interval or the latest possible position.
    1018             :   LifetimePosition FindOptimalSplitPos(LifetimePosition start,
    1019             :                                        LifetimePosition end);
    1020             : 
    1021             :   void Spill(LiveRange* range);
    1022             : 
    1023             :   // If we are trying to spill a range inside the loop try to
    1024             :   // hoist spill position out to the point just before the loop.
    1025             :   LifetimePosition FindOptimalSpillingPos(LiveRange* range,
    1026             :                                           LifetimePosition pos);
    1027             : 
    1028             :   const ZoneVector<TopLevelLiveRange*>& GetFixedRegisters() const;
    1029             :   const char* RegisterName(int allocation_index) const;
    1030             : 
    1031             :  private:
    1032             :   RegisterAllocationData* const data_;
    1033             :   const RegisterKind mode_;
    1034             :   const int num_registers_;
    1035             :   int num_allocatable_registers_;
    1036             :   const int* allocatable_register_codes_;
    1037             :   bool check_fp_aliasing_;
    1038             : 
    1039             :  private:
    1040             :   bool no_combining_;
    1041             : 
    1042             :   DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
    1043             : };
    1044             : 
    1045             : 
    1046             : class LinearScanAllocator final : public RegisterAllocator {
    1047             :  public:
    1048             :   LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind,
    1049             :                       Zone* local_zone);
    1050             : 
    1051             :   // Phase 4: compute register assignments.
    1052             :   void AllocateRegisters();
    1053             : 
    1054             :  private:
    1055             :   ZoneVector<LiveRange*>& unhandled_live_ranges() {
    1056             :     return unhandled_live_ranges_;
    1057             :   }
    1058             :   ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; }
    1059             :   ZoneVector<LiveRange*>& inactive_live_ranges() {
    1060             :     return inactive_live_ranges_;
    1061             :   }
    1062             : 
    1063             :   void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
    1064             : 
    1065             :   // Helper methods for updating the life range lists.
    1066             :   void AddToActive(LiveRange* range);
    1067             :   void AddToInactive(LiveRange* range);
    1068             :   void AddToUnhandledSorted(LiveRange* range);
    1069             :   void AddToUnhandledUnsorted(LiveRange* range);
    1070             :   void SortUnhandled();
    1071             :   bool UnhandledIsSorted();
    1072             :   void ActiveToHandled(LiveRange* range);
    1073             :   void ActiveToInactive(LiveRange* range);
    1074             :   void InactiveToHandled(LiveRange* range);
    1075             :   void InactiveToActive(LiveRange* range);
    1076             : 
    1077             :   // Helper methods for allocating registers.
    1078             :   bool TryReuseSpillForPhi(TopLevelLiveRange* range);
    1079             :   bool TryAllocateFreeReg(LiveRange* range,
    1080             :                           const Vector<LifetimePosition>& free_until_pos);
    1081             :   bool TryAllocatePreferredReg(LiveRange* range,
    1082             :                                const Vector<LifetimePosition>& free_until_pos);
    1083             :   void GetFPRegisterSet(MachineRepresentation rep, int* num_regs,
    1084             :                         int* num_codes, const int** codes) const;
    1085             :   void FindFreeRegistersForRange(LiveRange* range,
    1086             :                                  Vector<LifetimePosition> free_until_pos);
    1087             :   void ProcessCurrentRange(LiveRange* current);
    1088             :   void AllocateBlockedReg(LiveRange* range);
    1089             :   bool TrySplitAndSpillSplinter(LiveRange* range);
    1090             : 
    1091             :   // Spill the given life range after position pos.
    1092             :   void SpillAfter(LiveRange* range, LifetimePosition pos);
    1093             : 
    1094             :   // Spill the given life range after position [start] and up to position [end].
    1095             :   void SpillBetween(LiveRange* range, LifetimePosition start,
    1096             :                     LifetimePosition end);
    1097             : 
    1098             :   // Spill the given life range after position [start] and up to position [end].
    1099             :   // Range is guaranteed to be spilled at least until position [until].
    1100             :   void SpillBetweenUntil(LiveRange* range, LifetimePosition start,
    1101             :                          LifetimePosition until, LifetimePosition end);
    1102             : 
    1103             :   void SplitAndSpillIntersecting(LiveRange* range);
    1104             : 
    1105             :   ZoneVector<LiveRange*> unhandled_live_ranges_;
    1106             :   ZoneVector<LiveRange*> active_live_ranges_;
    1107             :   ZoneVector<LiveRange*> inactive_live_ranges_;
    1108             : 
    1109             : #ifdef DEBUG
    1110             :   LifetimePosition allocation_finger_;
    1111             : #endif
    1112             : 
    1113             :   DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator);
    1114             : };
    1115             : 
    1116             : 
    1117             : class SpillSlotLocator final : public ZoneObject {
    1118             :  public:
    1119             :   explicit SpillSlotLocator(RegisterAllocationData* data);
    1120             : 
    1121             :   void LocateSpillSlots();
    1122             : 
    1123             :  private:
    1124      915917 :   RegisterAllocationData* data() const { return data_; }
    1125             : 
    1126             :   RegisterAllocationData* const data_;
    1127             : 
    1128             :   DISALLOW_COPY_AND_ASSIGN(SpillSlotLocator);
    1129             : };
    1130             : 
    1131             : 
    1132             : class OperandAssigner final : public ZoneObject {
    1133             :  public:
    1134             :   explicit OperandAssigner(RegisterAllocationData* data);
    1135             : 
    1136             :   // Phase 5: assign spill splots.
    1137             :   void AssignSpillSlots();
    1138             : 
    1139             :   // Phase 6: commit assignment.
    1140             :   void CommitAssignment();
    1141             : 
    1142             :  private:
    1143    15993812 :   RegisterAllocationData* data() const { return data_; }
    1144             : 
    1145             :   RegisterAllocationData* const data_;
    1146             : 
    1147             :   DISALLOW_COPY_AND_ASSIGN(OperandAssigner);
    1148             : };
    1149             : 
    1150             : 
    1151             : class ReferenceMapPopulator final : public ZoneObject {
    1152             :  public:
    1153             :   explicit ReferenceMapPopulator(RegisterAllocationData* data);
    1154             : 
    1155             :   // Phase 7: compute values for pointer maps.
    1156             :   void PopulateReferenceMaps();
    1157             : 
    1158             :  private:
    1159    25182700 :   RegisterAllocationData* data() const { return data_; }
    1160             : 
    1161             :   bool SafePointsAreInOrder() const;
    1162             : 
    1163             :   RegisterAllocationData* const data_;
    1164             : 
    1165             :   DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator);
    1166             : };
    1167             : 
    1168             : 
    1169             : class LiveRangeBoundArray;
    1170             : // Insert moves of the form
    1171             : //
    1172             : //          Operand(child_(k+1)) = Operand(child_k)
    1173             : //
    1174             : // where child_k and child_(k+1) are consecutive children of a range (so
    1175             : // child_k->next() == child_(k+1)), and Operand(...) refers to the
    1176             : // assigned operand, be it a register or a slot.
    1177             : class LiveRangeConnector final : public ZoneObject {
    1178             :  public:
    1179             :   explicit LiveRangeConnector(RegisterAllocationData* data);
    1180             : 
    1181             :   // Phase 8: reconnect split ranges with moves, when the control flow
    1182             :   // between the ranges is trivial (no branches).
    1183             :   void ConnectRanges(Zone* local_zone);
    1184             : 
    1185             :   // Phase 9: insert moves to connect ranges across basic blocks, when the
    1186             :   // control flow between them cannot be trivially resolved, such as joining
    1187             :   // branches.
    1188             :   void ResolveControlFlow(Zone* local_zone);
    1189             : 
    1190             :  private:
    1191   110991549 :   RegisterAllocationData* data() const { return data_; }
    1192    93397174 :   InstructionSequence* code() const { return data()->code(); }
    1193    11575257 :   Zone* code_zone() const { return code()->zone(); }
    1194             : 
    1195             :   bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
    1196             : 
    1197             :   int ResolveControlFlow(const InstructionBlock* block,
    1198             :                          const InstructionOperand& cur_op,
    1199             :                          const InstructionBlock* pred,
    1200             :                          const InstructionOperand& pred_op);
    1201             : 
    1202             :   void CommitSpillsInDeferredBlocks(TopLevelLiveRange* range,
    1203             :                                     LiveRangeBoundArray* array,
    1204             :                                     Zone* temp_zone);
    1205             : 
    1206             :   RegisterAllocationData* const data_;
    1207             : 
    1208             :   DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector);
    1209             : };
    1210             : 
    1211             : }  // namespace compiler
    1212             : }  // namespace internal
    1213             : }  // namespace v8
    1214             : 
    1215             : #endif  // V8_REGISTER_ALLOCATOR_H_

Generated by: LCOV version 1.10