Changeset 90602 in webkit


Ignore:
Timestamp:
Jul 7, 2011 4:54:57 PM (13 years ago)
Author:
commit-queue@webkit.org
Message:

DFG JIT does not implement op_construct.
https://bugs.webkit.org/show_bug.cgi?id=64066

Patch by Filip Pizlo <fpizlo@apple.com> on 2011-07-07
Reviewed by Gavin Barraclough.

  • dfg/DFGAliasTracker.h:

(JSC::DFG::AliasTracker::recordConstruct):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::emitCall):

  • dfg/DFGNode.h:
  • dfg/DFGNonSpeculativeJIT.cpp:

(JSC::DFG::NonSpeculativeJIT::compile):

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

(JSC::DFG::dfgLinkFor):

  • dfg/DFGRepatch.h:
  • dfg/DFGSpeculativeJIT.cpp:

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

Location:
trunk/Source/JavaScriptCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r90601 r90602  
     12011-07-07  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT does not implement op_construct.
     4        https://bugs.webkit.org/show_bug.cgi?id=64066
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        * dfg/DFGAliasTracker.h:
     9        (JSC::DFG::AliasTracker::recordConstruct):
     10        * dfg/DFGByteCodeParser.cpp:
     11        (JSC::DFG::ByteCodeParser::addCall):
     12        (JSC::DFG::ByteCodeParser::parseBlock):
     13        * dfg/DFGJITCodeGenerator.cpp:
     14        (JSC::DFG::JITCodeGenerator::emitCall):
     15        * dfg/DFGNode.h:
     16        * dfg/DFGNonSpeculativeJIT.cpp:
     17        (JSC::DFG::NonSpeculativeJIT::compile):
     18        * dfg/DFGOperations.cpp:
     19        * dfg/DFGOperations.h:
     20        * dfg/DFGRepatch.cpp:
     21        (JSC::DFG::dfgLinkFor):
     22        * dfg/DFGRepatch.h:
     23        * dfg/DFGSpeculativeJIT.cpp:
     24        (JSC::DFG::SpeculativeJIT::compile):
     25
    1262011-07-07  Filip Pizlo  <fpizlo@apple.com>
    227
  • trunk/Source/JavaScriptCore/dfg/DFGAliasTracker.h

    r90529 r90602  
    108108    }
    109109
     110    void recordConstruct(NodeIndex construct)
     111    {
     112        ASSERT_UNUSED(construct, m_graph[construct].op == Construct);
     113        m_candidateAliasGetByVal = NoNode;
     114    }
     115
    110116private:
    111117    // This method returns true for arguments:
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r90533 r90602  
    411411        m_graph.m_varArgChildren.append(child);
    412412        m_numPassedVarArgs++;
     413    }
     414   
     415    NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
     416    {
     417        addVarArgChild(get(currentInstruction[1].u.operand));
     418        int argCount = currentInstruction[2].u.operand;
     419        int registerOffset = currentInstruction[3].u.operand;
     420        int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
     421        for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
     422            addVarArgChild(get(argIdx));
     423        NodeIndex call = addToGraph(Node::VarArg, op);
     424        Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
     425        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
     426            set(putInstruction[1].u.operand, call);
     427        if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
     428            m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
     429        return call;
    413430    }
    414431
     
    11021119           
    11031120        case op_call: {
    1104             addVarArgChild(get(currentInstruction[1].u.operand));
    1105             int argCount = currentInstruction[2].u.operand;
    1106             int registerOffset = currentInstruction[3].u.operand;
    1107             int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
    1108             for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
    1109                 addVarArgChild(get(argIdx));
    1110             NodeIndex call = addToGraph(Node::VarArg, Call);
     1121            NodeIndex call = addCall(interpreter, currentInstruction, Call);
    11111122            aliases.recordCall(call);
    1112             Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
    1113             if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
    1114                 set(putInstruction[1].u.operand, call);
    1115             if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
    1116                 m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
    11171123            NEXT_OPCODE(op_call);
     1124        }
     1125           
     1126        case op_construct: {
     1127            NodeIndex construct = addCall(interpreter, currentInstruction, Construct);
     1128            aliases.recordConstruct(construct);
     1129            NEXT_OPCODE(op_construct);
    11181130        }
    11191131           
    11201132        case op_call_put_result: {
    1121 #if !ASSERT_DISABLED
    1122             Instruction* callInstruction = currentInstruction - OPCODE_LENGTH(op_call);
    1123             ASSERT(interpreter->getOpcodeID(callInstruction->u.opcode) == op_call);
    1124 #endif
    11251133            NEXT_OPCODE(op_call_put_result);
    11261134        }
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r90529 r90602  
    471471void JITCodeGenerator::emitCall(Node& node)
    472472{
     473    P_DFGOperation_E slowCallFunction;
     474    bool isCall;
     475   
     476    if (node.op == Call) {
     477        slowCallFunction = operationLinkCall;
     478        isCall = true;
     479    } else {
     480        ASSERT(node.op == Construct);
     481        slowCallFunction = operationLinkConstruct;
     482        isCall = false;
     483    }
     484   
    473485    NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
    474486    JSValueOperand callee(this, calleeNodeIndex);
     
    502514    }
    503515   
    504     switch (node.op) {
    505     case Call:
    506         m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
    507         break;
    508        
    509     default:
    510         ASSERT_NOT_REACHED();
    511     }
     516    m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
    512517   
    513518    flushRegisters();
     
    519524    JITCompiler::Jump slowPath;
    520525   
    521     switch (node.op) {
    522     case Call:
    523         slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
    524         m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
    525         m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
    526         break;
    527        
    528     default:
    529         ASSERT_NOT_REACHED();
    530     }
     526    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
     527    m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
     528    m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
    531529
    532530    m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     
    540538   
    541539    m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    542     JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(operationLinkCall, m_jit.graph()[m_compileIndex].exceptionInfo);
     540    JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, m_jit.graph()[m_compileIndex].exceptionInfo);
    543541    m_jit.move(Imm32(numArgs), GPRInfo::regT1);
    544542    m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     
    551549    jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
    552550   
    553     m_jit.addJSCall(fastCall, slowCall, targetToCheck, true, m_jit.graph()[m_compileIndex].exceptionInfo);
     551    m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].exceptionInfo);
    554552}
    555553
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r90529 r90602  
    143143    /* Calls. */\
    144144    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
     145    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
    145146    \
    146147    /* Nodes for misc operations. */\
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp

    r90529 r90602  
    10691069       
    10701070    case Call:
     1071    case Construct:
    10711072        emitCall(node);
    10721073        break;
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r90529 r90602  
    432432}
    433433
    434 static void* handleHostCall(ExecState* execCallee, JSValue callee)
     434static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
    435435{
    436436    ExecState* exec = execCallee->callerFrame();
    437437    JSGlobalData* globalData = &exec->globalData();
    438     CallData callData;
    439     CallType callType = getCallData(callee, callData);
    440    
    441     ASSERT(callType != CallTypeJS);
    442    
    443     if (callType == CallTypeHost) {
    444         if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
    445             globalData->exception = createStackOverflowError(exec);
    446             return 0;
    447         }
     438    if (kind == CodeForCall) {
     439        CallData callData;
     440        CallType callType = getCallData(callee, callData);
     441   
     442        ASSERT(callType != CallTypeJS);
     443   
     444        if (callType == CallTypeHost) {
     445            if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
     446                globalData->exception = createStackOverflowError(exec);
     447                return 0;
     448            }
    448449       
    449         execCallee->setScopeChain(exec->scopeChain());
     450            execCallee->setScopeChain(exec->scopeChain());
    450451       
    451         globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
     452            globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
    452453       
    453         if (globalData->exception)
    454             return 0;
    455         return reinterpret_cast<void*>(getHostCallReturnValue);
    456     }
    457    
    458     ASSERT(callType == CallTypeNone);
     454            if (globalData->exception)
     455                return 0;
     456            return reinterpret_cast<void*>(getHostCallReturnValue);
     457        }
     458   
     459        ASSERT(callType == CallTypeNone);
     460    } else {
     461        ASSERT(kind == CodeForConstruct);
     462       
     463        ConstructData constructData;
     464        ConstructType constructType = getConstructData(callee, constructData);
     465       
     466        ASSERT(constructType = ConstructTypeJS);
     467       
     468        if (constructType == ConstructTypeHost) {
     469            if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
     470                globalData->exception = createStackOverflowError(exec);
     471                return 0;
     472            }
     473           
     474            execCallee->setScopeChain(exec->scopeChain());
     475           
     476            globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
     477           
     478            if (globalData->exception)
     479                return 0;
     480            return reinterpret_cast<void*>(getHostCallReturnValue);
     481        }
     482       
     483        ASSERT(constructType == ConstructTypeNone);
     484    }
    459485    exec->globalData().exception = createNotAFunctionError(exec, callee);
    460486    return 0;
    461487}
    462488
    463 void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr);
    464 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall);
    465 void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
     489inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
    466490{
    467491    ExecState* exec = execCallee->callerFrame();
     
    470494    JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
    471495    if (!calleeAsFunctionCell)
    472         return handleHostCall(execCallee, calleeAsValue);
     496        return handleHostCall(execCallee, calleeAsValue, kind);
    473497    JSFunction* callee = asFunction(calleeAsFunctionCell);
    474498    ExecutableBase* executable = callee->executable();
     
    477501    CodeBlock* codeBlock = 0;
    478502    if (executable->isHostFunction())
    479         codePtr = executable->generatedJITCodeForCall().addressForCall();
     503        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
    480504    else {
    481505        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
    482         JSObject* error = functionExecutable->compileForCall(exec, callee->scope());
     506        JSObject* error = functionExecutable->compileFor(exec, callee->scope(), kind);
    483507        if (error) {
    484508            globalData->exception = createStackOverflowError(exec);
    485509            return 0;
    486510        }
    487         codeBlock = &functionExecutable->generatedBytecodeForCall();
     511        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
    488512        if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
    489             codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
     513            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
    490514        else
    491             codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
     515            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
    492516        execCallee->setScopeChain(callee->scope());
    493517    }
     
    496520        callLinkInfo.setSeen();
    497521    else
    498         dfgLinkCall(execCallee, callLinkInfo, codeBlock, callee, codePtr);
     522        dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
    499523    return codePtr.executableAddress();
    500524}
    501525
    502 void* operationVirtualCall(ExecState* execCallee)
     526void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr);
     527FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall);
     528void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
     529{
     530    return linkFor(execCallee, returnAddress, CodeForCall);
     531}
     532
     533void* operationLinkConstructWithReturnAddress(ExecState*, ReturnAddressPtr);
     534FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkConstruct);
     535void* operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
     536{
     537    return linkFor(execCallee, returnAddress, CodeForConstruct);
     538}
     539
     540inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
    503541{
    504542    ExecState* exec = execCallee->callerFrame();
     
    507545    JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
    508546    if (UNLIKELY(!calleeAsFunctionCell))
    509         return handleHostCall(execCallee, calleeAsValue);
     547        return handleHostCall(execCallee, calleeAsValue, kind);
    510548   
    511549    JSFunction* function = asFunction(calleeAsFunctionCell);
    512550    ExecutableBase* executable = function->executable();
    513     if (UNLIKELY(!executable->hasJITCodeForCall())) {
     551    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
    514552        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
    515553        JSObject* error = functionExecutable->compileForCall(exec, function->scope());
     
    520558    }
    521559    execCallee->setScopeChain(function->scopeUnchecked());
    522     return executable->generatedJITCodeForCallWithArityCheck().executableAddress();
     560    return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
     561}
     562
     563void* operationVirtualCall(ExecState* execCallee)
     564{
     565    return virtualFor(execCallee, CodeForCall);
     566}
     567
     568void* operationVirtualConstruct(ExecState* execCallee)
     569{
     570    return virtualFor(execCallee, CodeForConstruct);
    523571}
    524572
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r90529 r90602  
    4949typedef void (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*);
    5050typedef double (*D_DFGOperation_DD)(double, double);
     51typedef void *(*P_DFGOperation_E)(ExecState*);
    5152
    5253// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
     
    8485void* operationVirtualCall(ExecState*);
    8586void* operationLinkCall(ExecState*);
     87void* operationVirtualConstruct(ExecState*);
     88void* operationLinkConstruct(ExecState*);
    8689
    8790// This method is used to lookup an exception hander, keyed by faultLocation, which is
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp

    r90601 r90602  
    514514}
    515515
    516 void dfgLinkCall(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr)
     516void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind)
    517517{
    518518    CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
     
    526526    }
    527527   
    528     repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
     528    if (kind == CodeForCall) {
     529        repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
     530        return;
     531    }
     532    ASSERT(kind == CodeForConstruct);
     533    repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct);
    529534}
    530535
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.h

    r90529 r90602  
    3838void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
    3939void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
    40 void dfgLinkCall(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr);
     40void dfgLinkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind);
    4141
    4242} } // namespace JSC::DFG
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r90529 r90602  
    11461146       
    11471147    case Call:
     1148    case Construct:
    11481149        emitCall(node);
    11491150        break;
Note: See TracChangeset for help on using the changeset viewer.