Ignore:
Timestamp:
Nov 4, 2019, 2:20:37 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
<rdar://problem/56266847>

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.

After discussing this change with Phil I realized that the ResultType(s) that were taking space in ArithProfile are not needed: they never change and a copy is already in the bytecode instruction itself.
Removing them allowed shrinking both kinds of ArithProfile to fit in 16 bits (9 and 13 respectively).
I kept the two kinds separate because they may shrink or grow independently in the future.

This also required adding the "orh" instruction to the offline assembler, to set bits in the ArithProfile.
This in turn motivated the addition of "storeh", as on RISC platforms "orh" on a memory location is actually loadh -> orh -> storeh.

  • 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::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::setLhsObservedType):
(JSC::BinaryArithProfile::setRhsObservedType):
(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

    r251106 r252015  
    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()
     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 */
     150using UnaryArithProfileBase = uint16_t;
     151class 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
     160public:
     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 */
     223using BinaryArithProfileBase = uint16_t;
     224class 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
     234public:
     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
    232297    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
    233298    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
     
    239304    void observeLHS(JSValue lhs)
    240305    {
    241         ArithProfile newProfile = *this;
     306        BinaryArithProfile newProfile = *this;
    242307        if (lhs.isNumber()) {
    243308            if (lhs.isInt32())
     
    255320        observeLHS(lhs);
    256321
    257         ArithProfile newProfile = *this;
     322        BinaryArithProfile newProfile = *this;
    258323        if (rhs.isNumber()) {
    259324            if (rhs.isInt32())
     
    267332    }
    268333
    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.
     334    bool isObservedTypeEmpty()
     335    {
     336        return lhsObservedType().isEmpty() && rhsObservedType().isEmpty();
     337    }
    309338
    310339    friend class JSC::LLIntOffsetsExtractor;
     
    315344namespace WTF {
    316345
    317 void printInternal(PrintStream&, const JSC::ArithProfile&);
     346void printInternal(PrintStream&, const JSC::UnaryArithProfile&);
     347void printInternal(PrintStream&, const JSC::BinaryArithProfile&);
    318348void printInternal(PrintStream&, const JSC::ObservedType&);
    319349
Note: See TracChangeset for help on using the changeset viewer.