2008-09-14 Maciej Stachowiak <mjs@apple.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Sep 2008 06:26:15 +0000 (06:26 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Sep 2008 06:26:15 +0000 (06:26 +0000)
        Reviewed by Cameron Zwarich.

        - speed up JS construction by extracting "prototype" lookup so PIC applies.

        ~0.5% speedup on SunSpider
        Speeds up some of the V8 tests as well, most notably earley-boyer.

        * VM/CTI.cpp:
        (JSC::CTI::compileOpCall): Account for extra arg for prototype.
        (JSC::CTI::privateCompileMainPass): Account for increased size of op_construct.
        * VM/CodeGenerator.cpp:
        (JSC::CodeGenerator::emitConstruct): Emit separate lookup to get prototype property.
        * VM/Machine.cpp:
        (JSC::Machine::privateExecute): Expect prototype arg in op_construct.
        (JSC::Machine::cti_op_construct_JSConstruct): ditto
        (JSC::Machine::cti_op_construct_NotJSConstruct): ditto

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

JavaScriptCore/ChangeLog
JavaScriptCore/VM/CTI.cpp
JavaScriptCore/VM/CodeGenerator.cpp
JavaScriptCore/VM/Machine.cpp

index 4f5ec15ae480317fcb13d30aa2885071838230af..80bf354d80d389e25d5864f5c937bf8b1086c114 100644 (file)
@@ -1,3 +1,22 @@
+2008-09-14  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Cameron Zwarich.
+        
+        - speed up JS construction by extracting "prototype" lookup so PIC applies.
+        
+        ~0.5% speedup on SunSpider
+        Speeds up some of the V8 tests as well, most notably earley-boyer.
+
+        * VM/CTI.cpp:
+        (JSC::CTI::compileOpCall): Account for extra arg for prototype.
+        (JSC::CTI::privateCompileMainPass): Account for increased size of op_construct.
+        * VM/CodeGenerator.cpp:
+        (JSC::CodeGenerator::emitConstruct): Emit separate lookup to get prototype property.
+        * VM/Machine.cpp:
+        (JSC::Machine::privateExecute): Expect prototype arg in op_construct.
+        (JSC::Machine::cti_op_construct_JSConstruct): ditto
+        (JSC::Machine::cti_op_construct_NotJSConstruct): ditto
+
 2008-09-10  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Eric Seidel.
index 2e5b4d3faec0a8f1341190d48b9579e1294233e8..6a2a36d9a8566863de20fbdc12777a6c8a6ffcd9 100644 (file)
@@ -412,9 +412,10 @@ OpcodeID currentOpcodeID = static_cast<OpcodeID>(-1);
 void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type)
 {
     if (type == OpConstruct) {
-        emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 12);
+        emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
+        emitPutArgConstant(instruction[i + 5].u.operand, 12);
         emitPutArgConstant(instruction[i + 4].u.operand, 8);
-        emitPutArgConstant(instruction[i + 3].u.operand, 4);
+        emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
     } else {
         emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
         emitPutArgConstant(instruction[i + 5].u.operand, 12);
@@ -433,7 +434,7 @@ void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType
         emitCall(i, Machine::cti_op_call_eval);
         m_jit.emitRestoreArgumentReference();
 
-       emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
+        emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
 
         m_jit.cmpl_i32r(reinterpret_cast<unsigned>(JSImmediate::impossibleValue()), X86::eax);
         wasEval = m_jit.emitUnlinkedJne();
@@ -824,7 +825,7 @@ void CTI::privateCompileMainPass()
         }
         case op_construct: {
             compileOpCall(instruction, i, OpConstruct);
-            i += 5;
+            i += 6;
             break;
         }
         case op_get_by_val: {
index af3d952c4802809b3405a32b8096804679f7f8e9..c4f878a4d192154a4792be7ddee14cc18545bda5 100644 (file)
@@ -1100,6 +1100,11 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
     // op_construct will read "func" before writing out the call frame, so this
     // is safe.
 
+    RefPtr<RegisterID> protectFunc = func;
+
+    // Reserve space for prototype
+    RefPtr<RegisterID> funcProto = newTemporary();
+
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
@@ -1113,9 +1118,12 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
         emitNode(argv.last().get(), n);
     }
 
+    emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype);
+
     emitOpcode(op_construct);
     instructions().append(dst->index());
     instructions().append(func->index());
+    instructions().append(funcProto->index());
     instructions().append(argv.size() ? argv[0]->index() : m_temporaries.size()); // argv
     instructions().append(argv.size()); // argc
     return dst;
index 635b235fd4b8a14f1ba736fb782bdc930ccd41e7..c613de575915835f780ddb1118e4f6c29683b70b 100644 (file)
@@ -3279,7 +3279,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         NEXT_OPCODE;
     }
     BEGIN_OPCODE(op_construct) {
-        /* construct dst(r) constr(r) firstArg(r) argCount(n)
+        /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n)
 
            Invoke register "constr" as a constructor. For JS
            functions, the calling convention is exactly as for the
@@ -3287,10 +3287,15 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
            created Object. For native constructors, a null "this"
            value is passed. In either case, the firstArg and argCount
            registers are interpreted as for the "call" opcode.
+
+           Register constrProto must contain the prototype property of
+           register constsr. This is to enable polymorphic inline
+           caching of this lookup.
         */
 
         int dst = (++vPC)->u.operand;
         int constr = (++vPC)->u.operand;
+        int constrProto = (++vPC)->u.operand;
         int firstArg = (++vPC)->u.operand;
         int argCount = (++vPC)->u.operand;
 
@@ -3307,7 +3312,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
                 (*enabledProfilerReference)->willExecute(exec, constructor);
 
             JSObject* prototype;
-            JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
+            JSValue* p = r[constrProto].jsValue(exec);
             if (p->isObject())
                 prototype = static_cast<JSObject*>(p);
             else
@@ -4429,8 +4434,9 @@ void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
     Register* registerBase = registerFile->base();
     
     JSValue* constrVal = ARG_src1;
-    int firstArg = ARG_int2;
-    int argCount = ARG_int3;
+    JSValue* constrProtoVal = ARG_src2;
+    int firstArg = ARG_int3;
+    int argCount = ARG_int4;
 
     ConstructData constructData;
 #ifndef NDEBUG
@@ -4438,7 +4444,7 @@ void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
 #endif
         constrVal->getConstructData(constructData);
 
-    // Removing this line of code causes a measurable regression on squirrelfish.
+    // Removing this line of code causes a measurable regression on sunspider.
     JSObject* constructor = static_cast<JSObject*>(constrVal);
 
     ASSERT(constructType == ConstructTypeJS);
@@ -4447,7 +4453,7 @@ void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
         (*ARG_profilerReference)->willExecute(exec, constructor);
 
     JSObject* prototype;
-    JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
+    JSValue* p = constrProtoVal;
     if (p->isObject())
         prototype = static_cast<JSObject*>(p);
     else
@@ -4485,8 +4491,8 @@ JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS)
     Register* r = ARG_r;
 
     JSValue* constrVal = ARG_src1;
-    int firstArg = ARG_int2;
-    int argCount = ARG_int3;
+    int firstArg = ARG_int3;
+    int argCount = ARG_int4;
 
     ConstructData constructData;
     ConstructType constructType = constrVal->getConstructData(constructData);