Changeset 92593 in webkit


Ignore:
Timestamp:
Aug 8, 2011 5:50:59 AM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT does not track speculation decisions for global variables
https://bugs.webkit.org/show_bug.cgi?id=65825

Reviewed by Gavin Barraclough.

Added the capability to track predictions for global variables, and
ensured that code can abstract over the source of prediction (local
versus global variable) wherever it is appropriate to do so. Also
cleaned up the code in SpeculativeJIT that decides how to speculate
based on recorded predictions (for example instead of using isInteger,
which makes sense for local predictions where the GetLocal would
return an integer value, we now tend to use shouldSpeculateInteger,
which checks if the value is either already an integer or should be
speculated to be an integer).

This is an 0.8% win on SunSpider, almost entirely thanks to a 25%
win on controlflow-recursive. It's also a 4.8% win on v8-crypto.

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::predictArray):
(JSC::DFG::ByteCodeParser::predictInt32):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::predictGlobalVar):
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::getGlobalVarPrediction):
(JSC::DFG::Graph::getPrediction):

  • dfg/DFGSpeculativeJIT.cpp:

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

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::shouldSpeculateInteger):
(JSC::DFG::SpeculativeJIT::shouldSpeculateDouble):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r92573 r92593  
     12011-08-08  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT does not track speculation decisions for global variables
     4        https://bugs.webkit.org/show_bug.cgi?id=65825
     5
     6        Reviewed by Gavin Barraclough.
     7       
     8        Added the capability to track predictions for global variables, and
     9        ensured that code can abstract over the source of prediction (local
     10        versus global variable) wherever it is appropriate to do so.  Also
     11        cleaned up the code in SpeculativeJIT that decides how to speculate
     12        based on recorded predictions (for example instead of using isInteger,
     13        which makes sense for local predictions where the GetLocal would
     14        return an integer value, we now tend to use shouldSpeculateInteger,
     15        which checks if the value is either already an integer or should be
     16        speculated to be an integer).
     17       
     18        This is an 0.8% win on SunSpider, almost entirely thanks to a 25%
     19        win on controlflow-recursive.  It's also a 4.8% win on v8-crypto.
     20
     21        * dfg/DFGByteCodeParser.cpp:
     22        (JSC::DFG::ByteCodeParser::predictArray):
     23        (JSC::DFG::ByteCodeParser::predictInt32):
     24        (JSC::DFG::ByteCodeParser::parseBlock):
     25        * dfg/DFGGraph.cpp:
     26        (JSC::DFG::Graph::dump):
     27        * dfg/DFGGraph.h:
     28        (JSC::DFG::Graph::predictGlobalVar):
     29        (JSC::DFG::Graph::predict):
     30        (JSC::DFG::Graph::getGlobalVarPrediction):
     31        (JSC::DFG::Graph::getPrediction):
     32        * dfg/DFGSpeculativeJIT.cpp:
     33        (JSC::DFG::SpeculativeJIT::compile):
     34        * dfg/DFGSpeculativeJIT.h:
     35        (JSC::DFG::SpeculativeJIT::shouldSpeculateInteger):
     36        (JSC::DFG::SpeculativeJIT::shouldSpeculateDouble):
     37
    1382011-08-07  Martin Robinson  <mrobinson@igalia.com>
    239
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r91728 r92593  
    431431    void predictArray(NodeIndex nodeIndex)
    432432    {
    433         Node* nodePtr = &m_graph[nodeIndex];
    434 
    435         if (nodePtr->op == GetLocal)
    436             m_graph.predict(nodePtr->local(), PredictArray);
     433        m_graph.predict(m_graph[nodeIndex], PredictArray);
    437434    }
    438435
     
    446443        if (nodePtr->op == ValueToInt32)
    447444            nodePtr = &m_graph[nodePtr->child1()];
    448 
    449         if (nodePtr->op == GetLocal)
    450             m_graph.predict(nodePtr->local(), PredictInt32);
     445       
     446        m_graph.predict(*nodePtr, PredictInt32);
    451447    }
    452448
     
    702698            // If both operands can statically be determined to the numbers, then this is an arithmetic add.
    703699            // Otherwise, we must assume this may be performing a concatenation to a string.
    704             if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult()) {
    705                 if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
    706                     predictInt32(op1);
    707                     predictInt32(op2);
    708                 }
     700            if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
     701                predictInt32(op1);
     702                predictInt32(op2);
     703            }
     704            if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult())
    709705                set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2)));
    710             } else
     706            else
    711707                set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2));
    712708            NEXT_OPCODE(op_add);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r92038 r92593  
    137137    if (node.hasLocal())
    138138        printf("  predicting %s", predictionToString(getPrediction(node.local())));
     139    if (node.hasVarNumber())
     140        printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
    139141   
    140142    printf("\n");
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r92038 r92593  
    3131#include <RegisterFile.h>
    3232#include <dfg/DFGNode.h>
     33#include <wtf/HashMap.h>
    3334#include <wtf/Vector.h>
    3435#include <wtf/StdLibExtras.h>
     
    195196        } else if ((unsigned)operand < m_variablePredictions.size())
    196197            m_variablePredictions[operand].m_value |= prediction;
    197            
     198    }
     199   
     200    void predictGlobalVar(unsigned varNumber, PredictedType prediction)
     201    {
     202        HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVarPredictions.find(varNumber + 1);
     203        if (iter == m_globalVarPredictions.end()) {
     204            PredictionSlot predictionSlot;
     205            predictionSlot.m_value |= prediction;
     206            m_globalVarPredictions.add(varNumber + 1, predictionSlot);
     207        } else
     208            iter->second.m_value |= prediction;
     209    }
     210   
     211    void predict(Node& node, PredictedType prediction)
     212    {
     213        switch (node.op) {
     214        case GetLocal:
     215            predict(node.local(), prediction);
     216            break;
     217        case GetGlobalVar:
     218            predictGlobalVar(node.varNumber(), prediction);
     219            break;
     220        default:
     221            break;
     222        }
    198223    }
    199224
     
    208233        return PredictNone;
    209234    }
     235   
     236    PredictedType getGlobalVarPrediction(unsigned varNumber)
     237    {
     238        HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVarPredictions.find(varNumber + 1);
     239        if (iter == m_globalVarPredictions.end())
     240            return PredictNone;
     241        return iter->second.m_value;
     242    }
     243   
     244    PredictedType getPrediction(Node& node)
     245    {
     246        Node* nodePtr = &node;
     247       
     248        if (nodePtr->op == ValueToNumber)
     249            nodePtr = &(*this)[nodePtr->child1()];
     250
     251        if (nodePtr->op == ValueToInt32)
     252            nodePtr = &(*this)[nodePtr->child1()];
     253       
     254        switch (nodePtr->op) {
     255        case GetLocal:
     256            return getPrediction(nodePtr->local());
     257        case GetGlobalVar:
     258            return getGlobalVarPrediction(nodePtr->varNumber());
     259        default:
     260            return PredictNone;
     261        }
     262    }
    210263
    211264#ifndef NDEBUG
     
    224277    Vector<PredictionSlot, 16> m_argumentPredictions;
    225278    Vector<PredictionSlot, 16> m_variablePredictions;
     279    HashMap<unsigned, PredictionSlot> m_globalVarPredictions;
    226280};
    227281
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r92148 r92593  
    655655
    656656    case ValueToNumber: {
    657         if (isInteger(node.child1())) {
     657        if (shouldSpeculateInteger(node.child1())) {
    658658            SpeculateIntegerOperand op1(this, node.child1());
    659659            GPRTemporary result(this, op1);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r92148 r92593  
    156156            || (info.spillFormat() | DataFormatJS) == DataFormatJSInteger;
    157157    }
    158 
    159     bool isRegisterDataFormatDouble(NodeIndex nodeIndex)
     158   
     159    bool shouldSpeculateInteger(NodeIndex nodeIndex)
     160    {
     161        if (isInteger(nodeIndex))
     162            return true;
     163       
     164        if (isInt32Prediction(m_jit.graph().getPrediction(m_jit.graph()[nodeIndex])))
     165            return true;
     166       
     167        return false;
     168    }
     169
     170    bool shouldSpeculateDouble(NodeIndex nodeIndex)
    160171    {
    161172        Node& node = m_jit.graph()[nodeIndex];
     
    167178            return true;
    168179       
    169         if (node.op == GetLocal && isDoublePrediction(m_jit.graph().getPrediction(node.local())))
     180        if (isDoublePrediction(m_jit.graph().getPrediction(node)))
    170181            return true;
    171182       
     
    175186    bool shouldSpeculateInteger(NodeIndex op1, NodeIndex op2)
    176187    {
    177         return !(isRegisterDataFormatDouble(op1) || isRegisterDataFormatDouble(op2)) && (isInteger(op1) || isInteger(op2));
     188        return !(shouldSpeculateDouble(op1) || shouldSpeculateDouble(op2)) && (shouldSpeculateInteger(op1) || shouldSpeculateInteger(op2));
    178189    }
    179190
Note: See TracChangeset for help on using the changeset viewer.