js/src/jit/RegisterSets.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef jit_RegisterSets_h
     8 #define jit_RegisterSets_h
    10 #include "mozilla/Alignment.h"
    11 #include "mozilla/MathAlgorithms.h"
    13 #include "jit/IonAllocPolicy.h"
    14 #include "jit/Registers.h"
    16 namespace js {
    17 namespace jit {
    19 struct AnyRegister {
    20     typedef uint32_t Code;
    22     static const uint32_t Total = Registers::Total + FloatRegisters::Total;
    23     static const uint32_t Invalid = UINT_MAX;
    25     union {
    26         Registers::Code gpr_;
    27         FloatRegisters::Code fpu_;
    28     };
    29     bool isFloat_;
    31     AnyRegister()
    32     { }
    33     explicit AnyRegister(Register gpr) {
    34         gpr_ = gpr.code();
    35         isFloat_ = false;
    36     }
    37     explicit AnyRegister(FloatRegister fpu) {
    38         fpu_ = fpu.code();
    39         isFloat_ = true;
    40     }
    41     static AnyRegister FromCode(uint32_t i) {
    42         JS_ASSERT(i < Total);
    43         AnyRegister r;
    44         if (i < Registers::Total) {
    45             r.gpr_ = Register::Code(i);
    46             r.isFloat_ = false;
    47         } else {
    48             r.fpu_ = FloatRegister::Code(i - Registers::Total);
    49             r.isFloat_ = true;
    50         }
    51         return r;
    52     }
    53     bool isFloat() const {
    54         return isFloat_;
    55     }
    56     Register gpr() const {
    57         JS_ASSERT(!isFloat());
    58         return Register::FromCode(gpr_);
    59     }
    60     FloatRegister fpu() const {
    61         JS_ASSERT(isFloat());
    62         return FloatRegister::FromCode(fpu_);
    63     }
    64     bool operator ==(const AnyRegister &other) const {
    65         return isFloat()
    66                ? (other.isFloat() && fpu_ == other.fpu_)
    67                : (!other.isFloat() && gpr_ == other.gpr_);
    68     }
    69     bool operator !=(const AnyRegister &other) const {
    70         return isFloat()
    71                ? (!other.isFloat() || fpu_ != other.fpu_)
    72                : (other.isFloat() || gpr_ != other.gpr_);
    73     }
    74     const char *name() const {
    75         return isFloat()
    76                ? FloatRegister::FromCode(fpu_).name()
    77                : Register::FromCode(gpr_).name();
    78     }
    79     const Code code() const {
    80         return isFloat()
    81                ? fpu_ + Registers::Total
    82                : gpr_;
    83     }
    84     bool volatile_() const {
    85         return isFloat() ? fpu().volatile_() : gpr().volatile_();
    86     }
    87 };
    89 // Registers to hold a boxed value. Uses one register on 64 bit
    90 // platforms, two registers on 32 bit platforms.
    91 class ValueOperand
    92 {
    93 #if defined(JS_NUNBOX32)
    94     Register type_;
    95     Register payload_;
    97   public:
    98     MOZ_CONSTEXPR ValueOperand(Register type, Register payload)
    99       : type_(type), payload_(payload)
   100     { }
   102     Register typeReg() const {
   103         return type_;
   104     }
   105     Register payloadReg() const {
   106         return payload_;
   107     }
   109     Register scratchReg() const {
   110         return payloadReg();
   111     }
   112     bool operator==(const ValueOperand &o) const {
   113         return type_ == o.type_ && payload_ == o.payload_;
   114     }
   115     bool operator!=(const ValueOperand &o) const {
   116         return !(*this == o);
   117     }
   119 #elif defined(JS_PUNBOX64)
   120     Register value_;
   122   public:
   123     explicit MOZ_CONSTEXPR ValueOperand(Register value)
   124       : value_(value)
   125     { }
   127     Register valueReg() const {
   128         return value_;
   129     }
   131     Register scratchReg() const {
   132         return valueReg();
   133     }
   134     bool operator==(const ValueOperand &o) const {
   135         return value_ == o.value_;
   136     }
   137     bool operator!=(const ValueOperand &o) const {
   138         return !(*this == o);
   139     }
   140 #endif
   142     ValueOperand() {}
   143 };
   145 // Registers to hold either either a typed or untyped value.
   146 class TypedOrValueRegister
   147 {
   148     // Type of value being stored.
   149     MIRType type_;
   151     // Space to hold either an AnyRegister or a ValueOperand.
   152     union U {
   153         mozilla::AlignedStorage2<AnyRegister> typed;
   154         mozilla::AlignedStorage2<ValueOperand> value;
   155     } data;
   157     AnyRegister &dataTyped() {
   158         JS_ASSERT(hasTyped());
   159         return *data.typed.addr();
   160     }
   161     ValueOperand &dataValue() {
   162         JS_ASSERT(hasValue());
   163         return *data.value.addr();
   164     }
   166     const AnyRegister &dataTyped() const {
   167         JS_ASSERT(hasTyped());
   168         return *data.typed.addr();
   169     }
   170     const ValueOperand &dataValue() const {
   171         JS_ASSERT(hasValue());
   172         return *data.value.addr();
   173     }
   175   public:
   177     TypedOrValueRegister()
   178       : type_(MIRType_None)
   179     {}
   181     TypedOrValueRegister(MIRType type, AnyRegister reg)
   182       : type_(type)
   183     {
   184         dataTyped() = reg;
   185     }
   187     TypedOrValueRegister(ValueOperand value)
   188       : type_(MIRType_Value)
   189     {
   190         dataValue() = value;
   191     }
   193     MIRType type() const {
   194         return type_;
   195     }
   197     bool hasTyped() const {
   198         return type() != MIRType_None && type() != MIRType_Value;
   199     }
   201     bool hasValue() const {
   202         return type() == MIRType_Value;
   203     }
   205     AnyRegister typedReg() const {
   206         return dataTyped();
   207     }
   209     ValueOperand valueReg() const {
   210         return dataValue();
   211     }
   213     AnyRegister scratchReg() {
   214         if (hasValue())
   215             return AnyRegister(valueReg().scratchReg());
   216         return typedReg();
   217     }
   218 };
   220 // A constant value, or registers to hold a typed/untyped value.
   221 class ConstantOrRegister
   222 {
   223     // Whether a constant value is being stored.
   224     bool constant_;
   226     // Space to hold either a Value or a TypedOrValueRegister.
   227     union U {
   228         mozilla::AlignedStorage2<Value> constant;
   229         mozilla::AlignedStorage2<TypedOrValueRegister> reg;
   230     } data;
   232     Value &dataValue() {
   233         JS_ASSERT(constant());
   234         return *data.constant.addr();
   235     }
   236     TypedOrValueRegister &dataReg() {
   237         JS_ASSERT(!constant());
   238         return *data.reg.addr();
   239     }
   241   public:
   243     ConstantOrRegister()
   244     {}
   246     ConstantOrRegister(Value value)
   247       : constant_(true)
   248     {
   249         dataValue() = value;
   250     }
   252     ConstantOrRegister(TypedOrValueRegister reg)
   253       : constant_(false)
   254     {
   255         dataReg() = reg;
   256     }
   258     bool constant() {
   259         return constant_;
   260     }
   262     Value value() {
   263         return dataValue();
   264     }
   266     TypedOrValueRegister reg() {
   267         return dataReg();
   268     }
   269 };
   271 struct Int32Key {
   272     bool isRegister_;
   273     union {
   274         Register reg_;
   275         int32_t constant_;
   276     };
   278     explicit Int32Key(Register reg)
   279       : isRegister_(true), reg_(reg)
   280     { }
   282     explicit Int32Key(int32_t index)
   283       : isRegister_(false), constant_(index)
   284     { }
   286     inline void bumpConstant(int diff) {
   287         JS_ASSERT(!isRegister_);
   288         constant_ += diff;
   289     }
   290     inline Register reg() const {
   291         JS_ASSERT(isRegister_);
   292         return reg_;
   293     }
   294     inline int32_t constant() const {
   295         JS_ASSERT(!isRegister_);
   296         return constant_;
   297     }
   298     inline bool isRegister() const {
   299         return isRegister_;
   300     }
   301     inline bool isConstant() const {
   302         return !isRegister_;
   303     }
   304 };
   306 template <typename T>
   307 class TypedRegisterSet
   308 {
   309     uint32_t bits_;
   311   public:
   312     explicit MOZ_CONSTEXPR TypedRegisterSet(uint32_t bits)
   313       : bits_(bits)
   314     { }
   316     MOZ_CONSTEXPR TypedRegisterSet() : bits_(0)
   317     { }
   318     MOZ_CONSTEXPR TypedRegisterSet(const TypedRegisterSet<T> &set) : bits_(set.bits_)
   319     { }
   321     static inline TypedRegisterSet All() {
   322         return TypedRegisterSet(T::Codes::AllocatableMask);
   323     }
   324     static inline TypedRegisterSet Intersect(const TypedRegisterSet &lhs,
   325                                              const TypedRegisterSet &rhs) {
   326         return TypedRegisterSet(lhs.bits_ & rhs.bits_);
   327     }
   328     static inline TypedRegisterSet Union(const TypedRegisterSet &lhs,
   329                                          const TypedRegisterSet &rhs) {
   330         return TypedRegisterSet(lhs.bits_ | rhs.bits_);
   331     }
   332     static inline TypedRegisterSet Not(const TypedRegisterSet &in) {
   333         return TypedRegisterSet(~in.bits_ & T::Codes::AllocatableMask);
   334     }
   335     static inline TypedRegisterSet VolatileNot(const TypedRegisterSet &in) {
   336         const uint32_t allocatableVolatile =
   337             T::Codes::AllocatableMask & T::Codes::VolatileMask;
   338         return TypedRegisterSet(~in.bits_ & allocatableVolatile);
   339     }
   340     static inline TypedRegisterSet Volatile() {
   341         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::VolatileMask);
   342     }
   343     static inline TypedRegisterSet NonVolatile() {
   344         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::NonVolatileMask);
   345     }
   346     bool has(T reg) const {
   347         return !!(bits_ & (1 << reg.code()));
   348     }
   349     void addUnchecked(T reg) {
   350         bits_ |= (1 << reg.code());
   351     }
   352     void add(T reg) {
   353         JS_ASSERT(!has(reg));
   354         addUnchecked(reg);
   355     }
   356     void add(ValueOperand value) {
   357 #if defined(JS_NUNBOX32)
   358         add(value.payloadReg());
   359         add(value.typeReg());
   360 #elif defined(JS_PUNBOX64)
   361         add(value.valueReg());
   362 #else
   363 #error "Bad architecture"
   364 #endif
   365     }
   366     // Determemine if some register are still allocated.  This function should
   367     // be used with the set of allocatable registers used for the initialization
   368     // of the current set.
   369     bool someAllocated(const TypedRegisterSet &allocatable) const {
   370         return allocatable.bits_ & ~bits_;
   371     }
   372     bool empty() const {
   373         return !bits_;
   374     }
   375     void take(T reg) {
   376         JS_ASSERT(has(reg));
   377         takeUnchecked(reg);
   378     }
   379     void takeUnchecked(T reg) {
   380         bits_ &= ~(1 << reg.code());
   381     }
   382     void take(ValueOperand value) {
   383 #if defined(JS_NUNBOX32)
   384         take(value.payloadReg());
   385         take(value.typeReg());
   386 #elif defined(JS_PUNBOX64)
   387         take(value.valueReg());
   388 #else
   389 #error "Bad architecture"
   390 #endif
   391     }
   392     void takeUnchecked(ValueOperand value) {
   393 #if defined(JS_NUNBOX32)
   394         takeUnchecked(value.payloadReg());
   395         takeUnchecked(value.typeReg());
   396 #elif defined(JS_PUNBOX64)
   397         takeUnchecked(value.valueReg());
   398 #else
   399 #error "Bad architecture"
   400 #endif
   401     }
   402     ValueOperand takeValueOperand() {
   403 #if defined(JS_NUNBOX32)
   404         return ValueOperand(takeAny(), takeAny());
   405 #elif defined(JS_PUNBOX64)
   406         return ValueOperand(takeAny());
   407 #else
   408 #error "Bad architecture"
   409 #endif
   410     }
   411     T getAny() const {
   412         // The choice of first or last here is mostly arbitrary, as they are
   413         // about the same speed on popular architectures. We choose first, as
   414         // it has the advantage of using the "lower" registers more often. These
   415         // registers are sometimes more efficient (e.g. optimized encodings for
   416         // EAX on x86).
   417         return getFirst();
   418     }
   419     T getAnyExcluding(T preclude) {
   420         JS_ASSERT(!empty());
   421         if (!has(preclude))
   422             return getAny();
   424         take(preclude);
   425         JS_ASSERT(!empty());
   426         T result = getAny();
   427         add(preclude);
   428         return result;
   429     }
   430     T getFirst() const {
   431         JS_ASSERT(!empty());
   432         return T::FromCode(mozilla::CountTrailingZeroes32(bits_));
   433     }
   434     T getLast() const {
   435         JS_ASSERT(!empty());
   436         int ireg = 31 - mozilla::CountLeadingZeroes32(bits_);
   437         return T::FromCode(ireg);
   438     }
   439     T takeAny() {
   440         JS_ASSERT(!empty());
   441         T reg = getAny();
   442         take(reg);
   443         return reg;
   444     }
   445     T takeAnyExcluding(T preclude) {
   446         T reg = getAnyExcluding(preclude);
   447         take(reg);
   448         return reg;
   449     }
   450     ValueOperand takeAnyValue() {
   451 #if defined(JS_NUNBOX32)
   452         T type = takeAny();
   453         T payload = takeAny();
   454         return ValueOperand(type, payload);
   455 #elif defined(JS_PUNBOX64)
   456         T reg = takeAny();
   457         return ValueOperand(reg);
   458 #else
   459 #error "Bad architecture"
   460 #endif
   461     }
   462     T takeFirst() {
   463         JS_ASSERT(!empty());
   464         T reg = getFirst();
   465         take(reg);
   466         return reg;
   467     }
   468     T takeLast() {
   469         JS_ASSERT(!empty());
   470         T reg = getLast();
   471         take(reg);
   472         return reg;
   473     }
   474     void clear() {
   475         bits_ = 0;
   476     }
   477     uint32_t bits() const {
   478         return bits_;
   479     }
   480     uint32_t size() const {
   481         return mozilla::CountPopulation32(bits_);
   482     }
   483     bool operator ==(const TypedRegisterSet<T> &other) const {
   484         return other.bits_ == bits_;
   485     }
   486 };
   488 typedef TypedRegisterSet<Register> GeneralRegisterSet;
   489 typedef TypedRegisterSet<FloatRegister> FloatRegisterSet;
   491 class AnyRegisterIterator;
   493 class RegisterSet {
   494     GeneralRegisterSet gpr_;
   495     FloatRegisterSet fpu_;
   497     friend class AnyRegisterIterator;
   499   public:
   500     RegisterSet()
   501     { }
   502     MOZ_CONSTEXPR RegisterSet(const GeneralRegisterSet &gpr, const FloatRegisterSet &fpu)
   503       : gpr_(gpr),
   504         fpu_(fpu)
   505     { }
   506     static inline RegisterSet All() {
   507         return RegisterSet(GeneralRegisterSet::All(), FloatRegisterSet::All());
   508     }
   509     static inline RegisterSet Intersect(const RegisterSet &lhs, const RegisterSet &rhs) {
   510         return RegisterSet(GeneralRegisterSet::Intersect(lhs.gpr_, rhs.gpr_),
   511                            FloatRegisterSet::Intersect(lhs.fpu_, rhs.fpu_));
   512     }
   513     static inline RegisterSet Union(const RegisterSet &lhs, const RegisterSet &rhs) {
   514         return RegisterSet(GeneralRegisterSet::Union(lhs.gpr_, rhs.gpr_),
   515                            FloatRegisterSet::Union(lhs.fpu_, rhs.fpu_));
   516     }
   517     static inline RegisterSet Not(const RegisterSet &in) {
   518         return RegisterSet(GeneralRegisterSet::Not(in.gpr_),
   519                            FloatRegisterSet::Not(in.fpu_));
   520     }
   521     static inline RegisterSet VolatileNot(const RegisterSet &in) {
   522         return RegisterSet(GeneralRegisterSet::VolatileNot(in.gpr_),
   523                            FloatRegisterSet::VolatileNot(in.fpu_));
   524     }
   525     static inline RegisterSet Volatile() {
   526         return RegisterSet(GeneralRegisterSet::Volatile(), FloatRegisterSet::Volatile());
   527     }
   528     bool has(Register reg) const {
   529         return gpr_.has(reg);
   530     }
   531     bool has(FloatRegister reg) const {
   532         return fpu_.has(reg);
   533     }
   534     bool has(AnyRegister reg) const {
   535         return reg.isFloat() ? has(reg.fpu()) : has(reg.gpr());
   536     }
   537     void add(Register reg) {
   538         gpr_.add(reg);
   539     }
   540     void add(FloatRegister reg) {
   541         fpu_.add(reg);
   542     }
   543     void add(const AnyRegister &any) {
   544         if (any.isFloat())
   545             add(any.fpu());
   546         else
   547             add(any.gpr());
   548     }
   549     void add(ValueOperand value) {
   550 #if defined(JS_NUNBOX32)
   551         add(value.payloadReg());
   552         add(value.typeReg());
   553 #elif defined(JS_PUNBOX64)
   554         add(value.valueReg());
   555 #else
   556 #error "Bad architecture"
   557 #endif
   558     }
   559     void add(TypedOrValueRegister reg) {
   560         if (reg.hasValue())
   561             add(reg.valueReg());
   562         else if (reg.hasTyped())
   563             add(reg.typedReg());
   564     }
   565     void addUnchecked(Register reg) {
   566         gpr_.addUnchecked(reg);
   567     }
   568     void addUnchecked(FloatRegister reg) {
   569         fpu_.addUnchecked(reg);
   570     }
   571     void addUnchecked(const AnyRegister &any) {
   572         if (any.isFloat())
   573             addUnchecked(any.fpu());
   574         else
   575             addUnchecked(any.gpr());
   576     }
   577     bool empty(bool floats) const {
   578         return floats ? fpu_.empty() : gpr_.empty();
   579     }
   580     FloatRegister takeFloat() {
   581         return fpu_.takeAny();
   582     }
   583     Register takeGeneral() {
   584         return gpr_.takeAny();
   585     }
   586     ValueOperand takeValueOperand() {
   587 #if defined(JS_NUNBOX32)
   588         return ValueOperand(takeGeneral(), takeGeneral());
   589 #elif defined(JS_PUNBOX64)
   590         return ValueOperand(takeGeneral());
   591 #else
   592 #error "Bad architecture"
   593 #endif
   594     }
   595     void take(const AnyRegister &reg) {
   596         if (reg.isFloat())
   597             fpu_.take(reg.fpu());
   598         else
   599             gpr_.take(reg.gpr());
   600     }
   601     AnyRegister takeAny(bool isFloat) {
   602         if (isFloat)
   603             return AnyRegister(takeFloat());
   604         return AnyRegister(takeGeneral());
   605     }
   606     void clear() {
   607         gpr_.clear();
   608         fpu_.clear();
   609     }
   610     MOZ_CONSTEXPR GeneralRegisterSet gprs() const {
   611         return gpr_;
   612     }
   613     MOZ_CONSTEXPR FloatRegisterSet fpus() const {
   614         return fpu_;
   615     }
   616     bool operator ==(const RegisterSet &other) const {
   617         return other.gpr_ == gpr_ && other.fpu_ == fpu_;
   618     }
   620     void takeUnchecked(Register reg) {
   621         gpr_.takeUnchecked(reg);
   622     }
   623     void takeUnchecked(FloatRegister reg) {
   624         fpu_.takeUnchecked(reg);
   625     }
   626     void takeUnchecked(AnyRegister reg) {
   627         if (reg.isFloat())
   628             fpu_.takeUnchecked(reg.fpu());
   629         else
   630             gpr_.takeUnchecked(reg.gpr());
   631     }
   632     void takeUnchecked(ValueOperand value) {
   633         gpr_.takeUnchecked(value);
   634     }
   635     void takeUnchecked(TypedOrValueRegister reg) {
   636         if (reg.hasValue())
   637             takeUnchecked(reg.valueReg());
   638         else if (reg.hasTyped())
   639             takeUnchecked(reg.typedReg());
   640     }
   641 };
   643 // iterates in whatever order happens to be convenient.
   644 // Use TypedRegisterBackwardIterator or TypedRegisterForwardIterator if a
   645 // specific order is required.
   646 template <typename T>
   647 class TypedRegisterIterator
   648 {
   649     TypedRegisterSet<T> regset_;
   651   public:
   652     TypedRegisterIterator(TypedRegisterSet<T> regset) : regset_(regset)
   653     { }
   654     TypedRegisterIterator(const TypedRegisterIterator &other) : regset_(other.regset_)
   655     { }
   657     bool more() const {
   658         return !regset_.empty();
   659     }
   660     TypedRegisterIterator<T> operator ++(int) {
   661         TypedRegisterIterator<T> old(*this);
   662         regset_.takeAny();
   663         return old;
   664     }
   665     TypedRegisterIterator<T>& operator ++() {
   666         regset_.takeAny();
   667         return *this;
   668     }
   669     T operator *() const {
   670         return regset_.getAny();
   671     }
   672 };
   674 // iterates backwards, that is, rn to r0
   675 template <typename T>
   676 class TypedRegisterBackwardIterator
   677 {
   678     TypedRegisterSet<T> regset_;
   680   public:
   681     TypedRegisterBackwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
   682     { }
   683     TypedRegisterBackwardIterator(const TypedRegisterBackwardIterator &other)
   684       : regset_(other.regset_)
   685     { }
   687     bool more() const {
   688         return !regset_.empty();
   689     }
   690     TypedRegisterBackwardIterator<T> operator ++(int) {
   691         TypedRegisterBackwardIterator<T> old(*this);
   692         regset_.takeLast();
   693         return old;
   694     }
   695     TypedRegisterBackwardIterator<T>& operator ++() {
   696         regset_.takeLast();
   697         return *this;
   698     }
   699     T operator *() const {
   700         return regset_.getLast();
   701     }
   702 };
   704 // iterates forwards, that is r0 to rn
   705 template <typename T>
   706 class TypedRegisterForwardIterator
   707 {
   708     TypedRegisterSet<T> regset_;
   710   public:
   711     TypedRegisterForwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
   712     { }
   713     TypedRegisterForwardIterator(const TypedRegisterForwardIterator &other) : regset_(other.regset_)
   714     { }
   716     bool more() const {
   717         return !regset_.empty();
   718     }
   719     TypedRegisterForwardIterator<T> operator ++(int) {
   720         TypedRegisterForwardIterator<T> old(*this);
   721         regset_.takeFirst();
   722         return old;
   723     }
   724     TypedRegisterForwardIterator<T>& operator ++() {
   725         regset_.takeFirst();
   726         return *this;
   727     }
   728     T operator *() const {
   729         return regset_.getFirst();
   730     }
   731 };
   733 typedef TypedRegisterIterator<Register> GeneralRegisterIterator;
   734 typedef TypedRegisterIterator<FloatRegister> FloatRegisterIterator;
   735 typedef TypedRegisterBackwardIterator<Register> GeneralRegisterBackwardIterator;
   736 typedef TypedRegisterBackwardIterator<FloatRegister> FloatRegisterBackwardIterator;
   737 typedef TypedRegisterForwardIterator<Register> GeneralRegisterForwardIterator;
   738 typedef TypedRegisterForwardIterator<FloatRegister> FloatRegisterForwardIterator;
   740 class AnyRegisterIterator
   741 {
   742     GeneralRegisterIterator geniter_;
   743     FloatRegisterIterator floatiter_;
   745   public:
   746     AnyRegisterIterator()
   747       : geniter_(GeneralRegisterSet::All()), floatiter_(FloatRegisterSet::All())
   748     { }
   749     AnyRegisterIterator(GeneralRegisterSet genset, FloatRegisterSet floatset)
   750       : geniter_(genset), floatiter_(floatset)
   751     { }
   752     AnyRegisterIterator(const RegisterSet &set)
   753       : geniter_(set.gpr_), floatiter_(set.fpu_)
   754     { }
   755     AnyRegisterIterator(const AnyRegisterIterator &other)
   756       : geniter_(other.geniter_), floatiter_(other.floatiter_)
   757     { }
   758     bool more() const {
   759         return geniter_.more() || floatiter_.more();
   760     }
   761     AnyRegisterIterator operator ++(int) {
   762         AnyRegisterIterator old(*this);
   763         if (geniter_.more())
   764             geniter_++;
   765         else
   766             floatiter_++;
   767         return old;
   768     }
   769     AnyRegister operator *() const {
   770         if (geniter_.more())
   771             return AnyRegister(*geniter_);
   772         return AnyRegister(*floatiter_);
   773     }
   774 };
   776 class ABIArg
   777 {
   778   public:
   779     enum Kind { GPR, FPU, Stack };
   781   private:
   782     Kind kind_;
   783     union {
   784         Registers::Code gpr_;
   785         FloatRegisters::Code fpu_;
   786         uint32_t offset_;
   787     } u;
   789   public:
   790     ABIArg() : kind_(Kind(-1)) { u.offset_ = -1; }
   791     ABIArg(Register gpr) : kind_(GPR) { u.gpr_ = gpr.code(); }
   792     ABIArg(FloatRegister fpu) : kind_(FPU) { u.fpu_ = fpu.code(); }
   793     ABIArg(uint32_t offset) : kind_(Stack) { u.offset_ = offset; }
   795     Kind kind() const { return kind_; }
   796     Register gpr() const { JS_ASSERT(kind() == GPR); return Register::FromCode(u.gpr_); }
   797     FloatRegister fpu() const { JS_ASSERT(kind() == FPU); return FloatRegister::FromCode(u.fpu_); }
   798     uint32_t offsetFromArgBase() const { JS_ASSERT(kind() == Stack); return u.offset_; }
   800     bool argInRegister() const { return kind() != Stack; }
   801     AnyRegister reg() const { return kind_ == GPR ? AnyRegister(gpr()) : AnyRegister(fpu()); }
   802 };
   804 } // namespace jit
   805 } // namespace js
   807 #endif /* jit_RegisterSets_h */

mercurial