Ignore:
Timestamp:
Oct 14, 2019, 3:52:11 PM (6 years ago)
Author:
[email protected]
Message:

Unreviewed, rolling out r251090.
https://bugs.webkit.org/show_bug.cgi?id=202959

"broke tests" (Requested by RMorisset on #webkit).

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/251090

File:
1 edited

Legend:

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

    r251090 r251106  
    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(BitfieldType bits)
    137         : m_bits(bits)
    138     {
    139     }
    140 
    141     bool hasBits(int mask) const { return m_bits & mask; }
    142     void setBit(int mask) { m_bits |= mask; }
    143 
    144     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.
    145 };
    146 
    147 /* This class stores the following components in 16 bits:
    148  * - ObservedResults
    149  * - ResultType for the argument
    150  * - ObservedType for the argument
    151  */
    152 class UnaryArithProfile : public ArithProfile<uint16_t> {
    153     static constexpr unsigned argResultTypeShift = observedResultsNumBitsNeeded;
    154     static constexpr unsigned argObservedTypeShift = argResultTypeShift + ResultType::numBitsNeeded;
    155 
    156     static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(uint16_t) * 8, "Should fit in a uint16_t");
    157 
    158     static constexpr uint16_t clearArgObservedTypeBitMask = static_cast<uint16_t>(~(0b111 << argObservedTypeShift));
    159 
    160     static constexpr uint16_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
    161     static constexpr uint16_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
    162 
    163 public:
    164     UnaryArithProfile(ResultType arg)
    165         : ArithProfile<uint16_t>(arg.bits() << argResultTypeShift)
    166     {
    167         ASSERT(argResultType().bits() == arg.bits());
    168         ASSERT(argObservedType().isEmpty());
    169         ASSERT(argObservedType().isEmpty());
    170     }
    171 
    172     UnaryArithProfile()
    173         : UnaryArithProfile(ResultType::unknownType())
    174     {
    175     }
    176 
    177     static constexpr uint16_t observedIntBits()
    178     {
    179         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    180         constexpr uint16_t bits = observedInt32.bits() << argObservedTypeShift;
    181         static_assert(bits == 0x2000, "");
    182         return bits;
    183     }
    184     static constexpr uint16_t observedNumberBits()
    185     {
    186         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    187         constexpr uint16_t bits = observedNumber.bits() << argObservedTypeShift;
    188         static_assert(bits == 0x4000, "");
    189         return bits;
    190     }
    191 
    192     ResultType argResultType() const { return ResultType((m_bits >> argResultTypeShift) & resultTypeMask); }
    193 
    194     constexpr ObservedType argObservedType() const { return ObservedType((m_bits >> argObservedTypeShift) & observedTypeMask); }
    195     void setArgObservedType(ObservedType type)
    196     {
    197         uint16_t bits = m_bits;
    198         bits &= clearArgObservedTypeBitMask;
    199         bits |= type.bits() << argObservedTypeShift;
    200         m_bits = bits;
    201         ASSERT(argObservedType() == type);
    202     }
    203 
    204     void argSawInt32() { setArgObservedType(argObservedType().withInt32()); }
    205     void argSawNumber() { setArgObservedType(argObservedType().withNumber()); }
    206     void argSawNonNumber() { setArgObservedType(argObservedType().withNonNumber()); }
    207 
    208     void observeArg(JSValue arg)
    209     {
    210         UnaryArithProfile newProfile = *this;
    211         if (arg.isNumber()) {
    212             if (arg.isInt32())
    213                 newProfile.argSawInt32();
    214             else
    215                 newProfile.argSawNumber();
    216         } else
    217             newProfile.argSawNonNumber();
    218 
    219         m_bits = newProfile.bits();
    220     }
    221 
    222     bool isObservedTypeEmpty()
    223     {
    224         return argObservedType().isEmpty();
    225     }
    226 
    227     friend class JSC::LLIntOffsetsExtractor;
    228 };
    229 
    230 /* This class stores the following components in 32 bits:
    231  * - ObservedResults
    232  * - ResultType for right-hand-side
    233  * - ResultType for left-hand-side
    234  * - ObservedType for right-hand-side
    235  * - ObservedType for left-hand-side
    236  * - a bit used by division to indicate whether a special fast path was taken
    237  */
    238 class BinaryArithProfile : public ArithProfile<uint32_t> {
    239     static constexpr uint32_t rhsResultTypeShift = observedResultsNumBitsNeeded;
    240     static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
    241     static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
    242     static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
    243 
    244     static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
    245     static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~(0b111 << rhsObservedTypeShift));
    246     static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~(0b111 << lhsObservedTypeShift));
    247 
    248     static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
    249     static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
    250 
    251 public:
    252     static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
    253     static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(uint32_t) * 8, "Should fit in a uint32_t.");
    254     static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
    255     static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
    256     static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
    257 
    258     BinaryArithProfile(ResultType lhs, ResultType rhs)
    259         : ArithProfile<uint32_t>((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift))
    260     {
    261         ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());
    262         ASSERT(lhsObservedType().isEmpty());
    263         ASSERT(rhsObservedType().isEmpty());
    264     }
    265 
    266     BinaryArithProfile(OperandTypes types)
    267         : BinaryArithProfile(types.first(), types.second())
    268     { }
    269 
    270     BinaryArithProfile()
    271         : BinaryArithProfile(ResultType::unknownType(), ResultType::unknownType())
    272     {
    273     }
    274 
    275     static constexpr uint32_t observedIntIntBits()
    276     {
    277         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    278         constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    279         static_assert(bits == 0x900000, "");
    280         return bits;
    281     }
    282     static constexpr uint32_t observedNumberIntBits()
    283     {
    284         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    285         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    286         constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    287         static_assert(bits == 0x1100000, "");
    288         return bits;
    289     }
    290     static constexpr uint32_t observedIntNumberBits()
    291     {
    292         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    293         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    294         constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    295         static_assert(bits == 0xa00000, "");
    296         return bits;
    297     }
    298     static constexpr uint32_t observedNumberNumberBits()
    299     {
    300         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    301         constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    302         static_assert(bits == 0x1200000, "");
    303         return bits;
    304     }
    305 
    306     ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); }
    307     ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); }
    308 
    309     constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
    310     constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
    311     void setLhsObservedType(ObservedType type)
    312     {
    313         uint32_t bits = m_bits;
    314         bits &= clearLhsObservedTypeBitMask;
    315         bits |= type.bits() << lhsObservedTypeShift;
    316         m_bits = bits;
    317         ASSERT(lhsObservedType() == type);
    318     }
    319 
    320     void setRhsObservedType(ObservedType type)
    321     {
    322         uint32_t bits = m_bits;
    323         bits &= clearRhsObservedTypeBitMask;
    324         bits |= type.bits() << rhsObservedTypeShift;
    325         m_bits = bits;
    326         ASSERT(rhsObservedType() == type);
    327     }
    328 
    329     bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
    330 
    331232    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
    332233    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
     
    338239    void observeLHS(JSValue lhs)
    339240    {
    340         BinaryArithProfile newProfile = *this;
     241        ArithProfile newProfile = *this;
    341242        if (lhs.isNumber()) {
    342243            if (lhs.isInt32())
     
    354255        observeLHS(lhs);
    355256
    356         BinaryArithProfile newProfile = *this;
     257        ArithProfile newProfile = *this;
    357258        if (rhs.isNumber()) {
    358259            if (rhs.isInt32())
     
    366267    }
    367268
    368     bool isObservedTypeEmpty()
    369     {
    370         return lhsObservedType().isEmpty() && rhsObservedType().isEmpty();
    371     }
     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.
    372309
    373310    friend class JSC::LLIntOffsetsExtractor;
     
    378315namespace WTF {
    379316
    380 void printInternal(PrintStream&, const JSC::UnaryArithProfile&);
    381 void printInternal(PrintStream&, const JSC::BinaryArithProfile&);
     317void printInternal(PrintStream&, const JSC::ArithProfile&);
    382318void printInternal(PrintStream&, const JSC::ObservedType&);
    383319
Note: See TracChangeset for help on using the changeset viewer.