Changeset 95563 in webkit


Ignore:
Timestamp:
Sep 20, 2011 1:10:56 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT performs too many negative zero checks, and too many
overflow checks
https://bugs.webkit.org/show_bug.cgi?id=68430

Reviewed by Oliver Hunt.

This adds comprehensive support for deciding how to perform an
arithmetic operations based on a combination of overflow profiling,
negative zero profiling, value profiling, and a static analysis of
how the results of these operations get used.

This is a 72% speed-up on stanford-crypto-sha256-iterative, and a
2.5% speed-up on the Kraken average, a 1.4% speed-up on the V8
geomean, and neutral on SunSpider. It's also an 8.5% speed-up on
V8-crypto, because apparenty everything we do speeds up crypto.

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::toInt32):
(JSC::DFG::ByteCodeParser::toNumber):
(JSC::DFG::ByteCodeParser::isSmallInt32Constant):
(JSC::DFG::ByteCodeParser::valueOfInt32Constant):
(JSC::DFG::ByteCodeParser::weaklyPredictInt32):
(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::handleMinMax):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::processPhiStack):
(JSC::DFG::ByteCodeParser::parse):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):

  • dfg/DFGNode.h:

(JSC::DFG::nodeUsedAsNumber):
(JSC::DFG::nodeCanTruncateInteger):
(JSC::DFG::nodeCanIgnoreNegativeZero):
(JSC::DFG::nodeCanSpeculateInteger):
(JSC::DFG::arithNodeFlagsAsString):
(JSC::DFG::Node::Node):
(JSC::DFG::Node::hasArithNodeFlags):
(JSC::DFG::Node::rawArithNodeFlags):
(JSC::DFG::Node::arithNodeFlags):
(JSC::DFG::Node::arithNodeFlagsForCompare):
(JSC::DFG::Node::setArithNodeFlag):
(JSC::DFG::Node::mergeArithNodeFlags):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::fixpoint):
(JSC::DFG::Propagator::isNotNegZero):
(JSC::DFG::Propagator::isNotZero):
(JSC::DFG::Propagator::propagateArithNodeFlags):
(JSC::DFG::Propagator::propagateArithNodeFlagsForward):
(JSC::DFG::Propagator::propagateArithNodeFlagsBackward):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::propagatePredictionsForward):
(JSC::DFG::Propagator::propagatePredictionsBackward):
(JSC::DFG::Propagator::toDouble):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::fixup):
(JSC::DFG::Propagator::startIndexForChildren):
(JSC::DFG::Propagator::endIndexForPureCSE):
(JSC::DFG::Propagator::pureCSE):
(JSC::DFG::Propagator::clobbersWorld):
(JSC::DFG::Propagator::setReplacement):
(JSC::DFG::Propagator::performNodeCSE):
(JSC::DFG::Propagator::localCSE):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95559 r95563  
     12011-09-20  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT performs too many negative zero checks, and too many
     4        overflow checks
     5        https://bugs.webkit.org/show_bug.cgi?id=68430
     6
     7        Reviewed by Oliver Hunt.
     8       
     9        This adds comprehensive support for deciding how to perform an
     10        arithmetic operations based on a combination of overflow profiling,
     11        negative zero profiling, value profiling, and a static analysis of
     12        how the results of these operations get used.
     13       
     14        This is a 72% speed-up on stanford-crypto-sha256-iterative, and a
     15        2.5% speed-up on the Kraken average, a 1.4% speed-up on the V8
     16        geomean, and neutral on SunSpider. It's also an 8.5% speed-up on
     17        V8-crypto, because apparenty everything we do speeds up crypto.
     18
     19        * dfg/DFGByteCodeParser.cpp:
     20        (JSC::DFG::ByteCodeParser::toInt32):
     21        (JSC::DFG::ByteCodeParser::toNumber):
     22        (JSC::DFG::ByteCodeParser::isSmallInt32Constant):
     23        (JSC::DFG::ByteCodeParser::valueOfInt32Constant):
     24        (JSC::DFG::ByteCodeParser::weaklyPredictInt32):
     25        (JSC::DFG::ByteCodeParser::makeSafe):
     26        (JSC::DFG::ByteCodeParser::handleMinMax):
     27        (JSC::DFG::ByteCodeParser::handleIntrinsic):
     28        (JSC::DFG::ByteCodeParser::parseBlock):
     29        (JSC::DFG::ByteCodeParser::processPhiStack):
     30        (JSC::DFG::ByteCodeParser::parse):
     31        * dfg/DFGGraph.cpp:
     32        (JSC::DFG::Graph::dump):
     33        * dfg/DFGJITCodeGenerator.cpp:
     34        (JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):
     35        * dfg/DFGNode.h:
     36        (JSC::DFG::nodeUsedAsNumber):
     37        (JSC::DFG::nodeCanTruncateInteger):
     38        (JSC::DFG::nodeCanIgnoreNegativeZero):
     39        (JSC::DFG::nodeCanSpeculateInteger):
     40        (JSC::DFG::arithNodeFlagsAsString):
     41        (JSC::DFG::Node::Node):
     42        (JSC::DFG::Node::hasArithNodeFlags):
     43        (JSC::DFG::Node::rawArithNodeFlags):
     44        (JSC::DFG::Node::arithNodeFlags):
     45        (JSC::DFG::Node::arithNodeFlagsForCompare):
     46        (JSC::DFG::Node::setArithNodeFlag):
     47        (JSC::DFG::Node::mergeArithNodeFlags):
     48        * dfg/DFGPropagator.cpp:
     49        (JSC::DFG::Propagator::fixpoint):
     50        (JSC::DFG::Propagator::isNotNegZero):
     51        (JSC::DFG::Propagator::isNotZero):
     52        (JSC::DFG::Propagator::propagateArithNodeFlags):
     53        (JSC::DFG::Propagator::propagateArithNodeFlagsForward):
     54        (JSC::DFG::Propagator::propagateArithNodeFlagsBackward):
     55        (JSC::DFG::Propagator::propagateNodePredictions):
     56        (JSC::DFG::Propagator::propagatePredictionsForward):
     57        (JSC::DFG::Propagator::propagatePredictionsBackward):
     58        (JSC::DFG::Propagator::toDouble):
     59        (JSC::DFG::Propagator::fixupNode):
     60        (JSC::DFG::Propagator::fixup):
     61        (JSC::DFG::Propagator::startIndexForChildren):
     62        (JSC::DFG::Propagator::endIndexForPureCSE):
     63        (JSC::DFG::Propagator::pureCSE):
     64        (JSC::DFG::Propagator::clobbersWorld):
     65        (JSC::DFG::Propagator::setReplacement):
     66        (JSC::DFG::Propagator::performNodeCSE):
     67        (JSC::DFG::Propagator::localCSE):
     68        * dfg/DFGSpeculativeJIT.cpp:
     69        (JSC::DFG::SpeculativeJIT::compile):
     70        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
     71
    1722011-09-19  Oliver Hunt  <oliver@apple.com>
    273
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95523 r95563  
    194194            return node.child1();
    195195
    196         if (node.op == UInt32ToNumberSafe)
    197             return node.child1();
    198 
    199196        // Check for numeric constants boxed as JSValues.
    200197        if (node.op == JSConstant) {
     
    222219        }
    223220
    224         return addToGraph(ValueToNumber, index);
     221        return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index);
    225222    }
    226223
     
    265262        return intValue >= -5 && intValue <= 5;
    266263    }
    267     bool isDoubleConstant(NodeIndex nodeIndex)
    268     {
    269         return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isNumber();
    270     }
    271264    // Convenience methods for getting constant values.
    272265    JSValue valueOfJSConstant(NodeIndex index)
     
    279272        ASSERT(isInt32Constant(nodeIndex));
    280273        return valueOfJSConstant(nodeIndex).asInt32();
    281     }
    282     double valueOfDoubleConstant(NodeIndex nodeIndex)
    283     {
    284         ASSERT(isDoubleConstant(nodeIndex));
    285         double value;
    286         bool okay = valueOfJSConstant(nodeIndex).getNumber(value);
    287         ASSERT_UNUSED(okay, okay);
    288         return value;
    289274    }
    290275
     
    487472            case ArithAdd:
    488473            case ArithSub:
    489             case ArithMulIgnoreZero:
    490             case ArithMulSpecNotNegZero:
    491             case ArithMulPossiblyNegZero:
    492             case ArithMulSafe:
     474            case ArithMul:
    493475            case ValueAdd:
    494476                m_reusableNodeStack.append(&m_graph[nodePtr->child1()]);
     
    526508    }
    527509   
    528     NodeType makeSafe(NodeType op)
     510    NodeIndex makeSafe(NodeIndex nodeIndex)
    529511    {
    530512        if (!m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
    531             return op;
     513            return nodeIndex;
    532514       
    533515#if ENABLE(DFG_DEBUG_VERBOSE)
    534         printf("Making %s @%lu safe at bc#%u because slow-case counter is at %u\n", Graph::opName(op), m_graph.size(), m_currentIndex, m_profiledBlock->slowCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
     516        printf("Making %s @%u safe at bc#%u because slow-case counter is at %u\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_profiledBlock->slowCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
    535517#endif
    536518       
    537         switch (op) {
     519        switch (m_graph[nodeIndex].op) {
    538520        case UInt32ToNumber:
    539             return UInt32ToNumberSafe;
    540521        case ArithAdd:
    541             return ArithAddSafe;
    542522        case ArithSub:
    543             return ArithSubSafe;
    544            
    545             // We initialize ArithMul to ArithMulIgnoreZero and push it towards
    546             // safer variants as we learn more, unless we already know that it
    547             // can overflow. If it doesn't overflow, we first turn it into
    548             // PossiblyNegZero if we see that it had been -0 during old JIT
    549             // execution.
    550         case ArithMulIgnoreZero:
     523        case ValueAdd:
     524            m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow);
     525            break;
     526           
     527        case ArithMul:
    551528            if (m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex))
    552                 return ArithMulSafe;
     529                m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
    553530            else
    554                 return ArithMulPossiblyNegZero;
    555            
    556         case ValueAdd:
    557             return ValueAddSafe;
     531                m_graph[nodeIndex].mergeArithNodeFlags(NodeMayNegZero);
     532            break;
     533           
    558534        default:
    559535            ASSERT_NOT_REACHED();
    560             return Phantom; // Have to return something.
    561         }
     536            break;
     537        }
     538       
     539        return nodeIndex;
    562540    }
    563541   
    564     NodeIndex getTrueResult(NodeIndex nodeIndex)
    565     {
    566         switch (m_graph[nodeIndex].op) {
    567         case ArithMulIgnoreZero:
    568             m_graph[nodeIndex].op = ArithMulSpecNotNegZero;
    569             break;
    570         case ArithMulPossiblyNegZero:
    571             m_graph[nodeIndex].op = ArithMulSafe;
    572             break;
    573         default:
    574             break;
    575         }
    576         return nodeIndex;
    577     }
    578    
    579     bool isMultiply(NodeIndex nodeIndex)
    580     {
    581         switch (m_graph[nodeIndex].op) {
    582         case ArithMulSpecNotNegZero:
    583         case ArithMulIgnoreZero:
    584         case ArithMulPossiblyNegZero:
    585         case ArithMulSafe:
    586             return true;
    587         default:
    588             return false;
    589         }
    590     }
    591 
    592542    JSGlobalData* m_globalData;
    593543    CodeBlock* m_codeBlock;
     
    690640   
    691641    if (lastArg == firstArg + 2) {
    692         set(resultOperand, addToGraph(op, getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
     642        set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
    693643        return true;
    694644    }
     
    714664            set(resultOperand, constantNaN());
    715665        else
    716             set(resultOperand, addToGraph(ArithAbs, getToNumber(absArg)));
     666            set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(absArg)));
    717667        return true;
    718668    }
     
    858808                    result = addToGraph(BitURShift, op1, op2);
    859809                else
    860                     result = addToGraph(makeSafe(UInt32ToNumber), op1);
     810                    result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), op1));
    861811            }  else {
    862812                // Cannot optimize at this stage; shift & potentially rebox as a double.
    863813                result = addToGraph(BitURShift, op1, op2);
    864                 result = addToGraph(makeSafe(UInt32ToNumber), result);
     814                result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result));
    865815            }
    866816            set(currentInstruction[1].u.operand, result, PredictInt32);
     
    874824            NodeIndex op = getToNumber(srcDst);
    875825            weaklyPredictInt32(op);
    876             set(srcDst, addToGraph(makeSafe(ArithAdd), op, one()));
     826            set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
    877827            NEXT_OPCODE(op_pre_inc);
    878828        }
     
    884834            weaklyPredictInt32(op);
    885835            set(result, op);
    886             set(srcDst, addToGraph(makeSafe(ArithAdd), op, one()));
     836            set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
    887837            NEXT_OPCODE(op_post_inc);
    888838        }
     
    892842            NodeIndex op = getToNumber(srcDst);
    893843            weaklyPredictInt32(op);
    894             set(srcDst, addToGraph(makeSafe(ArithSub), op, one()));
     844            set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
    895845            NEXT_OPCODE(op_pre_dec);
    896846        }
     
    902852            weaklyPredictInt32(op);
    903853            set(result, op);
    904             set(srcDst, addToGraph(makeSafe(ArithSub), op, one()));
     854            set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
    905855            NEXT_OPCODE(op_post_dec);
    906856        }
     
    918868            }
    919869           
    920             // If both inputs are multiplies, then we need to make sure to play
    921             // it safe with -0.
    922             if (isMultiply(op1) && isMultiply(op2)) {
    923                 getTrueResult(op1);
    924                 getTrueResult(op2);
    925             }
    926            
    927870            if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
    928                 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithAdd), toNumber(op1), toNumber(op2)));
     871                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2))));
    929872            else
    930                 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ValueAdd), op1, op2));
     873                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2)));
    931874            NEXT_OPCODE(op_add);
    932875        }
     
    940883            }
    941884           
    942             // For the left child we need to be careful about negative zero,
    943             // since -0 - 0 is -0.  If the right child is -0 then it doesn't
    944             // matter, since 0 - -0 is 0 and 0 - 0 is 0.
    945             getTrueResult(op1);
    946            
    947             set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithSub), op1, op2));
     885            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2)));
    948886            NEXT_OPCODE(op_sub);
    949887        }
    950888
    951889        case op_mul: {
    952             // We could be fancy here and skip the getTrueResult, instead making
    953             // getTrueResult operate transitively. But we do this the simple way, for
    954             // now.
    955             NodeIndex op1 = getTrueResult(getToNumber(currentInstruction[2].u.operand));
    956             NodeIndex op2 = getTrueResult(getToNumber(currentInstruction[3].u.operand));
    957             set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithMulIgnoreZero), op1, op2));
     890            // Multiply requires that the inputs are not truncated, unfortunately.
     891            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
     892            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
     893            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2)));
    958894            NEXT_OPCODE(op_mul);
    959895        }
     
    10901026            NodeIndex base = get(currentInstruction[1].u.operand);
    10911027            NodeIndex property = get(currentInstruction[2].u.operand);
    1092             NodeIndex value = getTrueResult(get(currentInstruction[3].u.operand));
     1028            NodeIndex value = get(currentInstruction[3].u.operand);
    10931029            weaklyPredictArray(base);
    10941030            weaklyPredictInt32(property);
     
    11671103
    11681104        case op_put_by_id: {
    1169             NodeIndex value = getTrueResult(get(currentInstruction[3].u.operand));
     1105            NodeIndex value = get(currentInstruction[3].u.operand);
    11701106            NodeIndex base = get(currentInstruction[1].u.operand);
    11711107            unsigned identifier = currentInstruction[2].u.operand;
     
    11881124
    11891125        case op_put_global_var: {
    1190             NodeIndex value = getTrueResult(get(currentInstruction[2].u.operand));
     1126            NodeIndex value = get(currentInstruction[2].u.operand);
    11911127            addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
    11921128            NEXT_OPCODE(op_put_global_var);
     
    14701406
    14711407            Node* phiNode = &m_graph[entry.m_phi];
    1472             if (phiNode->refCount()) {
    1473                 if (m_graph[valueInPredecessor].op == SetLocal) {
    1474                     // Any live SetLocal should ensure that it gets the true value.
    1475                     // Currently this means that ArithMuls distinguish between
    1476                     // negative zero and positive zero.
    1477                     getTrueResult(m_graph[valueInPredecessor].child1());
    1478                 }
     1408            if (phiNode->refCount())
    14791409                m_graph.ref(valueInPredecessor);
    1480             }
    14811410
    14821411            if (phiNode->child1() == NoNode) {
     
    15631492    m_graph.m_parameterSlots = m_parameterSlots;
    15641493
    1565 #if ENABLE(DFG_DEBUG_VERBOSE)
    1566     m_graph.dump(m_codeBlock);
    1567 #endif
    1568 
    15691494    return true;
    15701495}
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r95389 r95563  
    102102    }
    103103
     104    if (node.hasArithNodeFlags()) {
     105        printf("%s%s", hasPrinted ? ", " : "", arithNodeFlagsAsString(node.rawArithNodeFlags()));
     106        hasPrinted = true;
     107    }
    104108    if (node.hasVarNumber()) {
    105109        printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r95523 r95563  
    762762    }
    763763       
    764     case ArithMulIgnoreZero:
    765     case ArithMulPossiblyNegZero:
    766     case ArithMulSpecNotNegZero:
    767     case ArithMulSafe: {
     764    case ArithMul: {
    768765        overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
    769766        overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
     
    856853        break;
    857854           
    858     case ArithMulIgnoreZero:
    859     case ArithMulPossiblyNegZero:
    860     case ArithMulSpecNotNegZero:
    861     case ArithMulSafe:
     855    case ArithMul:
    862856        m_jit.mulDouble(tmp2FPR, tmp1FPR);
    863857        break;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95523 r95563  
    2727#define DFGNode_h
    2828
     29#include <wtf/BoundsCheckedPointer.h>
    2930#include <wtf/Platform.h>
    3031
    3132// Emit various logging information for debugging, including dumping the dataflow graphs.
    3233#define ENABLE_DFG_DEBUG_VERBOSE 0
     34// Emit dumps during propagation, in addition to just after.
     35#define ENABLE_DFG_DEBUG_PROPAGATION_VERBOSE 0
    3336// Emit logging for OSR exit value recoveries at every node, not just nodes that
    3437// actually has speculation checks.
     
    106109};
    107110
     111typedef unsigned ArithNodeFlags;
     112#define NodeUseBottom      0x00
     113#define NodeUsedAsNumber   0x01
     114#define NodeNeedsNegZero   0x02
     115#define NodeUsedAsMask     0x03
     116#define NodeMayOverflow    0x04
     117#define NodeMayNegZero     0x08
     118#define NodeBehaviorMask   0x0c
     119
     120static inline bool nodeUsedAsNumber(ArithNodeFlags flags)
     121{
     122    return !!(flags & NodeUsedAsNumber);
     123}
     124
     125static inline bool nodeCanTruncateInteger(ArithNodeFlags flags)
     126{
     127    return !nodeUsedAsNumber(flags);
     128}
     129
     130static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags)
     131{
     132    return !(flags & NodeNeedsNegZero);
     133}
     134
     135static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags)
     136{
     137    if (flags & NodeMayOverflow)
     138        return !nodeUsedAsNumber(flags);
     139   
     140    if (flags & NodeMayNegZero)
     141        return nodeCanIgnoreNegativeZero(flags);
     142   
     143    return true;
     144}
     145
     146#ifndef NDEBUG
     147static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
     148{
     149    if (!flags)
     150        return "<empty>";
     151
     152    static const int size = 64;
     153    static char description[size];
     154    BoundsCheckedPointer<char> ptr(description, size);
     155   
     156    bool hasPrinted = false;
     157   
     158    if (flags & NodeUsedAsNumber) {
     159        ptr.strcat("UsedAsNum");
     160        hasPrinted = true;
     161    }
     162   
     163    if (flags & NodeNeedsNegZero) {
     164        if (hasPrinted)
     165            ptr.strcat("|");
     166        ptr.strcat("NeedsNegZero");
     167        hasPrinted = true;
     168    }
     169   
     170    if (flags & NodeMayOverflow) {
     171        if (hasPrinted)
     172            ptr.strcat("|");
     173        ptr.strcat("MayOverflow");
     174        hasPrinted = true;
     175    }
     176   
     177    if (flags & NodeMayNegZero) {
     178        if (hasPrinted)
     179            ptr.strcat("|");
     180        ptr.strcat("MayNegZero");
     181        hasPrinted = true;
     182    }
     183   
     184    *ptr++ = 0;
     185   
     186    return description;
     187}
     188#endif
     189
    108190// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
    109191// and some additional informative flags (must generate, is constant, etc).
     
    149231    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
    150232    macro(UInt32ToNumber, NodeResultNumber) \
    151     macro(UInt32ToNumberSafe, NodeResultNumber) \
    152233    \
    153234    /* Nodes for arithmetic operations. */\
    154235    macro(ArithAdd, NodeResultNumber) \
    155236    macro(ArithSub, NodeResultNumber) \
    156     macro(ArithAddSafe, NodeResultNumber) /* Safe variants are those that are known to take old JIT slow path */\
    157     macro(ArithSubSafe, NodeResultNumber) \
    158     macro(ArithMulSpecNotNegZero, NodeResultNumber) /* Speculate that the result is not negative zero. */ \
    159     macro(ArithMulIgnoreZero, NodeResultNumber) /* If it's negative zero, ignore it. */ \
    160     macro(ArithMulPossiblyNegZero, NodeResultNumber) /* It definitely may be negative zero but we haven't decided what to do about it yet. No code generation for this node; it either turns into ArithMulIgnoreZero or ArithMulSafe. */ \
    161     macro(ArithMulSafe, NodeResultNumber) /* It may be negative zero, or it may produce other forms of double, so speculate double. */\
     237    macro(ArithMul, NodeResultNumber) \
    162238    macro(ArithDiv, NodeResultNumber) \
    163239    macro(ArithMod, NodeResultNumber) \
     
    174250    /* Add of values may either be arithmetic, or result in string concatenation. */\
    175251    macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
    176     macro(ValueAddSafe, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
    177252    \
    178253    /* Property access. */\
     
    263338    {
    264339        ASSERT(!(op & NodeHasVarArgs));
     340        ASSERT(!hasArithNodeFlags());
    265341        children.fixed.child1 = child1;
    266342        children.fixed.child2 = child2;
     
    391467        ASSERT(hasIdentifier());
    392468        return m_opInfo;
     469    }
     470   
     471    bool hasArithNodeFlags()
     472    {
     473        switch (op) {
     474        case ValueToNumber:
     475        case ValueToDouble:
     476        case UInt32ToNumber:
     477        case ArithAdd:
     478        case ArithSub:
     479        case ArithMul:
     480        case ArithAbs:
     481        case ArithMin:
     482        case ArithMax:
     483        case ValueAdd:
     484            return true;
     485        default:
     486            return false;
     487        }
     488    }
     489   
     490    ArithNodeFlags rawArithNodeFlags()
     491    {
     492        ASSERT(hasArithNodeFlags());
     493        return m_opInfo;
     494    }
     495   
     496    // This corrects the arithmetic node flags, so that irrelevant bits are
     497    // ignored. In particular, anything other than ArithMul does not need
     498    // to know if it can speculate on negative zero.
     499    ArithNodeFlags arithNodeFlags()
     500    {
     501        ArithNodeFlags result = rawArithNodeFlags();
     502        if (op == ArithMul)
     503            return result;
     504        return result & ~NodeNeedsNegZero;
     505    }
     506   
     507    ArithNodeFlags arithNodeFlagsForCompare()
     508    {
     509        if (hasArithNodeFlags())
     510            return arithNodeFlags();
     511        return 0;
     512    }
     513   
     514    void setArithNodeFlag(ArithNodeFlags flags)
     515    {
     516        ASSERT(hasArithNodeFlags());
     517        m_opInfo = flags;
     518    }
     519   
     520    bool mergeArithNodeFlags(ArithNodeFlags flags)
     521    {
     522        if (!hasArithNodeFlags())
     523            return false;
     524        ArithNodeFlags newFlags = m_opInfo | flags;
     525        if (newFlags == m_opInfo)
     526            return false;
     527        m_opInfo = newFlags;
     528        return true;
    393529    }
    394530   
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95523 r95563  
    7676    void fixpoint()
    7777    {
    78 #if ENABLE(DFG_DEBUG_VERBOSE)
     78#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     79    m_graph.dump(m_codeBlock);
     80#endif
     81
     82#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    7983        m_count = 0;
    8084#endif
     
    8286            m_changed = false;
    8387           
     88            // Up here we start with a backward pass because we suspect that to be
     89            // more profitable.
     90            propagateArithNodeFlagsBackward();
     91            if (!m_changed)
     92                break;
     93           
     94            m_changed = false;
     95            propagateArithNodeFlagsForward();
     96        } while (m_changed);
     97       
     98#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     99        m_count = 0;
     100#endif
     101        do {
     102            m_changed = false;
     103           
    84104            // Forward propagation is near-optimal for both topologically-sorted and
    85105            // DFS-sorted code.
    86             propagateForward();
     106            propagatePredictionsForward();
    87107            if (!m_changed)
    88108                break;
     
    93113            // found a sound solution and (2) short-circuits backward flow.
    94114            m_changed = false;
    95             propagateBackward();
     115            propagatePredictionsBackward();
    96116        } while (m_changed);
    97117       
    98118        fixup();
    99119       
    100 #if ENABLE(DFG_DEBUG_VERBOSE)
     120#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    101121        printf("Graph after propagation fixup:\n");
    102122        m_graph.dump(m_codeBlock);
     
    105125        localCSE();
    106126
    107 #if ENABLE(DFG_DEBUG_VERBOSE)
     127#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    108128        printf("Graph after CSE:\n");
    109129        m_graph.dump(m_codeBlock);
     
    113133
    114134#if ENABLE(DFG_DEBUG_VERBOSE)
    115         printf("Graph after virtual register allocation:\n");
     135        printf("Graph after propagation:\n");
    116136        m_graph.dump(m_codeBlock);
    117137#endif
     
    119139   
    120140private:
     141    bool isNotNegZero(NodeIndex nodeIndex)
     142    {
     143        if (!m_graph.isNumberConstant(m_codeBlock, nodeIndex))
     144            return false;
     145        double value = m_graph.valueOfNumberConstant(m_codeBlock, nodeIndex);
     146        return !value && 1.0 / value < 0.0;
     147    }
     148   
     149    bool isNotZero(NodeIndex nodeIndex)
     150    {
     151        if (!m_graph.isNumberConstant(m_codeBlock, nodeIndex))
     152            return false;
     153        return !!m_graph.valueOfNumberConstant(m_codeBlock, nodeIndex);
     154    }
     155   
     156    void propagateArithNodeFlags(Node& node)
     157    {
     158        if (!node.shouldGenerate())
     159            return;
     160       
     161        NodeType op = node.op;
     162        ArithNodeFlags flags = 0;
     163       
     164        if (node.hasArithNodeFlags())
     165            flags = node.rawArithNodeFlags();
     166       
     167#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     168        printf("   %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags));
     169#endif
     170       
     171        flags &= NodeUsedAsMask;
     172       
     173        bool changed = false;
     174       
     175        switch (op) {
     176        case ValueToInt32:
     177        case BitAnd:
     178        case BitOr:
     179        case BitXor:
     180        case BitLShift:
     181        case BitRShift:
     182        case BitURShift: {
     183            // These operations are perfectly happy with truncated integers,
     184            // so we don't want to propagate anything.
     185            break;
     186        }
     187           
     188        case ValueToNumber:
     189        case ValueToDouble:
     190        case UInt32ToNumber: {
     191            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     192            break;
     193        }
     194           
     195        case ArithAdd:
     196        case ValueAdd: {
     197            if (isNotNegZero(node.child1()) || isNotNegZero(node.child2()))
     198                flags &= ~NodeNeedsNegZero;
     199           
     200            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     201            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
     202            break;
     203        }
     204           
     205        case ArithSub: {
     206            if (isNotZero(node.child1()) || isNotZero(node.child2()))
     207                flags &= ~NodeNeedsNegZero;
     208           
     209            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     210            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
     211            break;
     212        }
     213           
     214        case ArithMul: {
     215            // As soon as a multiply happens, we can easily end up in the part
     216            // of the double domain where the point at which you do truncation
     217            // can change the outcome. So, ArithMul always checks for overflow
     218            // no matter what, and always forces its inputs to check as well.
     219           
     220            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
     221            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     222            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
     223            break;
     224        }
     225           
     226        case ArithMin:
     227        case ArithMax: {
     228            flags |= NodeUsedAsNumber;
     229            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     230            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
     231            break;
     232        }
     233           
     234        case ArithAbs: {
     235            flags &= ~NodeNeedsNegZero;
     236            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     237            break;
     238        }
     239           
     240        case PutByVal: {
     241            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
     242            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
     243            changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
     244            break;
     245        }
     246           
     247        case GetByVal: {
     248            changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
     249            changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
     250            break;
     251        }
     252           
     253        default:
     254            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
     255            if (op & NodeHasVarArgs) {
     256                for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
     257                    changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags);
     258            } else {
     259                if (node.child1() == NoNode)
     260                    break;
     261                changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     262                if (node.child2() == NoNode)
     263                    break;
     264                changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
     265                if (node.child3() == NoNode)
     266                    break;
     267                changed |= m_graph[node.child3()].mergeArithNodeFlags(flags);
     268            }
     269            break;
     270        }
     271
     272#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     273        printf("%s\n", changed ? "CHANGED" : "");
     274#endif
     275       
     276        m_changed |= changed;
     277    }
     278   
     279    void propagateArithNodeFlagsForward()
     280    {
     281#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     282        printf("Propagating arithmetic node flags forward [%u]\n", ++m_count);
     283#endif
     284        for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
     285            propagateArithNodeFlags(m_graph[m_compileIndex]);
     286    }
     287   
     288    void propagateArithNodeFlagsBackward()
     289    {
     290#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     291        printf("Propagating arithmetic node flags backward [%u]\n", ++m_count);
     292#endif
     293        for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
     294            propagateArithNodeFlags(m_graph[m_compileIndex]);
     295    }
     296   
    121297    bool setPrediction(PredictedType prediction)
    122298    {
     
    144320    }
    145321   
    146     void propagateNode(Node& node)
     322    void propagateNodePredictions(Node& node)
    147323    {
    148324        if (!node.shouldGenerate())
     
    151327        NodeType op = node.op;
    152328
    153 #if ENABLE(DFG_DEBUG_VERBOSE)
    154         printf("   %s[%u]: ", Graph::opName(op), m_compileIndex);
     329#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     330        printf("   %s @%u: ", Graph::opName(op), m_compileIndex);
    155331#endif
    156332       
     
    185361        case BitLShift:
    186362        case BitURShift:
    187         case UInt32ToNumber:
    188363        case ValueToInt32:
    189364        case ArithMod: {
     
    192367        }
    193368           
     369        case UInt32ToNumber: {
     370            if (nodeCanSpeculateInteger(node.arithNodeFlags()))
     371                changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction));
     372            else
     373                changed |= setPrediction(makePrediction(PredictNumber, StrongPrediction));
     374            break;
     375        }
     376
    194377        case ValueToNumber: {
    195378            PredictedType prediction = m_predictions[node.child1()];
    196379           
    197380            if (isStrongPrediction(prediction)) {
    198                 if (isNumberPrediction(prediction))
    199                     changed |= mergePrediction(prediction);
     381                if (!(prediction & PredictDouble) && nodeCanSpeculateInteger(node.arithNodeFlags()))
     382                    changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
    200383                else
    201384                    changed |= mergePrediction(makePrediction(PredictNumber, StrongPrediction));
     
    211394            if (isStrongPrediction(left) && isStrongPrediction(right)) {
    212395                if (isNumberPrediction(left) && isNumberPrediction(right)) {
    213                     if (isInt32Prediction(mergePredictions(left, right)))
     396                    if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
    214397                        changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
    215398                    else
     
    226409        case ArithAdd:
    227410        case ArithSub:
    228         case ArithMulIgnoreZero:
    229         case ArithMulPossiblyNegZero:
    230         case ArithMulSpecNotNegZero:
     411        case ArithMul:
    231412        case ArithMin:
    232413        case ArithMax: {
     
    235416           
    236417            if (isStrongPrediction(left) && isStrongPrediction(right)) {
    237                 if (isInt32Prediction(mergePredictions(left, right)))
     418                if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
    238419                    changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
    239420                else
     
    251432        case ArithAbs: {
    252433            PredictedType child = m_predictions[node.child1()];
    253             if (isStrongPrediction(child))
    254                 changed |= mergePrediction(child);
    255             break;
    256         }
    257            
    258         case ArithAddSafe:
    259         case ArithSubSafe:
    260         case ArithMulSafe:
    261         case UInt32ToNumberSafe: {
    262             changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
    263             break;
    264         }
    265 
    266         case ValueAddSafe: {
    267             PredictedType left = m_predictions[node.child1()];
    268             PredictedType right = m_predictions[node.child2()];
    269            
    270             if (isStrongPrediction(left) && isStrongPrediction(right)) {
    271                 if (isNumberPrediction(left) && isNumberPrediction(right))
    272                     changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction));
    273                 else if (!(left & PredictNumber) || !(right & PredictNumber)) {
    274                     // left or right is definitely something other than a number.
    275                     changed |= mergePrediction(makePrediction(PredictString, StrongPrediction));
    276                 } else
    277                     changed |= mergePrediction(makePrediction(PredictString | PredictInt32 | PredictDouble, StrongPrediction));
     434            if (isStrongPrediction(child)) {
     435                if (nodeCanSpeculateInteger(node.arithNodeFlags()))
     436                    changed |= mergePrediction(child);
     437                else
     438                    changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
    278439            }
    279440            break;
     
    390551        }
    391552
    392 #if ENABLE(DFG_DEBUG_VERBOSE)
     553#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    393554        printf("expect(%s) ", predictionToString(m_predictions[m_compileIndex]));
    394555        printf("use(%s) %s\n", predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : "");
     
    398559    }
    399560   
    400     void propagateForward()
    401     {
    402 #if ENABLE(DFG_DEBUG_VERBOSE)
    403         printf("Propagating forward [%u]\n", ++m_count);
     561    void propagatePredictionsForward()
     562    {
     563#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     564        printf("Propagating predictions forward [%u]\n", ++m_count);
    404565#endif
    405566        for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
    406             propagateNode(m_graph[m_compileIndex]);
    407     }
    408    
    409     void propagateBackward()
    410     {
    411 #if ENABLE(DFG_DEBUG_VERBOSE)
    412         printf("Propagating backward [%u]\n", ++m_count);
     567            propagateNodePredictions(m_graph[m_compileIndex]);
     568    }
     569   
     570    void propagatePredictionsBackward()
     571    {
     572#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     573        printf("Propagating predictions backward [%u]\n", ++m_count);
    413574#endif
    414575        for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
    415             propagateNode(m_graph[m_compileIndex]);
     576            propagateNodePredictions(m_graph[m_compileIndex]);
    416577    }
    417578   
     
    419580    {
    420581        if (m_graph[nodeIndex].op == ValueToNumber) {
    421 #if ENABLE(DFG_DEBUG_VERBOSE)
     582#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    422583            printf("  @%u -> ValueToDouble", nodeIndex);
    423584#endif
     
    433594        NodeType op = node.op;
    434595
    435 #if ENABLE(DFG_DEBUG_VERBOSE)
    436         printf("   %s[%u]: ", Graph::opName(op), m_compileIndex);
     596#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     597        printf("   %s @%u: ", Graph::opName(op), m_compileIndex);
    437598#endif
    438599       
    439600        switch (op) {
    440601        case ValueAdd: {
     602            if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
     603                toDouble(node.child1());
     604                toDouble(node.child2());
     605                break;
     606            }
     607           
    441608            PredictedType left = m_predictions[node.child1()];
    442609            PredictedType right = m_predictions[node.child2()];
     
    453620        case ArithAdd:
    454621        case ArithSub:
    455         case ArithMulIgnoreZero:
    456         case ArithMulPossiblyNegZero:
    457         case ArithMulSpecNotNegZero:
     622        case ArithMul:
    458623        case ArithMin:
    459624        case ArithMax: {
     625            if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
     626                toDouble(node.child1());
     627                toDouble(node.child2());
     628                break;
     629            }
     630           
    460631            PredictedType left = m_predictions[node.child1()];
    461632            PredictedType right = m_predictions[node.child2()];
     
    477648           
    478649        case ArithAbs: {
     650            if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
     651                toDouble(node.child1());
     652                break;
     653            }
     654           
    479655            PredictedType prediction = m_predictions[node.child1()];
    480656            if (isStrongPrediction(prediction) && (prediction & PredictDouble))
     
    488664        }
    489665           
    490         case ArithAddSafe:
    491         case ArithSubSafe:
    492         case ArithMulSafe: {
    493             toDouble(node.child1());
    494             toDouble(node.child2());
    495             break;
    496         }
    497            
    498         case ValueAddSafe: {
    499             PredictedType left = m_predictions[node.child1()];
    500             PredictedType right = m_predictions[node.child2()];
    501            
    502             if (isStrongPrediction(left) && isStrongPrediction(right) && isNumberPrediction(left) && isNumberPrediction(right)) {
    503                 toDouble(node.child2());
    504                 toDouble(node.child1());
    505             }
    506             break;
    507         }
    508        
    509666        default:
    510667            break;
    511668        }
    512669
    513 #if ENABLE(DFG_DEBUG_VERBOSE)
     670#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    514671        printf("\n");
    515672#endif
     
    518675    void fixup()
    519676    {
    520 #if ENABLE(DFG_DEBUG_VERBOSE)
     677#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    521678        printf("Performing Fixup\n");
    522679#endif
     
    578735    {
    579736        NodeIndex result = computeStartIndexForChildren(child1, child2, child3);
    580 #if ENABLE(DFG_DEBUG_VERBOSE)
     737#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    581738        printf("  lookback %u: ", result);
    582739#endif
     
    598755            result++;
    599756        ASSERT(result <= m_compileIndex);
    600 #if ENABLE(DFG_DEBUG_VERBOSE)
     757#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    601758        printf("  limit %u: ", result);
    602759#endif
     
    614771            Node& otherNode = m_graph[index];
    615772            if (node.op != otherNode.op)
     773                continue;
     774           
     775            if (node.arithNodeFlagsForCompare() != otherNode.arithNodeFlagsForCompare())
    616776                continue;
    617777           
     
    662822        switch (node.op) {
    663823        case ValueAdd:
    664         case ValueAddSafe:
    665824        case CompareLess:
    666825        case CompareLessEq:
     
    799958            return;
    800959       
    801 #if ENABLE(DFG_DEBUG_VERBOSE)
     960#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    802961        printf("   Replacing @%u -> @%u", m_compileIndex, replacement);
    803962#endif
     
    825984            return;
    826985       
    827 #if ENABLE(DFG_DEBUG_VERBOSE)
    828         printf("   %s[%u]: ", Graph::opName(m_graph[m_compileIndex].op), m_compileIndex);
     986#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     987        printf("   %s @%u: ", Graph::opName(m_graph[m_compileIndex].op), m_compileIndex);
    829988#endif
    830989
     
    840999        case ArithAdd:
    8411000        case ArithSub:
    842         case ArithMulIgnoreZero:
    843         case ArithMulPossiblyNegZero:
    844         case ArithMulSpecNotNegZero:
     1001        case ArithMul:
    8451002        case ArithMod:
    8461003        case ArithDiv:
     
    8491006        case ArithMax:
    8501007        case ArithSqrt:
    851         case ArithAddSafe:
    852         case ArithSubSafe:
    853         case ArithMulSafe:
    8541008            setReplacement(pureCSE(node));
    8551009            break;
     
    9131067       
    9141068        m_lastSeen[node.op & NodeIdMask] = m_compileIndex;
    915 #if ENABLE(DFG_DEBUG_VERBOSE)
     1069#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    9161070        printf("\n");
    9171071#endif
     
    9281082    void localCSE()
    9291083    {
    930 #if ENABLE(DFG_DEBUG_VERBOSE)
     1084#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    9311085        printf("Performing local CSE:");
    9321086#endif
     
    9931147    PredictionTracker m_variableUses;
    9941148
    995 #if ENABLE(DFG_DEBUG_VERBOSE)
     1149#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    9961150    unsigned m_count;
    9971151#endif
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95523 r95563  
    841841
    842842    case UInt32ToNumber: {
     843        if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
     844            // We know that this sometimes produces doubles. So produce a double every
     845            // time. This at least allows subsequent code to not have weird conditionals.
     846           
     847            IntegerOperand op1(this, node.child1());
     848            FPRTemporary result(this);
     849           
     850            GPRReg inputGPR = op1.gpr();
     851            FPRReg outputFPR = result.fpr();
     852           
     853            m_jit.convertInt32ToDouble(inputGPR, outputFPR);
     854           
     855            JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
     856            m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);
     857            positive.link(&m_jit);
     858           
     859            doubleResult(outputFPR, m_compileIndex);
     860        }
     861       
    843862        IntegerOperand op1(this, node.child1());
    844863        GPRTemporary result(this, op1);
     
    852871    }
    853872       
    854     case UInt32ToNumberSafe: {
    855         // We know that this sometimes produces doubles. So produce a double every
    856         // time. This at least allows subsequent code to not have weird conditionals.
    857        
    858         IntegerOperand op1(this, node.child1());
    859         FPRTemporary result(this);
    860        
    861         GPRReg inputGPR = op1.gpr();
    862         FPRReg outputFPR = result.fpr();
    863        
    864         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
    865        
    866         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
    867         m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);
    868         positive.link(&m_jit);
    869        
    870         doubleResult(outputFPR, m_compileIndex);
    871         break;
    872     }
    873 
    874873    case ValueToInt32: {
     874        if (shouldNotSpeculateInteger(node.child1())) {
     875            // Do it the safe way.
     876            nonSpeculativeValueToInt32(node);
     877            break;
     878        }
     879       
    875880        SpeculateIntegerOperand op1(this, node.child1());
    876881        GPRTemporary result(this, op1);
     
    881886
    882887    case ValueToNumber: {
    883         if (shouldSpeculateInteger(node.child1())) {
    884             SpeculateIntegerOperand op1(this, node.child1());
    885             GPRTemporary result(this, op1);
    886             m_jit.move(op1.gpr(), result.gpr());
    887             integerResult(result.gpr(), m_compileIndex, op1.format());
     888        if (shouldNotSpeculateInteger(node.child1())) {
     889            SpeculateDoubleOperand op1(this, node.child1());
     890            FPRTemporary result(this, op1);
     891            m_jit.moveDouble(op1.fpr(), result.fpr());
     892            doubleResult(result.fpr(), m_compileIndex);
    888893            break;
    889894        }
    890         SpeculateDoubleOperand op1(this, node.child1());
    891         FPRTemporary result(this, op1);
    892         m_jit.moveDouble(op1.fpr(), result.fpr());
    893         doubleResult(result.fpr(), m_compileIndex);
     895       
     896        SpeculateIntegerOperand op1(this, node.child1());
     897        GPRTemporary result(this, op1);
     898        m_jit.move(op1.gpr(), result.gpr());
     899        integerResult(result.gpr(), m_compileIndex, op1.format());
    894900        break;
    895901    }
     
    905911    case ValueAdd:
    906912    case ArithAdd: {
    907         if (shouldSpeculateInteger(node.child1(), node.child2())) {
     913        if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    908914            if (isInt32Constant(node.child1())) {
    909915                int32_t imm1 = valueOfInt32Constant(node.child1());
    910916                SpeculateIntegerOperand op2(this, node.child2());
    911917                GPRTemporary result(this);
    912 
    913                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
     918               
     919                if (nodeCanTruncateInteger(node.arithNodeFlags())) {
     920                    m_jit.move(op2.gpr(), result.gpr());
     921                    m_jit.add32(Imm32(imm1), result.gpr());
     922                } else
     923                    speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
    914924
    915925                integerResult(result.gpr(), m_compileIndex);
     
    922932                GPRTemporary result(this);
    923933               
    924                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
     934                if (nodeCanTruncateInteger(node.arithNodeFlags())) {
     935                    m_jit.move(op1.gpr(), result.gpr());
     936                    m_jit.add32(Imm32(imm2), result.gpr());
     937                } else
     938                    speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
    925939
    926940                integerResult(result.gpr(), m_compileIndex);
     
    935949            GPRReg gpr2 = op2.gpr();
    936950            GPRReg gprResult = result.gpr();
    937             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
    938 
    939             if (gpr1 == gprResult)
    940                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
    941             else if (gpr2 == gprResult)
    942                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
    943             else
    944                 speculationCheck(check);
     951           
     952            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
     953                if (gpr1 == gprResult)
     954                    m_jit.add32(gpr2, gprResult);
     955                else {
     956                    m_jit.move(gpr2, gprResult);
     957                    m_jit.add32(gpr1, gprResult);
     958                }
     959            } else {
     960                MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
     961               
     962                if (gpr1 == gprResult)
     963                    speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
     964                else if (gpr2 == gprResult)
     965                    speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
     966                else
     967                    speculationCheck(check);
     968            }
    945969
    946970            integerResult(gprResult, m_compileIndex);
     
    948972        }
    949973       
    950         // Fall through to safe cases.
    951     }
    952        
    953     case ValueAddSafe:
    954     case ArithAddSafe: {
    955974        if (shouldSpeculateNumber(node.child1(), node.child2())) {
    956975            SpeculateDoubleOperand op1(this, node.child1());
     
    966985        }
    967986       
    968         ASSERT(op == ValueAdd || op == ValueAddSafe);
     987        ASSERT(op == ValueAdd);
    969988       
    970989        JSValueOperand op1(this, node.child1());
     
    9871006
    9881007    case ArithSub: {
    989         if (shouldSpeculateInteger(node.child1(), node.child2())) {
     1008        if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    9901009            if (isInt32Constant(node.child2())) {
    9911010                SpeculateIntegerOperand op1(this, node.child1());
     
    9931012                GPRTemporary result(this);
    9941013
    995                 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
     1014                if (nodeCanTruncateInteger(node.arithNodeFlags())) {
     1015                    m_jit.move(op1.gpr(), result.gpr());
     1016                    m_jit.sub32(Imm32(imm2), result.gpr());
     1017                } else
     1018                    speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
    9961019
    9971020                integerResult(result.gpr(), m_compileIndex);
     
    10031026            GPRTemporary result(this);
    10041027
    1005             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
     1028            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
     1029                m_jit.move(op1.gpr(), result.gpr());
     1030                m_jit.sub32(op2.gpr(), result.gpr());
     1031            } else
     1032                speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
    10061033
    10071034            integerResult(result.gpr(), m_compileIndex);
     
    10091036        }
    10101037       
    1011         // Fall through to safe case.
    1012     }
    1013        
    1014     case ArithSubSafe: {
    10151038        SpeculateDoubleOperand op1(this, node.child1());
    10161039        SpeculateDoubleOperand op2(this, node.child2());
     
    10251048    }
    10261049
    1027     case ArithMulSpecNotNegZero:
    1028     case ArithMulPossiblyNegZero:
    1029     case ArithMulIgnoreZero: {
    1030         if (shouldSpeculateInteger(node.child1(), node.child2())) {
     1050    case ArithMul: {
     1051        if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    10311052            SpeculateIntegerOperand op1(this, node.child1());
    10321053            SpeculateIntegerOperand op2(this, node.child2());
     
    10351056            GPRReg reg1 = op1.gpr();
    10361057            GPRReg reg2 = op2.gpr();
     1058           
     1059            // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
     1060            // here. A multiply on integers performed in the double domain and then truncated to
     1061            // an integer will give a different result than a multiply performed in the integer
     1062            // domain and then truncated, if the integer domain result would have resulted in
     1063            // something bigger than what a 32-bit integer can hold. JavaScript mandates that
     1064            // the semantics are always as if the multiply had been performed in the double
     1065            // domain.
     1066           
    10371067            speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
    1038 
    1039             // Only the ArithMulSpecNotNegZero opcode requires that we actually turn
    1040             // negative zero into a double. The other two mean that all users of this
    1041             // result don't care if it's a positive or negative zero.
    1042             if (op == ArithMulSpecNotNegZero) {
     1068           
     1069            // Check for negative zero, if the users of this node care about such things.
     1070            if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
    10431071                MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
    10441072                speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
     
    10511079        }
    10521080       
    1053         // Fall through to safe case.
    1054     }
    1055 
    1056     case ArithMulSafe: {
    10571081        SpeculateDoubleOperand op1(this, node.child1());
    10581082        SpeculateDoubleOperand op2(this, node.child2());
     
    11101134       
    11111135    case ArithAbs: {
    1112         if (shouldSpeculateInteger(node.child1())) {
     1136        if (shouldSpeculateInteger(node.child1()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    11131137            SpeculateIntegerOperand op1(this, node.child1());
    11141138            GPRTemporary result(this, op1);
     
    11371161    case ArithMin:
    11381162    case ArithMax: {
    1139         if (shouldSpeculateInteger(node.child1(), node.child2())) {
     1163        if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    11401164            SpeculateStrictInt32Operand op1(this, node.child1());
    11411165            SpeculateStrictInt32Operand op2(this, node.child2());
     
    19171941        bool found = false;
    19181942       
    1919         if (nodePtr->op == UInt32ToNumber || nodePtr->op == UInt32ToNumberSafe) {
     1943        if (nodePtr->op == UInt32ToNumber) {
    19201944            NodeIndex nodeIndex = nodePtr->child1();
    19211945            nodePtr = &m_jit.graph()[nodeIndex];
     
    19481972                    break;
    19491973                case UInt32ToNumber:
    1950                 case UInt32ToNumberSafe:
    19511974                    uint32ToNumberIndex = info.nodeIndex();
    19521975                    break;
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r95484 r95563  
    779779    emitJumpSlowCaseIfNotImmediateInteger(regT0);
    780780    emitJumpSlowCaseIfNotImmediateInteger(regT1);
     781#if ENABLE(VALUE_PROFILER)
     782    RareCaseProfile* profile = m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
     783#endif
    781784    if (opcodeID == op_add)
    782785        addSlowCase(branchAdd32(Overflow, regT1, regT0));
     
    801804            // so that the speculative JIT knows that we failed speculation
    802805            // because of a negative zero.
    803             add32(Imm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
     806            add32(Imm32(1), AbsoluteAddress(&profile->m_counter));
    804807            addSlowCase(jump());
    805808            done.link(this);
     
    965968    int32_t value;
    966969    if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
     970#if ENABLE(VALUE_PROFILER)
     971        // Add a special fast case profile because the DFG JIT will expect one.
     972        m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
     973#endif
    967974        emitGetVirtualRegister(op2, regT0);
    968975        emitJumpSlowCaseIfNotImmediateInteger(regT0);
     
    970977        emitFastArithReTagImmediate(regT0, regT0);
    971978    } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
     979#if ENABLE(VALUE_PROFILER)
     980        // Add a special fast case profile because the DFG JIT will expect one.
     981        m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
     982#endif
    972983        emitGetVirtualRegister(op1, regT0);
    973984        emitJumpSlowCaseIfNotImmediateInteger(regT0);
Note: See TracChangeset for help on using the changeset viewer.