Ignore:
Timestamp:
Oct 14, 2019, 1:28:41 PM (6 years ago)
Author:
[email protected]
Message:

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

Reviewed by Keith Miller.

ArithProfile was for a long time only used for add/sub/mul/div, but recently it started being used for negate. And it will soon also have to be used for inc and dec due to BigInt.
So in this patch I make a separate version that only has the data for a single argument, and thus takes half as much memory.

  • bytecode/ArithProfile.cpp:

(JSC::ArithProfile<BitfieldType>::emitObserveResult):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetDouble const):
(JSC::ArithProfile<BitfieldType>::emitSetDouble const):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetNonNumeric const):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetBigInt const):
(JSC::ArithProfile<BitfieldType>::emitSetNonNumeric const):
(JSC::ArithProfile<BitfieldType>::emitSetBigInt const):
(WTF::printInternal):

  • bytecode/ArithProfile.h:

(JSC::ArithProfile::didObserveNonInt32 const):
(JSC::ArithProfile::didObserveDouble const):
(JSC::ArithProfile::didObserveNonNegZeroDouble const):
(JSC::ArithProfile::didObserveNegZeroDouble const):
(JSC::ArithProfile::didObserveNonNumeric const):
(JSC::ArithProfile::didObserveBigInt const):
(JSC::ArithProfile::didObserveInt32Overflow const):
(JSC::ArithProfile::didObserveInt52Overflow const):
(JSC::ArithProfile::setObservedNonNegZeroDouble):
(JSC::ArithProfile::setObservedNegZeroDouble):
(JSC::ArithProfile::setObservedNonNumeric):
(JSC::ArithProfile::setObservedBigInt):
(JSC::ArithProfile::setObservedInt32Overflow):
(JSC::ArithProfile::setObservedInt52Overflow):
(JSC::ArithProfile::observeResult):
(JSC::ArithProfile::addressOfBits const):
(JSC::ArithProfile::bits const):
(JSC::ArithProfile::ArithProfile):
(JSC::ArithProfile::hasBits const):
(JSC::ArithProfile::setBit):
(JSC::UnaryArithProfile::UnaryArithProfile):
(JSC::UnaryArithProfile::observedIntBits):
(JSC::UnaryArithProfile::observedNumberBits):
(JSC::UnaryArithProfile::argResultType const):
(JSC::UnaryArithProfile::argObservedType const):
(JSC::UnaryArithProfile::setArgObservedType):
(JSC::UnaryArithProfile::argSawInt32):
(JSC::UnaryArithProfile::argSawNumber):
(JSC::UnaryArithProfile::argSawNonNumber):
(JSC::UnaryArithProfile::observeArg):
(JSC::UnaryArithProfile::isObservedTypeEmpty):
(JSC::BinaryArithProfile::BinaryArithProfile):
(JSC::BinaryArithProfile::observedIntIntBits):
(JSC::BinaryArithProfile::observedNumberIntBits):
(JSC::BinaryArithProfile::observedIntNumberBits):
(JSC::BinaryArithProfile::observedNumberNumberBits):
(JSC::BinaryArithProfile::observeLHS):
(JSC::BinaryArithProfile::observeLHSAndRHS):
(JSC::BinaryArithProfile::isObservedTypeEmpty):

  • bytecode/BytecodeList.rb:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::addJITAddIC):
(JSC::CodeBlock::addJITMulIC):
(JSC::CodeBlock::addJITSubIC):
(JSC::CodeBlock::addJITNegIC):
(JSC::CodeBlock::binaryArithProfileForBytecodeOffset):
(JSC::CodeBlock::unaryArithProfileForBytecodeOffset):
(JSC::CodeBlock::binaryArithProfileForPC):
(JSC::CodeBlock::unaryArithProfileForPC):
(JSC::CodeBlock::couldTakeSpecialFastCase):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::addMathIC):

  • bytecode/Fits.h:
  • bytecode/MethodOfGettingAValueProfile.cpp:

(JSC::MethodOfGettingAValueProfile::emitReportValue const):
(JSC::MethodOfGettingAValueProfile::reportValue):

  • bytecode/MethodOfGettingAValueProfile.h:

(JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitUnaryOp):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::UnaryOpNode::emitBytecode):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::makeDivSafe):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::methodOfGettingAValueProfileFor):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileValueAdd):
(JSC::DFG::SpeculativeJIT::compileValueSub):
(JSC::DFG::SpeculativeJIT::compileValueNegate):
(JSC::DFG::SpeculativeJIT::compileValueMul):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
(JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
(JSC::FTL::DFG::LowerDFGToB3::compileUnaryMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileBinaryMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub):
(JSC::FTL::DFG::LowerDFGToB3::compileValueNegate):

  • jit/JIT.h:
  • jit/JITAddGenerator.cpp:

(JSC::JITAddGenerator::generateInline):
(JSC::JITAddGenerator::generateFastPath):

  • jit/JITAddGenerator.h:
  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_op_negate):
(JSC::JIT::emit_op_add):
(JSC::JIT::emitMathICFast):
(JSC::JIT::emitMathICSlow):
(JSC::JIT::emit_op_div):
(JSC::JIT::emit_op_mul):
(JSC::JIT::emit_op_sub):

  • jit/JITDivGenerator.cpp:

(JSC::JITDivGenerator::generateFastPath):

  • jit/JITDivGenerator.h:

(JSC::JITDivGenerator::JITDivGenerator):

  • jit/JITInlines.h:

(JSC::JIT::copiedArithProfile):

  • jit/JITMathIC.h:

(JSC::JITMathIC::JITMathIC):
(JSC::JITMathIC::generateInline):
(JSC::JITMathIC::arithProfile const):
(JSC::isBinaryProfileEmpty):
(JSC::JITBinaryMathIC::JITBinaryMathIC):
(JSC::isUnaryProfileEmpty):
(JSC::JITUnaryMathIC::JITUnaryMathIC):

  • jit/JITMulGenerator.cpp:

(JSC::JITMulGenerator::generateInline):
(JSC::JITMulGenerator::generateFastPath):

  • jit/JITMulGenerator.h:
  • jit/JITNegGenerator.cpp:

(JSC::JITNegGenerator::generateInline):
(JSC::JITNegGenerator::generateFastPath):

  • jit/JITNegGenerator.h:
  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/JITSubGenerator.cpp:

(JSC::JITSubGenerator::generateInline):
(JSC::JITSubGenerator::generateFastPath):

  • jit/JITSubGenerator.h:
  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LLIntOffsetsExtractor.cpp:

(JSC::LLIntOffsetsExtractor::dummy):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • parser/ResultType.h:

(JSC::ResultType::ResultType):

  • runtime/CommonSlowPaths.cpp:

(JSC::updateArithProfileForUnaryArithOp):
(JSC::updateArithProfileForBinaryArithOp):
(JSC::SLOW_PATH_DECL):

File:
1 edited

Legend:

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

    r240138 r251090  
    6767};
    6868
    69 struct ArithProfile {
    70 private:
    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 
     69template <typename BitfieldType>
     70class ArithProfile {
    8671public:
    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 
    16572    enum ObservedResults {
    16673        NonNegZeroDouble = 1 << 0,
     
    17178        BigInt           = 1 << 5,
    17279    };
    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; }
     80    static constexpr uint32_t observedResultsNumBitsNeeded = 6;
    19881
    19982    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); }
     
    21295    void setObservedInt32Overflow() { setBit(Int32Overflow); }
    21396    void setObservedInt52Overflow() { setBit(Int52Overflow); }
    214 
    215     const void* addressOfBits() const { return &m_bits; }
    21697
    21798    void observeResult(JSValue value)
     
    230111    }
    231112
     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
     135protected:
     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 */
     152class 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
     163public:
     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 */
     238class 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
     251public:
     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
    232331    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
    233332    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
     
    239338    void observeLHS(JSValue lhs)
    240339    {
    241         ArithProfile newProfile = *this;
     340        BinaryArithProfile newProfile = *this;
    242341        if (lhs.isNumber()) {
    243342            if (lhs.isInt32())
     
    255354        observeLHS(lhs);
    256355
    257         ArithProfile newProfile = *this;
     356        BinaryArithProfile newProfile = *this;
    258357        if (rhs.isNumber()) {
    259358            if (rhs.isInt32())
     
    267366    }
    268367
    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 
    289 private:
    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.
     368    bool isObservedTypeEmpty()
     369    {
     370        return lhsObservedType().isEmpty() && rhsObservedType().isEmpty();
     371    }
    309372
    310373    friend class JSC::LLIntOffsetsExtractor;
     
    315378namespace WTF {
    316379
    317 void printInternal(PrintStream&, const JSC::ArithProfile&);
     380void printInternal(PrintStream&, const JSC::UnaryArithProfile&);
     381void printInternal(PrintStream&, const JSC::BinaryArithProfile&);
    318382void printInternal(PrintStream&, const JSC::ObservedType&);
    319383
Note: See TracChangeset for help on using the changeset viewer.