Title: [91225] trunk/Source/_javascript_Core
Revision
91225
Author
[email protected]
Date
2011-07-18 17:26:14 -0700 (Mon, 18 Jul 2011)

Log Message

https://bugs.webkit.org/show_bug.cgi?id=64760
DFG JIT - Should be able to compile program code.

Reviewed by Geoff Garen.

Add support for op_end, hooks to compile program code in Executable.cpp.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
    - Add support for op_end
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::link):
    - Added, separate out steps of compileFunction.
(JSC::DFG::JITCompiler::compile):
    - Added, compile program code.
(JSC::DFG::JITCompiler::compileFunction):
    - Sections separated out to helper functions.
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::JITCompiler):
    - Added m_exceptionCheckCount.
* runtime/Executable.cpp:
(JSC::tryDFGCompile):
(JSC::tryDFGCompileFunction):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::compileForCallInternal):
    - Renamed tryDFGCompile to tryDFGCompileFunction, added tryDFGCompile to compile program code.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (91224 => 91225)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-19 00:25:49 UTC (rev 91224)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-19 00:26:14 UTC (rev 91225)
@@ -1,5 +1,36 @@
 2011-07-18  Gavin Barraclough  <[email protected]>
 
+        https://bugs.webkit.org/show_bug.cgi?id=64760
+        DFG JIT - Should be able to compile program code.
+
+        Reviewed by Geoff Garen.
+
+        Add support for op_end, hooks to compile program code in Executable.cpp.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+            - Add support for op_end
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileEntry):
+        (JSC::DFG::JITCompiler::compileBody):
+        (JSC::DFG::JITCompiler::link):
+            - Added, separate out steps of compileFunction.
+        (JSC::DFG::JITCompiler::compile):
+            - Added, compile program code.
+        (JSC::DFG::JITCompiler::compileFunction):
+            - Sections separated out to helper functions.
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::JITCompiler):
+            - Added m_exceptionCheckCount.
+        * runtime/Executable.cpp:
+        (JSC::tryDFGCompile):
+        (JSC::tryDFGCompileFunction):
+        (JSC::ProgramExecutable::compileInternal):
+        (JSC::FunctionExecutable::compileForCallInternal):
+            - Renamed tryDFGCompile to tryDFGCompileFunction, added tryDFGCompile to compile program code.
+
+2011-07-18  Gavin Barraclough  <[email protected]>
+
         https://bugs.webkit.org/show_bug.cgi?id=64678
         Fix bugs in Object.prototype this handling.
 

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (91224 => 91225)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-07-19 00:25:49 UTC (rev 91224)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-07-19 00:26:14 UTC (rev 91225)
@@ -1112,11 +1112,14 @@
             LAST_OPCODE(op_loop_if_greatereq);
         }
 
-        case op_ret: {
+        case op_ret:
             addToGraph(Return, get(currentInstruction[1].u.operand));
             LAST_OPCODE(op_ret);
-        }
             
+        case op_end:
+            addToGraph(Return, get(currentInstruction[1].u.operand));
+            LAST_OPCODE(op_end);
+            
         case op_call: {
             NodeIndex call = addCall(interpreter, currentInstruction, Call);
             aliases.recordCall(call);

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (91224 => 91225)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-07-19 00:25:49 UTC (rev 91224)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-07-19 00:26:14 UTC (rev 91225)
@@ -223,38 +223,21 @@
     ASSERT(!(entriesIter != entriesEnd));
 }
 
-void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+void JITCompiler::compileEntry()
 {
-    // === Stage 1 - Function header code generation ===
-    //
     // This code currently matches the old JIT. In the function header we need to
     // pop the return address (since we do not allow any recursion on the machine
     // stack), and perform a fast register file check.
-
-    // This is the main entry point, without performing an arity check.
     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292
     // We'll need to convert the remaining cti_ style calls (specifically the register file
     // check) which will be dependent on stack layout. (We'd need to account for this in
     // both normal return code and when jumping to an exception handler).
     preserveReturnAddressAfterCall(GPRInfo::regT2);
     emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
-    // If we needed to perform an arity check we will already have moved the return address,
-    // so enter after this.
-    Label fromArityCheck(this);
+}
 
-    // Setup a pointer to the codeblock in the CallFrameHeader.
-    emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
-
-    // Plant a check that sufficient space is available in the RegisterFile.
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
-    addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
-    Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1);
-    // Return here after register file check.
-    Label fromRegisterFileCheck = label();
-
-
-    // === Stage 2 - Function body code generation ===
-    //
+void JITCompiler::compileBody()
+{
     // We generate the speculative code path, followed by the non-speculative
     // code for the function. Next we need to link the two together, making
     // bail-outs from the speculative path jump to the corresponding point on
@@ -304,24 +287,17 @@
         nonSpeculative.compile(checkIterator);
     }
 
-    // === Stage 3 - Function footer code generation ===
-    //
-    // Generate code to lookup and jump to exception handlers, to perform the slow
-    // register file check (if the fast one in the function header fails), and
-    // generate the entry point with arity check.
-
     // Iterate over the m_calls vector, checking for exception checks,
     // and linking them to here.
-    unsigned exceptionCheckCount = 0;
     for (unsigned i = 0; i < m_calls.size(); ++i) {
         Jump& exceptionCheck = m_calls[i].m_exceptionCheck;
         if (exceptionCheck.isSet()) {
             exceptionCheck.link(this);
-            ++exceptionCheckCount;
+            ++m_exceptionCheckCount;
         }
     }
     // If any exception checks were linked, generate code to lookup a handler.
-    if (exceptionCheckCount) {
+    if (m_exceptionCheckCount) {
         // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
         // an identifier for the operation that threw the exception, which we can use
         // to look up handler information. The identifier we use is the return address
@@ -334,38 +310,11 @@
         // and the address of the handler in returnValueGPR2.
         jump(GPRInfo::returnValueGPR2);
     }
+}
 
-    // Generate the register file check; if the fast check in the function head fails,
-    // we need to call out to a helper function to check whether more space is available.
-    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
-    registerFileCheck.link(this);
-    move(stackPointerRegister, GPRInfo::argumentGPR0);
-    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-    Call callRegisterFileCheck = call();
-    jump(fromRegisterFileCheck);
-
-    // The fast entry point into a function does not check the correct number of arguments
-    // have been passed to the call (we only use the fast entry point where we can statically
-    // determine the correct number of arguments have been passed, or have already checked).
-    // In cases where an arity check is necessary, we enter here.
-    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
-    Label arityCheck = label();
-    preserveReturnAddressAfterCall(GPRInfo::regT2);
-    emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
-    branch32(Equal, GPRInfo::regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this);
-    move(stackPointerRegister, GPRInfo::argumentGPR0);
-    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-    Call callArityCheck = call();
-    move(GPRInfo::regT0, GPRInfo::callFrameRegister);
-    jump(fromArityCheck);
-
-
-    // === Stage 4 - Link ===
-    //
+void JITCompiler::link(LinkBuffer& linkBuffer)
+{
     // Link the code, populate data in CodeBlock data structures.
-
-    LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator);
-
 #if DFG_DEBUG_VERBOSE
     fprintf(stderr, "JIT code start at %p\n", linkBuffer.debugAddress());
 #endif
@@ -377,7 +326,7 @@
     }
 
     if (m_codeBlock->needsCallReturnIndices()) {
-        m_codeBlock->callReturnIndexVector().reserveCapacity(exceptionCheckCount);
+        m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionCheckCount);
         for (unsigned i = 0; i < m_calls.size(); ++i) {
             if (m_calls[i].m_handlesExceptions) {
                 unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call);
@@ -419,7 +368,76 @@
         info.cachedPrototype.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoObj));
         info.callReturnLocation = linkBuffer.locationOf(m_methodGets[i].m_slowCall);
     }
+}
+
+void JITCompiler::compile(JITCode& entry)
+{
+    // Preserve the return address to the callframe.
+    compileEntry();
+    // Generate the body of the program.
+    compileBody();
+    // Link
+    LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator);
+    link(linkBuffer);
+    entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+}
+
+void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+{
+    compileEntry();
+
+    // === Function header code generation ===
+    // This is the main entry point, without performing an arity check.
+    // If we needed to perform an arity check we will already have moved the return address,
+    // so enter after this.
+    Label fromArityCheck(this);
+    // Setup a pointer to the codeblock in the CallFrameHeader.
+    emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
+    // Plant a check that sufficient space is available in the RegisterFile.
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
+    addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
+    Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1);
+    // Return here after register file check.
+    Label fromRegisterFileCheck = label();
+
+
+    // === Function body code generation ===
+    compileBody();
+
+    // === Function footer code generation ===
+    //
+    // Generate code to perform the slow register file check (if the fast one in
+    // the function header fails), and generate the entry point with arity check.
+    //
+    // Generate the register file check; if the fast check in the function head fails,
+    // we need to call out to a helper function to check whether more space is available.
+    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
+    registerFileCheck.link(this);
+    move(stackPointerRegister, GPRInfo::argumentGPR0);
+    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    Call callRegisterFileCheck = call();
+    jump(fromRegisterFileCheck);
     
+    // The fast entry point into a function does not check the correct number of arguments
+    // have been passed to the call (we only use the fast entry point where we can statically
+    // determine the correct number of arguments have been passed, or have already checked).
+    // In cases where an arity check is necessary, we enter here.
+    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
+    Label arityCheck = label();
+    preserveReturnAddressAfterCall(GPRInfo::regT2);
+    emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
+    branch32(Equal, GPRInfo::regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this);
+    move(stackPointerRegister, GPRInfo::argumentGPR0);
+    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    Call callArityCheck = call();
+    move(GPRInfo::regT0, GPRInfo::callFrameRegister);
+    jump(fromArityCheck);
+
+
+    // === Link ===
+    LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator);
+    link(linkBuffer);
+    
     // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs.
     linkBuffer.link(callRegisterFileCheck, cti_register_file_check);
     linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (91224 => 91225)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-07-19 00:25:49 UTC (rev 91224)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-07-19 00:26:14 UTC (rev 91225)
@@ -110,9 +110,11 @@
         : m_globalData(globalData)
         , m_graph(dfg)
         , m_codeBlock(codeBlock)
+        , m_exceptionCheckCount(0)
     {
     }
 
+    void compile(JITCode& entry);
     void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck);
 
     // Accessors for properties.
@@ -279,6 +281,11 @@
     }
 
 private:
+    // Internal implementation to compile.
+    void compileEntry();
+    void compileBody();
+    void link(LinkBuffer&);
+
     // These methods used in linking the speculative & non-speculative paths together.
     void fillNumericToDouble(NodeIndex, FPRReg, GPRReg temporary);
     void fillInt32ToInteger(NodeIndex, GPRReg);
@@ -296,7 +303,9 @@
     CodeBlock* m_codeBlock;
 
     // Vector of calls out from JIT code, including exception handler information.
+    // Count of the number of CallRecords with exception handlers.
     Vector<CallRecord> m_calls;
+    unsigned m_exceptionCheckCount;
 
     struct PropertyAccessRecord {
         PropertyAccessRecord(Call functionCall, int8_t deltaCheckImmToCall, int8_t deltaCallToStructCheck, int8_t deltaCallToLoadOrStore, int8_t deltaCallToSlowCase, int8_t deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR)

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (91224 => 91225)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2011-07-19 00:25:49 UTC (rev 91224)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2011-07-19 00:26:14 UTC (rev 91225)
@@ -43,6 +43,51 @@
 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
 
 #if ENABLE(JIT)
+#if ENABLE(DFG_JIT)
+static bool tryDFGCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode)
+{
+#if ENABLE(DFG_JIT_RESTRICTIONS)
+    // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
+    if (codeBlock->numberOfJumpTargets())
+        return false;
+#endif
+
+    JSGlobalData* globalData = &exec->globalData();
+    DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
+    if (!parse(dfg, globalData, codeBlock))
+        return false;
+
+    dfg.predictArgumentTypes(exec);
+
+    DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
+    dataFlowJIT.compile(jitCode);
+    return true;
+}
+
+static bool tryDFGCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+{
+#if ENABLE(DFG_JIT_RESTRICTIONS)
+    // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
+    if (codeBlock->numberOfJumpTargets())
+        return false;
+#endif
+
+    JSGlobalData* globalData = &exec->globalData();
+    DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
+    if (!parse(dfg, globalData, codeBlock))
+        return false;
+
+    dfg.predictArgumentTypes(exec);
+
+    DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
+    dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
+    return true;
+}
+#else
+static bool tryDFGCompile(ExecState*, CodeBlock*, JITCode&) { return false; }
+static bool tryDFGCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+#endif
+
 class ExecutableFinalizer : public WeakHandleOwner {
     virtual void finalize(Handle<Unknown> handle, void*)
     {
@@ -226,7 +271,9 @@
 
 #if ENABLE(JIT)
     if (exec->globalData().canUseJIT()) {
-        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get());
+        bool dfgCompiled = tryDFGCompile(exec, m_programCodeBlock.get(), m_jitCodeForCall);
+        if (!dfgCompiled)
+            m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get());
 #if !ENABLE(OPCODE_SAMPLING)
         if (!BytecodeGenerator::dumpsGeneratedCode())
             m_programCodeBlock->discardBytecode();
@@ -258,36 +305,6 @@
 #endif
 }
 
-#if ENABLE(JIT)
-static bool tryDFGCompile(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
-{
-    JSGlobalData* globalData = &exec->globalData();
-#if ENABLE(DFG_JIT)
-#if ENABLE(DFG_JIT_RESTRICTIONS)
-    // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
-    if (codeBlock->numberOfJumpTargets())
-        return false;
-#endif
-
-    DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
-    if (!parse(dfg, globalData, codeBlock))
-        return false;
-
-    dfg.predictArgumentTypes(exec);
-
-    DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
-    dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
-    return true;
-#else
-    UNUSED_PARAM(globalData);
-    UNUSED_PARAM(codeBlock);
-    UNUSED_PARAM(jitCode);
-    UNUSED_PARAM(jitCodeWithArityCheck);
-    return false;
-#endif
-}
-#endif
-
 void ProgramExecutable::visitChildren(SlotVisitor& visitor)
 {
     ASSERT_GC_OBJECT_INHERITS(this, &s_info);
@@ -332,7 +349,7 @@
 
 #if ENABLE(JIT)
     if (exec->globalData().canUseJIT()) {
-        bool dfgCompiled = tryDFGCompile(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
+        bool dfgCompiled = tryDFGCompileFunction(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
         if (!dfgCompiled)
             m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to