Changeset 165085 in webkit for trunk/Source/JavaScriptCore/dfg


Ignore:
Timestamp:
Mar 4, 2014, 5:03:55 PM (11 years ago)
Author:
[email protected]
Message:

DFG and FTL should specialize for and support CompareStrictEq over Misc (i.e. boolean, undefined, or null)
https://bugs.webkit.org/show_bug.cgi?id=129563

Source/JavaScriptCore:

Reviewed by Geoffrey Garen.

This adds a specialization of CompareStrictEq over Misc. I noticed the need for this
when I saw that we didn't support CompareStrictEq(Untyped) in FTL but that the main
user of this was EarleyBoyer, and in that benchmark what it was really doing was
comparing undefined, null, and booleans to each other.

This also adds support for miscellaneous things that I needed to make my various test
cases work. This includes comparison over booleans and the various Throw-related node
types.

This also improves constant folding of CompareStrictEq and CompareEq.

Also found a bug where we were claiming that GetByVals on typed arrays are OutOfBounds
based on profiling, which caused some downstream badness. We don't actually support
compiling OutOfBounds GetByVals on typed arrays. The DFG would ignore the flag and just
emit a bounds check, but in the FTL path, the SSA lowering phase would assume that it
shouldn't factor out the bounds check since the access is not InBounds but then the
backend would ignore the flag and assume that the bounds check was already emitted.
This showed up on an existing test but I added a test for this explicitly to have more
certain coverage. The fix is to not mark something as OutOfBounds if the semantics are
that we'll have a bounds check anyway.

This is a 1% speed-up on Octane mostly because of raytrace, but also because of just
general progressions across the board. No speed-up yet on EarleyBoyer, since there is
still a lot more coverage work to be done there.

  • bytecode/SpeculatedType.cpp:

(JSC::speculationToAbbreviatedString):
(JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
(JSC::valuesCouldBeEqual):

  • bytecode/SpeculatedType.h:

(JSC::isMiscSpeculation):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGNode.h:

(JSC::DFG::Node::shouldSpeculateMisc):

  • dfg/DFGSafeToExecute.h:

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

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::speculateMisc):
(JSC::DFG::SpeculativeJIT::speculate):

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

(JSC::DFG::SpeculativeJIT::compileMiscStrictEq):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileMiscStrictEq):

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileCompareEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
(JSC::FTL::LowerDFGToLLVM::compileThrow):
(JSC::FTL::LowerDFGToLLVM::isNotMisc):
(JSC::FTL::LowerDFGToLLVM::isMisc):
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateMisc):

  • tests/stress/float32-array-out-of-bounds.js: Added.
  • tests/stress/weird-equality-folding-cases.js: Added.

LayoutTests:

Reviewed by Geoffrey Garen.

  • js/regress/fold-strict-eq-expected.txt: Added.
  • js/regress/fold-strict-eq.html: Added.
  • js/regress/misc-strict-eq-expected.txt: Added.
  • js/regress/misc-strict-eq.html: Added.
  • js/regress/script-tests/fold-strict-eq.js: Added.

(foo):
(test):

  • js/regress/script-tests/misc-strict-eq.js: Added.
Location:
trunk/Source/JavaScriptCore/dfg
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r164620 r165085  
    918918            SpeculatedType leftType = forNode(node->child1()).m_type;
    919919            SpeculatedType rightType = forNode(node->child2()).m_type;
    920             if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
    921                 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType))) {
     920            if (!valuesCouldBeEqual(leftType, rightType)) {
    922921                setConstant(node, jsBoolean(false));
    923922                break;
     
    944943        JSValue right = forNode(rightNode).value();
    945944        if (left && right) {
    946             if (left.isNumber() && right.isNumber()) {
    947                 setConstant(node, jsBoolean(left.asNumber() == right.asNumber()));
    948                 break;
    949             }
    950945            if (left.isString() && right.isString()) {
     946                // We need this case because JSValue::strictEqual is otherwise too racy for
     947                // string comparisons.
    951948                const StringImpl* a = asString(left)->tryGetValueImpl();
    952949                const StringImpl* b = asString(right)->tryGetValueImpl();
     
    955952                    break;
    956953                }
    957             }
    958         }
     954            } else {
     955                setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
     956                break;
     957            }
     958        }
     959       
     960        SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
     961        SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
     962        if (!(leftLUB & rightLUB)) {
     963            setConstant(node, jsBoolean(false));
     964            break;
     965        }
     966       
    959967        forNode(node).setType(SpecBoolean);
    960968        node->setCanExit(true); // This is overly conservative.
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r164229 r165085  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    133133
    134134ArrayMode ArrayMode::refine(
    135     Graph& graph, CodeOrigin codeOrigin,
     135    Graph& graph, Node* node,
    136136    SpeculatedType base, SpeculatedType index, SpeculatedType value,
    137137    NodeFlags flags) const
     
    200200       
    201201        ArrayMode result;
    202         if (graph.hasExitSite(codeOrigin, OutOfBounds) || !isInBounds())
    203             result = withSpeculation(Array::OutOfBounds);
    204         else
     202        switch (node->op()) {
     203        case PutByVal:
     204            if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
     205                result = withSpeculation(Array::OutOfBounds);
     206            else
     207                result = withSpeculation(Array::InBounds);
     208            break;
     209           
     210        default:
    205211            result = withSpeculation(Array::InBounds);
     212            break;
     213        }
    206214       
    207215        if (isInt8ArraySpeculation(base))
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h

    r164424 r165085  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    221221    }
    222222   
    223     ArrayMode refine(Graph&, CodeOrigin, SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone, NodeFlags = 0) const;
     223    ArrayMode refine(Graph&, Node*, SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone, NodeFlags = 0) const;
    224224   
    225225    bool alreadyChecked(Graph&, Node*, AbstractValue&) const;
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r164651 r165085  
    433433                break;
    434434            }
     435            if (node->child1()->shouldSpeculateMisc() && node->child2()->shouldSpeculateMisc()) {
     436                fixEdge<MiscUse>(node->child1());
     437                fixEdge<MiscUse>(node->child2());
     438                break;
     439            }
    435440            break;
    436441        }
     
    453458            node->setArrayMode(
    454459                node->arrayMode().refine(
    455                     m_graph, node->origin.semantic,
     460                    m_graph, node,
    456461                    node->child1()->prediction(),
    457462                    node->child2()->prediction(),
     
    511516            node->setArrayMode(
    512517                node->arrayMode().refine(
    513                     m_graph, node->origin.semantic,
     518                    m_graph, node,
    514519                    child1->prediction(),
    515520                    child2->prediction(),
     
    597602            node->setArrayMode(
    598603                node->arrayMode().refine(
    599                     m_graph, node->origin.semantic,
     604                    m_graph, node,
    600605                    node->child1()->prediction() & SpecCell,
    601606                    SpecInt32,
     
    17511756           
    17521757        arrayMode = arrayMode.refine(
    1753             m_graph, node->origin.semantic, node->child1()->prediction(), node->prediction());
     1758            m_graph, node, node->child1()->prediction(), node->prediction());
    17541759           
    17551760        if (arrayMode.type() == Array::Generic) {
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r164651 r165085  
    14001400        return isBooleanSpeculation(prediction());
    14011401    }
     1402   
     1403    bool shouldSpeculateMisc()
     1404    {
     1405        return isMiscSpeculation(prediction());
     1406    }
    14021407   
    14031408    bool shouldSpeculateStringIdent()
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r164620 r165085  
    6060        case NotCellUse:
    6161        case OtherUse:
     62        case MiscUse:
    6263        case MachineIntUse:
    6364            return;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r164764 r165085  
    38033803    }
    38043804       
     3805    case MiscUse: {
     3806        compileMiscStrictEq(node);
     3807        return false;
     3808    }
     3809       
    38053810    case UntypedUse: {
    38063811        return nonSpeculativeStrictEq(node);
     
    48314836}
    48324837
     4838void SpeculativeJIT::speculateMisc(Edge edge, JSValueRegs regs)
     4839{
     4840#if USE(JSVALUE64)
     4841    typeCheck(
     4842        regs, edge, SpecMisc,
     4843        m_jit.branch64(MacroAssembler::Above, regs.gpr(), MacroAssembler::TrustedImm64(TagBitTypeOther | TagBitBool | TagBitUndefined)));
     4844#else
     4845    typeCheck(
     4846        regs, edge, SpecMisc | SpecInt32,
     4847        m_jit.branch32(MacroAssembler::Equal, regs.tagGPR(), MacroAssembler::TrustedImm32(JSValue::Int32Tag)));
     4848    typeCheck(
     4849        regs, edge, SpecMisc,
     4850        m_jit.branch32(MacroAssembler::Below, regs.tagGPR(), MacroAssembler::TrustedImm32(JSValue::UndefinedTag)));
     4851#endif
     4852}
     4853
     4854void SpeculativeJIT::speculateMisc(Edge edge)
     4855{
     4856    if (!needsTypeCheck(edge, SpecMisc))
     4857        return;
     4858   
     4859    JSValueOperand operand(this, edge, ManualOperandSpeculation);
     4860    speculateMisc(edge, operand.jsValueRegs());
     4861}
     4862
    48334863void SpeculativeJIT::speculate(Node*, Edge edge)
    48344864{
     
    48924922    case OtherUse:
    48934923        speculateOther(edge);
     4924        break;
     4925    case MiscUse:
     4926        speculateMisc(edge);
    48944927        break;
    48954928    default:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r164813 r165085  
    19861986    void compileStringIdentEquality(Node*);
    19871987    void compileStringZeroLength(Node*);
     1988    void compileMiscStrictEq(Node*);
    19881989
    19891990    void emitObjectOrOtherBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
     
    22042205    void speculateNotCell(Edge);
    22052206    void speculateOther(Edge);
     2207    void speculateMisc(Edge, JSValueRegs);
     2208    void speculateMisc(Edge);
    22062209    void speculate(Node*, Edge);
    22072210   
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r164766 r165085  
    612612
    613613    booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
     614}
     615
     616void SpeculativeJIT::compileMiscStrictEq(Node* node)
     617{
     618    JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
     619    JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
     620    GPRTemporary result(this);
     621   
     622    speculateMisc(node->child1(), op1.jsValueRegs());
     623    speculateMisc(node->child2(), op2.jsValueRegs());
     624   
     625    m_jit.move(TrustedImm32(0), result.gpr());
     626    JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR());
     627    m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr());
     628    notEqual.link(&m_jit);
     629    booleanResult(result.gpr(), node);
    614630}
    615631
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r164764 r165085  
    647647   
    648648    jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
     649}
     650
     651void SpeculativeJIT::compileMiscStrictEq(Node* node)
     652{
     653    JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
     654    JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
     655    GPRTemporary result(this);
     656   
     657    speculateMisc(node->child1(), op1.jsValueRegs());
     658    speculateMisc(node->child2(), op2.jsValueRegs());
     659   
     660    m_jit.compare32(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
     661    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
     662    jsValueResult(result.gpr(), node, DataFormatJSBoolean);
    649663}
    650664
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp

    r164229 r165085  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    9898        out.print("Other");
    9999        break;
     100    case MiscUse:
     101        out.print("Misc");
     102        break;
    100103    default:
    101104        RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r164424 r165085  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5555    NotCellUse,
    5656    OtherUse,
     57    MiscUse,
    5758    LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.
    5859};
     
    9798    case OtherUse:
    9899        return SpecOther;
     100    case MiscUse:
     101        return SpecMisc;
    99102    default:
    100103        RELEASE_ASSERT_NOT_REACHED();
Note: See TracChangeset for help on using the changeset viewer.