Ignore:
Timestamp:
Jan 1, 2009, 7:06:10 PM (16 years ago)
Author:
[email protected]
Message:

2009-01-01 Gavin Barraclough <[email protected]>

Reviewed by Darin Adler.

Allow 32-bit integers to be stored in JSImmediates, on x64-bit.
Presently the top 32-bits of a 64-bit JSImmediate serve as a sign extension of a 31-bit
int stored in the low word (shifted left by one, to make room for a tag). In the new
format, the top 31-bits serve as a sign extension of a 32-bit int, still shifted left by
one.

The new behavior is enabled using a flag in Platform.h, 'WTF_USE_ALTERNATE_JSIMMEDIATE'.
When this is set the constants defining the range of ints allowed to be stored as
JSImmediate values is extended. The code in JSImmediate.h can safely operate on either
format. This patch updates the JIT so that it can also operate with the new format.

~2% progression on x86-64, with & without the JIT, on sunspider & v8 tests.

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::addPtr): (JSC::MacroAssembler::orPtr): (JSC::MacroAssembler::or32): (JSC::MacroAssembler::rshiftPtr): (JSC::MacroAssembler::rshift32): (JSC::MacroAssembler::subPtr): (JSC::MacroAssembler::xorPtr): (JSC::MacroAssembler::xor32): (JSC::MacroAssembler::move): (JSC::MacroAssembler::compareImm64ForBranch): (JSC::MacroAssembler::compareImm64ForBranchEquality): (JSC::MacroAssembler::jePtr): (JSC::MacroAssembler::jgePtr): (JSC::MacroAssembler::jlPtr): (JSC::MacroAssembler::jlePtr): (JSC::MacroAssembler::jnePtr): (JSC::MacroAssembler::jnzSubPtr): (JSC::MacroAssembler::joAddPtr): (JSC::MacroAssembler::jzSubPtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::addq_rr): (JSC::X86Assembler::orq_ir): (JSC::X86Assembler::subq_ir): (JSC::X86Assembler::xorq_rr): (JSC::X86Assembler::sarq_CLr): (JSC::X86Assembler::sarq_i8r): (JSC::X86Assembler::cmpq_ir):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq): (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArith_op_lshift): (JSC::JIT::compileFastArithSlow_op_lshift): (JSC::JIT::compileFastArith_op_rshift): (JSC::JIT::compileFastArithSlow_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::compileFastArithSlow_op_add): (JSC::JIT::compileFastArith_op_mul): (JSC::JIT::compileFastArithSlow_op_mul): (JSC::JIT::compileFastArith_op_post_inc): (JSC::JIT::compileFastArithSlow_op_post_inc): (JSC::JIT::compileFastArith_op_post_dec): (JSC::JIT::compileFastArithSlow_op_post_dec): (JSC::JIT::compileFastArith_op_pre_inc): (JSC::JIT::compileFastArithSlow_op_pre_inc): (JSC::JIT::compileFastArith_op_pre_dec): (JSC::JIT::compileFastArithSlow_op_pre_dec): (JSC::JIT::compileBinaryArithOp):
  • jit/JITInlineMethods.h: (JSC::JIT::getConstantOperand): (JSC::JIT::getConstantOperandImmediateInt): (JSC::JIT::isOperandConstantImmediateInt): (JSC::JIT::isOperandConstant31BitImmediateInt): (JSC::JIT::emitFastArithDeTagImmediate): (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): (JSC::JIT::emitFastArithReTagImmediate): (JSC::JIT::emitFastArithImmToInt): (JSC::JIT::emitFastArithIntToImmNoCheck):
  • runtime/JSImmediate.h: (JSC::JSImmediate::isPositiveNumber): (JSC::JSImmediate::isNegative): (JSC::JSImmediate::rightShiftImmediateNumbers): (JSC::JSImmediate::canDoFastAdditiveOperations): (JSC::JSImmediate::makeValue): (JSC::JSImmediate::makeInt): (JSC::JSImmediate::makeBool): (JSC::JSImmediate::intValue): (JSC::JSImmediate::rawValue): (JSC::JSImmediate::toBoolean): (JSC::JSImmediate::from):
  • wtf/Platform.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSImmediate.h

    r39342 r39540  
    8989        friend class JIT;
    9090   
    91         static const uint32_t TagMask           = 0x3u; // primary tag is 2 bits long
    92         static const uint32_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
    93         static const uint32_t TagBitTypeOther   = 0x2u; // second bit set indicates immediate other than an integer
    94 
    95         static const uint32_t ExtendedTagMask         = 0xCu; // extended tag holds a further two bits
    96         static const uint32_t ExtendedTagBitBool      = 0x4u;
    97         static const uint32_t ExtendedTagBitUndefined = 0x8u;
    98 
    99         static const uint32_t FullTagTypeMask      = TagMask | ExtendedTagMask;
    100         static const uint32_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
    101         static const uint32_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
    102         static const uint32_t FullTagTypeNull      = TagBitTypeOther;
    103 
    104         static const uint32_t IntegerPayloadShift  = 1u;
    105         static const uint32_t ExtendedPayloadShift = 4u;
    106 
    107         static const uint32_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
     91        static const int32_t TagMask           = 0x3; // primary tag is 2 bits long
     92        static const int32_t TagBitTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit
     93        static const int32_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
     94
     95        static const int32_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
     96        static const int32_t ExtendedTagBitBool      = 0x4;
     97        static const int32_t ExtendedTagBitUndefined = 0x8;
     98
     99        static const int32_t FullTagTypeMask      = TagMask | ExtendedTagMask;
     100        static const int32_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
     101        static const int32_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
     102        static const int32_t FullTagTypeNull      = TagBitTypeOther;
     103
     104        static const int32_t IntegerPayloadShift  = 1;
     105        static const int32_t ExtendedPayloadShift = 4;
     106
     107        static const int32_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
     108
     109#if USE(ALTERNATE_JSIMMEDIATE)
     110        static const intptr_t signBit = 0x100000000ll;
     111#else
     112        static const int32_t signBit = 0x80000000;
     113#endif
    108114 
    109115    public:
     
    121127        {
    122128            // A single mask to check for the sign bit and the number tag all at once.
    123             return (rawValue(v) & (0x80000000 | TagBitTypeInteger)) == TagBitTypeInteger;
     129            return (rawValue(v) & (signBit | TagBitTypeInteger)) == TagBitTypeInteger;
    124130        }
    125131       
     
    138144        {
    139145            ASSERT(isNumber(v));
    140             return rawValue(v) & 0x80000000;
     146            return rawValue(v) & signBit;
    141147        }
    142148
     
    195201        {
    196202            ASSERT(areBothImmediateNumbers(val, shift));
    197             return makeValue((static_cast<intptr_t>(rawValue(val)) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger);
     203            return makeValue((rawValue(val) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger);
    198204        }
    199205
     
    202208            // Number is non-negative and an operation involving two of these can't overflow.
    203209            // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
    204             return (rawValue(v) & (TagBitTypeInteger + (3u << 30))) == TagBitTypeInteger;
     210            return (rawValue(v) & (TagBitTypeInteger + (signBit | (signBit >> 1)))) == TagBitTypeInteger;
    205211        }
    206212
     
    256262
    257263    private:
     264#if USE(ALTERNATE_JSIMMEDIATE)
     265        static const int minImmediateInt = ((-INT_MAX) - 1);
     266        static const int maxImmediateInt = INT_MAX;
     267#else
    258268        static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
    259269        static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
     270#endif
    260271        static const unsigned maxImmediateUInt = maxImmediateInt;
    261272
    262         static ALWAYS_INLINE JSValue* makeValue(uintptr_t integer)
     273        static ALWAYS_INLINE JSValue* makeValue(intptr_t integer)
    263274        {
    264275            return reinterpret_cast<JSValue*>(integer);
     
    267278        static ALWAYS_INLINE JSValue* makeInt(int32_t value)
    268279        {
    269             // FIXME: Why does the result of this need be a 64-bit value?
    270             // Integer immediates are still only 31-bit on x86-64.
    271             return makeValue((value << IntegerPayloadShift) | static_cast<uintptr_t>(TagBitTypeInteger));
     280            return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagBitTypeInteger);
    272281        }
    273282       
    274283        static ALWAYS_INLINE JSValue* makeBool(bool b)
    275284        {
    276             return makeValue((static_cast<uintptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
     285            return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
    277286        }
    278287       
     
    289298        static ALWAYS_INLINE int32_t intValue(JSValue* v)
    290299        {
    291             return static_cast<int32_t>(static_cast<intptr_t>(rawValue(v)) >> IntegerPayloadShift);
     300            return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
    292301        }
    293302       
     
    302311        }
    303312       
    304         static ALWAYS_INLINE uintptr_t rawValue(JSValue* v)
    305         {
    306             return reinterpret_cast<uintptr_t>(v);
     313        static ALWAYS_INLINE intptr_t rawValue(JSValue* v)
     314        {
     315            return reinterpret_cast<intptr_t>(v);
    307316        }
    308317
     
    323332    {
    324333        ASSERT(isImmediate(v));
    325         uintptr_t bits = rawValue(v);
     334        intptr_t bits = rawValue(v);
    326335        return (bits & TagBitTypeInteger)
    327336            ? bits != TagBitTypeInteger // !0 ints
     
    392401        if ((i < minImmediateInt) | (i > maxImmediateInt))
    393402            return noValue();
    394         return makeInt(static_cast<uintptr_t>(i));
     403        return makeInt(static_cast<intptr_t>(i));
    395404    }
    396405
     
    399408        if (i > maxImmediateUInt)
    400409            return noValue();
    401         return makeInt(static_cast<uintptr_t>(i));
     410        return makeInt(static_cast<intptr_t>(i));
    402411    }
    403412
Note: See TracChangeset for help on using the changeset viewer.