2009-01-08 Gavin Barraclough <barraclough@apple.com>
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Jan 2009 08:11:00 +0000 (08:11 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Jan 2009 08:11:00 +0000 (08:11 +0000)
        Reviewed by Oliver Hunt.

        Encode immediates in the low word of JSValuePtrs, on x86-64.

        On 32-bit platforms a JSValuePtr may represent a 31-bit signed integer.
        On 64-bit platforms, if USE(ALTERNATE_JSIMMEDIATE) is defined, a full
        32-bit integer may be stored in an immediate.

        Presently USE(ALTERNATE_JSIMMEDIATE) uses the same encoding as the default
        immediate format - the value is left shifted by one, so a one bit tag can
        be added to indicate the value is an immediate.  However this means that
        values must be commonly be detagged (by right shifting by one) before
        arithmetic operations can be performed on immediates.  This patch modifies
        the formattting so the the high bits of the immediate mark values as being
        integer.

        * assembler/MacroAssembler.h:
        (JSC::MacroAssembler::not32):
        (JSC::MacroAssembler::orPtr):
        (JSC::MacroAssembler::zeroExtend32ToPtr):
        (JSC::MacroAssembler::jaePtr):
        (JSC::MacroAssembler::jbPtr):
        (JSC::MacroAssembler::jnzPtr):
        (JSC::MacroAssembler::jzPtr):
        * assembler/X86Assembler.h:
        (JSC::X86Assembler::):
        (JSC::X86Assembler::notl_r):
        (JSC::X86Assembler::testq_i32r):
        * jit/JIT.cpp:
        (JSC::JIT::privateCompileMainPass):
        (JSC::JIT::privateCompileSlowCases):
        (JSC::JIT::privateCompileCTIMachineTrampolines):
        * jit/JIT.h:
        * jit/JITArithmetic.cpp:
        (JSC::JIT::compileFastArith_op_lshift):
        (JSC::JIT::compileFastArith_op_rshift):
        (JSC::JIT::compileFastArith_op_bitand):
        (JSC::JIT::compileFastArithSlow_op_bitand):
        (JSC::JIT::compileFastArith_op_mod):
        (JSC::JIT::compileFastArithSlow_op_mod):
        (JSC::JIT::compileFastArith_op_add):
        (JSC::JIT::compileFastArith_op_mul):
        (JSC::JIT::compileFastArith_op_post_inc):
        (JSC::JIT::compileFastArith_op_post_dec):
        (JSC::JIT::compileFastArith_op_pre_inc):
        (JSC::JIT::compileFastArith_op_pre_dec):
        (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate):
        (JSC::JIT::compileBinaryArithOp):
        * jit/JITCall.cpp:
        (JSC::JIT::compileOpCallSlowCase):
        * jit/JITInlineMethods.h:
        (JSC::JIT::emitJumpIfJSCell):
        (JSC::JIT::emitJumpIfNotJSCell):
        (JSC::JIT::emitJumpIfImmNum):
        (JSC::JIT::emitJumpSlowCaseIfNotImmNum):
        (JSC::JIT::emitJumpSlowCaseIfNotImmNums):
        (JSC::JIT::emitFastArithDeTagImmediate):
        (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero):
        (JSC::JIT::emitFastArithReTagImmediate):
        (JSC::JIT::emitFastArithImmToInt):
        (JSC::JIT::emitFastArithIntToImmNoCheck):
        (JSC::JIT::emitTagAsBoolImmediate):
        * jit/JITPropertyAccess.cpp:
        (JSC::resizePropertyStorage):
        (JSC::JIT::privateCompilePutByIdTransition):
        (JSC::JIT::privateCompilePatchGetArrayLength):
        (JSC::JIT::privateCompileGetByIdSelf):
        (JSC::JIT::privateCompileGetByIdProto):
        (JSC::JIT::privateCompileGetByIdChain):
        (JSC::JIT::privateCompilePutByIdReplace):
        * runtime/JSImmediate.h:
        (JSC::JSImmediate::isNumber):
        (JSC::JSImmediate::isPositiveNumber):
        (JSC::JSImmediate::areBothImmediateNumbers):
        (JSC::JSImmediate::xorImmediateNumbers):
        (JSC::JSImmediate::rightShiftImmediateNumbers):
        (JSC::JSImmediate::canDoFastAdditiveOperations):
        (JSC::JSImmediate::addImmediateNumbers):
        (JSC::JSImmediate::subImmediateNumbers):
        (JSC::JSImmediate::makeInt):
        (JSC::JSImmediate::toBoolean):
        * wtf/Platform.h:

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

JavaScriptCore/ChangeLog
JavaScriptCore/assembler/MacroAssembler.h
JavaScriptCore/assembler/X86Assembler.h
JavaScriptCore/jit/JIT.cpp
JavaScriptCore/jit/JIT.h
JavaScriptCore/jit/JITArithmetic.cpp
JavaScriptCore/jit/JITCall.cpp
JavaScriptCore/jit/JITInlineMethods.h
JavaScriptCore/jit/JITPropertyAccess.cpp
JavaScriptCore/runtime/JSImmediate.h
JavaScriptCore/wtf/Platform.h

index f910614..f79493f 100644 (file)
@@ -1,3 +1,88 @@
+2009-01-08  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Encode immediates in the low word of JSValuePtrs, on x86-64.
+
+        On 32-bit platforms a JSValuePtr may represent a 31-bit signed integer.
+        On 64-bit platforms, if USE(ALTERNATE_JSIMMEDIATE) is defined, a full
+        32-bit integer may be stored in an immediate.
+        
+        Presently USE(ALTERNATE_JSIMMEDIATE) uses the same encoding as the default
+        immediate format - the value is left shifted by one, so a one bit tag can
+        be added to indicate the value is an immediate.  However this means that
+        values must be commonly be detagged (by right shifting by one) before
+        arithmetic operations can be performed on immediates.  This patch modifies
+        the formattting so the the high bits of the immediate mark values as being
+        integer.
+
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::not32):
+        (JSC::MacroAssembler::orPtr):
+        (JSC::MacroAssembler::zeroExtend32ToPtr):
+        (JSC::MacroAssembler::jaePtr):
+        (JSC::MacroAssembler::jbPtr):
+        (JSC::MacroAssembler::jnzPtr):
+        (JSC::MacroAssembler::jzPtr):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::):
+        (JSC::X86Assembler::notl_r):
+        (JSC::X86Assembler::testq_i32r):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        (JSC::JIT::privateCompileCTIMachineTrampolines):
+        * jit/JIT.h:
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::compileFastArith_op_lshift):
+        (JSC::JIT::compileFastArith_op_rshift):
+        (JSC::JIT::compileFastArith_op_bitand):
+        (JSC::JIT::compileFastArithSlow_op_bitand):
+        (JSC::JIT::compileFastArith_op_mod):
+        (JSC::JIT::compileFastArithSlow_op_mod):
+        (JSC::JIT::compileFastArith_op_add):
+        (JSC::JIT::compileFastArith_op_mul):
+        (JSC::JIT::compileFastArith_op_post_inc):
+        (JSC::JIT::compileFastArith_op_post_dec):
+        (JSC::JIT::compileFastArith_op_pre_inc):
+        (JSC::JIT::compileFastArith_op_pre_dec):
+        (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate):
+        (JSC::JIT::compileBinaryArithOp):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitJumpIfJSCell):
+        (JSC::JIT::emitJumpIfNotJSCell):
+        (JSC::JIT::emitJumpIfImmNum):
+        (JSC::JIT::emitJumpSlowCaseIfNotImmNum):
+        (JSC::JIT::emitJumpSlowCaseIfNotImmNums):
+        (JSC::JIT::emitFastArithDeTagImmediate):
+        (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero):
+        (JSC::JIT::emitFastArithReTagImmediate):
+        (JSC::JIT::emitFastArithImmToInt):
+        (JSC::JIT::emitFastArithIntToImmNoCheck):
+        (JSC::JIT::emitTagAsBoolImmediate):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::resizePropertyStorage):
+        (JSC::JIT::privateCompilePutByIdTransition):
+        (JSC::JIT::privateCompilePatchGetArrayLength):
+        (JSC::JIT::privateCompileGetByIdSelf):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdChain):
+        (JSC::JIT::privateCompilePutByIdReplace):
+        * runtime/JSImmediate.h:
+        (JSC::JSImmediate::isNumber):
+        (JSC::JSImmediate::isPositiveNumber):
+        (JSC::JSImmediate::areBothImmediateNumbers):
+        (JSC::JSImmediate::xorImmediateNumbers):
+        (JSC::JSImmediate::rightShiftImmediateNumbers):
+        (JSC::JSImmediate::canDoFastAdditiveOperations):
+        (JSC::JSImmediate::addImmediateNumbers):
+        (JSC::JSImmediate::subImmediateNumbers):
+        (JSC::JSImmediate::makeInt):
+        (JSC::JSImmediate::toBoolean):
+        * wtf/Platform.h:
+
 2009-01-08  Sam Weinig  <sam@webkit.org>
 
         Revert r39720. It broke Interpreted mode.
index aad075e..9f8d474 100644 (file)
@@ -579,6 +579,11 @@ public:
         m_assembler.imull_i32r(src, imm.m_value, dest);
     }
     
+    void not32(RegisterID srcDest)
+    {
+        m_assembler.notl_r(srcDest);
+    }
+    
     void orPtr(RegisterID src, RegisterID dest)
     {
 #if PLATFORM(X86_64)
@@ -588,6 +593,16 @@ public:
 #endif
     }
 
+    void orPtr(ImmPtr imm, RegisterID dest)
+    {
+#if PLATFORM(X86_64)
+        move(imm, scratchRegister);
+        m_assembler.orq_rr(scratchRegister, dest);
+#else
+        or32(Imm32(imm), dest);
+#endif
+    }
+
     void orPtr(Imm32 imm, RegisterID dest)
     {
 #if PLATFORM(X86_64)
@@ -1002,6 +1017,15 @@ public:
 #endif
     }
 
+    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+#if PLATFORM(X86_64)
+        m_assembler.movl_rr(src, dest);
+#else
+        if (src != dest)
+            move(src, dest);
+#endif
+    }
 
 
     // Forwards / external control flow operations:
@@ -1117,6 +1141,38 @@ public:
         return Jump(m_assembler.ja());
     }
     
+    Jump jaePtr(RegisterID left, RegisterID right)
+    {
+#if PLATFORM(X86_64)
+        m_assembler.cmpq_rr(right, left);
+        return Jump(m_assembler.jae());
+#else
+        return jae32(left, right);
+#endif
+    }
+
+    Jump jaePtr(RegisterID reg, ImmPtr ptr)
+    {
+#if PLATFORM(X86_64)
+        intptr_t imm = ptr.asIntptr();
+        if (CAN_SIGN_EXTEND_32_64(imm)) {
+            compareImm64ForBranch(reg, imm);
+            return Jump(m_assembler.jae());
+        } else {
+            move(ptr, scratchRegister);
+            return jaePtr(reg, scratchRegister);
+        }
+#else
+        return jae32(reg, Imm32(ptr));
+#endif
+    }
+
+    Jump jae32(RegisterID left, RegisterID right)
+    {
+        m_assembler.cmpl_rr(right, left);
+        return Jump(m_assembler.jae());
+    }
+
     Jump jae32(RegisterID left, Imm32 right)
     {
         compareImm32ForBranch(left, right.m_value);
@@ -1135,6 +1191,44 @@ public:
         return Jump(m_assembler.jae());
     }
     
+    Jump jbPtr(RegisterID left, RegisterID right)
+    {
+#if PLATFORM(X86_64)
+        m_assembler.cmpq_rr(right, left);
+        return Jump(m_assembler.jb());
+#else
+        return jb32(left, right);
+#endif
+    }
+
+    Jump jbPtr(RegisterID reg, ImmPtr ptr)
+    {
+#if PLATFORM(X86_64)
+        intptr_t imm = ptr.asIntptr();
+        if (CAN_SIGN_EXTEND_32_64(imm)) {
+            compareImm64ForBranch(reg, imm);
+            return Jump(m_assembler.jb());
+        } else {
+            move(ptr, scratchRegister);
+            return jbPtr(reg, scratchRegister);
+        }
+#else
+        return jb32(reg, Imm32(ptr));
+#endif
+    }
+
+    Jump jb32(RegisterID left, RegisterID right)
+    {
+        m_assembler.cmpl_rr(right, left);
+        return Jump(m_assembler.jb());
+    }
+
+    Jump jb32(RegisterID left, Imm32 right)
+    {
+        compareImm32ForBranch(left, right.m_value);
+        return Jump(m_assembler.jb());
+    }
+    
     Jump jb32(RegisterID left, Address right)
     {
         m_assembler.cmpl_mr(right.offset, right.base, left);
@@ -1468,6 +1562,17 @@ public:
 #endif
     }
 
+    Jump jnzPtr(RegisterID reg, ImmPtr mask)
+    {
+#if PLATFORM(X86_64)
+        move(mask, scratchRegister);
+        m_assembler.testq_rr(scratchRegister, reg);
+        return Jump(m_assembler.jne());
+#else
+        return jnz32(reg, Imm32(mask));
+#endif
+    }
+
     Jump jnzPtr(Address address, Imm32 mask = Imm32(-1))
     {
 #if PLATFORM(X86_64)
@@ -1500,6 +1605,17 @@ public:
 #endif
     }
 
+    Jump jzPtr(RegisterID reg, ImmPtr mask)
+    {
+#if PLATFORM(X86_64)
+        move(mask, scratchRegister);
+        m_assembler.testq_rr(scratchRegister, reg);
+        return Jump(m_assembler.je());
+#else
+        return jz32(reg, Imm32(mask));
+#endif
+    }
+
     Jump jzPtr(Address address, Imm32 mask = Imm32(-1))
     {
 #if PLATFORM(X86_64)
index d9e4979..3b0ce65 100644 (file)
@@ -181,6 +181,7 @@ public:
         GROUP2_OP_SAR = 7,
 
         GROUP3_OP_TEST = 0,
+        GROUP3_OP_NOT  = 2,
         GROUP3_OP_IDIV = 7,
 
         GROUP5_OP_CALLN = 2,
@@ -363,6 +364,11 @@ public:
     }
 #endif
 
+    void notl_r(RegisterID dst)
+    {
+        m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
+    }
+
     void orl_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
@@ -715,7 +721,7 @@ public:
 
     void testq_i32r(int imm, RegisterID dst)
     {
-        m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP3_OP_TEST, dst);
+        m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
         m_formatter.immediate32(imm);
     }
 
index bee7cf7..0ce9bc1 100644 (file)
@@ -348,12 +348,17 @@ void JIT::privateCompileMainPass()
             if (isOperandConstantImmediateInt(op2)) {
                 emitGetVirtualRegister(op1, X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
-                addJump(jlPtr(X86::eax, ImmPtr(JSValuePtr::encode(getConstantOperand(op2)))), target + 3);
+#if USE(ALTERNATE_JSIMMEDIATE)
+                int32_t op2imm = JSImmediate::intValue(getConstantOperand(op2));
+#else
+                int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+                addJump(jl32(X86::eax, Imm32(op2imm)), target + 3);
             } else {
                 emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::edx);
-                addJump(jlPtr(X86::eax, X86::edx), target + 3);
+                addJump(jl32(X86::eax, X86::edx), target + 3);
             }
             NEXT_OPCODE(op_loop_if_less);
         }
@@ -366,12 +371,17 @@ void JIT::privateCompileMainPass()
             if (isOperandConstantImmediateInt(op2)) {
                 emitGetVirtualRegister(op1, X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
-                addJump(jlePtr(X86::eax, ImmPtr(JSValuePtr::encode(getConstantOperand(op2)))), target + 3);
+#if USE(ALTERNATE_JSIMMEDIATE)
+                int32_t op2imm = JSImmediate::intValue(getConstantOperand(op2));
+#else
+                int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+                addJump(jle32(X86::eax, Imm32(op2imm)), target + 3);
             } else {
                 emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::edx);
-                addJump(jlePtr(X86::eax, X86::edx), target + 3);
+                addJump(jle32(X86::eax, X86::edx), target + 3);
             }
             NEXT_OPCODE(op_loop_if_less);
         }
@@ -395,8 +405,8 @@ void JIT::privateCompileMainPass()
 
             // check if any are immediates
             move(X86::eax, X86::ebx);
-            or32(X86::ecx, X86::ebx);
-            or32(X86::edx, X86::ebx);
+            orPtr(X86::ecx, X86::ebx);
+            orPtr(X86::edx, X86::ebx);
             emitJumpSlowCaseIfNotJSCell(X86::ebx);
 
             // check that all are object type - this is a bit of a bithack to avoid excess branching;
@@ -563,7 +573,17 @@ void JIT::privateCompileMainPass()
         case op_get_by_val: {
             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
             emitJumpSlowCaseIfNotImmNum(X86::edx);
+#if USE(ALTERNATE_JSIMMEDIATE)
+            // This is technically incorrect - we're zero-extending an int32.  On the hot path this doesn't matter.
+            // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if
+            // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation
+            // size is always less than 4Gb).  As such zero extending wil have been correct (and extending the value
+            // to 64-bits is necessary since it's used in the address calculation.  We zero extend rather than sign
+            // extending since it makes it easier to re-tag the value in the slow case.
+            zeroExtend32ToPtr(X86::edx, X86::edx);
+#else
             emitFastArithImmToInt(X86::edx);
+#endif
             emitJumpSlowCaseIfNotJSCell(X86::eax);
             addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
 
@@ -591,7 +611,12 @@ void JIT::privateCompileMainPass()
         case op_put_by_val: {
             emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
             emitJumpSlowCaseIfNotImmNum(X86::edx);
+#if USE(ALTERNATE_JSIMMEDIATE)
+            // See comment in op_get_by_val.
+            zeroExtend32ToPtr(X86::edx, X86::edx);
+#else
             emitFastArithImmToInt(X86::edx);
+#endif
             emitJumpSlowCaseIfNotJSCell(X86::eax);
             addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
 
@@ -619,7 +644,7 @@ void JIT::privateCompileMainPass()
             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
 
             Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(JSImmediate::zeroImmediate())));
-            addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
+            addJump(emitJumpIfImmNum(X86::eax), target + 2);
 
             addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2);
             addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))));
@@ -691,20 +716,25 @@ void JIT::privateCompileMainPass()
             if (isOperandConstantImmediateInt(op2)) {
                 emitGetVirtualRegister(op1, X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
-                addJump(jgePtr(X86::eax, ImmPtr(JSValuePtr::encode(getConstantOperand(op2)))), target + 3);
+#if USE(ALTERNATE_JSIMMEDIATE)
+                int32_t op2imm = JSImmediate::intValue(getConstantOperand(op2));
+#else
+                int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+                addJump(jge32(X86::eax, Imm32(op2imm)), target + 3);
             } else {
                 emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
                 emitJumpSlowCaseIfNotImmNum(X86::eax);
                 emitJumpSlowCaseIfNotImmNum(X86::edx);
-                addJump(jgePtr(X86::eax, X86::edx), target + 3);
+                addJump(jge32(X86::eax, X86::edx), target + 3);
             }
             NEXT_OPCODE(op_jnless);
         }
         case op_not: {
             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
-            xorPtr(Imm32(JSImmediate::FullTagTypeBool), X86::eax);
-            addSlowCase(jnz32(X86::eax, Imm32(JSImmediate::FullTagTypeMask)));
-            xorPtr(Imm32(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
+            xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax);
+            addSlowCase(jnzPtr(X86::eax, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));
+            xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), X86::eax);
             emitPutVirtualRegister(currentInstruction[1].u.operand);
             NEXT_OPCODE(op_not);
         }
@@ -713,7 +743,7 @@ void JIT::privateCompileMainPass()
             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
 
             addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(JSImmediate::zeroImmediate()))), target + 2);
-            Jump isNonZero = jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger));
+            Jump isNonZero = emitJumpIfImmNum(X86::eax);
 
             addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))), target + 2);
             addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))));
@@ -806,7 +836,12 @@ void JIT::privateCompileMainPass()
         case op_bitnot: {
             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
             emitJumpSlowCaseIfNotImmNum(X86::eax);
-            xorPtr(Imm32(~JSImmediate::TagBitTypeInteger), X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+            not32(X86::eax);
+            emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+            xorPtr(Imm32(~JSImmediate::TagTypeInteger), X86::eax);
+#endif
             emitPutVirtualRegister(currentInstruction[1].u.operand);
             NEXT_OPCODE(op_bitnot);
         }
@@ -834,7 +869,7 @@ void JIT::privateCompileMainPass()
             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
 
             Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(JSImmediate::zeroImmediate())));
-            addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
+            addJump(emitJumpIfImmNum(X86::eax), target + 2);
 
             addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2);
             addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))));
@@ -862,7 +897,7 @@ void JIT::privateCompileMainPass()
             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
             xorPtr(X86::edx, X86::eax);
-            emitFastArithReTagImmediate(X86::eax);
+            emitFastArithReTagImmediate(X86::eax, X86::eax);
             emitPutVirtualRegister(currentInstruction[1].u.operand);
             NEXT_OPCODE(op_bitxor);
         }
@@ -945,7 +980,7 @@ void JIT::privateCompileMainPass()
             int srcVReg = currentInstruction[2].u.operand;
             emitGetVirtualRegister(srcVReg, X86::eax);
             
-            Jump wasImmediate = jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger));
+            Jump wasImmediate = emitJumpIfImmNum(X86::eax);
 
             emitJumpSlowCaseIfNotJSCell(X86::eax, srcVReg);
             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
@@ -1253,7 +1288,7 @@ void JIT::privateCompileSlowCases()
             Jump notImm = getSlowCase(iter);
             linkSlowCase(iter);
             linkSlowCase(iter);
-            emitFastArithIntToImmNoCheck(X86::edx);
+            emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
             notImm.link(this);
             emitPutJITStubArg(X86::eax, 1);
             emitPutJITStubArg(X86::edx, 2);
@@ -1342,7 +1377,7 @@ void JIT::privateCompileSlowCases()
             Jump notImm = getSlowCase(iter);
             linkSlowCase(iter);
             linkSlowCase(iter);
-            emitFastArithIntToImmNoCheck(X86::edx);
+            emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
             notImm.link(this);
             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx);
             emitPutJITStubArg(X86::eax, 1);
@@ -1395,7 +1430,7 @@ void JIT::privateCompileSlowCases()
         }
         case op_not: {
             linkSlowCase(iter);
-            xorPtr(Imm32(JSImmediate::FullTagTypeBool), X86::eax);
+            xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax);
             emitPutJITStubArg(X86::eax, 1);
             emitCTICall(Interpreter::cti_op_not);
             emitPutVirtualRegister(currentInstruction[1].u.operand);
@@ -1689,8 +1724,8 @@ void JIT::privateCompileCTIMachineTrampolines()
 
     Jump array_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
 
-    // X86::eax contains a 64 bit value (is signed, is zero extended) so we don't need sign extend here.
-    emitFastArithIntToImmNoCheck(X86::eax);
+    // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
+    emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
 
     ret();
 
@@ -1707,8 +1742,8 @@ void JIT::privateCompileCTIMachineTrampolines()
 
     Jump string_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
 
-    // X86::eax contains a 64 bit value (is signed, is zero extended) so we don't need sign extend here.
-    emitFastArithIntToImmNoCheck(X86::eax);
+    // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
+    emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
     
     ret();
 #endif
index 9dc68be..931eb3b 100644 (file)
 #include <wtf/AlwaysInline.h>
 #include <wtf/Vector.h>
 
-#define STUB_ARGS_code 0x0C
-#define STUB_ARGS_registerFile 0x0D
-#define STUB_ARGS_callFrame 0x0E
-#define STUB_ARGS_exception 0x0F
-#define STUB_ARGS_profilerReference 0x10
-#define STUB_ARGS_globalData 0x11
+#define STUB_ARGS_offset 0x0C
+#define STUB_ARGS_code (STUB_ARGS_offset)
+#define STUB_ARGS_registerFile (STUB_ARGS_offset + 1)
+#define STUB_ARGS_callFrame (STUB_ARGS_offset + 2)
+#define STUB_ARGS_exception (STUB_ARGS_offset + 3)
+#define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4)
+#define STUB_ARGS_globalData (STUB_ARGS_offset + 5)
 
 #define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame])
 #define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile])
@@ -435,7 +436,6 @@ namespace JSC {
         JSValuePtr getConstantOperand(unsigned src);
         int32_t getConstantOperandImmediateInt(unsigned src);
         bool isOperandConstantImmediateInt(unsigned src);
-        bool isOperandConstant31BitImmediateInt(unsigned src);
 
         Jump emitJumpIfJSCell(RegisterID);
         void emitJumpSlowCaseIfJSCell(RegisterID);
@@ -454,16 +454,19 @@ namespace JSC {
         }
         void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
 
+        JIT::Jump emitJumpIfImmNum(RegisterID);
         void emitJumpSlowCaseIfNotImmNum(RegisterID);
         void emitJumpSlowCaseIfNotImmNums(RegisterID, RegisterID, RegisterID);
 
         Jump checkStructure(RegisterID reg, Structure* structure);
 
+#if !USE(ALTERNATE_JSIMMEDIATE)
         void emitFastArithDeTagImmediate(RegisterID);
         Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
-        void emitFastArithReTagImmediate(RegisterID);
+#endif
+        void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
         void emitFastArithImmToInt(RegisterID);
-        void emitFastArithIntToImmNoCheck(RegisterID);
+        void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
 
         void emitTagAsBoolImmediate(RegisterID reg);
 
index 73994da..f95bab8 100644 (file)
@@ -60,13 +60,11 @@ void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2
     and32(Imm32(0x1f), X86::ecx);
 #endif
     lshift32(X86::ecx, X86::eax);
-#if USE(ALTERNATE_JSIMMEDIATE)
-    emitFastArithIntToImmNoCheck(X86::eax);
-#else
+#if !USE(ALTERNATE_JSIMMEDIATE)
     addSlowCase(joAdd32(X86::eax, X86::eax));
     signExtend32ToPtr(X86::eax, X86::eax);
-    emitFastArithReTagImmediate(X86::eax);
 #endif
+    emitFastArithReTagImmediate(X86::eax, X86::eax);
     emitPutVirtualRegister(result);
 }
 void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
@@ -97,7 +95,11 @@ void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2
         emitGetVirtualRegister(op1, X86::eax);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+#if USE(ALTERNATE_JSIMMEDIATE)
+        rshift32(Imm32(JSImmediate::getTruncatedUInt32(getConstantOperand(op2)) & 0x1f), X86::eax);
+#else
         rshiftPtr(Imm32(JSImmediate::getTruncatedUInt32(getConstantOperand(op2)) & 0x1f), X86::eax);
+#endif
     } else {
         emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
@@ -108,9 +110,17 @@ void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2
         // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
         and32(Imm32(0x1f), X86::ecx);
 #endif
+#if USE(ALTERNATE_JSIMMEDIATE)
+        rshift32(X86::ecx, X86::eax);
+#else
         rshiftPtr(X86::ecx, X86::eax);
+#endif
     }
-    orPtr(Imm32(JSImmediate::TagBitTypeInteger), X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+    emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+    orPtr(Imm32(JSImmediate::TagTypeInteger), X86::eax);
+#endif
     emitPutVirtualRegister(result);
 }
 void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
@@ -130,14 +140,28 @@ void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2
 
 void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2)
 {
-    if (isOperandConstant31BitImmediateInt(op1)) {
+    if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, X86::eax);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+        int32_t imm = JSImmediate::intValue(getConstantOperand(op1));
+        andPtr(Imm32(imm), X86::eax);
+        if (imm >= 0)
+            emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax);
-    } else if (isOperandConstant31BitImmediateInt(op2)) {
+#endif
+    } else if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, X86::eax);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+        int32_t imm = JSImmediate::intValue(getConstantOperand(op2));
+        andPtr(Imm32(imm), X86::eax);
+        if (imm >= 0)
+            emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax);
+#endif
     } else {
         emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
         andPtr(X86::edx, X86::eax);
@@ -148,10 +172,10 @@ void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2
 void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkSlowCase(iter);
-    if (isOperandConstant31BitImmediateInt(op1)) {
+    if (isOperandConstantImmediateInt(op1)) {
         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
         emitPutJITStubArg(X86::eax, 2);
-    } else if (isOperandConstant31BitImmediateInt(op2)) {
+    } else if (isOperandConstantImmediateInt(op2)) {
         emitPutJITStubArg(X86::eax, 1);
         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     } else {
@@ -168,19 +192,15 @@ void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2)
     emitJumpSlowCaseIfNotImmNum(X86::eax);
     emitJumpSlowCaseIfNotImmNum(X86::ecx);
 #if USE(ALTERNATE_JSIMMEDIATE)
-    addSlowCase(jePtr(X86::ecx, ImmPtr(JSImmediate::zeroImmediate())));
-    emitFastArithImmToInt(X86::eax);
-    emitFastArithImmToInt(X86::ecx);
+    addSlowCase(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(JSImmediate::zeroImmediate()))));
     mod32(X86::ecx, X86::eax, X86::edx);
-    emitFastArithIntToImmNoCheck(X86::edx);
 #else
     emitFastArithDeTagImmediate(X86::eax);
     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
     mod32(X86::ecx, X86::eax, X86::edx);
     signExtend32ToPtr(X86::edx, X86::edx);
-    emitFastArithReTagImmediate(X86::edx);
 #endif
-    move(X86::edx, X86::eax);
+    emitFastArithReTagImmediate(X86::edx, X86::eax);
     emitPutVirtualRegister(result);
 }
 void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter)
@@ -193,8 +213,8 @@ void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vecto
     Jump notImm1 = getSlowCase(iter);
     Jump notImm2 = getSlowCase(iter);
     linkSlowCase(iter);
-    emitFastArithReTagImmediate(X86::eax);
-    emitFastArithReTagImmediate(X86::ecx);
+    emitFastArithReTagImmediate(X86::eax, X86::eax);
+    emitFastArithReTagImmediate(X86::ecx, X86::ecx);
     notImm1.link(this);
     notImm2.link(this);
 #endif
@@ -216,9 +236,8 @@ void JIT::compileFastArith_op_add(Instruction* currentInstruction)
 #if USE(ALTERNATE_JSIMMEDIATE)
         // FIXME: investigate performing a 31-bit add here (can we preserve upper bit & detect overflow from low word to high?)
         //        (or, detect carry? - if const is positive, will only carry when overflowing from negative to positive?)
-        emitFastArithImmToInt(X86::eax);
         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax));
-        emitFastArithIntToImmNoCheck(X86::eax);
+        emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
 #else
         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax));
         signExtend32ToPtr(X86::eax, X86::eax);
@@ -230,7 +249,7 @@ void JIT::compileFastArith_op_add(Instruction* currentInstruction)
 #if USE(ALTERNATE_JSIMMEDIATE)
         emitFastArithImmToInt(X86::eax);
         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax));
-        emitFastArithIntToImmNoCheck(X86::eax);
+        emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
 #else
         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax));
         signExtend32ToPtr(X86::eax, X86::eax);
@@ -305,29 +324,25 @@ void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
         emitGetVirtualRegister(op2, X86::eax);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-        emitFastArithImmToInt(X86::eax);
         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
-        emitFastArithIntToImmNoCheck(X86::eax);
 #else
         emitFastArithDeTagImmediate(X86::eax);
         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
         signExtend32ToPtr(X86::eax, X86::eax);
-        emitFastArithReTagImmediate(X86::eax);
 #endif
+        emitFastArithReTagImmediate(X86::eax, X86::eax);
         emitPutVirtualRegister(result);
     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
         emitGetVirtualRegister(op1, X86::eax);
         emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-        emitFastArithImmToInt(X86::eax);
         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
-        emitFastArithIntToImmNoCheck(X86::eax);
 #else
         emitFastArithDeTagImmediate(X86::eax);
         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
         signExtend32ToPtr(X86::eax, X86::eax);
-        emitFastArithReTagImmediate(X86::eax);
 #endif
+        emitFastArithReTagImmediate(X86::eax, X86::eax);
         emitPutVirtualRegister(result);
     } else
         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
@@ -357,9 +372,8 @@ void JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst)
     move(X86::eax, X86::edx);
     emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-    emitFastArithImmToInt(X86::edx);
     addSlowCase(joAdd32(Imm32(1), X86::edx));
-    emitFastArithIntToImmNoCheck(X86::edx);
+    emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
 #else
     addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
     signExtend32ToPtr(X86::edx, X86::edx);
@@ -383,9 +397,8 @@ void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst)
     move(X86::eax, X86::edx);
     emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-    emitFastArithImmToInt(X86::edx);
     addSlowCase(joSub32(Imm32(1), X86::edx));
-    emitFastArithIntToImmNoCheck(X86::edx);
+    emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
 #else
     addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
     signExtend32ToPtr(X86::edx, X86::edx);
@@ -408,10 +421,9 @@ void JIT::compileFastArith_op_pre_inc(unsigned srcDst)
     emitGetVirtualRegister(srcDst, X86::eax);
     emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-    emitFastArithImmToInt(X86::eax);
     // FIXME: Could add ptr & specify int64; no need to re-sign-extend?
     addSlowCase(joAdd32(Imm32(1), X86::eax));
-    emitFastArithIntToImmNoCheck(X86::eax);
+    emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
 #else
     addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
     signExtend32ToPtr(X86::eax, X86::eax);
@@ -434,9 +446,8 @@ void JIT::compileFastArith_op_pre_dec(unsigned srcDst)
     emitGetVirtualRegister(srcDst, X86::eax);
     emitJumpSlowCaseIfNotImmNum(X86::eax);
 #if USE(ALTERNATE_JSIMMEDIATE)
-    emitFastArithImmToInt(X86::eax);
     addSlowCase(joSub32(Imm32(1), X86::eax));
-    emitFastArithIntToImmNoCheck(X86::eax);
+    emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
 #else
     addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
     signExtend32ToPtr(X86::eax, X86::eax);
@@ -555,9 +566,7 @@ void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSourc
     __ cmpl_ir(0x8000, tempReg2);
     __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
     // Yes it really really really is representable as a JSImmediate.
-    emitFastArithIntToImmNoCheck(tempReg1);
-    if (tempReg1 != X86::eax)
-        __ movl_rr(tempReg1, X86::eax);
+    emitFastArithIntToImmNoCheck(tempReg1, X86::eax);
     emitPutVirtualRegister(dst);
 }
 
@@ -575,7 +584,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         ASSERT(types.second().mightBeNumber());
 
         // Check op2 is a number
-        __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
+        __ testl_i32r(JSImmediate::TagTypeInteger, X86::edx);
         JmpSrc op2imm = __ jne();
         if (!types.second().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
@@ -585,7 +594,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
 
         // (1) In this case src2 is a reusable number cell.
         //     Slow case if src1 is not a number type.
-        __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
+        __ testl_i32r(JSImmediate::TagTypeInteger, X86::eax);
         JmpSrc op1imm = __ jne();
         if (!types.first().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
@@ -622,7 +631,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         ASSERT(types.first().mightBeNumber());
 
         // Check op1 is a number
-        __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
+        __ testl_i32r(JSImmediate::TagTypeInteger, X86::eax);
         JmpSrc op1imm = __ jne();
         if (!types.first().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
@@ -632,7 +641,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
 
         // (1) In this case src1 is a reusable number cell.
         //     Slow case if src2 is not a number type.
-        __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
+        __ testl_i32r(JSImmediate::TagTypeInteger, X86::edx);
         JmpSrc op2imm = __ jne();
         if (!types.second().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
@@ -679,7 +688,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         __ subl_rr(X86::edx, X86::eax);
         addSlowCase(__ jo());
         signExtend32ToPtr(X86::eax, X86::eax);
-        emitFastArithReTagImmediate(X86::eax);
+        emitFastArithReTagImmediate(X86::eax, X86::eax);
     } else {
         ASSERT(opcodeID == op_mul);
         // convert eax & edx from JSImmediates to ints, and check if either are zero
@@ -698,7 +707,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         __ imull_rr(X86::edx, X86::eax);
         addSlowCase(__ jo());
         signExtend32ToPtr(X86::eax, X86::eax);
-        emitFastArithReTagImmediate(X86::eax);
+        emitFastArithReTagImmediate(X86::eax, X86::eax);
     }
     emitPutVirtualRegister(dst);
 
index 6e27bae..0e85d75 100644 (file)
@@ -277,7 +277,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
         compileOpConstructSetupArgs(instruction);
 
     // Fast check for JS function.
-    Jump callLinkFailNotObject = jnz32(X86::ecx, Imm32(JSImmediate::TagMask));
+    Jump callLinkFailNotObject = emitJumpIfNotJSCell(X86::ecx);
     Jump callLinkFailNotJSFunction = jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr));
 
     // First, in the case of a construct, allocate the new object.
@@ -309,7 +309,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
         compileOpConstructSetupArgs(instruction);
 
     // Check for JSFunctions.
-    Jump isNotObject = jnzPtr(X86::ecx, Imm32(JSImmediate::TagMask));
+    Jump isNotObject = emitJumpIfNotJSCell(X86::ecx);
     Jump isJSFunction = jePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr));
 
     // This handles host functions
index 6bff5db..3804ba9 100644 (file)
@@ -128,24 +128,6 @@ ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
     return m_codeBlock->isConstantRegisterIndex(src) && JSImmediate::isNumber(getConstantOperand(src));
 }
 
-ALWAYS_INLINE bool JIT::isOperandConstant31BitImmediateInt(unsigned src)
-{
-    if (!m_codeBlock->isConstantRegisterIndex(src))
-        return false;
-
-    JSValuePtr value = getConstantOperand(src);
-
-#if USE(ALTERNATE_JSIMMEDIATE)
-    if (!JSImmediate::isNumber(value))
-        return false;
-
-    int32_t imm = JSImmediate::intValue(value);
-    return (imm == ((imm << 1) >> 1));
-#else
-    return JSImmediate::isNumber(value);
-#endif
-}
-
 // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
 ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
 {
@@ -281,7 +263,11 @@ ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure
 
 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
 {
+#if USE(ALTERNATE_JSIMMEDIATE)
+    return jzPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagMask)));
+#else
     return jz32(reg, Imm32(JSImmediate::TagMask));
+#endif
 }
 
 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg)
@@ -291,7 +277,11 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg)
 
 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
 {
+#if USE(ALTERNATE_JSIMMEDIATE)
+    return jnzPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagMask)));
+#else
     return jnz32(reg, Imm32(JSImmediate::TagMask));
+#endif
 }
 
 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg)
@@ -311,49 +301,81 @@ ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&
         linkSlowCase(iter);
 }
 
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmNum(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+    return jaePtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger)));
+#else
+    return jnz32(reg, Imm32(JSImmediate::TagTypeInteger));
+#endif
+}
+
 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNum(RegisterID reg)
 {
-    addSlowCase(jz32(reg, Imm32(JSImmediate::TagBitTypeInteger)));
+#if USE(ALTERNATE_JSIMMEDIATE)
+    addSlowCase(jbPtr(reg, ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger))));
+#else
+    addSlowCase(jz32(reg, Imm32(JSImmediate::TagTypeInteger)));
+#endif
 }
 
 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNums(RegisterID reg1, RegisterID reg2, RegisterID scratch)
 {
     move(reg1, scratch);
-    and32(reg2, scratch);
+    andPtr(reg2, scratch);
     emitJumpSlowCaseIfNotImmNum(scratch);
 }
 
+#if !USE(ALTERNATE_JSIMMEDIATE)
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
-    subPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
+    subPtr(Imm32(JSImmediate::TagTypeInteger), reg);
 }
 
 ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
 {
-    return jzSubPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
+    return jzSubPtr(Imm32(JSImmediate::TagTypeInteger), reg);
 }
+#endif
 
-ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID reg)
+ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest)
 {
-    addPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
+#if USE(ALTERNATE_JSIMMEDIATE)
+    emitFastArithIntToImmNoCheck(src, dest);
+#else
+    if (src != dest)
+        move(src, dest);
+    addPtr(Imm32(JSImmediate::TagTypeInteger), dest);
+#endif
 }
 
 ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
 {
+#if USE(ALTERNATE_JSIMMEDIATE)
+    UNUSED_PARAM(reg);
+#else
     rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
+#endif
 }
 
-ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID reg)
+// operand is int32_t, must have been zero-extended if register is 64-bit.
+ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
 {
-    signExtend32ToPtr(reg, reg);
-    addPtr(reg, reg);
-    emitFastArithReTagImmediate(reg);
+#if USE(ALTERNATE_JSIMMEDIATE)
+    if (src != dest)
+        move(src, dest);
+    orPtr(ImmPtr(reinterpret_cast<void*>(JSImmediate::TagTypeInteger)), dest);
+#else
+    signExtend32ToPtr(src, dest);
+    addPtr(dest, dest);
+    emitFastArithReTagImmediate(dest, dest);
+#endif
 }
 
 ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
 {
     lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg);
-    or32(Imm32(JSImmediate::FullTagTypeBool), reg);
+    or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg);
 }
 
 ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
index f79056d..6740bec 100644 (file)
@@ -182,10 +182,10 @@ void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<Sl
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
 }
 
-static JSValueEncodedAsPointer* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize)
+static JSObject* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize)
 {
     baseObject->allocatePropertyStorage(oldSize, newSize);
-    return JSValuePtr::encode(baseObject);
+    return baseObject;
 }
 
 static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure)
@@ -197,7 +197,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
 {
     JumpList failureCases;
     // Check eax is an object of the right Structure.
-    failureCases.append(jnz32(X86::eax, Imm32(JSImmediate::TagMask)));
+    failureCases.append(emitJumpIfNotJSCell(X86::eax));
     failureCases.append(jnePtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(oldStructure)));
     JumpList successCases;
 
@@ -317,13 +317,11 @@ void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
 
     // Checks out okay! - get the length from the storage
     loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
-    loadPtr(Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_length)), X86::ecx);
+    load32(Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_length)), X86::ecx);
 
     Jump failureCases2 = ja32(X86::ecx, Imm32(JSImmediate::maxImmediateInt));
 
-    add32(X86::ecx, X86::ecx);
-    add32(Imm32(1), X86::ecx);
-    signExtend32ToPtr(X86::ecx, X86::eax);
+    emitFastArithIntToImmNoCheck(X86::ecx, X86::eax);
     Jump success = jump();
 
     void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
@@ -349,7 +347,7 @@ void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
 void JIT::privateCompileGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
 {
     // Check eax is an object of the right Structure.
-    Jump failureCases1 = jnz32(X86::eax, Imm32(JSImmediate::TagMask));
+    Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
     Jump failureCases2 = checkStructure(X86::eax, structure);
 
     // Checks out okay! - getDirectOffset
@@ -423,7 +421,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     loadPtr(protoPropertyStorage, X86::edx);
 
     // Check eax is an object of the right Structure.
-    Jump failureCases1 = jne32(X86::eax, Imm32(JSImmediate::TagMask));
+    Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
     Jump failureCases2 = checkStructure(X86::eax, structure);
 
     // Check the prototype object's Structure had not changed.
@@ -641,7 +639,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     JumpList bucketsOfFail;
 
     // Check eax is an object of the right Structure.
-    bucketsOfFail.append(jne32(X86::eax, Imm32(JSImmediate::TagMask)));
+    bucketsOfFail.append(emitJumpIfNotJSCell(X86::eax));
     bucketsOfFail.append(checkStructure(X86::eax, structure));
 
     Structure* currStructure = structure;
@@ -680,7 +678,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 void JIT::privateCompilePutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
 {
     // Check eax is an object of the right Structure.
-    Jump failureCases1 = jne32(X86::eax, Imm32(JSImmediate::TagMask));
+    Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
     Jump failureCases2 = checkStructure(X86::eax, structure);
 
     // checks out okay! - putDirectOffset
index bd0eccc..37bca2a 100644 (file)
@@ -82,33 +82,51 @@ namespace JSC {
      *                      [ zero ]                       [ zero ]       [ tag 'other' ]
      */
 
+    /*
+     * On 64-bit platforms, we support an alternative encoding form for immediates, if
+     * USE(ALTERNATE_JSIMMEDIATE) is defined.
+     *
+     * The top 16-bits denote the type:
+     *
+     * Pointer: 0000:PPPP:PPPP:PPPP
+     * Integer: FFFF:0000:IIII:IIII
+     *
+     * 32-bit signed integers are marked with the 16-bit tag '0xFFFF'.  The tag '0x0000'
+     * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
+     * values are encoded in the same manner as the default format.
+     */
+
     class JSImmediate {
     private:
         friend class JIT;
     
-        static const int32_t TagMask           = 0x3; // primary tag is 2 bits long
-        static const int32_t TagBitTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit
-        static const int32_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
+#if USE(ALTERNATE_JSIMMEDIATE)
+        static const intptr_t TagTypeInteger = 0xffff000000000000ll; // bottom bit set indicates integer, this dominates the following bit
+#else
+        static const intptr_t TagTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit
+#endif
+        static const intptr_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
+        static const intptr_t TagMask           = TagTypeInteger | TagBitTypeOther;
 
-        static const int32_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
-        static const int32_t ExtendedTagBitBool      = 0x4;
-        static const int32_t ExtendedTagBitUndefined = 0x8;
+        static const intptr_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
+        static const intptr_t ExtendedTagBitBool      = 0x4;
+        static const intptr_t ExtendedTagBitUndefined = 0x8;
 
-        static const int32_t FullTagTypeMask      = TagMask | ExtendedTagMask;
-        static const int32_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
-        static const int32_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
-        static const int32_t FullTagTypeNull      = TagBitTypeOther;
+        static const intptr_t FullTagTypeMask      = TagMask | ExtendedTagMask;
+        static const intptr_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
+        static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
+        static const intptr_t FullTagTypeNull      = TagBitTypeOther;
 
+#if USE(ALTERNATE_JSIMMEDIATE)
+        static const int32_t IntegerPayloadShift  = 0;
+#else
         static const int32_t IntegerPayloadShift  = 1;
+#endif
         static const int32_t ExtendedPayloadShift = 4;
 
-        static const int32_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
+        static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
 
-#if USE(ALTERNATE_JSIMMEDIATE)
-        static const intptr_t signBit = 0x100000000ll;
-#else
         static const int32_t signBit = 0x80000000;
-#endif
  
     public:
         static ALWAYS_INLINE bool isImmediate(JSValuePtr v)
@@ -118,13 +136,13 @@ namespace JSC {
         
         static ALWAYS_INLINE bool isNumber(JSValuePtr v)
         {
-            return rawValue(v) & TagBitTypeInteger;
+            return rawValue(v) & TagTypeInteger;
         }
 
         static ALWAYS_INLINE bool isPositiveNumber(JSValuePtr v)
         {
             // A single mask to check for the sign bit and the number tag all at once.
-            return (rawValue(v) & (signBit | TagBitTypeInteger)) == TagBitTypeInteger;
+            return (rawValue(v) & (signBit | TagTypeInteger)) == TagTypeInteger;
         }
         
         static ALWAYS_INLINE bool isBoolean(JSValuePtr v)
@@ -174,7 +192,7 @@ namespace JSC {
 
         static ALWAYS_INLINE bool areBothImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
         {
-            return rawValue(v1) & rawValue(v2) & TagBitTypeInteger;
+            return rawValue(v1) & rawValue(v2) & TagTypeInteger;
         }
 
         static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
@@ -186,7 +204,7 @@ namespace JSC {
         static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
         {
             ASSERT(areBothImmediateNumbers(v1, v2));
-            return makeValue((rawValue(v1) ^ rawValue(v2)) | TagBitTypeInteger);
+            return makeValue((rawValue(v1) ^ rawValue(v2)) | TagTypeInteger);
         }
 
         static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
@@ -198,28 +216,32 @@ namespace JSC {
         static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift)
         {
             ASSERT(areBothImmediateNumbers(val, shift));
-            return makeValue((rawValue(val) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger);
+#if USE(ALTERNATE_JSIMMEDIATE)
+            return makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(rawValue(val)) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f))) | TagTypeInteger);
+#else
+            return makeValue((rawValue(val) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagTypeInteger);
+#endif
         }
 
         static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v)
         {
             // Number is non-negative and an operation involving two of these can't overflow.
             // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
-            return (rawValue(v) & (TagBitTypeInteger + (signBit | (signBit >> 1)))) == TagBitTypeInteger;
+            return (rawValue(v) & (TagTypeInteger + (signBit | (signBit >> 1)))) == TagTypeInteger;
         }
 
         static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
         {
             ASSERT(canDoFastAdditiveOperations(v1));
             ASSERT(canDoFastAdditiveOperations(v2));
-            return makeValue(rawValue(v1) + rawValue(v2) - TagBitTypeInteger);
+            return makeValue(rawValue(v1) + rawValue(v2) - TagTypeInteger);
         }
 
         static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
         {
             ASSERT(canDoFastAdditiveOperations(v1));
             ASSERT(canDoFastAdditiveOperations(v2));
-            return makeValue(rawValue(v1) - rawValue(v2) + TagBitTypeInteger);
+            return makeValue(rawValue(v1) - rawValue(v2) + TagTypeInteger);
         }
 
         static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v)
@@ -273,9 +295,13 @@ namespace JSC {
             return JSValuePtr::makeImmediate(integer);
         }
 
+#if USE(ALTERNATE_JSIMMEDIATE)
+        static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value)
+#else
         static ALWAYS_INLINE JSValuePtr makeInt(int32_t value)
+#endif
         {
-            return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagBitTypeInteger);
+            return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeInteger);
         }
         
         static ALWAYS_INLINE JSValuePtr makeBool(bool b)
@@ -330,8 +356,8 @@ namespace JSC {
     {
         ASSERT(isImmediate(v));
         intptr_t bits = rawValue(v);
-        return (bits & TagBitTypeInteger)
-            ? bits != TagBitTypeInteger // !0 ints
+        return (bits & TagTypeInteger)
+            ? bits != TagTypeInteger // !0 ints
             : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
     }
 
index 3bf04c4..14c8747 100644 (file)
 /* x86-64 support is under development. */
 #if PLATFORM(X86_64) && PLATFORM(MAC)
     #define ENABLE_JIT 0
-    #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 0
-    #define ENABLE_JIT_OPTIMIZE_CALL 0
-    #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 0
+    #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+    #define ENABLE_JIT_OPTIMIZE_CALL 1
+    #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
     #define WTF_USE_ALTERNATE_JSIMMEDIATE 1
 /* The JIT is tested & working on x86 Mac */
 #elif PLATFORM(X86) && PLATFORM(MAC)