Ignore:
Timestamp:
Nov 7, 2018, 5:47:27 PM (7 years ago)
Author:
Caio Lima
Message:

[BigInt] Add support to BigInt into ValueAdd
https://bugs.webkit.org/show_bug.cgi?id=186177

Reviewed by Keith Miller.

JSTests:

  • stress/big-int-negate-jit.js:
  • stress/value-add-big-int-and-string.js: Added.
  • stress/value-add-big-int-prediction-propagation.js: Added.
  • stress/value-add-big-int-untyped.js: Added.

PerformanceTests:

The idea of BigIntBench is to provide a set of microbenchmarks and
benchmarks to evaluate how fast BigInt computations are happening on
JSC implementation.

Now, we are adding microbenchmarks in this set,
but the plan is to move these tests to "JSTest/microbenchmarks" when
BigInt is enabled by default. After that, the focus of Bigint bench is
to provide a set of tests that represents real use cases of BigInt in
JS programs.

  • BigIntBench/big-int-add-prediction-propagation.js: Added.
  • BigIntBench/big-int-simple-add.js: Added.
  • BigIntBench/big-int-simple-sub.js: Added.

Source/JavaScriptCore:

We are adding a very primitive specialization case of BigInts into ValueAdd.
When compiling a speculated version of this node to BigInt, we are currently
calling 'operationAddBigInt', a function that expects only BigInts as
parameter and effectly add numbers using JSBigInt::add. To properly
speculate BigInt operands, we changed ArithProfile to observe when
its result is a BigInt. With this new observation, we are able to identify
when ValueAdd results into a String or BigInt.

Here are some numbers for this specialization running
microbenchmarks:

big-int-simple-add 21.5411+-1.1096 15.3502+-0.7027 definitely 1.4033x faster
big-int-add-prediction-propagation 13.7762+-0.5578 10.8117+-0.5330 definitely 1.2742x faster

  • bytecode/ArithProfile.cpp:

(JSC::ArithProfile::emitObserveResult):
(JSC::ArithProfile::shouldEmitSetNonNumeric const):
(JSC::ArithProfile::shouldEmitSetBigInt const):
(JSC::ArithProfile::emitSetNonNumeric const):
(JSC::ArithProfile::emitSetBigInt const):
(WTF::printInternal):
(JSC::ArithProfile::shouldEmitSetNonNumber const): Deleted.
(JSC::ArithProfile::emitSetNonNumber const): Deleted.

  • bytecode/ArithProfile.h:

(JSC::ArithProfile::observedUnaryInt):
(JSC::ArithProfile::observedUnaryNumber):
(JSC::ArithProfile::observedBinaryIntInt):
(JSC::ArithProfile::observedBinaryNumberInt):
(JSC::ArithProfile::observedBinaryIntNumber):
(JSC::ArithProfile::observedBinaryNumberNumber):
(JSC::ArithProfile::didObserveNonInt32 const):
(JSC::ArithProfile::didObserveNonNumeric const):
(JSC::ArithProfile::didObserveBigInt const):
(JSC::ArithProfile::setObservedNonNumeric):
(JSC::ArithProfile::setObservedBigInt):
(JSC::ArithProfile::observeResult):
(JSC::ArithProfile::didObserveNonNumber const): Deleted.
(JSC::ArithProfile::setObservedNonNumber): Deleted.

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::mayHaveNonNumericResult):
(JSC::DFG::Node::mayHaveBigIntResult):
(JSC::DFG::Node::mayHaveNonNumberResult): Deleted.

  • dfg/DFGNodeFlags.cpp:

(JSC::DFG::dumpNodeFlags):

  • dfg/DFGNodeFlags.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileValueAdd):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):

  • runtime/CommonSlowPaths.cpp:

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

Tools:

  • Scripts/run-jsc-benchmarks:
File:
1 edited

Legend:

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

    r237547 r237972  
    6969struct ArithProfile {
    7070private:
    71     static constexpr uint32_t numberOfFlagBits = 5;
     71    static constexpr uint32_t numberOfFlagBits = 6;
    7272    static constexpr uint32_t rhsResultTypeShift = numberOfFlagBits;
    7373    static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
     
    122122        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    123123        constexpr uint32_t bits = observedInt32.bits() << lhsObservedTypeShift;
    124         static_assert(bits == 0x400000, "");
     124        static_assert(bits == 0x800000, "");
    125125        return fromInt(bits);
    126126    }
     
    129129        constexpr ObservedType observedNumber { ObservedType().withNumber() };
    130130        constexpr uint32_t bits = observedNumber.bits() << lhsObservedTypeShift;
    131         static_assert(bits == 0x800000, "");
     131        static_assert(bits == 0x1000000, "");
    132132        return fromInt(bits);
    133133    }
     
    136136        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    137137        constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    138         static_assert(bits == 0x480000, "");
     138        static_assert(bits == 0x900000, "");
    139139        return fromInt(bits);
    140140    }
     
    144144        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    145145        constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    146         static_assert(bits == 0x880000, "");
     146        static_assert(bits == 0x1100000, "");
    147147        return fromInt(bits);
    148148    }
     
    152152        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    153153        constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    154         static_assert(bits == 0x500000, "");
     154        static_assert(bits == 0xa00000, "");
    155155        return fromInt(bits);
    156156    }
     
    159159        constexpr ObservedType observedNumber { ObservedType().withNumber() };
    160160        constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    161         static_assert(bits == 0x900000, "");
     161        static_assert(bits == 0x1200000, "");
    162162        return fromInt(bits);
    163163    }
     
    166166        NonNegZeroDouble = 1 << 0,
    167167        NegZeroDouble    = 1 << 1,
    168         NonNumber        = 1 << 2,
     168        NonNumeric       = 1 << 2,
    169169        Int32Overflow    = 1 << 3,
    170170        Int52Overflow    = 1 << 4,
     171        BigInt           = 1 << 5,
    171172    };
    172173
     
    196197    bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
    197198
    198     bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); }
     199    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); }
    199200    bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); }
    200201    bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); }
    201202    bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); }
    202     bool didObserveNonNumber() const { return hasBits(NonNumber); }
     203    bool didObserveNonNumeric() const { return hasBits(NonNumeric); }
     204    bool didObserveBigInt() const { return hasBits(BigInt); }
    203205    bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); }
    204206    bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); }
     
    206208    void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); }
    207209    void setObservedNegZeroDouble() { setBit(NegZeroDouble); }
    208     void setObservedNonNumber() { setBit(NonNumber); }
     210    void setObservedNonNumeric() { setBit(NonNumeric); }
     211    void setObservedBigInt() { setBit(BigInt); }
    209212    void setObservedInt32Overflow() { setBit(Int32Overflow); }
    210213    void setObservedInt52Overflow() { setBit(Int52Overflow); }
     
    220223            return;
    221224        }
    222         m_bits |= NonNumber;
     225        if (value && value.isBigInt()) {
     226            m_bits |= BigInt;
     227            return;
     228        }
     229        m_bits |= NonNumeric;
    223230    }
    224231
     
    262269#if ENABLE(JIT)   
    263270    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
    264     // double. Sets NonNumber if it sees a non-number.
     271    // double. Sets NonNumeric if it sees a non-numeric.
    265272    void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
    266273   
     
    270277   
    271278    // Sets NonNumber.
    272     void emitSetNonNumber(CCallHelpers&) const;
    273     bool shouldEmitSetNonNumber() const;
     279    void emitSetNonNumeric(CCallHelpers&) const;
     280    bool shouldEmitSetNonNumeric() const;
     281
     282    // Sets BigInt
     283    void emitSetBigInt(CCallHelpers&) const;
     284    bool shouldEmitSetBigInt() const;
    274285#endif // ENABLE(JIT)
    275286
Note: See TracChangeset for help on using the changeset viewer.