⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 278568 in webkit


Ignore:
Timestamp:
Jun 7, 2021, 12:55:30 PM (5 years ago)
Author:
rmorisset@apple.com
Message:

Optimize compareStrictEq when neither side is a double and at least one is neither a string nor a BigInt
https://bugs.webkit.org/show_bug.cgi?id=226676

Reviewed by Filip Pizlo.

JSTests:

I made two variants of the already existing poly-stricteq microbenchmarks with different types in the array.
I also tweaked all three so that we more reliably reach the FTL.
Finally I added a stress-test to verify that I did not introduce an OSR exit bug.

  • microbenchmarks/poly-stricteq-not-double-nor-string.js: Added.

(foo):
(test):

  • microbenchmarks/poly-stricteq-not-double.js: Added.

(foo):
(test):

  • microbenchmarks/poly-stricteq.js:

(foo):
(test):

  • stress/poly-stricteq-not-double-nor-string-fail.js: Added.

(foo):
(test):

Source/JavaScriptCore:

There is exactly one case where x === y must return false despite x and y being JSValues with the same bits:

NaN === NaN

There are a few cases where x === y must return true despite x and y being JSValues with potentially different bits:

Double === Int32
String === String
HeapBigInt === HeapBigInt
HeapBigInt === BigInt32 (if they are enabled)

If we don't have a double on either side, at least one side has neither a String nor a HeapBigInt, and BigInt32 are disabled, we can clearly ignore all of these pathological cases.

This optimization was decided based on looking at DFG graphs of Speedometer2; here is a sample of the compareStrictEq(Untyped, Untyped), courtesy of Phil:

Final|Array|String|Bool, Final|Array|String|Bool
Array|String|Bool, String|Bool (twice)
Array|String|Bool, String|Int32 (once in DFG, once in FTL)

! Array|String|Bool, Array|Bool
! Final|Other, Final|Other
! Int32|Other, Int32

Final|StringIdent, Final|StringIdent (3 times)
Final|StringIdent|BoolInt32, StringIdent|BoolInt32 (twice)
String|Bool, String|Bool (4 times)
DoublePureNaN, String|Bool

! Other, Function|Other
! Final|Other, Final|Function|Other (twice)

Final|String|Bool|Other, Final|String|Bool|Other (3 times, two in the FTL)
Final|String|Int32, String|Int32 (four times)
String|Int32|Bool, Function|String|Int32|Bool (twice)
String|DoublePureNaN, String|Bool (twice)

! Final|Bool|Other, Final|Function|Other (four times, twice in FTL)
I marked with a ! those for which this optimization should apply.

The only slightly interesting part of this patch is DFG::SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString where I took care to skip every test whose result we can predict from the abstract interpreter.

Results on microbenchmarks:

poly-stricteq-not-double 45.5793+-0.5304 ? 46.0306+-0.5621 ?
poly-stricteq-not-double-nor-string 45.5829+-0.5750 16.9089+-0.3070 definitely 2.6958x faster
poly-stricteq 49.9719+-0.6450 48.9855+-0.5227 might be 1.0201x faster

I also measured the amount of code that we generate in the DFG on JetStream2.
The results here are disappointing but still measurable. Before:

DFG_fast_CompareStrictEq totalBytes: 468425 count: 10951 avg: 42.774632
DFG_fast_CompareStrictEq totalBytes: 468020 count: 10917 avg: 42.870752
DFG_fast_CompareStrictEq totalBytes: 467424 count: 10888 avg: 42.930198

After:

DFG_fast_CompareStrictEq totalBytes: 463946 count: 10917 avg: 42.497573
DFG_fast_CompareStrictEq totalBytes: 474492 count: 11138 avg: 42.601185
DFG_fast_CompareStrictEq totalBytes: 467138 count: 10970 avg: 42.583227

  • bytecode/SpeculatedType.h:

(JSC::isNeitherDoubleNorHeapBigIntNorStringSpeculation):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):

  • dfg/DFGNode.h:

(JSC::DFG::Node::shouldSpeculateNeitherDoubleNorHeapBigIntNorString):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::SafeToExecuteEdge::operator()):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality):
(JSC::DFG::SpeculativeJIT::speculateNotDouble):
(JSC::DFG::SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString):
(JSC::DFG::SpeculativeJIT::speculate):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::checkMayCrashIfInputIsEmpty):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
(JSC::FTL::DFG::LowerDFGToB3::speculate):
(JSC::FTL::DFG::LowerDFGToB3::speculateNeitherDoubleNorHeapBigIntNorString):

Location:
trunk
Files:
3 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r278510 r278568  
     12021-06-07  Robin Morisset  <rmorisset@apple.com>
     2
     3        Optimize compareStrictEq when neither side is a double and at least one is neither a string nor a BigInt
     4        https://bugs.webkit.org/show_bug.cgi?id=226676
     5
     6        Reviewed by Filip Pizlo.
     7
     8        I made two variants of the already existing poly-stricteq microbenchmarks with different types in the array.
     9        I also tweaked all three so that we more reliably reach the FTL.
     10        Finally I added a stress-test to verify that I did not introduce an OSR exit bug.
     11
     12        * microbenchmarks/poly-stricteq-not-double-nor-string.js: Added.
     13        (foo):
     14        (test):
     15        * microbenchmarks/poly-stricteq-not-double.js: Added.
     16        (foo):
     17        (test):
     18        * microbenchmarks/poly-stricteq.js:
     19        (foo):
     20        (test):
     21        * stress/poly-stricteq-not-double-nor-string-fail.js: Added.
     22        (foo):
     23        (test):
     24
    1252021-06-04  Yusuke Suzuki  <ysuzuki@apple.com>
    226
  • trunk/JSTests/microbenchmarks/poly-stricteq.js

    r251463 r278568  
    77
    88for (var i = 0; i < 1000; ++i) {
    9     array.push(i);
    10     array.push((i%2) == 0);
     9    array.push((i % 2) == 0);
     10    array.push(3.14 * i);
    1111    array.push("" + i);
    1212    var o = {};
     
    1616
    1717var numStrictEqual = 0;
    18 for (var i = 0; i < array.length; ++i) {
    19     for (var j = i + 1; j < array.length; ++j) {
    20         if (array[i] === array[j])
    21             numStrictEqual++;
    22     }
     18
     19function foo(x, y)
     20{
     21    if(x === y)
     22        numStrictEqual++;
    2323}
    2424
    25 if (numStrictEqual != 249500)
    26     throw "Incorrect result: " + numStrictEqual;
     25function test()
     26{
     27    for (var i = 0; i < array.length; ++i) {
     28        for (var j = i + 1; j < array.length; ++j) {
     29            foo(array[i], array[j]);
     30        }
     31    }
     32
     33    if (numStrictEqual != 249500)
     34        throw "Incorrect result: " + numStrictEqual;
     35}
     36noInline(test);
     37test();
    2738
    2839
    29 
  • trunk/Source/JavaScriptCore/ChangeLog

    r278553 r278568  
     12021-06-07  Robin Morisset  <rmorisset@apple.com>
     2
     3        Optimize compareStrictEq when neither side is a double and at least one is neither a string nor a BigInt
     4        https://bugs.webkit.org/show_bug.cgi?id=226676
     5
     6        Reviewed by Filip Pizlo.
     7
     8        There is exactly one case where x === y must return false despite x and y being JSValues with the same bits:
     9            NaN === NaN
     10        There are a few cases where x === y must return true despite x and y being JSValues with potentially different bits:
     11            Double === Int32
     12            String === String
     13            HeapBigInt === HeapBigInt
     14            HeapBigInt === BigInt32 (if they are enabled)
     15        If we don't have a double on either side, at least one side has neither a String nor a HeapBigInt, and BigInt32 are disabled, we can clearly ignore all of these pathological cases.
     16
     17        This optimization was decided based on looking at DFG graphs of Speedometer2; here is a sample of the compareStrictEq(Untyped, Untyped), courtesy of Phil:
     18            Final|Array|String|Bool, Final|Array|String|Bool
     19            Array|String|Bool, String|Bool (twice)
     20            Array|String|Bool, String|Int32 (once in DFG, once in FTL)
     21        !   Array|String|Bool, Array|Bool
     22        !   Final|Other, Final|Other
     23        !   Int32|Other, Int32
     24            Final|StringIdent, Final|StringIdent (3 times)
     25            Final|StringIdent|BoolInt32, StringIdent|BoolInt32 (twice)
     26            String|Bool, String|Bool (4 times)
     27            DoublePureNaN, String|Bool
     28        !   Other, Function|Other
     29        !   Final|Other, Final|Function|Other (twice)
     30            Final|String|Bool|Other, Final|String|Bool|Other (3 times, two in the FTL)
     31            Final|String|Int32, String|Int32 (four times)
     32            String|Int32|Bool, Function|String|Int32|Bool (twice)
     33            String|DoublePureNaN, String|Bool (twice)
     34        !   Final|Bool|Other, Final|Function|Other (four times, twice in FTL)
     35        I marked with a ! those for which this optimization should apply.
     36
     37        The only slightly interesting part of this patch is DFG::SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString where I took care to skip every test whose result we can predict from the abstract interpreter.
     38
     39        Results on microbenchmarks:
     40            poly-stricteq-not-double                  45.5793+-0.5304     ?     46.0306+-0.5621        ?
     41            poly-stricteq-not-double-nor-string       45.5829+-0.5750     ^     16.9089+-0.3070        ^ definitely 2.6958x faster
     42            poly-stricteq                             49.9719+-0.6450           48.9855+-0.5227          might be 1.0201x faster
     43
     44        I also measured the amount of code that we generate in the DFG on JetStream2.
     45        The results here are disappointing but still measurable. Before:
     46            DFG_fast_CompareStrictEq totalBytes: 468425 count: 10951 avg: 42.774632
     47            DFG_fast_CompareStrictEq totalBytes: 468020 count: 10917 avg: 42.870752
     48            DFG_fast_CompareStrictEq totalBytes: 467424 count: 10888 avg: 42.930198
     49        After:
     50            DFG_fast_CompareStrictEq totalBytes: 463946 count: 10917 avg: 42.497573
     51            DFG_fast_CompareStrictEq totalBytes: 474492 count: 11138 avg: 42.601185
     52            DFG_fast_CompareStrictEq totalBytes: 467138 count: 10970 avg: 42.583227
     53
     54        * bytecode/SpeculatedType.h:
     55        (JSC::isNeitherDoubleNorHeapBigIntNorStringSpeculation):
     56        * dfg/DFGDoesGC.cpp:
     57        (JSC::DFG::doesGC):
     58        * dfg/DFGFixupPhase.cpp:
     59        (JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):
     60        * dfg/DFGNode.h:
     61        (JSC::DFG::Node::shouldSpeculateNeitherDoubleNorHeapBigIntNorString):
     62        * dfg/DFGSafeToExecute.h:
     63        (JSC::DFG::SafeToExecuteEdge::operator()):
     64        * dfg/DFGSpeculativeJIT.cpp:
     65        (JSC::DFG::SpeculativeJIT::compileStrictEq):
     66        (JSC::DFG::SpeculativeJIT::compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality):
     67        (JSC::DFG::SpeculativeJIT::compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality):
     68        (JSC::DFG::SpeculativeJIT::speculateNotDouble):
     69        (JSC::DFG::SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString):
     70        (JSC::DFG::SpeculativeJIT::speculate):
     71        * dfg/DFGSpeculativeJIT.h:
     72        * dfg/DFGUseKind.cpp:
     73        (WTF::printInternal):
     74        * dfg/DFGUseKind.h:
     75        (JSC::DFG::typeFilterFor):
     76        (JSC::DFG::checkMayCrashIfInputIsEmpty):
     77        * ftl/FTLCapabilities.cpp:
     78        (JSC::FTL::canCompile):
     79        * ftl/FTLLowerDFGToB3.cpp:
     80        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
     81        (JSC::FTL::DFG::LowerDFGToB3::speculate):
     82        (JSC::FTL::DFG::LowerDFGToB3::speculateNeitherDoubleNorHeapBigIntNorString):
     83
    1842021-06-07  Tuomas Karkkainen  <tuomas.webkit@apple.com>
    285
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r278465 r278568  
    445445}
    446446
     447inline bool isNeitherDoubleNorHeapBigIntNorStringSpeculation(SpeculatedType type)
     448{
     449    return !(type & (SpecFullDouble | SpecHeapBigInt | SpecString));
     450}
     451
    447452inline bool isOtherSpeculation(SpeculatedType value)
    448453{
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r278462 r278568  
    4848    //     2. Resolves a rope string, which allocates a string.
    4949    //     3. Produces a string (which allocates the string) except when we can prove that
    50     //        the string will always be one of the pre-allcoated SmallStrings.
     50    //        the string will always be one of the pre-allocated SmallStrings.
    5151    //     4. Triggers a structure transition (which can allocate a new structure)
    5252    //        unless it is a known transition between previously allocated structures
     
    497497            || node->isBinaryUseKind(ObjectUse)
    498498            || node->isBinaryUseKind(MiscUse, UntypedUse) || node->isBinaryUseKind(UntypedUse, MiscUse)
    499             || node->isBinaryUseKind(StringIdentUse, NotStringVarUse) || node->isBinaryUseKind(NotStringVarUse, StringIdentUse))
     499            || node->isBinaryUseKind(StringIdentUse, NotStringVarUse) || node->isBinaryUseKind(NotStringVarUse, StringIdentUse)
     500            || node->isBinaryUseKind(NotDoubleUse, NeitherDoubleNorHeapBigIntNorStringUse) || node->isBinaryUseKind(NotDoubleUse, NeitherDoubleNorHeapBigIntNorStringUse))
    500501            return false;
    501502        return true;
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r278465 r278568  
    44094409            return;
    44104410        }
     4411#if !USE(BIGINT32)
     4412        // As long as a BigInt32 and a HeapBigInt can compare equal, it is not sound to replace compareStrictEq by a simple comparison of the JSValue in the following cases.
     4413        if (node->child1()->shouldSpeculateNeitherDoubleNorHeapBigIntNorString()
     4414            && node->child2()->shouldSpeculateNotDouble()) {
     4415            fixEdge<NeitherDoubleNorHeapBigIntNorStringUse>(node->child1());
     4416            fixEdge<NotDoubleUse>(node->child2());
     4417            node->setOpAndDefaultFlags(CompareStrictEq);
     4418            return;
     4419        }
     4420        if (node->child1()->shouldSpeculateNotDouble()
     4421            && node->child2()->shouldSpeculateNeitherDoubleNorHeapBigIntNorString()) {
     4422            fixEdge<NotDoubleUse>(node->child1());
     4423            fixEdge<NeitherDoubleNorHeapBigIntNorStringUse>(node->child2());
     4424            node->setOpAndDefaultFlags(CompareStrictEq);
     4425            return;
     4426        }
     4427#endif
    44114428    }
    44124429
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r278465 r278568  
    28032803        return isNotDoubleSpeculation(prediction());
    28042804    }
     2805
     2806    bool shouldSpeculateNeitherDoubleNorHeapBigIntNorString()
     2807    {
     2808        return isNeitherDoubleNorHeapBigIntNorStringSpeculation(prediction());
     2809    }
    28052810   
    28062811    bool shouldSpeculateUntypedForArithmetic()
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r278465 r278568  
    9494        case DoubleRepAnyIntUse:
    9595        case NotDoubleUse:
     96        case NeitherDoubleNorHeapBigIntNorStringUse:
    9697            return;
    9798           
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r278476 r278568  
    69346934        return false;
    69356935    }
    6936    
     6936
     6937#if !USE(BIGINT32)
     6938    if (node->isBinaryUseKind(NotDoubleUse, NeitherDoubleNorHeapBigIntNorStringUse)) {
     6939        Edge notDoubleChild = node->child1();
     6940        Edge neitherDoubleNorHeapBigIntNorStringChild = node->child2();
     6941        unsigned branchIndexInBlock = detectPeepHoleBranch();
     6942        if (branchIndexInBlock != UINT_MAX) {
     6943            Node* branchNode = m_block->at(branchIndexInBlock);
     6944            compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(node, branchNode, notDoubleChild, neitherDoubleNorHeapBigIntNorStringChild);
     6945            use(notDoubleChild);
     6946            use(neitherDoubleNorHeapBigIntNorStringChild);
     6947            m_indexInBlock = branchIndexInBlock;
     6948            m_currentNode = branchNode;
     6949            return true;
     6950        }
     6951        compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(node, notDoubleChild, neitherDoubleNorHeapBigIntNorStringChild);
     6952        return false;
     6953    }
     6954    if (node->isBinaryUseKind(NeitherDoubleNorHeapBigIntNorStringUse, NotDoubleUse)) {
     6955        Edge neitherDoubleNorHeapBigIntNorStringChild = node->child1();
     6956        Edge notDoubleChild = node->child2();
     6957        unsigned branchIndexInBlock = detectPeepHoleBranch();
     6958        if (branchIndexInBlock != UINT_MAX) {
     6959            Node* branchNode = m_block->at(branchIndexInBlock);
     6960            compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(node, branchNode, notDoubleChild, neitherDoubleNorHeapBigIntNorStringChild);
     6961            use(notDoubleChild);
     6962            use(neitherDoubleNorHeapBigIntNorStringChild);
     6963            m_indexInBlock = branchIndexInBlock;
     6964            m_currentNode = branchNode;
     6965            return true;
     6966        }
     6967        compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(node, notDoubleChild, neitherDoubleNorHeapBigIntNorStringChild);
     6968        return false;
     6969    }
     6970#endif
     6971
    69376972    if (node->isBinaryUseKind(HeapBigIntUse)) {
    69386973        compileHeapBigIntEquality(node);
     
    71627197        jump(notTaken);
    71637198    }
     7199}
     7200
     7201void SpeculativeJIT::compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(Node* node, Edge notDoubleChild, Edge neitherDoubleNorHeapBigIntNorStringChild)
     7202{
     7203    JSValueOperand left(this, notDoubleChild, ManualOperandSpeculation);
     7204    JSValueOperand right(this, neitherDoubleNorHeapBigIntNorStringChild, ManualOperandSpeculation);
     7205
     7206    GPRTemporary temp(this);
     7207#if USE(JSVALUE64)
     7208    GPRTemporary result(this, Reuse, left, right);
     7209#else
     7210    GPRTemporary result(this, Reuse, left, PayloadWord);
     7211#endif
     7212    JSValueRegs leftRegs = left.jsValueRegs();
     7213    JSValueRegs rightRegs = right.jsValueRegs();
     7214    GPRReg tempGPR = temp.gpr();
     7215    GPRReg resultGPR = result.gpr();
     7216
     7217    speculateNotDouble(notDoubleChild, leftRegs, tempGPR);
     7218    speculateNeitherDoubleNorHeapBigIntNorString(neitherDoubleNorHeapBigIntNorStringChild, rightRegs, tempGPR);
     7219
     7220#if USE(JSVALUE64)
     7221    m_jit.compare64(JITCompiler::Equal, left.gpr(), right.gpr(), result.gpr());
     7222#else
     7223    m_jit.move(TrustedImm32(0), result.gpr());
     7224    JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, left.tagGPR(), right.tagGPR());
     7225    m_jit.compare32(JITCompiler::Equal, left.payloadGPR(), right.payloadGPR(), result.gpr());
     7226    notEqual.link(&m_jit);
     7227#endif
     7228    unblessedBooleanResult(resultGPR, node);
     7229}
     7230
     7231void SpeculativeJIT::compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(Node*, Node* branchNode, Edge notDoubleChild, Edge neitherDoubleNorHeapBigIntNorStringChild)
     7232{
     7233    JSValueOperand left(this, notDoubleChild, ManualOperandSpeculation);
     7234    JSValueOperand right(this, neitherDoubleNorHeapBigIntNorStringChild, ManualOperandSpeculation);
     7235
     7236    GPRTemporary temp(this);
     7237    JSValueRegs leftRegs = left.jsValueRegs();
     7238    JSValueRegs rightRegs = right.jsValueRegs();
     7239    GPRReg tempGPR = temp.gpr();
     7240
     7241    speculateNotDouble(notDoubleChild, leftRegs, tempGPR);
     7242    speculateNeitherDoubleNorHeapBigIntNorString(neitherDoubleNorHeapBigIntNorStringChild, rightRegs, tempGPR);
     7243
     7244    BasicBlock* taken = branchNode->branchData()->taken.block;
     7245    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
     7246
     7247#if USE(JSVALUE64)
     7248    if (taken == nextBlock()) {
     7249        branch64(JITCompiler::NotEqual, left.gpr(), right.gpr(), notTaken);
     7250        jump(taken);
     7251    } else {
     7252        branch64(JITCompiler::Equal, left.gpr(), right.gpr(), taken);
     7253        jump(notTaken);
     7254    }
     7255#else
     7256    branch32(JITCompiler::NotEqual, left.tagGPR(), right.tagGPR(), notTaken);
     7257    if (taken == nextBlock()) {
     7258        branch32(JITCompiler::NotEqual, left.payloadGPR(), right.payloadGPR(), notTaken);
     7259        jump(taken);
     7260    } else {
     7261        branch32(JITCompiler::Equal, left.payloadGPR(), right.payloadGPR(), taken);
     7262        jump(notTaken);
     7263    }
     7264#endif
    71647265}
    71657266
     
    1143311534}
    1143411535
     11536void SpeculativeJIT::speculateNotDouble(Edge edge, JSValueRegs regs, GPRReg tempGPR)
     11537{
     11538    if (!needsTypeCheck(edge, ~SpecFullDouble))
     11539        return;
     11540
     11541    JITCompiler::Jump done;
     11542
     11543    bool mayBeInt32 = needsTypeCheck(edge, ~SpecInt32Only);
     11544    if (mayBeInt32)
     11545        done = m_jit.branchIfInt32(regs);
     11546
     11547    DFG_TYPE_CHECK(regs, edge, ~SpecFullDouble, m_jit.branchIfNumber(regs, tempGPR));
     11548
     11549    if (mayBeInt32)
     11550        done.link(&m_jit);
     11551}
     11552
    1143511553void SpeculativeJIT::speculateNotDouble(Edge edge)
    1143611554{
     
    1144311561    GPRReg tempGPR = temp.gpr();
    1144411562   
    11445     JITCompiler::Jump done = m_jit.branchIfInt32(regs);
     11563    speculateNotDouble(edge, regs, tempGPR);
     11564}
     11565
     11566void SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString(Edge edge, JSValueRegs regs, GPRReg tempGPR)
     11567{
     11568    if (!needsTypeCheck(edge, ~(SpecFullDouble | SpecString)))
     11569        return;
     11570
     11571    MacroAssembler::JumpList done;
     11572
     11573    bool mayBeInt32 = needsTypeCheck(edge, ~SpecInt32Only);
     11574    if (mayBeInt32)
     11575        done.append(m_jit.branchIfInt32(regs));
     11576
    1144611577    DFG_TYPE_CHECK(regs, edge, ~SpecFullDouble, m_jit.branchIfNumber(regs, tempGPR));
    11447     done.link(&m_jit);
     11578
     11579    bool mayNotBeCell = needsTypeCheck(edge, SpecCell);
     11580    if (mayNotBeCell)
     11581        done.append(m_jit.branchIfNotCell(regs));
     11582
     11583    DFG_TYPE_CHECK(regs, edge, ~SpecString, m_jit.branchIfString(regs.payloadGPR()));
     11584    DFG_TYPE_CHECK(regs, edge, ~SpecHeapBigInt, m_jit.branchIfHeapBigInt(regs.payloadGPR()));
     11585
     11586    if (mayBeInt32 || mayNotBeCell)
     11587        done.link(&m_jit);
     11588}
     11589
     11590void SpeculativeJIT::speculateNeitherDoubleNorHeapBigIntNorString(Edge edge)
     11591{
     11592    if (!needsTypeCheck(edge, ~(SpecFullDouble | SpecString)))
     11593        return;
     11594
     11595    JSValueOperand operand(this, edge, ManualOperandSpeculation);
     11596    GPRTemporary temp(this);
     11597    JSValueRegs regs = operand.jsValueRegs();
     11598    GPRReg tempGPR = temp.gpr();
     11599
     11600    speculateNeitherDoubleNorHeapBigIntNorString(edge, regs, tempGPR);
    1144811601}
    1144911602
     
    1163211785    case NotDoubleUse:
    1163311786        speculateNotDouble(edge);
     11787        break;
     11788    case NeitherDoubleNorHeapBigIntNorStringUse:
     11789        speculateNeitherDoubleNorHeapBigIntNorString(edge);
    1163411790        break;
    1163511791    case OtherUse:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r278465 r278568  
    11901190    void compileHeapBigIntEquality(Node*);
    11911191    void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
     1192    void compileNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(Node*, Edge notDoubleEdge, Edge neitherDoubleNorHeapBigIntNorStringEdge);
     1193    void compilePeepHoleNotDoubleNeitherDoubleNorHeapBigIntNorStringStrictEquality(Node*, Node* branchNode, Edge notDoubleEdge, Edge neitherDoubleNorHeapBigIntNorStringEdge);
    11921194    void compileSymbolUntypedEquality(Node*, Edge symbolEdge, Edge untypedEdge);
    11931195
     
    16721674    void speculateNotCell(Edge);
    16731675    void speculateNotCellNorBigInt(Edge);
     1676    void speculateNotDouble(Edge, JSValueRegs, GPRReg temp);
    16741677    void speculateNotDouble(Edge);
     1678    void speculateNeitherDoubleNorHeapBigIntNorString(Edge, JSValueRegs, GPRReg temp);
     1679    void speculateNeitherDoubleNorHeapBigIntNorString(Edge);
    16751680    void speculateOther(Edge, JSValueRegs, GPRReg temp);
    16761681    void speculateOther(Edge, JSValueRegs);
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp

    r278465 r278568  
    174174        out.print("NotDouble");
    175175        return;
     176    case NeitherDoubleNorHeapBigIntNorStringUse:
     177        out.print("NeitherDoubleNorHeapBigIntNorString");
     178        return;
    176179    case KnownOtherUse:
    177180        out.print("KnownOther");
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r278465 r278568  
    8383    NotCellNorBigIntUse,
    8484    NotDoubleUse,
     85    NeitherDoubleNorHeapBigIntNorStringUse,
    8586    KnownOtherUse,
    8687    OtherUse,
     
    191192    case NotDoubleUse:
    192193        return ~SpecFullDouble;
     194    case NeitherDoubleNorHeapBigIntNorStringUse:
     195        return ~SpecFullDouble & ~SpecHeapBigInt & ~SpecString;
    193196    case KnownOtherUse:
    194197    case OtherUse:
     
    310313    case NotCellNorBigIntUse:
    311314    case NotDoubleUse:
     315    case NeitherDoubleNorHeapBigIntNorStringUse:
    312316        return false;
    313317    default:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r278465 r278568  
    530530                case DoubleRepAnyIntUse:
    531531                case NotDoubleUse:
     532                case NeitherDoubleNorHeapBigIntNorStringUse:
    532533                    // These are OK.
    533534                    break;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r278476 r278568  
    95039503       
    95049504        if (m_node->isBinaryUseKind(MiscUse, UntypedUse)
    9505             || m_node->isBinaryUseKind(UntypedUse, MiscUse)) {
     9505            || m_node->isBinaryUseKind(UntypedUse, MiscUse)
     9506#if !USE(BIGINT32)
     9507            || m_node->isBinaryUseKind(NotDoubleUse, NeitherDoubleNorHeapBigIntNorStringUse)
     9508            || m_node->isBinaryUseKind(NeitherDoubleNorHeapBigIntNorStringUse, NotDoubleUse)) {
     9509#else
     9510            ) {
     9511#endif
    95069512            speculate(m_node->child1());
    95079513            speculate(m_node->child2());
     
    1840718413            speculateNotDouble(edge);
    1840818414            break;
     18415        case NeitherDoubleNorHeapBigIntNorStringUse:
     18416            speculateNeitherDoubleNorHeapBigIntNorString(edge);
     18417            break;
    1840918418        case OtherUse:
    1841018419            speculateOther(edge);
     
    1846618475        LBasicBlock lastNext = m_out.appendTo(isNotInt32, continuation);
    1846718476        FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecFullDouble, isNumber(value));
     18477        m_out.jump(continuation);
     18478
     18479        m_out.appendTo(continuation, lastNext);
     18480    }
     18481
     18482    void speculateNeitherDoubleNorHeapBigIntNorString(Edge edge)
     18483    {
     18484        if (!m_interpreter.needsTypeCheck(edge))
     18485            return;
     18486
     18487        LValue value = lowJSValue(edge, ManualOperandSpeculation);
     18488
     18489        LBasicBlock isNotInt32 = m_out.newBlock();
     18490        LBasicBlock isCellBlock = m_out.newBlock();
     18491        LBasicBlock continuation = m_out.newBlock();
     18492
     18493        m_out.branch(isInt32(value, provenType(edge)), unsure(continuation), unsure(isNotInt32));
     18494
     18495        LBasicBlock lastNext = m_out.appendTo(isNotInt32, isCellBlock);
     18496        FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecFullDouble, isNumber(value));
     18497        m_out.branch(isCell(value, provenType(edge)), unsure(isCellBlock), unsure(continuation));
     18498
     18499        m_out.appendTo(isCellBlock, continuation);
     18500        FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecString, isString(value));
     18501        FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecHeapBigInt, isHeapBigInt(value));
    1846818502        m_out.jump(continuation);
    1846918503
Note: See TracChangeset for help on using the changeset viewer.