Changeset 97030 in webkit


Ignore:
Timestamp:
Oct 9, 2011 1:07:36 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG should not always speculate that a ByVal access has an integer index
https://bugs.webkit.org/show_bug.cgi?id=69716

Reviewed by Oliver Hunt.

1% win on SunSpider, neutral elsewhere.

  • dfg/DFGJITCodeGenerator.h:

(JSC::DFG::callOperation):

  • dfg/DFGNode.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::byValHasIntBase):
(JSC::DFG::Propagator::clobbersWorld):
(JSC::DFG::Propagator::getMethodLoadElimination):
(JSC::DFG::Propagator::checkStructureLoadElimination):
(JSC::DFG::Propagator::getByOffsetLoadElimination):
(JSC::DFG::Propagator::getPropertyStorageLoadElimination):
(JSC::DFG::Propagator::performNodeCSE):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r97025 r97030  
     12011-10-09  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should not always speculate that a ByVal access has an integer index
     4        https://bugs.webkit.org/show_bug.cgi?id=69716
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        1% win on SunSpider, neutral elsewhere.
     9
     10        * dfg/DFGJITCodeGenerator.h:
     11        (JSC::DFG::callOperation):
     12        * dfg/DFGNode.h:
     13        * dfg/DFGOperations.cpp:
     14        * dfg/DFGOperations.h:
     15        * dfg/DFGPropagator.cpp:
     16        (JSC::DFG::Propagator::byValHasIntBase):
     17        (JSC::DFG::Propagator::clobbersWorld):
     18        (JSC::DFG::Propagator::getMethodLoadElimination):
     19        (JSC::DFG::Propagator::checkStructureLoadElimination):
     20        (JSC::DFG::Propagator::getByOffsetLoadElimination):
     21        (JSC::DFG::Propagator::getPropertyStorageLoadElimination):
     22        (JSC::DFG::Propagator::performNodeCSE):
     23        * dfg/DFGSpeculativeJIT32_64.cpp:
     24        (JSC::DFG::SpeculativeJIT::compile):
     25        * dfg/DFGSpeculativeJIT64.cpp:
     26        (JSC::DFG::SpeculativeJIT::compile):
     27
    1282011-10-09  Yuqiang Xian  <yuqiang.xian@intel.com>
    229
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r96988 r97030  
    11551155        m_jit.move(GPRInfo::returnValueGPR, result);
    11561156    }
     1157    void callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     1158    {
     1159        setupStubArguments(arg1, arg2);
     1160        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1161
     1162        appendCallWithExceptionCheck(operation);
     1163        m_jit.move(GPRInfo::returnValueGPR, result);
     1164    }
    11571165    void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1, GPRReg arg2, void* pointer)
    11581166    {
     
    11681176    }
    11691177    void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1178    {
     1179        setupStubArguments(arg1, arg2, arg3);
     1180        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1181
     1182        appendCallWithExceptionCheck(operation);
     1183    }
     1184    void callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
    11701185    {
    11711186        setupStubArguments(arg1, arg2, arg3);
     
    13291344        setupResults(resultTag, resultPayload);
    13301345    }
     1346    void callOperation(J_DFGOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
     1347    {
     1348        m_jit.push(arg2Tag);
     1349        m_jit.push(arg2Payload);
     1350        m_jit.push(arg1);
     1351        m_jit.push(GPRInfo::callFrameRegister);
     1352
     1353        appendCallWithExceptionCheck(operation);
     1354        setupResults(resultTag, resultPayload);
     1355    }
    13311356    void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, void* pointer)
    13321357    {
     
    13521377        m_jit.push(arg1Tag);
    13531378        m_jit.push(arg1Payload);
     1379        m_jit.push(GPRInfo::callFrameRegister);
     1380
     1381        appendCallWithExceptionCheck(operation);
     1382    }
     1383    void callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
     1384    {
     1385        m_jit.push(arg3Tag);
     1386        m_jit.push(arg3Payload);
     1387        m_jit.push(arg2Tag);
     1388        m_jit.push(arg2Payload);
     1389        m_jit.push(arg1);
    13541390        m_jit.push(GPRInfo::callFrameRegister);
    13551391
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96993 r97030  
    322322    /* Since a put to 'length' may invalidate optimizations here, */\
    323323    /* this must be the directly subsequent property put. */\
    324     macro(GetByVal, NodeResultJS | NodeMustGenerate) \
     324    macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
    325325    macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
    326326    macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r96988 r97030  
    264264}
    265265
     266EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
     267{
     268    JSValue property = JSValue::decode(encodedProperty);
     269
     270    if (property.isUInt32())
     271        return getByVal(exec, base, property.asUInt32());
     272    if (property.isDouble()) {
     273        double propertyAsDouble = property.asDouble();
     274        uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
     275        if (propertyAsUInt32 == propertyAsDouble)
     276            return getByVal(exec, base, propertyAsUInt32);
     277    } else if (property.isString()) {
     278        if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
     279            return JSValue::encode(result);
     280    }
     281
     282    Identifier ident(exec, property.toString(exec));
     283    return JSValue::encode(JSValue(base).get(exec, ident));
     284}
     285
    266286EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName)
    267287{
     
    365385{
    366386    operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
     387}
     388
     389void DFG_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
     390{
     391    operationPutByValInternal<true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
     392}
     393
     394void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
     395{
     396    operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
    367397}
    368398
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r96988 r97030  
    5555typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*);
    5656typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
     57typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
    5758typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
    5859typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue);
     
    6667typedef RegisterSizedBoolean DFG_OPERATION (*Z_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
    6768typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
     69typedef void DFG_OPERATION (*V_DFGOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
    6870typedef void DFG_OPERATION (*V_DFGOperation_EJJP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
    6971typedef void DFG_OPERATION (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*);
     
    8385EncodedJSValue DFG_OPERATION operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
    8486EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
     87EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty);
    8588EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
    8689EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue encodedBase, Identifier*);
     
    101104void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
    102105void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
     106void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
     107void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
    103108void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
    104109EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*);
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96995 r97030  
    881881    }
    882882   
     883    bool byValHasIntBase(Node& node)
     884    {
     885        PredictedType prediction = m_graph[node.child2()].prediction();
     886        return (prediction & PredictInt32) || !prediction;
     887    }
     888   
    883889    bool clobbersWorld(NodeIndex nodeIndex)
    884890    {
     
    898904        case LogicalNot:
    899905            return !logicalNotIsPure(node);
     906        case GetByVal:
     907            return !byValHasIntBase(node);
    900908        default:
    901909            ASSERT_NOT_REACHED();
     
    10121020            case PutByVal:
    10131021            case PutByValAlias:
    1014                 // PutByVal currently always speculates that it's accessing an array with an
    1015                 // integer index, which means that it's impossible for it to cause a structure
    1016                 // change.
    1017                 break;
     1022                if (byValHasIntBase(node)) {
     1023                    // If PutByVal speculates that it's accessing an array with an
     1024                    // integer index, then it's impossible for it to cause a structure
     1025                    // change.
     1026                    break;
     1027                }
     1028                return NoNode;
    10181029               
    10191030            case ArrayPush:
     
    10771088            case PutByVal:
    10781089            case PutByValAlias:
    1079                 // PutByVal currently always speculates that it's accessing an array with an
    1080                 // integer index, which means that it's impossible for it to cause a structure
    1081                 // change.
    1082                 break;
     1090                if (byValHasIntBase(node)) {
     1091                    // If PutByVal speculates that it's accessing an array with an
     1092                    // integer index, then it's impossible for it to cause a structure
     1093                    // change.
     1094                    break;
     1095                }
     1096                return false;
    10831097               
    10841098            default:
     
    11171131            case PutByVal:
    11181132            case PutByValAlias:
    1119                 // PutByVal currently always speculates that it's accessing an array with an
    1120                 // integer index, which means that it's impossible for it to cause a structure
    1121                 // change.
    1122                 break;
     1133                if (byValHasIntBase(node)) {
     1134                    // If PutByVal speculates that it's accessing an array with an
     1135                    // integer index, then it's impossible for it to cause a structure
     1136                    // change.
     1137                    break;
     1138                }
     1139                return NoNode;
    11231140               
    11241141            default:
     
    11501167            case PutByVal:
    11511168            case PutByValAlias:
    1152                 // PutByVal currently always speculates that it's accessing an array with an
    1153                 // integer index, which means that it's impossible for it to cause a structure
    1154                 // change.
    1155                 break;
     1169                if (byValHasIntBase(node)) {
     1170                    // If PutByVal speculates that it's accessing an array with an
     1171                    // integer index, then it's impossible for it to cause a structure
     1172                    // change.
     1173                    break;
     1174                }
     1175                return NoNode;
    11561176               
    11571177            default:
     
    13221342           
    13231343        case GetByVal:
    1324             setReplacement(getByValLoadElimination(node.child1(), node.child2()));
     1344            if (byValHasIntBase(node))
     1345                setReplacement(getByValLoadElimination(node.child1(), node.child2()));
    13251346            break;
    13261347           
    13271348        case PutByVal:
    1328             if (getByValLoadElimination(node.child1(), node.child2()) != NoNode)
     1349            if (byValHasIntBase(node) && getByValLoadElimination(node.child1(), node.child2()) != NoNode)
    13291350                node.op = PutByValAlias;
    13301351            break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r97014 r97030  
    12731273
    12741274    case GetByVal: {
     1275        PredictedType basePrediction = at(node.child2()).prediction();
     1276        if (!(basePrediction & PredictInt32) && basePrediction) {
     1277            SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
     1278            JSValueOperand property(this, node.child2());
     1279            GPRReg baseGPR = base.gpr();
     1280            GPRReg propertyTagGPR = property.tagGPR();
     1281            GPRReg propertyPayloadGPR = property.payloadGPR();
     1282           
     1283            flushRegisters();
     1284            GPRResult2 resultTag(this);
     1285            GPRResult resultPayload(this);
     1286            callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR);
     1287           
     1288            jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
     1289            break;
     1290        }
     1291
    12751292        if (at(node.child1()).prediction() == PredictString) {
    12761293            compileGetByValOnString(node);
     
    13151332
    13161333    case PutByVal: {
     1334        PredictedType basePrediction = at(node.child2()).prediction();
     1335        if (!(basePrediction & PredictInt32) && basePrediction) {
     1336            SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
     1337            JSValueOperand property(this, node.child2());
     1338            JSValueOperand value(this, node.child3());
     1339            GPRReg baseGPR = base.gpr();
     1340            GPRReg propertyTagGPR = property.tagGPR();
     1341            GPRReg propertyPayloadGPR = property.payloadGPR();
     1342            GPRReg valueTagGPR = value.tagGPR();
     1343            GPRReg valuePayloadGPR = value.payloadGPR();
     1344           
     1345            flushRegisters();
     1346            callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
     1347           
     1348            noResult(m_compileIndex);
     1349            break;
     1350        }
     1351
    13171352        SpeculateCellOperand base(this, node.child1());
    13181353        SpeculateStrictInt32Operand property(this, node.child2());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r96993 r97030  
    13841384
    13851385    case GetByVal: {
     1386        PredictedType basePrediction = at(node.child2()).prediction();
     1387        if (!(basePrediction & PredictInt32) && basePrediction) {
     1388            JSValueOperand base(this, node.child1());
     1389            JSValueOperand property(this, node.child2());
     1390            GPRReg baseGPR = base.gpr();
     1391            GPRReg propertyGPR = property.gpr();
     1392           
     1393            flushRegisters();
     1394            GPRResult result(this);
     1395            callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
     1396           
     1397            jsValueResult(result.gpr(), m_compileIndex);
     1398            break;
     1399        }
     1400       
    13861401        if (at(node.child1()).prediction() == PredictString) {
    13871402            compileGetByValOnString(node);
     
    14251440
    14261441    case PutByVal: {
     1442        PredictedType basePrediction = at(node.child2()).prediction();
     1443        if (!(basePrediction & PredictInt32) && basePrediction) {
     1444            JSValueOperand arg1(this, node.child1());
     1445            JSValueOperand arg2(this, node.child2());
     1446            JSValueOperand arg3(this, node.child3());
     1447            GPRReg arg1GPR = arg1.gpr();
     1448            GPRReg arg2GPR = arg2.gpr();
     1449            GPRReg arg3GPR = arg3.gpr();
     1450            flushRegisters();
     1451           
     1452            callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
     1453           
     1454            noResult(m_compileIndex);
     1455            break;
     1456        }
     1457
    14271458        SpeculateCellOperand base(this, node.child1());
    14281459        SpeculateStrictInt32Operand property(this, node.child2());
     
    14891520
    14901521    case PutByValAlias: {
     1522        PredictedType basePrediction = at(node.child2()).prediction();
     1523        ASSERT_UNUSED(basePrediction, (basePrediction & PredictInt32) || !basePrediction);
     1524           
    14911525        SpeculateCellOperand base(this, node.child1());
    14921526        SpeculateStrictInt32Operand property(this, node.child2());
Note: See TracChangeset for help on using the changeset viewer.