Changeset 96562 in webkit


Ignore:
Timestamp:
Oct 3, 2011 6:05:38 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG backends don't have access to per-node predictions from the propagator
https://bugs.webkit.org/show_bug.cgi?id=69291

Reviewed by Oliver Hunt.

Nodes now have two notion of predictions: the heap prediction, which is
what came directly from value profiling, and the propagator's predictions,
which arise out of abstract interpretation. Every node has a propagator
prediction, but not every node has a heap prediction; and there is no
guarantee that a node that has both will keep them consistent as the
propagator may have additional information available to it.

This is performance neutral.

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:
  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::getPrediction):

  • dfg/DFGNode.h:

(JSC::DFG::Node::Node):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::getHeapPrediction):
(JSC::DFG::Node::predictHeap):
(JSC::DFG::Node::prediction):
(JSC::DFG::Node::predict):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::Propagator):
(JSC::DFG::Propagator::setPrediction):
(JSC::DFG::Propagator::mergePrediction):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::isPredictedNumerical):
(JSC::DFG::Propagator::logicalNotIsPure):
(JSC::DFG::Propagator::setReplacement):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96545 r96562  
     12011-10-03  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG backends don't have access to per-node predictions from the propagator
     4        https://bugs.webkit.org/show_bug.cgi?id=69291
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        Nodes now have two notion of predictions: the heap prediction, which is
     9        what came directly from value profiling, and the propagator's predictions,
     10        which arise out of abstract interpretation. Every node has a propagator
     11        prediction, but not every node has a heap prediction; and there is no
     12        guarantee that a node that has both will keep them consistent as the
     13        propagator may have additional information available to it.
     14       
     15        This is performance neutral.
     16
     17        * dfg/DFGGraph.cpp:
     18        (JSC::DFG::Graph::dump):
     19        * dfg/DFGGraph.h:
     20        * dfg/DFGJITCompiler.h:
     21        (JSC::DFG::JITCompiler::getPrediction):
     22        * dfg/DFGNode.h:
     23        (JSC::DFG::Node::Node):
     24        (JSC::DFG::Node::hasHeapPrediction):
     25        (JSC::DFG::Node::getHeapPrediction):
     26        (JSC::DFG::Node::predictHeap):
     27        (JSC::DFG::Node::prediction):
     28        (JSC::DFG::Node::predict):
     29        * dfg/DFGPropagator.cpp:
     30        (JSC::DFG::Propagator::Propagator):
     31        (JSC::DFG::Propagator::setPrediction):
     32        (JSC::DFG::Propagator::mergePrediction):
     33        (JSC::DFG::Propagator::propagateNodePredictions):
     34        (JSC::DFG::Propagator::fixupNode):
     35        (JSC::DFG::Propagator::isPredictedNumerical):
     36        (JSC::DFG::Propagator::logicalNotIsPure):
     37        (JSC::DFG::Propagator::setReplacement):
     38
    1392011-10-03  Jer Noble  <jer.noble@apple.com>
    240
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r96527 r96562  
    205205        else if (node.hasVarNumber())
    206206            printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
    207         else if (node.hasPrediction())
    208             printf("  predicting %s", predictionToString(node.getPrediction()));
     207        else if (node.hasHeapPrediction())
     208            printf("  predicting %s", predictionToString(node.getHeapPrediction()));
    209209        else if (node.hasMethodCheckData()) {
    210210            MethodCheckData& methodCheckData = m_methodCheckData[node.methodCheckDataIndex()];
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r96527 r96562  
    187187    }
    188188   
    189     bool predict(Node& node, PredictedType prediction)
    190     {
    191         switch (node.op) {
    192         case GetLocal:
    193         case SetLocal:
    194         case Phi:
    195         case SetArgument:
    196             return node.variableAccessData()->predict(prediction);
    197         case GetGlobalVar:
    198             return predictGlobalVar(node.varNumber(), prediction);
    199         case GetById:
    200         case GetMethod:
    201         case GetByVal:
    202         case Call:
    203         case Construct:
    204         case GetByOffset:
    205         case GetScopedVar:
    206         case Resolve:
    207         case ResolveBase:
    208         case ResolveBaseStrictPut:
    209         case ResolveGlobal:
    210             return node.predict(prediction);
    211         default:
    212             return false;
    213         }
    214     }
    215 
    216189    PredictedType getGlobalVarPrediction(unsigned varNumber)
    217190    {
     
    227200    {
    228201        return predictionFromValue(node.valueOfJSConstantNode(codeBlock));
    229     }
    230    
    231     PredictedType getPrediction(Node& node, CodeBlock* codeBlock)
    232     {
    233         Node* nodePtr = &node;
    234        
    235         if (nodePtr->op == ValueToNumber)
    236             nodePtr = &(*this)[nodePtr->child1()];
    237 
    238         if (nodePtr->op == ValueToInt32)
    239             nodePtr = &(*this)[nodePtr->child1()];
    240        
    241         switch (nodePtr->op) {
    242         case GetLocal:
    243         case SetLocal:
    244         case SetArgument:
    245         case Phi:
    246             return nodePtr->variableAccessData()->prediction();
    247         case GetGlobalVar:
    248             return getGlobalVarPrediction(nodePtr->varNumber());
    249         case GetById:
    250         case GetMethod:
    251         case GetByVal:
    252         case Call:
    253         case Construct:
    254         case GetByOffset:
    255             return nodePtr->getPrediction();
    256         case CheckMethod:
    257             return getMethodCheckPrediction(*nodePtr);
    258         case JSConstant:
    259             return getJSConstantPrediction(*nodePtr, codeBlock);
    260         default:
    261             return PredictNone;
    262         }
    263202    }
    264203   
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r96377 r96562  
    284284   
    285285    // Helper methods to get predictions
    286     PredictedType getPrediction(Node& node) { return graph().getPrediction(node, codeBlock()); }
     286    PredictedType getPrediction(Node& node) { return node.prediction(); }
    287287    PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); }
    288288
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96527 r96562  
    429429        , m_virtualRegister(InvalidVirtualRegister)
    430430        , m_refCount(0)
     431        , m_prediction(PredictNone)
    431432    {
    432433        ASSERT(!(op & NodeHasVarArgs));
     
    444445        , m_refCount(0)
    445446        , m_opInfo(imm.m_value)
     447        , m_prediction(PredictNone)
    446448    {
    447449        ASSERT(!(op & NodeHasVarArgs));
     
    459461        , m_opInfo(imm1.m_value)
    460462        , m_opInfo2(safeCast<unsigned>(imm2.m_value))
     463        , m_prediction(PredictNone)
    461464    {
    462465        ASSERT(!(op & NodeHasVarArgs));
     
    474477        , m_opInfo(imm1.m_value)
    475478        , m_opInfo2(safeCast<unsigned>(imm2.m_value))
     479        , m_prediction(PredictNone)
    476480    {
    477481        ASSERT(op & NodeHasVarArgs);
     
    755759    }
    756760   
    757     bool hasPrediction()
     761    bool hasHeapPrediction()
    758762    {
    759763        switch (op) {
     
    775779    }
    776780   
    777     PredictedType getPrediction()
    778     {
    779         ASSERT(hasPrediction());
     781    PredictedType getHeapPrediction()
     782    {
     783        ASSERT(hasHeapPrediction());
    780784        return static_cast<PredictedType>(m_opInfo2);
    781785    }
    782786   
    783     bool predict(PredictedType prediction)
    784     {
    785         ASSERT(hasPrediction());
     787    bool predictHeap(PredictedType prediction)
     788    {
     789        ASSERT(hasHeapPrediction());
    786790       
    787791        return mergePrediction(m_opInfo2, prediction);
     
    912916        ASSERT(op & NodeHasVarArgs);
    913917        return children.variable.numChildren;
     918    }
     919   
     920    PredictedType prediction()
     921    {
     922        return m_prediction;
     923    }
     924   
     925    bool predict(PredictedType prediction)
     926    {
     927        return mergePrediction(m_prediction, prediction);
    914928    }
    915929   
     
    938952    uintptr_t m_opInfo;
    939953    unsigned m_opInfo2;
     954    // The prediction ascribed to this node after propagation.
     955    PredictedType m_prediction;
    940956};
    941957
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96527 r96562  
    4343        , m_profiledBlock(profiledBlock)
    4444    {
    45         // Predictions is a forward flow property that propagates the values seen at
    46         // a particular value source to their various uses, ensuring that uses perform
    47         // speculation that does not contravene the expected values.
    48         m_predictions.resize(m_graph.size());
    49        
    5045        // Replacements are used to implement local common subexpression elimination.
    5146        m_replacements.resize(m_graph.size());
    5247       
    53         for (unsigned i = 0; i < m_graph.size(); ++i) {
    54             m_predictions[i] = PredictNone;
     48        for (unsigned i = 0; i < m_graph.size(); ++i)
    5549            m_replacements[i] = NoNode;
    56         }
    5750       
    5851        for (unsigned i = 0; i < LastNodeId; ++i)
     
    286279        ASSERT(m_graph[m_compileIndex].hasResult());
    287280       
    288         if (m_predictions[m_compileIndex] == prediction)
    289             return false;
    290        
    291         m_predictions[m_compileIndex] = prediction;
    292         return true;
     281        // setPrediction() is used when we know that there is no way that we can change
     282        // our minds about what the prediction is going to be. There is no semantic
     283        // difference between setPrediction() and mergePrediction() other than the
     284        // increased checking to validate this property.
     285        ASSERT(m_graph[m_compileIndex].prediction() == PredictNone || m_graph[m_compileIndex].prediction() == prediction);
     286       
     287        return m_graph[m_compileIndex].predict(prediction);
    293288    }
    294289   
     
    297292        ASSERT(m_graph[m_compileIndex].hasResult());
    298293       
    299         return JSC::mergePrediction(m_predictions[m_compileIndex], prediction);
     294        return m_graph[m_compileIndex].predict(prediction);
    300295    }
    301296   
     
    327322           
    328323        case SetLocal: {
    329             changed |= node.variableAccessData()->predict(m_predictions[node.child1()]);
     324            changed |= node.variableAccessData()->predict(m_graph[node.child1()].prediction());
    330325            break;
    331326        }
     
    343338
    344339        case ArithMod: {
    345             PredictedType left = m_predictions[node.child1()];
    346             PredictedType right = m_predictions[node.child2()];
     340            PredictedType left = m_graph[node.child1()].prediction();
     341            PredictedType right = m_graph[node.child2()].prediction();
    347342           
    348343            if (left && right) {
     
    364359
    365360        case ValueToNumber: {
    366             PredictedType prediction = m_predictions[node.child1()];
     361            PredictedType prediction = m_graph[node.child1()].prediction();
    367362           
    368363            if (prediction) {
     
    377372
    378373        case ValueAdd: {
    379             PredictedType left = m_predictions[node.child1()];
    380             PredictedType right = m_predictions[node.child2()];
     374            PredictedType left = m_graph[node.child1()].prediction();
     375            PredictedType right = m_graph[node.child2()].prediction();
    381376           
    382377            if (left && right) {
     
    401396        case ArithMax:
    402397        case ArithDiv: {
    403             PredictedType left = m_predictions[node.child1()];
    404             PredictedType right = m_predictions[node.child2()];
     398            PredictedType left = m_graph[node.child1()].prediction();
     399            PredictedType right = m_graph[node.child2()].prediction();
    405400           
    406401            if (left && right) {
     
    419414           
    420415        case ArithAbs: {
    421             PredictedType child = m_predictions[node.child1()];
     416            PredictedType child = m_graph[node.child1()].prediction();
    422417            if (child) {
    423418                if (nodeCanSpeculateInteger(node.arithNodeFlags()))
     
    444439        case GetMethod:
    445440        case GetByVal: {
    446             if (node.getPrediction())
    447                 changed |= mergePrediction(node.getPrediction());
     441            if (node.getHeapPrediction())
     442                changed |= mergePrediction(node.getHeapPrediction());
    448443            break;
    449444        }
     
    455450           
    456451        case GetByOffset: {
    457             if (node.getPrediction())
    458                 changed |= mergePrediction(node.getPrediction());
     452            if (node.getHeapPrediction())
     453                changed |= mergePrediction(node.getHeapPrediction());
    459454            break;
    460455        }
     
    467462        case Call:
    468463        case Construct: {
    469             if (node.getPrediction())
    470                 changed |= mergePrediction(node.getPrediction());
     464            if (node.getHeapPrediction())
     465                changed |= mergePrediction(node.getHeapPrediction());
    471466            break;
    472467        }
    473468           
    474469        case ConvertThis: {
    475             PredictedType prediction = m_predictions[node.child1()];
     470            PredictedType prediction = m_graph[node.child1()].prediction();
    476471            if (prediction) {
    477472                if (prediction & ~PredictObjectMask) {
    478                     prediction &= ~PredictObjectMask;
    479                     prediction |= PredictObjectUnknown;
     473                    prediction &= PredictObjectMask;
     474                    prediction = mergePredictions(prediction, PredictObjectUnknown);
    480475                }
    481476                changed |= mergePrediction(prediction);
     
    492487           
    493488        case PutGlobalVar: {
    494             changed |= m_graph.predictGlobalVar(node.varNumber(), m_predictions[node.child1()]);
     489            changed |= m_graph.predictGlobalVar(node.varNumber(), m_graph[node.child1()].prediction());
    495490            break;
    496491        }
     
    501496        case ResolveBaseStrictPut:
    502497        case ResolveGlobal: {
    503             PredictedType prediction = node.getPrediction();
     498            PredictedType prediction = node.getHeapPrediction();
    504499            if (prediction)
    505500                changed |= mergePrediction(prediction);
     
    540535           
    541536        case ToPrimitive: {
    542             PredictedType child = m_predictions[node.child1()];
     537            PredictedType child = m_graph[node.child1()].prediction();
    543538            if (child) {
    544539                if (isObjectPrediction(child)) {
     
    600595
    601596#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    602         printf("%s ", predictionToString(m_predictions[m_compileIndex]));
     597        printf("%s ", predictionToString(m_graph[m_compileIndex].prediction()));
    603598#endif
    604599       
     
    653648            }
    654649           
    655             PredictedType left = m_predictions[node.child1()];
    656             PredictedType right = m_predictions[node.child2()];
     650            PredictedType left = m_graph[node.child1()].prediction();
     651            PredictedType right = m_graph[node.child2()].prediction();
    657652           
    658653            if (left && right && isNumberPrediction(left) && isNumberPrediction(right)) {
     
    678673            }
    679674           
    680             PredictedType left = m_predictions[node.child1()];
    681             PredictedType right = m_predictions[node.child2()];
     675            PredictedType left = m_graph[node.child1()].prediction();
     676            PredictedType right = m_graph[node.child2()].prediction();
    682677           
    683678            if (left && right) {
     
    696691            }
    697692           
    698             PredictedType prediction = m_predictions[node.child1()];
     693            PredictedType prediction = m_graph[node.child1()].prediction();
    699694            if (prediction & PredictDouble)
    700695                toDouble(node.child1());
     
    708703           
    709704        case GetById: {
    710             bool isArray = isArrayPrediction(m_predictions[node.child1()]);
    711             bool isString = isStringPrediction(m_predictions[node.child1()]);
     705            bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
     706            bool isString = isStringPrediction(m_graph[node.child1()].prediction());
    712707            if (!isArray && !isString)
    713708                break;
    714             if (!isInt32Prediction(m_predictions[m_compileIndex]))
     709            if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
    715710                break;
    716711            if (m_codeBlock->identifier(node.identifierNumber()) != m_globalData.propertyNames->length)
     
    861856    bool isPredictedNumerical(Node& node)
    862857    {
    863         PredictedType left = m_predictions[node.child1()];
    864         PredictedType right = m_predictions[node.child2()];
     858        PredictedType left = m_graph[node.child1()].prediction();
     859        PredictedType right = m_graph[node.child2()].prediction();
    865860        return isNumberPrediction(left) && isNumberPrediction(right);
    866861    }
     
    868863    bool logicalNotIsPure(Node& node)
    869864    {
    870         PredictedType prediction = m_predictions[node.child1()];
     865        PredictedType prediction = m_graph[node.child1()].prediction();
    871866        return isBooleanPrediction(prediction) || !prediction;
    872867    }
     
    11661161        // Be safe. Don't try to perform replacements if the predictions don't
    11671162        // agree.
    1168         if (m_predictions[m_compileIndex] != m_predictions[replacement])
     1163        if (m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
    11691164            return;
    11701165       
     
    13891384    NodeIndex m_compileIndex;
    13901385   
    1391     Vector<PredictedType, 16> m_predictions;
    1392 
    13931386#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    13941387    unsigned m_count;
Note: See TracChangeset for help on using the changeset viewer.