2008-09-23 Maciej Stachowiak <mjs@apple.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Sep 2008 13:20:23 +0000 (13:20 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Sep 2008 13:20:23 +0000 (13:20 +0000)
        Reviewed by Cameron Zwarich.

        - inline the fast cases of !==, same as for ===

        2.9% speedup on EarleyBoyer benchmark

        * VM/CTI.cpp:
        (JSC::CTI::compileOpStrictEq): Factored stricteq codegen into this function,
        and parameterized so it can do the reverse version as well.
        (JSC::CTI::privateCompileMainPass): Use the above for stricteq and nstricteq.
        * VM/CTI.h:
        (JSC::CTI::): Declare above stuff.
        * VM/Machine.cpp:
        (JSC::Machine::cti_op_nstricteq): Removed fast cases, now handled inline.

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

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

index 2db959a135991b129f2d1ecd875671cc395d2f38..f9df92c46758577e4d571f2e672bf7313c4426be 100644 (file)
@@ -1,3 +1,20 @@
+2008-09-23  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Cameron Zwarich.
+
+        - inline the fast cases of !==, same as for ===
+        
+        2.9% speedup on EarleyBoyer benchmark
+
+        * VM/CTI.cpp:
+        (JSC::CTI::compileOpStrictEq): Factored stricteq codegen into this function,
+        and parameterized so it can do the reverse version as well.
+        (JSC::CTI::privateCompileMainPass): Use the above for stricteq and nstricteq.
+        * VM/CTI.h:
+        (JSC::CTI::): Declare above stuff.
+        * VM/Machine.cpp:
+        (JSC::Machine::cti_op_nstricteq): Removed fast cases, now handled inline.
+
 2008-09-23  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
 
         Reviewed by Oliver Hunt.
index fc3946b6dcf19e3abecf93557528ac043ebc580e..6859cc4c0cba01caee450b29115ba7aeb2596aa6 100644 (file)
@@ -522,6 +522,62 @@ void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType
     emitPutResult(dst);
 }
 
+void CTI::compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type)
+{
+    bool negated = (type == OpNStrictEq);
+
+    unsigned dst = instruction[i + 1].u.operand;
+    unsigned src1 = instruction[i + 2].u.operand;
+    unsigned src2 = instruction[i + 3].u.operand;
+
+    emitGetArg(src1, X86::eax);
+    emitGetArg(src2, X86::edx);
+
+    m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
+    X86Assembler::JmpSrc firstNotImmediate = m_jit.emitUnlinkedJe();
+    m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
+    X86Assembler::JmpSrc secondNotImmediate = m_jit.emitUnlinkedJe();
+
+    m_jit.cmpl_rr(X86::edx, X86::eax);
+    if (negated)
+        m_jit.setne_r(X86::eax);
+    else
+        m_jit.sete_r(X86::eax);
+    m_jit.movzbl_rr(X86::eax, X86::eax);
+    emitTagAsBoolImmediate(X86::eax);
+            
+    X86Assembler::JmpSrc bothWereImmediates = m_jit.emitUnlinkedJmp();
+
+    m_jit.link(firstNotImmediate, m_jit.label());
+
+    // check that edx is immediate but not the zero immediate
+    m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
+    m_jit.setz_r(X86::ecx);
+    m_jit.movzbl_rr(X86::ecx, X86::ecx); // ecx is now 1 if edx was nonimmediate
+    m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::edx);
+    m_jit.sete_r(X86::edx);
+    m_jit.movzbl_rr(X86::edx, X86::edx); // edx is now 1 if edx was the 0 immediate
+    m_jit.orl_rr(X86::ecx, X86::edx);
+
+    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i));
+
+    m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(negated)), X86::eax);
+
+    X86Assembler::JmpSrc firstWasNotImmediate = m_jit.emitUnlinkedJmp();
+
+    m_jit.link(secondNotImmediate, m_jit.label());
+    // check that eax is not the zero immediate (we know it must be immediate)
+    m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
+    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
+
+    m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(negated)), X86::eax);
+
+    m_jit.link(bothWereImmediates, m_jit.label());
+    m_jit.link(firstWasNotImmediate, m_jit.label());
+
+    emitPutResult(dst);
+}
+
 void CTI::emitSlowScriptCheck(unsigned opcodeIndex)
 {
     m_jit.subl_i8r(1, X86::esi);
@@ -1391,57 +1447,13 @@ void CTI::privateCompileMainPass()
         CTI_COMPILE_UNARY_OP(op_is_string)
         CTI_COMPILE_UNARY_OP(op_is_object)
         CTI_COMPILE_UNARY_OP(op_is_function)
-        CTI_COMPILE_BINARY_OP(op_nstricteq)
         case op_stricteq: {
-            unsigned dst = instruction[i + 1].u.operand;
-            unsigned src1 = instruction[i + 2].u.operand;
-            unsigned src2 = instruction[i + 3].u.operand;
-
-            emitGetArg(src1, X86::eax);
-            emitGetArg(src2, X86::edx);
-
-            m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
-            X86Assembler::JmpSrc firstNotImmediate = m_jit.emitUnlinkedJe();
-            m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
-            X86Assembler::JmpSrc secondNotImmediate = m_jit.emitUnlinkedJe();
-
-            m_jit.cmpl_rr(X86::edx, X86::eax);
-            m_jit.sete_r(X86::eax);
-            m_jit.movzbl_rr(X86::eax, X86::eax);
-            emitTagAsBoolImmediate(X86::eax);
-            
-            X86Assembler::JmpSrc bothWereImmediates = m_jit.emitUnlinkedJmp();
-
-            m_jit.link(firstNotImmediate, m_jit.label());
-
-            // check that edx is immediate but not the zero immediate
-            
-            m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
-            m_jit.setz_r(X86::ecx);
-            m_jit.movzbl_rr(X86::ecx, X86::ecx); // ecx is now 1 if edx was nonimmediate
-            m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::edx);
-            m_jit.sete_r(X86::edx);
-            m_jit.movzbl_rr(X86::edx, X86::edx); // edx is now 1 if edx was the 0 immediate
-            m_jit.orl_rr(X86::ecx, X86::edx);
-
-            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i));
-
-            m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(false)), X86::eax);
-
-            X86Assembler::JmpSrc firstWasNotImmediate = m_jit.emitUnlinkedJmp();
-
-            m_jit.link(secondNotImmediate, m_jit.label());
-            // check that eax is not the zero immediate (we know it must be immediate)
-            m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
-            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
-
-            m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(false)), X86::eax);
-
-            m_jit.link(bothWereImmediates, m_jit.label());
-            m_jit.link(firstWasNotImmediate, m_jit.label());
-
-            emitPutResult(dst);
-            
+            compileOpStrictEq(instruction, i, OpStrictEq);
+            i += 4;
+            break;
+        }
+        case op_nstricteq: {
+            compileOpStrictEq(instruction, i, OpNStrictEq);
             i += 4;
             break;
         }
index c0bbae500649292b5aadede5b329593f523f5639..156e4ee7590dadd74ea12d06093ee333a6c57bfc 100644 (file)
@@ -338,6 +338,8 @@ namespace JSC {
 
         enum CompileOpCallType { OpCallNormal, OpCallEval, OpConstruct };
         void compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type = OpCallNormal);
+        enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
+        void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
 
         void emitGetArg(unsigned src, X86Assembler::RegisterID dst);
         void emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch);
index 7662fdddc257185d100c89385bf028cb69e0195c..900cfec47b470a54d98075bdf1dae055f7b867ff 100644 (file)
@@ -5351,10 +5351,9 @@ JSValue* Machine::cti_op_nstricteq(CTI_ARGS)
     JSValue* src1 = ARG_src1;
     JSValue* src2 = ARG_src2;
 
-    if (JSImmediate::areBothImmediate(src1, src2))
-        return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
-    if (JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate()))
-        return jsBoolean(true);
+    // handled inline as fast cases
+    ASSERT(!JSImmediate::areBothImmediate(src1, src2));
+    ASSERT(!(JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate())));
     
     return jsBoolean(!strictEqualSlowCaseInline(src1, src2));
 }