Inline immediate number version of op_mul.
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Sep 2008 02:10:47 +0000 (02:10 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Sep 2008 02:10:47 +0000 (02:10 +0000)
Reviewed by Geoff Garen

Renamed mull_rr to imull_rr as that's what it's
actually doing, and added imull_i32r for the constant
case immediate multiply.

1.1% improvement to SunSpider.

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

JavaScriptCore/ChangeLog
JavaScriptCore/VM/CTI.cpp
JavaScriptCore/masm/X86Assembler.h

index 9c8e90e..98e714e 100644 (file)
@@ -1,3 +1,23 @@
+2008-09-10  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Inline immediate number version of op_mul.
+
+        Renamed mull_rr to imull_rr as that's what it's 
+        actually doing, and added imull_i32r for the constant
+        case immediate multiply.
+
+        1.1% improvement to SunSpider.
+
+        * VM/CTI.cpp:
+        (JSC::CTI::privateCompileMainPass):
+        (JSC::CTI::privateCompileSlowCases):
+        * masm/X86Assembler.h:
+        (JSC::X86Assembler::):
+        (JSC::X86Assembler::imull_rr):
+        (JSC::X86Assembler::imull_i32r):
+
 2008-09-10  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
 
         Not reviewed.
index 1f60a72..2b13a4d 100644 (file)
@@ -614,7 +614,43 @@ void CTI::privateCompileMainPass()
             i += 4;
             break;
         }
-        CTI_COMPILE_BINARY_OP(op_mul);
+        case op_mul: {
+            unsigned dst = instruction[i + 1].u.operand;
+            unsigned src1 = instruction[i + 2].u.operand;
+            unsigned src2 = instruction[i + 3].u.operand;
+            if (src1 < m_codeBlock->constantRegisters.size() || src2 < m_codeBlock->constantRegisters.size()) {
+                unsigned constant = src1;
+                unsigned nonconstant = src2;
+                if (!(src1 < m_codeBlock->constantRegisters.size())) {
+                    constant = src2;
+                    nonconstant = src1;
+                }
+                JSValue* value = m_codeBlock->constantRegisters[constant].jsValue(m_exec);
+                if (JSImmediate::isNumber(value)) {
+                    emitGetArg(nonconstant, X86::eax);
+                    emitJumpSlowCaseIfNotImm(X86::eax, i);
+                    emitFastArithImmToInt(X86::eax);
+                    m_jit.imull_i32r( X86::eax, getDeTaggedConstantImmediate(value), X86::eax);
+                    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+                    emitFastArithPotentiallyReTagImmediate(X86::eax);
+                    emitPutResult(dst);
+                    i += 4;
+                    break;
+                }
+            }
+
+            emitGetArg(src1, X86::eax);
+            emitGetArg(src2, X86::edx);
+            emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
+            emitFastArithDeTagImmediate(X86::eax);
+            emitFastArithImmToInt(X86::edx);
+            m_jit.imull_rr(X86::edx, X86::eax);
+            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
+            emitFastArithPotentiallyReTagImmediate(X86::eax);
+            emitPutResult(dst);
+            i += 4;
+            break;
+        }
         case op_new_func: {
             FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
@@ -1282,12 +1318,23 @@ void CTI::privateCompileLinkPass()
     m_jmpTable.clear();
 }
 
+#define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \
+    case name: { \
+        m_jit.link(iter->from, m_jit.label()); \
+        emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
+        emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \
+        emitCall(i, Machine::cti_##name); \
+        emitPutResult(instruction[i + 1].u.operand); \
+        i += 4; \
+        break; \
+    }
+    
 void CTI::privateCompileSlowCases()
 {
     Instruction* instruction = m_codeBlock->instructions.begin();
     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
         int i = iter->to;
-       m_jit.emitRestoreArgumentReference();
+        m_jit.emitRestoreArgumentReference();
         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
         case op_add: {
             unsigned dst = instruction[i + 1].u.operand;
@@ -1589,6 +1636,7 @@ void CTI::privateCompileSlowCases()
             i += 4;
             break;
         }
+        CTI_COMPILE_BINARY_OP_SLOW_CASE(op_mul);
         default:
             ASSERT_NOT_REACHED();
             break;
index 8a53f28..0255dcb 100644 (file)
@@ -182,6 +182,7 @@ public:
         OP_PUSH_EAX                     = 0x50,
         OP_POP_EAX                      = 0x58,
         PRE_OPERAND_SIZE                = 0x66,
+        OP_IMUL_GvEvIz                  = 0x69,
         OP_GROUP1_EvIz                  = 0x81,
         OP_GROUP1_EvIb                  = 0x83,
         OP_TEST_EvGv                    = 0x85,
@@ -211,7 +212,7 @@ public:
         OP2_JL_rel32    = 0x8C,
         OP2_JGE_rel32   = 0x8D,
         OP2_JLE_rel32   = 0x8E,
-        OP2_MUL_GvEv    = 0xAF,
+        OP2_IMUL_GvEv   = 0xAF,
         OP2_MOVZX_GvEw  = 0xB7,
 
         GROUP1_OP_ADD = 0,
@@ -472,12 +473,19 @@ public:
         emitModRm_opr(GROUP2_OP_SHL, dst);
     }
 
-    void mull_rr(RegisterID src, RegisterID dst)
+    void imull_rr(RegisterID src, RegisterID dst)
     {
         m_buffer->putByte(OP_2BYTE_ESCAPE);
-        m_buffer->putByte(OP2_MUL_GvEv);
+        m_buffer->putByte(OP2_IMUL_GvEv);
         emitModRm_rr(dst, src);
     }
+    
+    void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
+    {
+        m_buffer->putByte(OP_IMUL_GvEvIz);
+        emitModRm_rr(dst, src);
+        m_buffer->putInt(value);
+    }
 
     void idivl_r(RegisterID dst)
     {