Improve peformance of local variable initialisation.
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Sep 2008 03:00:43 +0000 (03:00 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Sep 2008 03:00:43 +0000 (03:00 +0000)
Reviewed by Maciej Stachowiak

Pull local and constant initialisation out of slideRegisterWindowForCall
and into its own opcode.  This allows the JIT to generate the initialisation
code for a function directly into the instruction stream and so avoids a few
branches on function entry.

Results a 1% progression in SunSpider, particularly in a number of the bitop
tests where the called functions are very fast.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@36695 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/VM/CTI.cpp
JavaScriptCore/VM/CTI.h
JavaScriptCore/VM/CodeBlock.cpp
JavaScriptCore/VM/CodeGenerator.cpp
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/VM/Opcode.h

index 039eaa1..e1bd116 100644 (file)
@@ -1,3 +1,30 @@
+2008-09-19  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Improve peformance of local variable initialisation.
+
+        Pull local and constant initialisation out of slideRegisterWindowForCall
+        and into its own opcode.  This allows the JIT to generate the initialisation
+        code for a function directly into the instruction stream and so avoids a few
+        branches on function entry.
+
+        Results a 1% progression in SunSpider, particularly in a number of the bitop
+        tests where the called functions are very fast. 
+
+        * VM/CTI.cpp:
+        (JSC::CTI::emitInitialiseRegister):
+        (JSC::CTI::privateCompileMainPass):
+        * VM/CTI.h:
+        * VM/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        * VM/CodeGenerator.cpp:
+        (JSC::CodeGenerator::CodeGenerator):
+        * VM/Machine.cpp:
+        (JSC::slideRegisterWindowForCall):
+        (JSC::Machine::privateExecute):
+        * VM/Opcode.h:
+
 2008-09-19  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Darin Adler.
index b233e3b..2cf5293 100644 (file)
@@ -180,6 +180,12 @@ ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, X86Assembler::RegisterID fro
     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
 }
 
+ALWAYS_INLINE void CTI::emitInitialiseRegister(unsigned dst)
+{
+    m_jit.movl_i32m(reinterpret_cast<unsigned>(jsUndefined()), dst * sizeof(Register), X86::edi);
+    // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
+}
+
 #if ENABLE(SAMPLING_TOOL)
 unsigned inCalledCode = 0;
 #endif
@@ -525,6 +531,13 @@ void CTI::emitSlowScriptCheck(unsigned opcodeIndex)
 
 void CTI::privateCompileMainPass()
 {
+    if (m_codeBlock->codeType == FunctionCode) {
+        for (int i = -m_codeBlock->numVars; i < 0; i++)
+            emitInitialiseRegister(i);
+    }
+    for (size_t i = 0; i < m_codeBlock->constantRegisters.size(); ++i)
+        emitInitialiseRegister(i);
+
     Instruction* instruction = m_codeBlock->instructions.begin();
     unsigned instructionCount = m_codeBlock->instructions.size();
 
@@ -1521,6 +1534,10 @@ void CTI::privateCompileMainPass()
             i += 3;
             break;
         }
+        case op_initialise_locals: {
+            i++;
+            break;
+        }
         case op_get_array_length:
         case op_get_by_id_chain:
         case op_get_by_id_generic:
index 657a65d..4350afd 100644 (file)
@@ -345,6 +345,8 @@ namespace JSC {
         void emitPutArgConstant(unsigned value, unsigned offset);
         void emitPutResult(unsigned dst, X86Assembler::RegisterID from = X86::eax);
 
+        void emitInitialiseRegister(unsigned dst);
+
         void emitPutCTIParam(void* value, unsigned name);
         void emitPutCTIParam(X86Assembler::RegisterID from, unsigned name);
         void emitGetCTIParam(unsigned name, X86Assembler::RegisterID to);
index 6b40c85..af3b354 100644 (file)
@@ -351,6 +351,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
 {
     int location = it - begin;
     switch (exec->machine()->getOpcodeID(it->u.opcode)) {
+        case op_initialise_locals: {
+            printf("[%4d] initialise_locals\n", location);
+            break;
+        }
         case op_unexpected_load: {
             int r0 = (++it)->u.operand;
             int k0 = (++it)->u.operand;
index ab1bbfe..410ec82 100644 (file)
@@ -268,6 +268,7 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
 {
+    emitOpcode(op_initialise_locals);
     codeBlock->globalData = m_globalData;
 
     m_codeBlock->numConstants = functionBody->neededConstants();
@@ -316,6 +317,7 @@ CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
 {
+    emitOpcode(op_initialise_locals);
     codeBlock->globalData = m_globalData;
 
     m_codeBlock->numConstants = evalNode->neededConstants();
index 8e1ecfb..73323f6 100644 (file)
@@ -543,11 +543,12 @@ ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* n
     }
     
     // initialize local variable slots
-    for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
-        (*it) = jsUndefined();
+#if ENABLE(CTI)
+    if (!newCodeBlock->ctiCode)
+#endif
+    {
 
-    for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
-        r[i] = newCodeBlock->constantRegisters[i];
+    }
 
     return r;
 }
@@ -3343,6 +3344,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
 
         NEXT_OPCODE;
     }
+    BEGIN_OPCODE(op_initialise_locals) {
+        for (Register* it = r - codeBlock->numVars + (codeBlock->codeType == EvalCode); it < r; ++it)
+            (*it) = jsUndefined();
+        for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
+            r[i] = codeBlock->constantRegisters[i];
+        ++vPC;
+        NEXT_OPCODE;
+    }
     BEGIN_OPCODE(op_construct) {
         /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n)
 
index 7181bc7..46ac05c 100644 (file)
@@ -40,6 +40,7 @@ namespace JSC {
 #define DUMP_OPCODE_STATS 0
 
     #define FOR_EACH_OPCODE_ID(macro) \
+        macro(op_initialise_locals) \
         macro(op_unexpected_load) \
         macro(op_new_object) \
         macro(op_new_array) \