Changeset 96567 in webkit


Ignore:
Timestamp:
Oct 3, 2011 7:55:54 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG should inline Array.push and Array.pop
https://bugs.webkit.org/show_bug.cgi?id=69314

Reviewed by Oliver Hunt.

1% speed-up in V8 due to 6% speed-up in V8-deltablue.

  • assembler/MacroAssemblerX86_64.h:

(JSC::MacroAssemblerX86_64::storePtr):

  • create_hash_table:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGIntrinsic.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasHeapPrediction):

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

(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::getByValLoadElimination):
(JSC::DFG::Propagator::getMethodLoadElimination):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

Location:
trunk/Source/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96564 r96567  
     12011-10-03  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should inline Array.push and Array.pop
     4        https://bugs.webkit.org/show_bug.cgi?id=69314
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        1% speed-up in V8 due to 6% speed-up in V8-deltablue.
     9
     10        * assembler/MacroAssemblerX86_64.h:
     11        (JSC::MacroAssemblerX86_64::storePtr):
     12        * create_hash_table:
     13        * dfg/DFGByteCodeParser.cpp:
     14        (JSC::DFG::ByteCodeParser::handleIntrinsic):
     15        (JSC::DFG::ByteCodeParser::parseBlock):
     16        * dfg/DFGGraph.cpp:
     17        (JSC::DFG::Graph::dump):
     18        * dfg/DFGIntrinsic.h:
     19        * dfg/DFGNode.h:
     20        (JSC::DFG::Node::hasHeapPrediction):
     21        * dfg/DFGOperations.cpp:
     22        * dfg/DFGOperations.h:
     23        * dfg/DFGPropagator.cpp:
     24        (JSC::DFG::Propagator::propagateNodePredictions):
     25        (JSC::DFG::Propagator::getByValLoadElimination):
     26        (JSC::DFG::Propagator::getMethodLoadElimination):
     27        * dfg/DFGSpeculativeJIT32_64.cpp:
     28        (JSC::DFG::SpeculativeJIT::compile):
     29        * dfg/DFGSpeculativeJIT64.cpp:
     30        (JSC::DFG::SpeculativeJIT::compile):
     31
    1322011-10-03  Filip Pizlo  <fpizlo@apple.com>
    233
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h

    r95901 r96567  
    299299    }
    300300
     301    void storePtr(TrustedImmPtr imm, BaseIndex address)
     302    {
     303        move(imm, scratchRegister);
     304        m_assembler.movq_rm(scratchRegister, address.offset, address.base, address.index, address.scale);
     305    }
     306   
    301307    DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
    302308    {
  • trunk/Source/JavaScriptCore/create_hash_table

    r95399 r96567  
    322322            }
    323323        }
     324        if ($name eq "arrayPrototypeTable") {
     325            if ($key eq "push") {
     326                $intrinsic = "DFG::ArrayPushIntrinsic";
     327            }
     328            if ($key eq "pop") {
     329                $intrinsic = "DFG::ArrayPopIntrinsic";
     330            }
     331        }
    324332        print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) INTRINSIC($intrinsic) },\n";
    325333        $i++;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r96564 r96567  
    7171   
    7272    // Handle intrinsic functions.
    73     bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int firstArg, int lastArg);
     73    bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int firstArg, int lastArg, PredictedType prediction);
    7474    // Parse a single basic block of bytecode instructions.
    7575    bool parseBlock(unsigned limit);
     
    682682}
    683683
    684 bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg)
     684bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg, PredictedType prediction)
    685685{
    686686    switch (intrinsic) {
     
    718718       
    719719        set(resultOperand, addToGraph(ArithSqrt, getToNumber(firstArg + 1)));
     720        return true;
     721    }
     722       
     723    case ArrayPushIntrinsic: {
     724        if (firstArg + 1 != lastArg)
     725            return false;
     726       
     727        NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(firstArg), get(firstArg + 1));
     728        if (usesResult)
     729            set(resultOperand, arrayPush);
     730       
     731        return true;
     732    }
     733       
     734    case ArrayPopIntrinsic: {
     735        if (firstArg != lastArg)
     736            return false;
     737       
     738        NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(firstArg));
     739        if (usesResult)
     740            set(resultOperand, arrayPop);
    720741        return true;
    721742    }
     
    15321553                int resultOperand = 0; // make compiler happy
    15331554                Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
     1555                PredictedType prediction = PredictNone;
    15341556                if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
    15351557                    resultOperand = putInstruction[1].u.operand;
    15361558                    usesResult = true;
     1559                    prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
    15371560                }
    15381561               
    15391562                DFG::Intrinsic intrinsic = m_graph.valueOfFunctionConstant(m_codeBlock, callTarget)->executable()->intrinsic();
    15401563               
    1541                 if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg)) {
     1564                if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg, prediction)) {
    15421565                    // NEXT_OPCODE() has to be inside braces.
    15431566                    NEXT_OPCODE(op_call);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r96562 r96567  
    209209        else if (node.hasMethodCheckData()) {
    210210            MethodCheckData& methodCheckData = m_methodCheckData[node.methodCheckDataIndex()];
    211             printf("  predicting function %p", methodCheckData.function);
     211            JSCell* functionCell = getJSFunction(methodCheckData.function);
     212            ExecutableBase* executable = 0;
     213            CodeBlock* primaryForCall = 0;
     214            CodeBlock* secondaryForCall = 0;
     215            CodeBlock* primaryForConstruct = 0;
     216            CodeBlock* secondaryForConstruct = 0;
     217            if (functionCell) {
     218                JSFunction* function = asFunction(functionCell);
     219                executable = function->executable();
     220                if (!executable->isHostFunction()) {
     221                    FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
     222                    if (functionExecutable->isGeneratedForCall()) {
     223                        primaryForCall = &functionExecutable->generatedBytecodeForCall();
     224                        secondaryForCall = primaryForCall->alternative();
     225                    }
     226                    if (functionExecutable->isGeneratedForConstruct()) {
     227                        primaryForConstruct = &functionExecutable->generatedBytecodeForConstruct();
     228                        secondaryForConstruct = primaryForConstruct->alternative();
     229                    }
     230                }
     231            }
     232            printf("  predicting function %p(%p(%p(%p) %p(%p)))", methodCheckData.function, executable, primaryForCall, secondaryForCall, primaryForConstruct, secondaryForConstruct);
    212233        }
    213234    }
  • trunk/Source/JavaScriptCore/dfg/DFGIntrinsic.h

    r95901 r96567  
    3434    MinIntrinsic,
    3535    MaxIntrinsic,
    36     SqrtIntrinsic
     36    SqrtIntrinsic,
     37    ArrayPushIntrinsic,
     38    ArrayPopIntrinsic
    3739};
    3840
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96562 r96567  
    343343    macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
    344344    \
     345    /* Optimizations for array mutation. */\
     346    macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     347    macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     348    \
    345349    /* Nodes for comparison operations. */\
    346350    macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
     
    773777        case ResolveBaseStrictPut:
    774778        case ResolveGlobal:
     779        case ArrayPop:
     780        case ArrayPush:
    775781            return true;
    776782        default:
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r96419 r96567  
    376376}
    377377
     378EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, JSArray* array, EncodedJSValue encodedValue)
     379{
     380    array->push(exec, JSValue::decode(encodedValue));
     381    return JSValue::encode(jsNumber(array->length()));
     382}
     383       
     384EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray* array)
     385{
     386    return JSValue::encode(array->pop());
     387}
     388       
    378389void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
    379390{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r96363 r96567  
    9898void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
    9999void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
     100EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, JSArray*, EncodedJSValue encodedValue);
     101EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*);
    100102void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
    101103void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96562 r96567  
    336336            break;
    337337        }
    338 
     338           
     339        case ArrayPop:
     340        case ArrayPush: {
     341            if (node.getHeapPrediction())
     342                changed |= mergePrediction(node.getHeapPrediction());
     343            break;
     344        }
     345           
    339346        case ArithMod: {
    340347            PredictedType left = m_graph[node.child1()].prediction();
     
    967974                // the GetByVal.
    968975                break;
     976            case ArrayPush:
     977                // A push cannot affect previously existing elements in the array.
     978                break;
    969979            default:
    970980                if (clobbersWorld(index))
     
    9981008                // integer index, which means that it's impossible for it to cause a structure
    9991009                // change.
     1010                break;
     1011               
     1012            case ArrayPush:
     1013            case ArrayPop:
     1014                // Pushing and popping cannot despecify a function.
    10001015                break;
    10011016               
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r96534 r96567  
    12611261    }
    12621262
     1263    case ArrayPush: {
     1264        SpeculateCellOperand base(this, node.child1());
     1265        JSValueOperand value(this, node.child2());
     1266        GPRTemporary storage(this);
     1267        GPRTemporary storageLength(this);
     1268       
     1269        GPRReg baseGPR = base.gpr();
     1270        GPRReg valueTagGPR = value.tagGPR();
     1271        GPRReg valuePayloadGPR = value.payloadGPR();
     1272        GPRReg storageGPR = storage.gpr();
     1273        GPRReg storageLengthGPR = storageLength.gpr();
     1274       
     1275        writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
     1276
     1277        if (!isKnownArray(node.child1()))
     1278            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     1279       
     1280        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     1281        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     1282       
     1283        // Refuse to handle bizarre lengths.
     1284        speculationCheck(m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
     1285       
     1286        MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
     1287       
     1288        m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     1289        m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     1290       
     1291        m_jit.add32(Imm32(1), storageLengthGPR);
     1292        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     1293        m_jit.add32(Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     1294        m_jit.move(Imm32(JSValue::Int32Tag), storageGPR);
     1295       
     1296        MacroAssembler::Jump done = m_jit.jump();
     1297       
     1298        slowPath.link(&m_jit);
     1299       
     1300        silentSpillAllRegisters(storageGPR, storageLengthGPR);
     1301        m_jit.push(valueTagGPR);
     1302        m_jit.push(valuePayloadGPR);
     1303        m_jit.push(baseGPR);
     1304        m_jit.push(GPRInfo::callFrameRegister);
     1305        appendCallWithExceptionCheck(operationArrayPush);
     1306        setupResults(storageGPR, storageLengthGPR);
     1307        silentFillAllRegisters(storageGPR, storageLengthGPR);
     1308       
     1309        done.link(&m_jit);
     1310       
     1311        jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
     1312        break;
     1313    }
     1314       
     1315    case ArrayPop: {
     1316        SpeculateCellOperand base(this, node.child1());
     1317        GPRTemporary valueTag(this);
     1318        GPRTemporary valuePayload(this);
     1319        GPRTemporary storage(this);
     1320        GPRTemporary storageLength(this);
     1321       
     1322        GPRReg baseGPR = base.gpr();
     1323        GPRReg valueTagGPR = valueTag.gpr();
     1324        GPRReg valuePayloadGPR = valuePayload.gpr();
     1325        GPRReg storageGPR = storage.gpr();
     1326        GPRReg storageLengthGPR = storageLength.gpr();
     1327       
     1328        if (!isKnownArray(node.child1()))
     1329            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     1330       
     1331        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     1332        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     1333       
     1334        MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
     1335       
     1336        m_jit.sub32(Imm32(1), storageLengthGPR);
     1337       
     1338        MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
     1339       
     1340        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
     1341        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
     1342       
     1343        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     1344
     1345        MacroAssembler::Jump notHole = m_jit.branchTestPtr(MacroAssembler::NonZero, valueTagGPR);
     1346        MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valuePayloadGPR);
     1347        notHole.link(&m_jit);
     1348       
     1349        m_jit.move(Imm32(0), storageLengthGPR);
     1350        m_jit.store32(storageLengthGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
     1351        m_jit.store32(storageLengthGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     1352        m_jit.sub32(MacroAssembler::Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     1353       
     1354        MacroAssembler::JumpList done;
     1355       
     1356        done.append(m_jit.jump());
     1357       
     1358        holeCase.link(&m_jit);
     1359        emptyArrayCase.link(&m_jit);
     1360        m_jit.move(MacroAssembler::Imm32(jsUndefined().tag()), valueTagGPR);
     1361        m_jit.move(MacroAssembler::Imm32(jsUndefined().payload()), valuePayloadGPR);
     1362        done.append(m_jit.jump());
     1363       
     1364        slowCase.link(&m_jit);
     1365       
     1366        silentSpillAllRegisters(valueTagGPR, valuePayloadGPR);
     1367        m_jit.push(baseGPR);
     1368        m_jit.push(GPRInfo::callFrameRegister);
     1369        appendCallWithExceptionCheck(operationArrayPop);
     1370        setupResults(valueTagGPR, valuePayloadGPR);
     1371        silentFillAllRegisters(valueTagGPR, valuePayloadGPR);
     1372       
     1373        done.link(&m_jit);
     1374       
     1375        jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
     1376        break;
     1377    }
     1378
    12631379    case DFG::Jump: {
    12641380        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r96527 r96567  
    13541354        break;
    13551355    }
     1356       
     1357    case ArrayPush: {
     1358        SpeculateCellOperand base(this, node.child1());
     1359        JSValueOperand value(this, node.child2());
     1360        GPRTemporary storage(this);
     1361        GPRTemporary storageLength(this);
     1362       
     1363        GPRReg baseGPR = base.gpr();
     1364        GPRReg valueGPR = value.gpr();
     1365        GPRReg storageGPR = storage.gpr();
     1366        GPRReg storageLengthGPR = storageLength.gpr();
     1367       
     1368        writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
     1369
     1370        if (!isKnownArray(node.child1()))
     1371            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     1372       
     1373        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     1374        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     1375       
     1376        // Refuse to handle bizarre lengths.
     1377        speculationCheck(m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
     1378       
     1379        MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
     1380       
     1381        m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     1382       
     1383        m_jit.add32(Imm32(1), storageLengthGPR);
     1384        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     1385        m_jit.add32(Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     1386        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
     1387       
     1388        MacroAssembler::Jump done = m_jit.jump();
     1389       
     1390        slowPath.link(&m_jit);
     1391       
     1392        silentSpillAllRegisters(storageLengthGPR);
     1393        setupStubArguments(baseGPR, valueGPR);
     1394        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1395        appendCallWithExceptionCheck(operationArrayPush);
     1396        m_jit.move(GPRInfo::returnValueGPR, storageLengthGPR);
     1397        silentFillAllRegisters(storageLengthGPR);
     1398       
     1399        done.link(&m_jit);
     1400       
     1401        jsValueResult(storageLengthGPR, m_compileIndex);
     1402        break;
     1403    }
     1404       
     1405    case ArrayPop: {
     1406        SpeculateCellOperand base(this, node.child1());
     1407        GPRTemporary value(this);
     1408        GPRTemporary storage(this);
     1409        GPRTemporary storageLength(this);
     1410       
     1411        GPRReg baseGPR = base.gpr();
     1412        GPRReg valueGPR = value.gpr();
     1413        GPRReg storageGPR = storage.gpr();
     1414        GPRReg storageLengthGPR = storageLength.gpr();
     1415       
     1416        if (!isKnownArray(node.child1()))
     1417            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     1418       
     1419        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     1420        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     1421       
     1422        MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
     1423       
     1424        m_jit.sub32(Imm32(1), storageLengthGPR);
     1425       
     1426        MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
     1427       
     1428        m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
     1429       
     1430        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     1431
     1432        MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
     1433       
     1434        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     1435        m_jit.sub32(MacroAssembler::Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     1436       
     1437        MacroAssembler::JumpList done;
     1438       
     1439        done.append(m_jit.jump());
     1440       
     1441        holeCase.link(&m_jit);
     1442        emptyArrayCase.link(&m_jit);
     1443        m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR);
     1444        done.append(m_jit.jump());
     1445       
     1446        slowCase.link(&m_jit);
     1447       
     1448        silentSpillAllRegisters(valueGPR);
     1449        m_jit.move(baseGPR, GPRInfo::argumentGPR1);
     1450        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1451        appendCallWithExceptionCheck(operationArrayPop);
     1452        m_jit.move(GPRInfo::returnValueGPR, valueGPR);
     1453        silentFillAllRegisters(valueGPR);
     1454       
     1455        done.link(&m_jit);
     1456       
     1457        jsValueResult(valueGPR, m_compileIndex);
     1458        break;
     1459    }
    13561460
    13571461    case DFG::Jump: {
Note: See TracChangeset for help on using the changeset viewer.