LCOV - code coverage report
Current view: top level - js/src/jit - RegisterSets.h (source / functions) Hit Total Coverage
Test: output.info Lines: 473 512 92.4 %
Date: 2017-07-14 16:53:18 Functions: 283 338 83.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_RegisterSets_h
       8             : #define jit_RegisterSets_h
       9             : 
      10             : #include "mozilla/MathAlgorithms.h"
      11             : 
      12             : #include "jit/JitAllocPolicy.h"
      13             : #include "jit/Registers.h"
      14             : 
      15             : namespace js {
      16             : namespace jit {
      17             : 
      18             : struct AnyRegister {
      19             :     typedef uint32_t Code;
      20             : 
      21             :     static const uint32_t Total = Registers::Total + FloatRegisters::Total;
      22             :     static const uint32_t Invalid = UINT_MAX;
      23             : 
      24             :   private:
      25             :     Code code_;
      26             : 
      27             :   public:
      28       24055 :     AnyRegister() = default;
      29             : 
      30       34170 :     explicit AnyRegister(Register gpr) {
      31       34170 :         code_ = gpr.code();
      32       34170 :     }
      33        5594 :     explicit AnyRegister(FloatRegister fpu) {
      34        5594 :         code_ = fpu.code() + Registers::Total;
      35        5594 :     }
      36         572 :     static AnyRegister FromCode(uint32_t i) {
      37         572 :         MOZ_ASSERT(i < Total);
      38         572 :         AnyRegister r;
      39         572 :         r.code_ = i;
      40         572 :         return r;
      41             :     }
      42      192814 :     bool isFloat() const {
      43      192814 :         return code_ >= Registers::Total;
      44             :     }
      45       72719 :     Register gpr() const {
      46       72719 :         MOZ_ASSERT(!isFloat());
      47       72719 :         return Register::FromCode(code_);
      48             :     }
      49        2718 :     FloatRegister fpu() const {
      50        2718 :         MOZ_ASSERT(isFloat());
      51        2718 :         return FloatRegister::FromCode(code_ - Registers::Total);
      52             :     }
      53       30594 :     bool operator ==(AnyRegister other) const {
      54       30594 :         return code_ == other.code_;
      55             :     }
      56             :     bool operator !=(AnyRegister other) const {
      57             :         return code_ != other.code_;
      58             :     }
      59        5034 :     const char* name() const {
      60        5034 :         return isFloat() ? fpu().name() : gpr().name();
      61             :     }
      62       26012 :     Code code() const {
      63       26012 :         return code_;
      64             :     }
      65             :     bool volatile_() const {
      66             :         return isFloat() ? fpu().volatile_() : gpr().volatile_();
      67             :     }
      68       22971 :     AnyRegister aliased(uint32_t aliasIdx) const {
      69       22971 :         AnyRegister ret;
      70       22971 :         if (isFloat()) {
      71         123 :             FloatRegister fret;
      72         123 :             fpu().aliased(aliasIdx, &fret);
      73         123 :             ret = AnyRegister(fret);
      74             :         } else {
      75       22848 :             Register gret;
      76       22848 :             gpr().aliased(aliasIdx, &gret);
      77       22848 :             ret = AnyRegister(gret);
      78             :         }
      79       22971 :         MOZ_ASSERT_IF(aliasIdx == 0, ret == *this);
      80       22971 :         return ret;
      81             :     }
      82       41917 :     uint32_t numAliased() const {
      83       41917 :         if (isFloat())
      84         164 :             return fpu().numAliased();
      85       41753 :         return gpr().numAliased();
      86             :     }
      87           0 :     bool aliases(const AnyRegister& other) const {
      88           0 :         if (isFloat() && other.isFloat())
      89           0 :             return fpu().aliases(other.fpu());
      90           0 :         if (!isFloat() && !other.isFloat())
      91           0 :             return gpr().aliases(other.gpr());
      92           0 :         return false;
      93             :     }
      94             :     // do the two registers hold the same type of data (e.g. both float32, both gpr)
      95             :     bool isCompatibleReg (const AnyRegister other) const {
      96             :         if (isFloat() && other.isFloat())
      97             :             return fpu().equiv(other.fpu());
      98             :         if (!isFloat() && !other.isFloat())
      99             :             return true;
     100             :         return false;
     101             :     }
     102             : 
     103             : };
     104             : 
     105             : // Registers to hold a boxed value. Uses one register on 64 bit
     106             : // platforms, two registers on 32 bit platforms.
     107             : class ValueOperand
     108             : {
     109             : #if defined(JS_NUNBOX32)
     110             :     Register type_;
     111             :     Register payload_;
     112             : 
     113             :   public:
     114             :     constexpr ValueOperand(Register type, Register payload)
     115             :       : type_(type), payload_(payload)
     116             :     { }
     117             : 
     118             :     Register typeReg() const {
     119             :         return type_;
     120             :     }
     121             :     Register payloadReg() const {
     122             :         return payload_;
     123             :     }
     124             :     bool aliases(Register reg) const {
     125             :         return type_ == reg || payload_ == reg;
     126             :     }
     127             :     Register scratchReg() const {
     128             :         return payloadReg();
     129             :     }
     130             :     bool operator==(const ValueOperand& o) const {
     131             :         return type_ == o.type_ && payload_ == o.payload_;
     132             :     }
     133             :     bool operator!=(const ValueOperand& o) const {
     134             :         return !(*this == o);
     135             :     }
     136             : 
     137             : #elif defined(JS_PUNBOX64)
     138             :     Register value_;
     139             : 
     140             :   public:
     141         683 :     explicit constexpr ValueOperand(Register value)
     142         683 :       : value_(value)
     143         683 :     { }
     144             : 
     145      118433 :     Register valueReg() const {
     146      118433 :         return value_;
     147             :     }
     148         282 :     bool aliases(Register reg) const {
     149         282 :         return value_ == reg;
     150             :     }
     151       21331 :     Register scratchReg() const {
     152       21331 :         return valueReg();
     153             :     }
     154       73076 :     bool operator==(const ValueOperand& o) const {
     155       73076 :         return value_ == o.value_;
     156             :     }
     157             :     bool operator!=(const ValueOperand& o) const {
     158             :         return !(*this == o);
     159             :     }
     160             : #endif
     161             : 
     162         210 :     ValueOperand() = default;
     163             : };
     164             : 
     165             : // Registers to hold either either a typed or untyped value.
     166             : class TypedOrValueRegister
     167             : {
     168             :     // Type of value being stored.
     169             :     MIRType type_;
     170             : 
     171         453 :     union U {
     172             :         AnyRegister typed;
     173             :         ValueOperand value;
     174             :     } data;
     175             : 
     176             :   public:
     177             : 
     178             :     TypedOrValueRegister() = default;
     179             : 
     180         124 :     TypedOrValueRegister(MIRType type, AnyRegister reg)
     181         124 :       : type_(type)
     182             :     {
     183         124 :         data.typed = reg;
     184         124 :     }
     185             : 
     186         329 :     MOZ_IMPLICIT TypedOrValueRegister(ValueOperand value)
     187         329 :       : type_(MIRType::Value)
     188             :     {
     189         329 :         data.value = value;
     190         329 :     }
     191             : 
     192        2614 :     MIRType type() const {
     193        2614 :         return type_;
     194             :     }
     195             : 
     196         281 :     bool hasTyped() const {
     197         281 :         return type() != MIRType::None && type() != MIRType::Value;
     198             :     }
     199             : 
     200        1793 :     bool hasValue() const {
     201        1793 :         return type() == MIRType::Value;
     202             :     }
     203             : 
     204         213 :     AnyRegister typedReg() const {
     205         213 :         MOZ_ASSERT(hasTyped());
     206         213 :         return data.typed;
     207             :     }
     208             : 
     209         900 :     ValueOperand valueReg() const {
     210         900 :         MOZ_ASSERT(hasValue());
     211         900 :         return data.value;
     212             :     }
     213             : 
     214             :     AnyRegister scratchReg() {
     215             :         if (hasValue())
     216             :             return AnyRegister(valueReg().scratchReg());
     217             :         return typedReg();
     218             :     }
     219             : };
     220             : 
     221             : // A constant value, or registers to hold a typed/untyped value.
     222             : class ConstantOrRegister
     223             : {
     224             :     // Whether a constant value is being stored.
     225             :     bool constant_;
     226             : 
     227             :     // Space to hold either a Value or a TypedOrValueRegister.
     228         163 :     union U {
     229             :         Value constant;
     230             :         TypedOrValueRegister reg;
     231             :     } data;
     232             : 
     233          73 :     const Value& dataValue() const {
     234          73 :         MOZ_ASSERT(constant());
     235          73 :         return data.constant;
     236             :     }
     237          39 :     void setDataValue(const Value& value) {
     238          39 :         MOZ_ASSERT(constant());
     239          39 :         data.constant = value;
     240          39 :     }
     241         149 :     const TypedOrValueRegister& dataReg() const {
     242         149 :         MOZ_ASSERT(!constant());
     243         149 :         return data.reg;
     244             :     }
     245         122 :     void setDataReg(const TypedOrValueRegister& reg) {
     246         122 :         MOZ_ASSERT(!constant());
     247         122 :         data.reg = reg;
     248         122 :     }
     249             : 
     250             :   public:
     251             : 
     252           2 :     ConstantOrRegister()
     253           2 :     {}
     254             : 
     255          39 :     MOZ_IMPLICIT ConstantOrRegister(const Value& value)
     256          39 :       : constant_(true)
     257             :     {
     258          39 :         setDataValue(value);
     259          39 :     }
     260             : 
     261         122 :     MOZ_IMPLICIT ConstantOrRegister(TypedOrValueRegister reg)
     262         122 :       : constant_(false)
     263             :     {
     264         122 :         setDataReg(reg);
     265         122 :     }
     266             : 
     267         567 :     bool constant() const {
     268         567 :         return constant_;
     269             :     }
     270             : 
     271          73 :     const Value& value() const {
     272          73 :         return dataValue();
     273             :     }
     274             : 
     275         149 :     const TypedOrValueRegister& reg() const {
     276         149 :         return dataReg();
     277             :     }
     278             : };
     279             : 
     280             : struct RegisterOrInt32Constant {
     281             :     bool isRegister_;
     282             :     union {
     283             :         Register reg_;
     284             :         int32_t constant_;
     285             :     };
     286             : 
     287           3 :     explicit RegisterOrInt32Constant(Register reg)
     288           3 :       : isRegister_(true), reg_(reg)
     289           3 :     { }
     290             : 
     291           4 :     explicit RegisterOrInt32Constant(int32_t index)
     292           4 :       : isRegister_(false), constant_(index)
     293           4 :     { }
     294             : 
     295           8 :     inline void bumpConstant(int diff) {
     296           8 :         MOZ_ASSERT(!isRegister_);
     297           8 :         constant_ += diff;
     298           8 :     }
     299          10 :     inline Register reg() const {
     300          10 :         MOZ_ASSERT(isRegister_);
     301          10 :         return reg_;
     302             :     }
     303           4 :     inline int32_t constant() const {
     304           4 :         MOZ_ASSERT(!isRegister_);
     305           4 :         return constant_;
     306             :     }
     307          22 :     inline bool isRegister() const {
     308          22 :         return isRegister_;
     309             :     }
     310           0 :     inline bool isConstant() const {
     311           0 :         return !isRegister_;
     312             :     }
     313             : };
     314             : 
     315             : template <typename T>
     316             : class TypedRegisterSet
     317             : {
     318             :   public:
     319             :     typedef T RegType;
     320             :     typedef typename T::SetType SetType;
     321             : 
     322             :   private:
     323             :     SetType bits_;
     324             : 
     325             :   public:
     326       56808 :     explicit constexpr TypedRegisterSet(SetType bits)
     327       56808 :       : bits_(bits)
     328       56808 :     { }
     329             : 
     330       42510 :     constexpr TypedRegisterSet() : bits_(0)
     331       42510 :     { }
     332      857267 :     constexpr TypedRegisterSet(const TypedRegisterSet<T>& set) : bits_(set.bits_)
     333      857267 :     { }
     334             : 
     335        2340 :     static inline TypedRegisterSet All() {
     336        2340 :         return TypedRegisterSet(T::Codes::AllocatableMask);
     337             :     }
     338         168 :     static inline TypedRegisterSet Intersect(const TypedRegisterSet& lhs,
     339             :                                              const TypedRegisterSet& rhs) {
     340         168 :         return TypedRegisterSet(lhs.bits_ & rhs.bits_);
     341             :     }
     342             :     static inline TypedRegisterSet Union(const TypedRegisterSet& lhs,
     343             :                                          const TypedRegisterSet& rhs) {
     344             :         return TypedRegisterSet(lhs.bits_ | rhs.bits_);
     345             :     }
     346          42 :     static inline TypedRegisterSet Not(const TypedRegisterSet& in) {
     347          42 :         return TypedRegisterSet(~in.bits_ & T::Codes::AllocatableMask);
     348             :     }
     349             :     static inline TypedRegisterSet Subtract(const TypedRegisterSet& lhs,
     350             :                                             const TypedRegisterSet& rhs)
     351             :     {
     352             :         return TypedRegisterSet(lhs.bits_ & ~rhs.bits_);
     353             :     }
     354           0 :     static inline TypedRegisterSet VolatileNot(const TypedRegisterSet& in) {
     355             :         const SetType allocatableVolatile =
     356           0 :             T::Codes::AllocatableMask & T::Codes::VolatileMask;
     357           0 :         return TypedRegisterSet(~in.bits_ & allocatableVolatile);
     358             :     }
     359       25610 :     static inline TypedRegisterSet Volatile() {
     360       25610 :         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::VolatileMask);
     361             :     }
     362          40 :     static inline TypedRegisterSet NonVolatile() {
     363          40 :         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::NonVolatileMask);
     364             :     }
     365             : 
     366      589257 :     bool empty() const {
     367      589257 :         return !bits_;
     368             :     }
     369        1609 :     void clear() {
     370        1609 :         bits_ = 0;
     371        1609 :     }
     372             : 
     373      687225 :     bool hasRegisterIndex(T reg) const {
     374      687225 :         return !!(bits_ & (SetType(1) << reg.code()));
     375             :     }
     376       80489 :     bool hasAllocatable(T reg) const {
     377       80489 :         return !(~bits_ & reg.alignedOrDominatedAliasedSet());
     378             :     }
     379             : 
     380        3440 :     void addRegisterIndex(T reg) {
     381        3440 :         bits_ |= (SetType(1) << reg.code());
     382        3440 :     }
     383       27343 :     void addAllocatable(T reg) {
     384       27343 :         bits_ |= reg.alignedOrDominatedAliasedSet();
     385       27342 :     }
     386             : 
     387             : 
     388      515635 :     void takeRegisterIndex(T reg) {
     389      515635 :         bits_ &= ~(SetType(1) << reg.code());
     390      515625 :     }
     391       53606 :     void takeAllocatable(T reg) {
     392       53606 :         bits_ &= ~reg.alignedOrDominatedAliasedSet();
     393       53606 :     }
     394             : 
     395             :     static constexpr RegTypeName DefaultType = RegType::DefaultType;
     396             : 
     397             :     template <RegTypeName Name>
     398     1033689 :     SetType allLive() const {
     399     1033689 :         return T::template LiveAsIndexableSet<Name>(bits_);
     400             :     }
     401             :     template <RegTypeName Name>
     402       18961 :     SetType allAllocatable() const {
     403       18961 :         return T::template AllocatableAsIndexableSet<Name>(bits_);
     404             :     }
     405             : 
     406      207456 :     static RegType FirstRegister(SetType set) {
     407      207456 :         return RegType::FromCode(RegType::FirstBit(set));
     408             :     }
     409      845224 :     static RegType LastRegister(SetType set) {
     410      845224 :         return RegType::FromCode(RegType::LastBit(set));
     411             :     }
     412             : 
     413       56142 :     SetType bits() const {
     414       56142 :         return bits_;
     415             :     }
     416       45552 :     uint32_t size() const {
     417       45552 :         return T::SetSize(bits_);
     418             :     }
     419             :     bool operator ==(const TypedRegisterSet<T>& other) const {
     420             :         return other.bits_ == bits_;
     421             :     }
     422       23565 :     TypedRegisterSet<T> reduceSetForPush() const {
     423       23565 :         return T::ReduceSetForPush(*this);
     424             :     }
     425       22729 :     uint32_t getPushSizeInBytes() const {
     426       22729 :         return T::GetPushSizeInBytes(*this);
     427             :     }
     428             : };
     429             : 
     430             : typedef TypedRegisterSet<Register> GeneralRegisterSet;
     431             : typedef TypedRegisterSet<FloatRegister> FloatRegisterSet;
     432             : 
     433             : class AnyRegisterIterator;
     434             : 
     435      138455 : class RegisterSet {
     436             :     GeneralRegisterSet gpr_;
     437             :     FloatRegisterSet fpu_;
     438             : 
     439             :     friend class AnyRegisterIterator;
     440             : 
     441             :   public:
     442       16134 :     RegisterSet()
     443       16134 :     { }
     444       12998 :     constexpr RegisterSet(const GeneralRegisterSet& gpr, const FloatRegisterSet& fpu)
     445       12998 :       : gpr_(gpr),
     446       12998 :         fpu_(fpu)
     447       12998 :     { }
     448           8 :     static inline RegisterSet All() {
     449           8 :         return RegisterSet(GeneralRegisterSet::All(), FloatRegisterSet::All());
     450             :     }
     451           4 :     static inline RegisterSet Intersect(const RegisterSet& lhs, const RegisterSet& rhs) {
     452           8 :         return RegisterSet(GeneralRegisterSet::Intersect(lhs.gpr_, rhs.gpr_),
     453          12 :                            FloatRegisterSet::Intersect(lhs.fpu_, rhs.fpu_));
     454             :     }
     455             :     static inline RegisterSet Union(const RegisterSet& lhs, const RegisterSet& rhs) {
     456             :         return RegisterSet(GeneralRegisterSet::Union(lhs.gpr_, rhs.gpr_),
     457             :                            FloatRegisterSet::Union(lhs.fpu_, rhs.fpu_));
     458             :     }
     459           0 :     static inline RegisterSet Not(const RegisterSet& in) {
     460           0 :         return RegisterSet(GeneralRegisterSet::Not(in.gpr_),
     461           0 :                            FloatRegisterSet::Not(in.fpu_));
     462             :     }
     463           0 :     static inline RegisterSet VolatileNot(const RegisterSet& in) {
     464           0 :         return RegisterSet(GeneralRegisterSet::VolatileNot(in.gpr_),
     465           0 :                            FloatRegisterSet::VolatileNot(in.fpu_));
     466             :     }
     467       12643 :     static inline RegisterSet Volatile() {
     468       12643 :         return RegisterSet(GeneralRegisterSet::Volatile(), FloatRegisterSet::Volatile());
     469             :     }
     470             : 
     471             :     bool empty() const {
     472             :         return fpu_.empty() && gpr_.empty();
     473             :     }
     474             :     void clear() {
     475             :         fpu_.clear();
     476             :         gpr_.clear();
     477             :     }
     478       11516 :     bool emptyGeneral() const {
     479       11516 :         return gpr_.empty();
     480             :     }
     481         406 :     bool emptyFloat() const {
     482         406 :         return fpu_.empty();
     483             :     }
     484             : 
     485             :     static constexpr RegTypeName DefaultType = RegTypeName::GPR;
     486             : 
     487       82607 :     constexpr GeneralRegisterSet gprs() const {
     488       82607 :         return gpr_;
     489             :     }
     490      113077 :     GeneralRegisterSet& gprs() {
     491      113077 :         return gpr_;
     492             :     }
     493      166407 :     constexpr FloatRegisterSet fpus() const {
     494      166407 :         return fpu_;
     495             :     }
     496       23180 :     FloatRegisterSet& fpus() {
     497       23180 :         return fpu_;
     498             :     }
     499             :     bool operator ==(const RegisterSet& other) const {
     500             :         return other.gpr_ == gpr_ && other.fpu_ == fpu_;
     501             :     }
     502             : 
     503             : };
     504             : 
     505             : // There are 2 use cases for register sets:
     506             : //
     507             : //   1. To serve as a pool of allocatable register. This is useful for working
     508             : //      on the code produced by some stub where free registers are available, or
     509             : //      when we can release some registers.
     510             : //
     511             : //   2. To serve as a list of typed registers. This is useful for working with
     512             : //      live registers and to manipulate them with the proper instructions. This
     513             : //      is used by the register allocator to fill the Safepoints.
     514             : //
     515             : // These 2 uses cases can be used on top of 3 different backend representation
     516             : // of register sets, which are either GeneralRegisterSet, FloatRegisterSet, or
     517             : // RegisterSet (for both). These classes are used to store the bit sets to
     518             : // represent each register.
     519             : //
     520             : // Each use case defines an Accessor class, such as AllocatableSetAccessor or
     521             : // LiveSetAccessor, which is parameterized with the type of the register
     522             : // set. These accessors are in charge of manipulating the register set in a
     523             : // consistent way.
     524             : //
     525             : // The RegSetCommonInterface class is used to wrap the accessors with convenient
     526             : // shortcuts which are based on the accessors.
     527             : //
     528             : // Then, to avoid to many levels of complexity while using these interfaces,
     529             : // shortcut templates are created to make it easy to distinguish between a
     530             : // register set used for allocating registers, or a register set used for making
     531             : // a collection of allocated (live) registers.
     532             : //
     533             : // This separation exists to prevent mixing LiveSet and AllocatableSet
     534             : // manipulations of the same register set, and ensure safety while avoiding
     535             : // false positive.
     536             : 
     537             : template <typename RegisterSet>
     538             : class AllocatableSet;
     539             : 
     540             : template <typename RegisterSet>
     541             : class LiveSet;
     542             : 
     543             : // Base accessors classes have the minimal set of raw methods to manipulate the register set
     544             : // given as parameter in a consistent manner.  These methods are:
     545             : //
     546             : //    - all<Type>: Returns a bit-set of all the register of a specific type
     547             : //      which are present.
     548             : //
     549             : //    - has: Returns if all the bits needed to take a register are present.
     550             : //
     551             : //    - takeUnchecked: Subtracts the bits used to represent the register in the
     552             : //      register set.
     553             : //
     554             : //    - addUnchecked: Adds the bits used to represent the register in the
     555             : //      register set.
     556             : 
     557             : // The AllocatableSet accessors are used to make a pool of unused
     558             : // registers. Taking or adding registers should consider the aliasing rules of
     559             : // the architecture.  For example, on ARM, the following piece of code should
     560             : // work fine, knowing that the double register |d0| is composed of float
     561             : // registers |s0| and |s1|:
     562             : //
     563             : //     AllocatableFloatRegisterSet regs;
     564             : //     regs.add(s0);
     565             : //     regs.add(s1);
     566             : //     // d0 is now available.
     567             : //     regs.take(d0);
     568             : //
     569             : // These accessors are useful for allocating registers within the functions used
     570             : // to generate stubs, trampolines, and inline caches (BaselineIC, IonCache).
     571             : template <typename Set>
     572         232 : class AllocatableSetAccessors
     573             : {
     574             :   public:
     575             :     typedef Set RegSet;
     576             :     typedef typename RegSet::RegType RegType;
     577             :     typedef typename RegSet::SetType SetType;
     578             : 
     579             :   protected:
     580             :     RegSet set_;
     581             : 
     582             :     template <RegTypeName Name>
     583        6432 :     SetType all() const {
     584        6432 :         return set_.template allAllocatable<Name>();
     585             :     }
     586             : 
     587             :   public:
     588         574 :     AllocatableSetAccessors() : set_() {}
     589        1643 :     explicit constexpr AllocatableSetAccessors(SetType set) : set_(set) {}
     590        2064 :     explicit constexpr AllocatableSetAccessors(RegSet set) : set_(set) {}
     591             : 
     592       16751 :     bool has(RegType reg) const {
     593       16751 :         return set_.hasAllocatable(reg);
     594             :     }
     595             : 
     596             :     template <RegTypeName Name>
     597             :     bool hasAny(RegType reg) const {
     598             :         return all<Name>() != 0;
     599             :     }
     600             : 
     601        1738 :     void addUnchecked(RegType reg) {
     602        1738 :         set_.addAllocatable(reg);
     603        1738 :     }
     604             : 
     605       12315 :     void takeUnchecked(RegType reg) {
     606       12315 :         set_.takeAllocatable(reg);
     607       12315 :     }
     608             : };
     609             : 
     610             : // Specialization of the AllocatableSet accessors for the RegisterSet aggregate.
     611             : template <>
     612             : class AllocatableSetAccessors<RegisterSet>
     613             : {
     614             :   public:
     615             :     typedef RegisterSet RegSet;
     616             :     typedef AnyRegister RegType;
     617             :     typedef char SetType;
     618             : 
     619             :   protected:
     620             :     RegisterSet set_;
     621             : 
     622             :     template <RegTypeName Name>
     623       12529 :     GeneralRegisterSet::SetType allGpr() const {
     624       12529 :         return set_.gprs().allAllocatable<Name>();
     625             :     }
     626             :     template <RegTypeName Name>
     627             :     FloatRegisterSet::SetType allFpu() const {
     628             :         return set_.fpus().allAllocatable<Name>();
     629             :     }
     630             : 
     631             :   public:
     632        4503 :     AllocatableSetAccessors() : set_() {}
     633             :     explicit constexpr AllocatableSetAccessors(SetType) = delete;
     634       11909 :     explicit constexpr AllocatableSetAccessors(RegisterSet set) : set_(set) {}
     635             : 
     636       63681 :     bool has(Register reg) const {
     637       63681 :         return set_.gprs().hasAllocatable(reg);
     638             :     }
     639          56 :     bool has(FloatRegister reg) const {
     640          56 :         return set_.fpus().hasAllocatable(reg);
     641             :     }
     642             : 
     643       25577 :     void addUnchecked(Register reg) {
     644       25577 :         set_.gprs().addAllocatable(reg);
     645       25576 :     }
     646          28 :     void addUnchecked(FloatRegister reg) {
     647          28 :         set_.fpus().addAllocatable(reg);
     648          28 :     }
     649             : 
     650       41264 :     void takeUnchecked(Register reg) {
     651       41264 :         set_.gprs().takeAllocatable(reg);
     652       41264 :     }
     653          28 :     void takeUnchecked(FloatRegister reg) {
     654          28 :         set_.fpus().takeAllocatable(reg);
     655          28 :     }
     656             : };
     657             : 
     658             : 
     659             : // The LiveSet accessors are used to collect a list of allocated
     660             : // registers. Taking or adding a register should *not* consider the aliases, as
     661             : // we care about interpreting the registers with the correct type.  For example,
     662             : // on x64, where one float registers can be interpreted as an Simd128, a Double,
     663             : // or a Float, adding xmm0 as an Simd128, does not make the register available
     664             : // as a Double.
     665             : //
     666             : //     LiveFloatRegisterSet regs;
     667             : //     regs.add(xmm0.asSimd128());
     668             : //     regs.take(xmm0); // Assert!
     669             : //
     670             : // These accessors are useful for recording the result of a register allocator,
     671             : // such as what the Backtracking allocator do on the Safepoints.
     672             : template <typename Set>
     673        6351 : class LiveSetAccessors
     674             : {
     675             :   public:
     676             :     typedef Set RegSet;
     677             :     typedef typename RegSet::RegType RegType;
     678             :     typedef typename RegSet::SetType SetType;
     679             : 
     680             :   protected:
     681             :     RegSet set_;
     682             : 
     683             :     template <RegTypeName Name>
     684     1033216 :     SetType all() const {
     685     1033216 :         return set_.template allLive<Name>();
     686             :     }
     687             : 
     688             :   public:
     689         839 :     LiveSetAccessors() : set_() {}
     690             :     explicit constexpr LiveSetAccessors(SetType set) : set_(set) {}
     691       48738 :     explicit constexpr LiveSetAccessors(RegSet set) : set_(set) {}
     692             : 
     693      519888 :     bool has(RegType reg) const {
     694      519888 :         return set_.hasRegisterIndex(reg);
     695             :     }
     696             : 
     697        2775 :     void addUnchecked(RegType reg) {
     698        2775 :         set_.addRegisterIndex(reg);
     699        2775 :     }
     700             : 
     701      515127 :     void takeUnchecked(RegType reg) {
     702      515127 :         set_.takeRegisterIndex(reg);
     703      515117 :     }
     704             : };
     705             : 
     706             : // Specialization of the LiveSet accessors for the RegisterSet aggregate.
     707             : template <>
     708       33375 : class LiveSetAccessors<RegisterSet>
     709             : {
     710             :   public:
     711             :     typedef RegisterSet RegSet;
     712             :     typedef AnyRegister RegType;
     713             :     typedef char SetType;
     714             : 
     715             :   protected:
     716             :     RegisterSet set_;
     717             : 
     718             :     template <RegTypeName Name>
     719         112 :     GeneralRegisterSet::SetType allGpr() const {
     720         112 :         return set_.gprs().allLive<Name>();
     721             :     }
     722             :     template <RegTypeName Name>
     723         360 :     FloatRegisterSet::SetType allFpu() const {
     724         360 :         return set_.fpus().allLive<Name>();
     725             :     }
     726             : 
     727             :   public:
     728       11631 :     LiveSetAccessors() : set_() {}
     729             :     explicit constexpr LiveSetAccessors(SetType) = delete;
     730       11773 :     explicit constexpr LiveSetAccessors(RegisterSet set) : set_(set) {}
     731             : 
     732        1438 :     bool has(Register reg) const {
     733        1438 :         return set_.gprs().hasRegisterIndex(reg);
     734             :     }
     735      165911 :     bool has(FloatRegister reg) const {
     736      165911 :         return set_.fpus().hasRegisterIndex(reg);
     737             :     }
     738             : 
     739         647 :     void addUnchecked(Register reg) {
     740         647 :         set_.gprs().addRegisterIndex(reg);
     741         647 :     }
     742          18 :     void addUnchecked(FloatRegister reg) {
     743          18 :         set_.fpus().addRegisterIndex(reg);
     744          18 :     }
     745             : 
     746         148 :     void takeUnchecked(Register reg) {
     747         148 :         set_.gprs().takeRegisterIndex(reg);
     748         148 :     }
     749         360 :     void takeUnchecked(FloatRegister reg) {
     750         360 :         set_.fpus().takeRegisterIndex(reg);
     751         360 :     }
     752             : };
     753             : 
     754             : #define DEFINE_ACCESSOR_CONSTRUCTORS_(REGSET)                         \
     755             :     typedef typename Parent::RegSet  RegSet;                          \
     756             :     typedef typename Parent::RegType RegType;                         \
     757             :     typedef typename Parent::SetType SetType;                         \
     758             :                                                                       \
     759             :     constexpr REGSET() : Parent() {}                                  \
     760             :     explicit constexpr REGSET(SetType set) : Parent(set) {}           \
     761             :     explicit constexpr REGSET(RegSet set) : Parent(set) {}
     762             : 
     763             : // This class adds checked accessors on top of the unchecked variants defined by
     764             : // AllocatableSet and LiveSet accessors. Also it defines interface which are
     765             : // specialized to the register set implementation, such as |getAny| and
     766             : // |takeAny| variants.
     767             : template <class Accessors, typename Set>
     768        6583 : class SpecializedRegSet : public Accessors
     769             : {
     770             :     typedef Accessors Parent;
     771             : 
     772             :   public:
     773       53858 :     DEFINE_ACCESSOR_CONSTRUCTORS_(SpecializedRegSet)
     774             : 
     775        5080 :     SetType bits() const {
     776        5080 :         return this->Parent::set_.bits();
     777             :     }
     778             : 
     779             :     using Parent::has;
     780             : 
     781             :     using Parent::addUnchecked;
     782        4324 :     void add(RegType reg) {
     783        4324 :         MOZ_ASSERT(!has(reg));
     784        4324 :         addUnchecked(reg);
     785        4324 :     }
     786             : 
     787             :     using Parent::takeUnchecked;
     788      527081 :     void take(RegType reg) {
     789      527081 :         MOZ_ASSERT(has(reg));
     790      527081 :         takeUnchecked(reg);
     791      527071 :     }
     792             : 
     793             :     template <RegTypeName Name>
     794           0 :     bool hasAny() const {
     795           0 :         return Parent::template all<Name>() != 0;
     796             :     }
     797             : 
     798             :     template <RegTypeName Name = RegSet::DefaultType>
     799      194458 :     RegType getFirst() const {
     800      194458 :         SetType set = Parent::template all<Name>();
     801      194458 :         MOZ_ASSERT(set);
     802      194458 :         return RegSet::FirstRegister(set);
     803             :     }
     804             :     template <RegTypeName Name = RegSet::DefaultType>
     805      845224 :     RegType getLast() const {
     806      845224 :         SetType set = Parent::template all<Name>();
     807      845224 :         MOZ_ASSERT(set);
     808      845224 :         return RegSet::LastRegister(set);
     809             :     }
     810             :     template <RegTypeName Name = RegSet::DefaultType>
     811       15747 :     RegType getAny() const {
     812             :         // The choice of first or last here is mostly arbitrary, as they are
     813             :         // about the same speed on popular architectures. We choose first, as
     814             :         // it has the advantage of using the "lower" registers more often. These
     815             :         // registers are sometimes more efficient (e.g. optimized encodings for
     816             :         // EAX on x86).
     817       15747 :         return getFirst<Name>();
     818             :     }
     819             : 
     820             :     template <RegTypeName Name = RegSet::DefaultType>
     821             :     RegType getAnyExcluding(RegType preclude) {
     822             :         if (!has(preclude))
     823             :             return getAny<Name>();
     824             : 
     825             :         take(preclude);
     826             :         RegType result = getAny<Name>();
     827             :         add(preclude);
     828             :         return result;
     829             :     }
     830             : 
     831             :     template <RegTypeName Name = RegSet::DefaultType>
     832        6674 :     RegType takeAny() {
     833        6674 :         RegType reg = getAny<Name>();
     834        6674 :         take(reg);
     835        6674 :         return reg;
     836             :     }
     837             :     template <RegTypeName Name = RegSet::DefaultType>
     838       89360 :     RegType takeFirst() {
     839       89360 :         RegType reg = getFirst<Name>();
     840       89360 :         take(reg);
     841       89359 :         return reg;
     842             :     }
     843             :     template <RegTypeName Name = RegSet::DefaultType>
     844      422248 :     RegType takeLast() {
     845      422248 :         RegType reg = getLast<Name>();
     846      422306 :         take(reg);
     847      422300 :         return reg;
     848             :     }
     849             : 
     850         172 :     ValueOperand takeAnyValue() {
     851             : #if defined(JS_NUNBOX32)
     852             :         return ValueOperand(takeAny<RegTypeName::GPR>(), takeAny<RegTypeName::GPR>());
     853             : #elif defined(JS_PUNBOX64)
     854         172 :         return ValueOperand(takeAny<RegTypeName::GPR>());
     855             : #else
     856             : #error "Bad architecture"
     857             : #endif
     858             :     }
     859             : 
     860          37 :     bool aliases(ValueOperand v) const {
     861             : #ifdef JS_NUNBOX32
     862             :         return has(v.typeReg()) || has(v.payloadReg());
     863             : #else
     864          37 :         return has(v.valueReg());
     865             : #endif
     866             :     }
     867             : 
     868             :     template <RegTypeName Name = RegSet::DefaultType>
     869             :     RegType takeAnyExcluding(RegType preclude) {
     870             :         RegType reg = getAnyExcluding<Name>(preclude);
     871             :         take(reg);
     872             :         return reg;
     873             :     }
     874             : };
     875             : 
     876             : // Specialization of the accessors for the RegisterSet aggregate.
     877             : template <class Accessors>
     878       33375 : class SpecializedRegSet<Accessors, RegisterSet> : public Accessors
     879             : {
     880             :     typedef Accessors Parent;
     881             : 
     882             :   public:
     883       39816 :     DEFINE_ACCESSOR_CONSTRUCTORS_(SpecializedRegSet)
     884             : 
     885        4848 :     GeneralRegisterSet gprs() const {
     886        4848 :         return this->Parent::set_.gprs();
     887             :     }
     888       45450 :     GeneralRegisterSet& gprs() {
     889       45450 :         return this->Parent::set_.gprs();
     890             :     }
     891          80 :     FloatRegisterSet fpus() const {
     892          80 :         return this->Parent::set_.fpus();
     893             :     }
     894       22746 :     FloatRegisterSet& fpus() {
     895       22746 :         return this->Parent::set_.fpus();
     896             :     }
     897             : 
     898       11516 :     bool emptyGeneral() const {
     899       11516 :         return this->Parent::set_.emptyGeneral();
     900             :     }
     901         406 :     bool emptyFloat() const {
     902         406 :         return this->Parent::set_.emptyFloat();
     903             :     }
     904             : 
     905             :     using Parent::has;
     906         401 :     bool has(AnyRegister reg) const {
     907         401 :         return reg.isFloat() ? has(reg.fpu()) : has(reg.gpr());
     908             :     }
     909             : 
     910             :     template <RegTypeName Name>
     911             :     bool hasAny() const {
     912             :         if (Name == RegTypeName::GPR)
     913             :             return Parent::template allGpr<RegTypeName::GPR>() != 0;
     914             :         return Parent::template allFpu<Name>() != 0;
     915             :     }
     916             : 
     917             :     using Parent::addUnchecked;
     918         527 :     void addUnchecked(AnyRegister reg) {
     919         527 :         if (reg.isFloat())
     920          17 :             addUnchecked(reg.fpu());
     921             :         else
     922         510 :             addUnchecked(reg.gpr());
     923         527 :     }
     924             : 
     925       25714 :     void add(Register reg) {
     926       25714 :         MOZ_ASSERT(!has(reg));
     927       25714 :         addUnchecked(reg);
     928       25713 :     }
     929          29 :     void add(FloatRegister reg) {
     930          29 :         MOZ_ASSERT(!has(reg));
     931          29 :         addUnchecked(reg);
     932          29 :     }
     933           6 :     void add(AnyRegister reg) {
     934           6 :         if (reg.isFloat())
     935           1 :             add(reg.fpu());
     936             :         else
     937           5 :             add(reg.gpr());
     938           6 :     }
     939             : 
     940             :     using Parent::takeUnchecked;
     941             :     void takeUnchecked(AnyRegister reg) {
     942             :         if (reg.isFloat())
     943             :             takeUnchecked(reg.fpu());
     944             :         else
     945             :             takeUnchecked(reg.gpr());
     946             :     }
     947             : 
     948       38218 :     void take(Register reg) {
     949       38218 :         MOZ_ASSERT(has(reg));
     950       38218 :         takeUnchecked(reg);
     951       38218 :     }
     952         388 :     void take(FloatRegister reg) {
     953         388 :         MOZ_ASSERT(has(reg));
     954         388 :         takeUnchecked(reg);
     955         388 :     }
     956           0 :     void take(AnyRegister reg) {
     957           0 :         if (reg.isFloat())
     958           0 :             take(reg.fpu());
     959             :         else
     960           0 :             take(reg.gpr());
     961           0 :     }
     962             : 
     963       12641 :     Register getAnyGeneral() const {
     964       12641 :         GeneralRegisterSet::SetType set = Parent::template allGpr<RegTypeName::GPR>();
     965       12641 :         MOZ_ASSERT(set);
     966       12641 :         return GeneralRegisterSet::FirstRegister(set);
     967             :     }
     968             :     template <RegTypeName Name = RegTypeName::Float64>
     969         360 :     FloatRegister getAnyFloat() const {
     970         360 :         FloatRegisterSet::SetType set = Parent::template allFpu<Name>();
     971         360 :         MOZ_ASSERT(set);
     972         360 :         return FloatRegisterSet::FirstRegister(set);
     973             :     }
     974             : 
     975       12641 :     Register takeAnyGeneral() {
     976       12641 :         Register reg = getAnyGeneral();
     977       12641 :         take(reg);
     978       12641 :         return reg;
     979             :     }
     980             :     template <RegTypeName Name = RegTypeName::Float64>
     981         360 :     FloatRegister takeAnyFloat() {
     982         360 :         FloatRegister reg = getAnyFloat<Name>();
     983         360 :         take(reg);
     984         360 :         return reg;
     985             :     }
     986             :     ValueOperand takeAnyValue() {
     987             : #if defined(JS_NUNBOX32)
     988             :         return ValueOperand(takeAnyGeneral(), takeAnyGeneral());
     989             : #elif defined(JS_PUNBOX64)
     990             :         return ValueOperand(takeAnyGeneral());
     991             : #else
     992             : #error "Bad architecture"
     993             : #endif
     994             :     }
     995             : };
     996             : 
     997             : 
     998             : // Interface which is common to all register set implementations. It overloads
     999             : // |add|, |take| and |takeUnchecked| methods for types such as |ValueOperand|
    1000             : // and |TypedOrValueRegister|.
    1001             : template <class Accessors, typename Set>
    1002       39958 : class CommonRegSet : public SpecializedRegSet<Accessors, Set>
    1003             : {
    1004             :     typedef SpecializedRegSet<Accessors, Set> Parent;
    1005             : 
    1006             :   public:
    1007       93673 :     DEFINE_ACCESSOR_CONSTRUCTORS_(CommonRegSet)
    1008             : 
    1009       10835 :     RegSet set() const {
    1010       10835 :         return this->Parent::set_;
    1011             :     }
    1012        1190 :     RegSet& set() {
    1013        1190 :         return this->Parent::set_;
    1014             :     }
    1015             : 
    1016      575656 :     bool empty() const {
    1017      575656 :         return this->Parent::set_.empty();
    1018             :     }
    1019        1609 :     void clear() {
    1020        1609 :         this->Parent::set_.clear();
    1021        1609 :     }
    1022             : 
    1023             :     using Parent::add;
    1024        1006 :     void add(ValueOperand value) {
    1025             : #if defined(JS_NUNBOX32)
    1026             :         add(value.payloadReg());
    1027             :         add(value.typeReg());
    1028             : #elif defined(JS_PUNBOX64)
    1029        1006 :         add(value.valueReg());
    1030             : #else
    1031             : #error "Bad architecture"
    1032             : #endif
    1033        1006 :     }
    1034             : 
    1035             :     using Parent::addUnchecked;
    1036           1 :     void addUnchecked(ValueOperand value) {
    1037             : #if defined(JS_NUNBOX32)
    1038             :         addUnchecked(value.payloadReg());
    1039             :         addUnchecked(value.typeReg());
    1040             : #elif defined(JS_PUNBOX64)
    1041           1 :         addUnchecked(value.valueReg());
    1042             : #else
    1043             : #error "Bad architecture"
    1044             : #endif
    1045           1 :     }
    1046             : 
    1047          23 :     void add(TypedOrValueRegister reg) {
    1048          23 :         if (reg.hasValue())
    1049          17 :             add(reg.valueReg());
    1050           6 :         else if (reg.hasTyped())
    1051           6 :             add(reg.typedReg());
    1052          23 :     }
    1053             : 
    1054             :     using Parent::take;
    1055        1393 :     void take(ValueOperand value) {
    1056             : #if defined(JS_NUNBOX32)
    1057             :         take(value.payloadReg());
    1058             :         take(value.typeReg());
    1059             : #elif defined(JS_PUNBOX64)
    1060        1393 :         take(value.valueReg());
    1061             : #else
    1062             : #error "Bad architecture"
    1063             : #endif
    1064        1393 :     }
    1065             :     void take(TypedOrValueRegister reg) {
    1066             :         if (reg.hasValue())
    1067             :             take(reg.valueReg());
    1068             :         else if (reg.hasTyped())
    1069             :             take(reg.typedReg());
    1070             :     }
    1071             : 
    1072             :     using Parent::takeUnchecked;
    1073          10 :     void takeUnchecked(ValueOperand value) {
    1074             : #if defined(JS_NUNBOX32)
    1075             :         takeUnchecked(value.payloadReg());
    1076             :         takeUnchecked(value.typeReg());
    1077             : #elif defined(JS_PUNBOX64)
    1078          10 :         takeUnchecked(value.valueReg());
    1079             : #else
    1080             : #error "Bad architecture"
    1081             : #endif
    1082          10 :     }
    1083             :     void takeUnchecked(TypedOrValueRegister reg) {
    1084             :         if (reg.hasValue())
    1085             :             takeUnchecked(reg.valueReg());
    1086             :         else if (reg.hasTyped())
    1087             :             takeUnchecked(reg.typedReg());
    1088             :     }
    1089             : };
    1090             : 
    1091             : 
    1092             : // These classes do not provide any additional members, they only use their
    1093             : // constructors to forward to the common interface for all register sets.  The
    1094             : // only benefit of these classes is to provide user friendly names.
    1095             : template <typename Set>
    1096        6351 : class LiveSet : public CommonRegSet<LiveSetAccessors<Set>, Set>
    1097             : {
    1098             :     typedef CommonRegSet<LiveSetAccessors<Set>, Set> Parent;
    1099             : 
    1100             :   public:
    1101       49576 :     DEFINE_ACCESSOR_CONSTRUCTORS_(LiveSet)
    1102             : };
    1103             : 
    1104             : template <typename Set>
    1105         232 : class AllocatableSet : public CommonRegSet<AllocatableSetAccessors<Set>, Set>
    1106             : {
    1107             :     typedef CommonRegSet<AllocatableSetAccessors<Set>, Set> Parent;
    1108             : 
    1109             :   public:
    1110        4281 :     DEFINE_ACCESSOR_CONSTRUCTORS_(AllocatableSet)
    1111             : 
    1112             :     LiveSet<Set> asLiveSet() const {
    1113             :         return LiveSet<Set>(this->set());
    1114             :     }
    1115             : };
    1116             : 
    1117             : #define DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(REGSET)               \
    1118             :     typedef Parent::RegSet  RegSet;                                         \
    1119             :     typedef Parent::RegType RegType;                                        \
    1120             :     typedef Parent::SetType SetType;                                        \
    1121             :                                                                             \
    1122             :     constexpr REGSET() : Parent() {}                                        \
    1123             :     explicit constexpr REGSET(SetType) = delete;                            \
    1124             :     explicit constexpr REGSET(RegSet set) : Parent(set) {}                  \
    1125             :     constexpr REGSET(GeneralRegisterSet gpr, FloatRegisterSet fpu)          \
    1126             :       : Parent(RegisterSet(gpr, fpu))                                       \
    1127             :     {}                                                                      \
    1128             :     REGSET(REGSET<GeneralRegisterSet> gpr, REGSET<FloatRegisterSet> fpu)    \
    1129             :       : Parent(RegisterSet(gpr.set(), fpu.set()))                           \
    1130             :     {}
    1131             : 
    1132             : template <>
    1133       33375 : class LiveSet<RegisterSet>
    1134             :   : public CommonRegSet<LiveSetAccessors<RegisterSet>, RegisterSet>
    1135             : {
    1136             :     // Note: We have to provide a qualified name for LiveSetAccessors, as it is
    1137             :     // interpreted as being the specialized class name inherited from the parent
    1138             :     // class specialization.
    1139             :     typedef CommonRegSet<jit::LiveSetAccessors<RegisterSet>, RegisterSet> Parent;
    1140             : 
    1141             :   public:
    1142       23404 :     DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(LiveSet)
    1143             : };
    1144             : 
    1145             : template <>
    1146             : class AllocatableSet<RegisterSet>
    1147             :   : public CommonRegSet<AllocatableSetAccessors<RegisterSet>, RegisterSet>
    1148             : {
    1149             :     // Note: We have to provide a qualified name for AllocatableSetAccessors, as
    1150             :     // it is interpreted as being the specialized class name inherited from the
    1151             :     // parent class specialization.
    1152             :     typedef CommonRegSet<jit::AllocatableSetAccessors<RegisterSet>, RegisterSet> Parent;
    1153             : 
    1154             :   public:
    1155       16412 :     DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(AllocatableSet)
    1156             : 
    1157       10692 :     LiveSet<RegisterSet> asLiveSet() const {
    1158       10692 :         return LiveSet<RegisterSet>(this->set());
    1159             :     }
    1160             : };
    1161             : 
    1162             : #undef DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_
    1163             : #undef DEFINE_ACCESSOR_CONSTRUCTORS_
    1164             : 
    1165             : typedef AllocatableSet<GeneralRegisterSet> AllocatableGeneralRegisterSet;
    1166             : typedef AllocatableSet<FloatRegisterSet> AllocatableFloatRegisterSet;
    1167             : typedef AllocatableSet<RegisterSet> AllocatableRegisterSet;
    1168             : 
    1169             : typedef LiveSet<GeneralRegisterSet> LiveGeneralRegisterSet;
    1170             : typedef LiveSet<FloatRegisterSet> LiveFloatRegisterSet;
    1171             : typedef LiveSet<RegisterSet> LiveRegisterSet;
    1172             : 
    1173             : // iterates in whatever order happens to be convenient.
    1174             : // Use TypedRegisterBackwardIterator or TypedRegisterForwardIterator if a
    1175             : // specific order is required.
    1176             : template <typename T>
    1177             : class TypedRegisterIterator
    1178             : {
    1179             :     LiveSet<TypedRegisterSet<T>> regset_;
    1180             : 
    1181             :   public:
    1182         116 :     explicit TypedRegisterIterator(TypedRegisterSet<T> regset) : regset_(regset)
    1183         116 :     { }
    1184             :     explicit TypedRegisterIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
    1185             :     { }
    1186             :     TypedRegisterIterator(const TypedRegisterIterator& other) : regset_(other.regset_)
    1187             :     { }
    1188             : 
    1189       13143 :     bool more() const {
    1190       13143 :         return !regset_.empty();
    1191             :     }
    1192        2482 :     TypedRegisterIterator<T>& operator ++() {
    1193        2482 :         regset_.template takeAny<RegTypeName::Any>();
    1194        2482 :         return *this;
    1195             :     }
    1196        6833 :     T operator*() const {
    1197        6833 :         return regset_.template getAny<RegTypeName::Any>();
    1198             :     }
    1199             : };
    1200             : 
    1201             : // iterates backwards, that is, rn to r0
    1202             : template <typename T>
    1203             : class TypedRegisterBackwardIterator
    1204             : {
    1205             :     LiveSet<TypedRegisterSet<T>> regset_;
    1206             : 
    1207             :   public:
    1208       35070 :     explicit TypedRegisterBackwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
    1209       35070 :     { }
    1210         880 :     explicit TypedRegisterBackwardIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
    1211         880 :     { }
    1212             :     TypedRegisterBackwardIterator(const TypedRegisterBackwardIterator& other)
    1213             :       : regset_(other.regset_)
    1214             :     { }
    1215             : 
    1216      458243 :     bool more() const {
    1217      458243 :         return !regset_.empty();
    1218             :     }
    1219      422248 :     TypedRegisterBackwardIterator<T>& operator ++() {
    1220      422248 :         regset_.template takeLast<RegTypeName::Any>();
    1221      422301 :         return *this;
    1222             :     }
    1223      423033 :     T operator*() const {
    1224      423033 :         return regset_.template getLast<RegTypeName::Any>();
    1225             :     }
    1226             : };
    1227             : 
    1228             : // iterates forwards, that is r0 to rn
    1229             : template <typename T>
    1230             : class TypedRegisterForwardIterator
    1231             : {
    1232             :     LiveSet<TypedRegisterSet<T>> regset_;
    1233             : 
    1234             :   public:
    1235       11221 :     explicit TypedRegisterForwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
    1236       11222 :     { }
    1237          40 :     explicit TypedRegisterForwardIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
    1238          40 :     { }
    1239             :     TypedRegisterForwardIterator(const TypedRegisterForwardIterator& other) : regset_(other.regset_)
    1240             :     { }
    1241             : 
    1242      100621 :     bool more() const {
    1243      100621 :         return !regset_.empty();
    1244             :     }
    1245       89360 :     TypedRegisterForwardIterator<T>& operator ++() {
    1246       89360 :         regset_.template takeFirst<RegTypeName::Any>();
    1247       89359 :         return *this;
    1248             :     }
    1249       89359 :     T operator*() const {
    1250       89359 :         return regset_.template getFirst<RegTypeName::Any>();
    1251             :     }
    1252             : };
    1253             : 
    1254             : typedef TypedRegisterIterator<Register> GeneralRegisterIterator;
    1255             : typedef TypedRegisterIterator<FloatRegister> FloatRegisterIterator;
    1256             : typedef TypedRegisterBackwardIterator<Register> GeneralRegisterBackwardIterator;
    1257             : typedef TypedRegisterBackwardIterator<FloatRegister> FloatRegisterBackwardIterator;
    1258             : typedef TypedRegisterForwardIterator<Register> GeneralRegisterForwardIterator;
    1259             : typedef TypedRegisterForwardIterator<FloatRegister> FloatRegisterForwardIterator;
    1260             : 
    1261             : class AnyRegisterIterator
    1262             : {
    1263             :     GeneralRegisterIterator geniter_;
    1264             :     FloatRegisterIterator floatiter_;
    1265             : 
    1266             :   public:
    1267             :     AnyRegisterIterator()
    1268             :       : geniter_(GeneralRegisterSet::All()), floatiter_(FloatRegisterSet::All())
    1269             :     { }
    1270             :     AnyRegisterIterator(GeneralRegisterSet genset, FloatRegisterSet floatset)
    1271             :       : geniter_(genset), floatiter_(floatset)
    1272             :     { }
    1273             :     explicit AnyRegisterIterator(const RegisterSet& set)
    1274             :       : geniter_(set.gpr_), floatiter_(set.fpu_)
    1275             :     { }
    1276          38 :     explicit AnyRegisterIterator(const LiveSet<RegisterSet>& set)
    1277          38 :       : geniter_(set.gprs()), floatiter_(set.fpus())
    1278          38 :     { }
    1279             :     AnyRegisterIterator(const AnyRegisterIterator& other)
    1280             :       : geniter_(other.geniter_), floatiter_(other.floatiter_)
    1281             :     { }
    1282        2280 :     bool more() const {
    1283        2280 :         return geniter_.more() || floatiter_.more();
    1284             :     }
    1285        2242 :     AnyRegisterIterator& operator ++() {
    1286        2242 :         if (geniter_.more())
    1287         532 :             ++geniter_;
    1288             :         else
    1289        1710 :             ++floatiter_;
    1290        2242 :         return *this;
    1291             :     }
    1292        6593 :     AnyRegister operator*() const {
    1293        6593 :         if (geniter_.more())
    1294        1508 :             return AnyRegister(*geniter_);
    1295        5085 :         return AnyRegister(*floatiter_);
    1296             :     }
    1297             : };
    1298             : 
    1299             : class ABIArg
    1300             : {
    1301             :   public:
    1302             :     enum Kind {
    1303             :         GPR,
    1304             : #ifdef JS_CODEGEN_REGISTER_PAIR
    1305             :         GPR_PAIR,
    1306             : #endif
    1307             :         FPU,
    1308             :         Stack
    1309             :     };
    1310             : 
    1311             :   private:
    1312             :     Kind kind_;
    1313             :     union {
    1314             :         Register::Code gpr_;
    1315             :         FloatRegister::Code fpu_;
    1316             :         uint32_t offset_;
    1317             :     } u;
    1318             : 
    1319             :   public:
    1320       37199 :     ABIArg() : kind_(Kind(-1)) { u.offset_ = -1; }
    1321       19652 :     explicit ABIArg(Register gpr) : kind_(GPR) { u.gpr_ = gpr.code(); }
    1322             :     explicit ABIArg(Register gprLow, Register gprHigh)
    1323             :     {
    1324             : #if defined(JS_CODEGEN_REGISTER_PAIR)
    1325             :         kind_ = GPR_PAIR;
    1326             : #else
    1327             :         MOZ_CRASH("Unsupported type of ABI argument.");
    1328             : #endif
    1329             :         u.gpr_ = gprLow.code();
    1330             :         MOZ_ASSERT(u.gpr_ % 2 == 0);
    1331             :         MOZ_ASSERT(u.gpr_ + 1 == gprHigh.code());
    1332             :     }
    1333           5 :     explicit ABIArg(FloatRegister fpu) : kind_(FPU) { u.fpu_ = fpu.code(); }
    1334          16 :     explicit ABIArg(uint32_t offset) : kind_(Stack) { u.offset_ = offset; }
    1335             : 
    1336       39346 :     Kind kind() const { return kind_; }
    1337             : #ifdef JS_CODEGEN_REGISTER_PAIR
    1338             :     bool isGeneralRegPair() const { return kind_ == GPR_PAIR; }
    1339             : #else
    1340             :     bool isGeneralRegPair() const { return false; }
    1341             : #endif
    1342             : 
    1343       19652 :     Register gpr() const {
    1344       19652 :         MOZ_ASSERT(kind() == GPR);
    1345       19652 :         return Register::FromCode(u.gpr_);
    1346             :     }
    1347           0 :     Register64 gpr64() const {
    1348             : #ifdef JS_PUNBOX64
    1349           0 :         return Register64(gpr());
    1350             : #else
    1351             :         return Register64(oddGpr(), evenGpr());
    1352             : #endif
    1353             :     }
    1354             :     Register evenGpr() const {
    1355             :         MOZ_ASSERT(isGeneralRegPair());
    1356             :         return Register::FromCode(u.gpr_);
    1357             :     }
    1358             :     Register oddGpr() const {
    1359             :         MOZ_ASSERT(isGeneralRegPair());
    1360             :         return Register::FromCode(u.gpr_ + 1);
    1361             :     }
    1362           5 :     FloatRegister fpu() const {
    1363           5 :         MOZ_ASSERT(kind() == FPU);
    1364           5 :         return FloatRegister::FromCode(u.fpu_);
    1365             :     }
    1366          16 :     uint32_t offsetFromArgBase() const {
    1367          16 :         MOZ_ASSERT(kind() == Stack);
    1368          16 :         return u.offset_;
    1369             :     }
    1370             : 
    1371           0 :     bool argInRegister() const { return kind() != Stack; }
    1372           0 :     AnyRegister reg() const { return kind_ == GPR ? AnyRegister(gpr()) : AnyRegister(fpu()); }
    1373             : 
    1374           0 :     bool operator==(const ABIArg& rhs) const {
    1375           0 :         if (kind_ != rhs.kind_)
    1376           0 :             return false;
    1377             : 
    1378           0 :         switch((int8_t)kind_) {
    1379           0 :             case GPR:   return u.gpr_ == rhs.u.gpr_;
    1380             : #if defined(JS_CODEGEN_REGISTER_PAIR)
    1381             :             case GPR_PAIR: return u.gpr_ == rhs.u.gpr_;
    1382             : #endif
    1383           0 :             case FPU:   return u.fpu_ == rhs.u.fpu_;
    1384           0 :             case Stack: return u.offset_ == rhs.u.offset_;
    1385           0 :             case -1:    return true;
    1386           0 :             default:    MOZ_CRASH("Invalid value for ABIArg kind");
    1387             :         }
    1388             :     }
    1389             : 
    1390           0 :     bool operator!=(const ABIArg& rhs) const {
    1391           0 :         return !(*this == rhs);
    1392             :     }
    1393             : };
    1394             : 
    1395             : // Get the set of registers which should be saved by a block of code which
    1396             : // clobbers all registers besides |unused|, but does not clobber floating point
    1397             : // registers.
    1398             : inline LiveGeneralRegisterSet
    1399          40 : SavedNonVolatileRegisters(const AllocatableGeneralRegisterSet& unused)
    1400             : {
    1401          40 :     LiveGeneralRegisterSet result;
    1402             : 
    1403         280 :     for (GeneralRegisterIterator iter(GeneralRegisterSet::NonVolatile()); iter.more(); ++iter) {
    1404         240 :         Register reg = *iter;
    1405         240 :         if (!unused.has(reg))
    1406          80 :             result.add(reg);
    1407             :     }
    1408             : 
    1409             :     // Some platforms require the link register to be saved, if calls can be made.
    1410             : #if defined(JS_CODEGEN_ARM)
    1411             :     result.add(Register::FromCode(Registers::lr));
    1412             : #elif defined(JS_CODEGEN_ARM64)
    1413             :     result.add(Register::FromCode(Registers::lr));
    1414             : #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
    1415             :     result.add(Register::FromCode(Registers::ra));
    1416             : #endif
    1417             : 
    1418          40 :     return result;
    1419             : }
    1420             : 
    1421             : } // namespace jit
    1422             : } // namespace js
    1423             : 
    1424             : #endif /* jit_RegisterSets_h */

Generated by: LCOV version 1.13