Ignore:
Timestamp:
Nov 4, 2019, 3:47:07 PM (6 years ago)
Author:
Truitt Savell
Message:

Unreviewed, rolling out r252015.

Broke the Windows build

Reverted changeset:

"Split ArithProfile into a Unary and a Binary version"
https://bugs.webkit.org/show_bug.cgi?id=202832
https://trac.webkit.org/changeset/252015

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/ArithProfile.h

    r252015 r252021  
    6767};
    6868
    69 template <typename BitfieldType>
    70 class ArithProfile {
     69struct ArithProfile {
     70private:
     71    static constexpr uint32_t numberOfFlagBits = 6;
     72    static constexpr uint32_t rhsResultTypeShift = numberOfFlagBits;
     73    static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
     74    static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
     75    static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
     76
     77    static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
     78    static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2))));
     79    static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2))));
     80
     81    static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
     82    static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
     83
     84    enum class ConstantTag { Constant };
     85
    7186public:
     87    static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
     88    static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) <= (sizeof(uint32_t) * 8) - 1, "Should fit in a uint32_t.");
     89    static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
     90    static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
     91    static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
     92
     93    ArithProfile(ResultType arg)
     94        : ArithProfile(ConstantTag::Constant, arg)
     95    {
     96        ASSERT(lhsResultType().bits() == arg.bits());
     97        ASSERT(lhsObservedType().isEmpty());
     98        ASSERT(rhsObservedType().isEmpty());
     99    }
     100
     101    ArithProfile(ResultType lhs, ResultType rhs)
     102        : ArithProfile(ConstantTag::Constant, lhs, rhs)
     103    {
     104        ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());
     105        ASSERT(lhsObservedType().isEmpty());
     106        ASSERT(rhsObservedType().isEmpty());
     107    }
     108
     109    ArithProfile(OperandTypes types)
     110        : ArithProfile(types.first(), types.second())
     111    { }
     112
     113    ArithProfile() = default;
     114
     115    static constexpr ArithProfile fromInt(uint32_t bits)
     116    {
     117        return ArithProfile { ConstantTag::Constant, bits };
     118    }
     119
     120    static constexpr ArithProfile observedUnaryInt()
     121    {
     122        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     123        constexpr uint32_t bits = observedInt32.bits() << lhsObservedTypeShift;
     124        static_assert(bits == 0x800000, "");
     125        return fromInt(bits);
     126    }
     127    static constexpr ArithProfile observedUnaryNumber()
     128    {
     129        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     130        constexpr uint32_t bits = observedNumber.bits() << lhsObservedTypeShift;
     131        static_assert(bits == 0x1000000, "");
     132        return fromInt(bits);
     133    }
     134    static constexpr ArithProfile observedBinaryIntInt()
     135    {
     136        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     137        constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
     138        static_assert(bits == 0x900000, "");
     139        return fromInt(bits);
     140    }
     141    static constexpr ArithProfile observedBinaryNumberInt()
     142    {
     143        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     144        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     145        constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
     146        static_assert(bits == 0x1100000, "");
     147        return fromInt(bits);
     148    }
     149    static constexpr ArithProfile observedBinaryIntNumber()
     150    {
     151        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     152        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     153        constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
     154        static_assert(bits == 0xa00000, "");
     155        return fromInt(bits);
     156    }
     157    static constexpr ArithProfile observedBinaryNumberNumber()
     158    {
     159        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     160        constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
     161        static_assert(bits == 0x1200000, "");
     162        return fromInt(bits);
     163    }
     164
    72165    enum ObservedResults {
    73166        NonNegZeroDouble = 1 << 0,
     
    78171        BigInt           = 1 << 5,
    79172    };
    80     static constexpr uint32_t observedResultsNumBitsNeeded = 6;
     173
     174    ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); }
     175    ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); }
     176
     177    constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
     178    constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
     179    void setLhsObservedType(ObservedType type)
     180    {
     181        uint32_t bits = m_bits;
     182        bits &= clearLhsObservedTypeBitMask;
     183        bits |= type.bits() << lhsObservedTypeShift;
     184        m_bits = bits;
     185        ASSERT(lhsObservedType() == type);
     186    }
     187
     188    void setRhsObservedType(ObservedType type)
     189    {
     190        uint32_t bits = m_bits;
     191        bits &= clearRhsObservedTypeBitMask;
     192        bits |= type.bits() << rhsObservedTypeShift;
     193        m_bits = bits;
     194        ASSERT(rhsObservedType() == type);
     195    }
     196
     197    bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
    81198
    82199    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); }
     
    95212    void setObservedInt32Overflow() { setBit(Int32Overflow); }
    96213    void setObservedInt52Overflow() { setBit(Int52Overflow); }
     214
     215    const void* addressOfBits() const { return &m_bits; }
    97216
    98217    void observeResult(JSValue value)
     
    111230    }
    112231
    113     const void* addressOfBits() const { return &m_bits; }
    114 
    115 #if ENABLE(JIT)
    116     // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
    117     // double. Sets NonNumeric if it sees a non-numeric.
    118     void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
    119 
    120     // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
    121     bool shouldEmitSetDouble() const;
    122     void emitSetDouble(CCallHelpers&) const;
    123 
    124     // Sets NonNumber.
    125     void emitSetNonNumeric(CCallHelpers&) const;
    126     bool shouldEmitSetNonNumeric() const;
    127 
    128     // Sets BigInt
    129     void emitSetBigInt(CCallHelpers&) const;
    130     bool shouldEmitSetBigInt() const;
    131 #endif // ENABLE(JIT)
    132 
    133     constexpr uint32_t bits() const { return m_bits; }
    134 
    135 protected:
    136     ArithProfile()
    137     {
    138     }
    139 
    140     bool hasBits(int mask) const { return m_bits & mask; }
    141     void setBit(int mask) { m_bits |= mask; }
    142 
    143     BitfieldType m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
    144 };
    145 
    146 /* This class stores the following components in 16 bits:
    147  * - ObservedResults
    148  * - ObservedType for the argument
    149  */
    150 using UnaryArithProfileBase = uint16_t;
    151 class UnaryArithProfile : public ArithProfile<UnaryArithProfileBase> {
    152     static constexpr unsigned argObservedTypeShift = observedResultsNumBitsNeeded;
    153 
    154     static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(UnaryArithProfileBase) * 8, "Should fit in a the type of the underlying bitfield.");
    155 
    156     static constexpr UnaryArithProfileBase clearArgObservedTypeBitMask = static_cast<UnaryArithProfileBase>(~(0b111 << argObservedTypeShift));
    157 
    158     static constexpr UnaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
    159 
    160 public:
    161     UnaryArithProfile()
    162         : ArithProfile<UnaryArithProfileBase>()
    163     {
    164         ASSERT(argObservedType().isEmpty());
    165         ASSERT(argObservedType().isEmpty());
    166     }
    167 
    168     static constexpr UnaryArithProfileBase observedIntBits()
    169     {
    170         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    171         constexpr UnaryArithProfileBase bits = observedInt32.bits() << argObservedTypeShift;
    172         return bits;
    173     }
    174     static constexpr UnaryArithProfileBase observedNumberBits()
    175     {
    176         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    177         constexpr UnaryArithProfileBase bits = observedNumber.bits() << argObservedTypeShift;
    178         return bits;
    179     }
    180 
    181     constexpr ObservedType argObservedType() const { return ObservedType((m_bits >> argObservedTypeShift) & observedTypeMask); }
    182     void setArgObservedType(ObservedType type)
    183     {
    184         UnaryArithProfileBase bits = m_bits;
    185         bits &= clearArgObservedTypeBitMask;
    186         bits |= type.bits() << argObservedTypeShift;
    187         m_bits = bits;
    188         ASSERT(argObservedType() == type);
    189     }
    190 
    191     void argSawInt32() { setArgObservedType(argObservedType().withInt32()); }
    192     void argSawNumber() { setArgObservedType(argObservedType().withNumber()); }
    193     void argSawNonNumber() { setArgObservedType(argObservedType().withNonNumber()); }
    194 
    195     void observeArg(JSValue arg)
    196     {
    197         UnaryArithProfile newProfile = *this;
    198         if (arg.isNumber()) {
    199             if (arg.isInt32())
    200                 newProfile.argSawInt32();
    201             else
    202                 newProfile.argSawNumber();
    203         } else
    204             newProfile.argSawNonNumber();
    205 
    206         m_bits = newProfile.bits();
    207     }
    208 
    209     bool isObservedTypeEmpty()
    210     {
    211         return argObservedType().isEmpty();
    212     }
    213 
    214     friend class JSC::LLIntOffsetsExtractor;
    215 };
    216 
    217 /* This class stores the following components in 16 bits:
    218  * - ObservedResults
    219  * - ObservedType for right-hand-side
    220  * - ObservedType for left-hand-side
    221  * - a bit used by division to indicate whether a special fast path was taken
    222  */
    223 using BinaryArithProfileBase = uint16_t;
    224 class BinaryArithProfile : public ArithProfile<BinaryArithProfileBase> {
    225     static constexpr uint32_t rhsObservedTypeShift = observedResultsNumBitsNeeded;
    226     static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
    227 
    228     static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
    229     static constexpr BinaryArithProfileBase clearRhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << rhsObservedTypeShift));
    230     static constexpr BinaryArithProfileBase clearLhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << lhsObservedTypeShift));
    231 
    232     static constexpr BinaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
    233 
    234 public:
    235     static constexpr BinaryArithProfileBase specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
    236     static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(BinaryArithProfileBase) * 8, "Should fit in a uint32_t.");
    237     static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
    238     static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
    239     static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
    240 
    241     BinaryArithProfile()
    242         : ArithProfile<BinaryArithProfileBase> ()
    243     {
    244         ASSERT(lhsObservedType().isEmpty());
    245         ASSERT(rhsObservedType().isEmpty());
    246     }
    247 
    248     static constexpr BinaryArithProfileBase observedIntIntBits()
    249     {
    250         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    251         constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    252         return bits;
    253     }
    254     static constexpr BinaryArithProfileBase observedNumberIntBits()
    255     {
    256         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    257         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    258         constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    259         return bits;
    260     }
    261     static constexpr BinaryArithProfileBase observedIntNumberBits()
    262     {
    263         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    264         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    265         constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    266         return bits;
    267     }
    268     static constexpr BinaryArithProfileBase observedNumberNumberBits()
    269     {
    270         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    271         constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    272         return bits;
    273     }
    274 
    275     constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
    276     constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
    277     void setLhsObservedType(ObservedType type)
    278     {
    279         BinaryArithProfileBase bits = m_bits;
    280         bits &= clearLhsObservedTypeBitMask;
    281         bits |= type.bits() << lhsObservedTypeShift;
    282         m_bits = bits;
    283         ASSERT(lhsObservedType() == type);
    284     }
    285 
    286     void setRhsObservedType(ObservedType type)
    287     {
    288         BinaryArithProfileBase bits = m_bits;
    289         bits &= clearRhsObservedTypeBitMask;
    290         bits |= type.bits() << rhsObservedTypeShift;
    291         m_bits = bits;
    292         ASSERT(rhsObservedType() == type);
    293     }
    294 
    295     bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
    296 
    297232    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
    298233    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
     
    304239    void observeLHS(JSValue lhs)
    305240    {
    306         BinaryArithProfile newProfile = *this;
     241        ArithProfile newProfile = *this;
    307242        if (lhs.isNumber()) {
    308243            if (lhs.isInt32())
     
    320255        observeLHS(lhs);
    321256
    322         BinaryArithProfile newProfile = *this;
     257        ArithProfile newProfile = *this;
    323258        if (rhs.isNumber()) {
    324259            if (rhs.isInt32())
     
    332267    }
    333268
    334     bool isObservedTypeEmpty()
    335     {
    336         return lhsObservedType().isEmpty() && rhsObservedType().isEmpty();
    337     }
     269#if ENABLE(JIT)   
     270    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
     271    // double. Sets NonNumeric if it sees a non-numeric.
     272    void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
     273   
     274    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
     275    bool shouldEmitSetDouble() const;
     276    void emitSetDouble(CCallHelpers&) const;
     277   
     278    // Sets NonNumber.
     279    void emitSetNonNumeric(CCallHelpers&) const;
     280    bool shouldEmitSetNonNumeric() const;
     281
     282    // Sets BigInt
     283    void emitSetBigInt(CCallHelpers&) const;
     284    bool shouldEmitSetBigInt() const;
     285#endif // ENABLE(JIT)
     286
     287    constexpr uint32_t bits() const { return m_bits; }
     288
     289private:
     290    constexpr explicit ArithProfile(ConstantTag, uint32_t bits)
     291        : m_bits(bits)
     292    {
     293    }
     294
     295    constexpr ArithProfile(ConstantTag, ResultType arg)
     296        : m_bits(arg.bits() << lhsResultTypeShift)
     297    {
     298    }
     299
     300    constexpr ArithProfile(ConstantTag, ResultType lhs, ResultType rhs)
     301        : m_bits((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift))
     302    {
     303    }
     304
     305    bool hasBits(int mask) const { return m_bits & mask; }
     306    void setBit(int mask) { m_bits |= mask; }
     307
     308    uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
    338309
    339310    friend class JSC::LLIntOffsetsExtractor;
     
    344315namespace WTF {
    345316
    346 void printInternal(PrintStream&, const JSC::UnaryArithProfile&);
    347 void printInternal(PrintStream&, const JSC::BinaryArithProfile&);
     317void printInternal(PrintStream&, const JSC::ArithProfile&);
    348318void printInternal(PrintStream&, const JSC::ObservedType&);
    349319
Note: See TracChangeset for help on using the changeset viewer.