Changeset 39958 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Jan 15, 2009, 7:20:35 PM (16 years ago)
Author:
[email protected]
Message:

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

Reviewed by Geoff Garen.

On x86-64 allow JSImmediate to encode 64-bit double precision values.
This patch only affects builds that set USE(ALTERNATE_JSIMMEDIATE).

Updates the implementation of JSValuePtr
and JSImmediate:: methods that operate on neumeric values to be be aware of the new representation. When this representation is in use, the class JSNumberCell is redundant and is compiled out.

The format of the new immediate representation is documented in JSImmediate.h.

  • JavaScriptCore.exp:
  • assembler/MacroAssembler.h: (JSC::MacroAssembler::subPtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::subq_rr): (JSC::X86Assembler::movq_rr): (JSC::X86Assembler::ucomisd_rr): (JSC::X86Assembler::X86InstructionFormatter::twoByteOp64):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::cti_op_stricteq): (JSC::Interpreter::cti_op_nstricteq):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq): (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArith_op_lshift): (JSC::JIT::compileFastArith_op_rshift): (JSC::JIT::compileFastArith_op_bitand): (JSC::JIT::compileFastArith_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/JITInlineMethods.h: (JSC::JIT::emitJumpIfBothJSCells): (JSC::JIT::emitJumpIfEitherNumber): (JSC::JIT::emitJumpIfNotEitherNumber): (JSC::JIT::emitJumpIfImmediateIntegerNumber): (JSC::JIT::emitJumpIfNotImmediateIntegerNumber): (JSC::JIT::emitJumpIfNotImmediateIntegerNumbers): (JSC::JIT::emitJumpSlowCaseIfNotImmediateIntegerNumber): (JSC::JIT::emitJumpSlowCaseIfNotImmediateIntegerNumbers): (JSC::JIT::emitFastArithDeTagImmediate): (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): (JSC::JIT::emitFastArithReTagImmediate): (JSC::JIT::emitFastArithIntToImmNoCheck):
  • runtime/JSCell.h:
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSImmediate.cpp: (JSC::JSImmediate::toThisObject): (JSC::JSImmediate::toObject): (JSC::JSImmediate::toString):
  • runtime/JSImmediate.h: (JSC::wtf_reinterpret_cast): (JSC::JSImmediate::isNumber): (JSC::JSImmediate::isIntegerNumber): (JSC::JSImmediate::isDoubleNumber): (JSC::JSImmediate::isPositiveIntegerNumber): (JSC::JSImmediate::areBothImmediateIntegerNumbers): (JSC::JSImmediate::makeInt): (JSC::JSImmediate::makeDouble): (JSC::JSImmediate::doubleValue): (JSC::doubleToBoolean): (JSC::JSImmediate::toBoolean): (JSC::JSImmediate::getTruncatedUInt32): (JSC::JSImmediate::makeOutOfIntegerRange): (JSC::JSImmediate::from): (JSC::JSImmediate::getTruncatedInt32): (JSC::JSImmediate::toDouble): (JSC::JSImmediate::getUInt32): (JSC::JSValuePtr::isInt32Fast): (JSC::JSValuePtr::isUInt32Fast): (JSC::JSValuePtr::areBothInt32Fast): (JSC::JSFastMath::canDoFastBitwiseOperations): (JSC::JSFastMath::xorImmediateNumbers): (JSC::JSFastMath::canDoFastRshift): (JSC::JSFastMath::canDoFastUrshift): (JSC::JSFastMath::rightShiftImmediateNumbers): (JSC::JSFastMath::canDoFastAdditiveOperations): (JSC::JSFastMath::addImmediateNumbers): (JSC::JSFastMath::subImmediateNumbers):
  • runtime/JSNumberCell.cpp: (JSC::jsNumberCell):
  • runtime/JSNumberCell.h: (JSC::createNumberStructure): (JSC::isNumberCell): (JSC::asNumberCell): (JSC::jsNumber): (JSC::JSValuePtr::isDoubleNumber): (JSC::JSValuePtr::getDoubleNumber): (JSC::JSValuePtr::isNumber): (JSC::JSValuePtr::uncheckedGetNumber): (JSC::jsNaN): (JSC::JSValuePtr::getNumber): (JSC::JSValuePtr::numberToInt32): (JSC::JSValuePtr::numberToUInt32):
  • runtime/JSValue.h:
  • runtime/NumberConstructor.cpp: (JSC::numberConstructorNegInfinity): (JSC::numberConstructorPosInfinity): (JSC::numberConstructorMaxValue): (JSC::numberConstructorMinValue):
  • runtime/NumberObject.cpp: (JSC::constructNumber):
  • runtime/NumberObject.h:
  • runtime/Operations.h: (JSC::JSValuePtr::equal): (JSC::JSValuePtr::equalSlowCaseInline): (JSC::JSValuePtr::strictEqual): (JSC::JSValuePtr::strictEqualSlowCaseInline):
  • wtf/Platform.h:
Location:
trunk/JavaScriptCore/runtime
Files:
12 edited

Legend:

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

    r39851 r39958  
    130130    }
    131131
    132     inline bool JSValuePtr::isNumberCell() const
    133     {
    134         return isCell() && asCell()->isNumber();
    135     }
    136 
    137132    inline bool JSCell::isObject() const
    138133    {
     
    176171
    177172    // --- JSValue inlines ----------------------------
    178 
    179     inline bool JSValuePtr::isNumber() const
    180     {
    181         return JSImmediate::isNumber(asValue()) || (isCell() && asCell()->isNumber());
    182     }
    183173
    184174    inline bool JSValuePtr::isString() const
  • trunk/JavaScriptCore/runtime/JSGlobalData.cpp

    r39951 r39958  
    8080    , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
    8181    , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
     82#if !USE(ALTERNATE_JSIMMEDIATE)
    8283    , numberStructure(JSNumberCell::createStructure(jsNull()))
     84#endif
    8385    , identifierTable(createIdentifierTable())
    8486    , propertyNames(new CommonIdentifiers(this))
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r39951 r39958  
    9393        RefPtr<Structure> notAnObjectErrorStubStructure;
    9494        RefPtr<Structure> notAnObjectStructure;
     95#if !USE(ALTERNATE_JSIMMEDIATE)
    9596        RefPtr<Structure> numberStructure;
     97#endif
    9698
    9799        IdentifierTable* identifierTable;
  • trunk/JavaScriptCore/runtime/JSImmediate.cpp

    r39670 r39958  
    3737    ASSERT(isImmediate(v));
    3838    if (isNumber(v))
    39         return constructNumberFromImmediateNumber(exec, v);
     39        return constructNumber(exec, v);
    4040    if (isBoolean(v))
    4141        return constructBooleanFromImmediateBoolean(exec, v);
     
    5252    ASSERT(isImmediate(v));
    5353    if (isNumber(v))
    54         return constructNumberFromImmediateNumber(exec, v);
     54        return constructNumber(exec, v);
    5555    if (isBoolean(v))
    5656        return constructBooleanFromImmediateBoolean(exec, v);
     
    7777{
    7878    ASSERT(isImmediate(v));
    79     if (isNumber(v))
     79    if (isIntegerNumber(v))
    8080        return UString::from(getTruncatedInt32(v));
     81#if USE(ALTERNATE_JSIMMEDIATE)
     82    if (isNumber(v)) {
     83        ASSERT(isDoubleNumber(v));
     84        double value = doubleValue(v);
     85        if (value == 0.0) // +0.0 or -0.0
     86            return "0";
     87        return UString::from(value);
     88    }
     89#else
     90        ASSERT(!isNumber(v));
     91#endif
    8192    if (jsBoolean(false) == v)
    8293        return "false";
  • trunk/JavaScriptCore/runtime/JSImmediate.h

    r39879 r39958  
    2626#include <wtf/AlwaysInline.h>
    2727#include <wtf/MathExtras.h>
     28#include <wtf/StdLibExtras.h>
    2829#include "JSValue.h"
    2930#include <limits>
     
    6869    JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i);
    6970
     71#if USE(ALTERNATE_JSIMMEDIATE)
     72    inline intptr_t reinterpretDoubleToIntptr(double value)
     73    {
     74        return WTF::bitwise_cast<intptr_t>(value);
     75    }
     76
     77    inline double reinterpretIntptrToDouble(intptr_t value)
     78    {
     79        return WTF::bitwise_cast<double>(value);
     80    }
     81#endif
     82
    7083    /*
    7184     * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
     
    112125    /*
    113126     * On 64-bit platforms, we support an alternative encoding form for immediates, if
    114      * USE(ALTERNATE_JSIMMEDIATE) is defined.
    115      *
    116      * The top 16-bits denote the type:
     127     * USE(ALTERNATE_JSIMMEDIATE) is defined.  When this format is used, double precision
     128     * floating point values may also be encoded as JSImmediates.
     129     *
     130     * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
     131     * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
     132     * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
     133     * have a payload of zero.  We assume that non-zero payloads are available to encode
     134     * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
     135     * all set represents a NaN with a non-zero payload, we can use this space in the NaN
     136     * ranges to encode other values (however there are also other ranges of NaN space that
     137     * could have been selected).  This range of NaN space is represented by 64-bit numbers
     138     * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
     139     * valid double-precision numbers will begin fall in these ranges.
     140     *
     141     * The scheme we have implemented encodes double precision values by adding 2^48 to the
     142     * 64-bit integer representation of the number.  After this manipulation, no encoded
     143     * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
     144     *
     145     * The top 16-bits denote the type of the encoded JSImmediate:
    117146     *
    118147     * Pointer: 0000:PPPP:PPPP:PPPP
     148     *          0001:****:****:****
     149     * Double:{         ...
     150     *          FFFE:****:****:****
    119151     * Integer: FFFF:0000:IIII:IIII
    120152     *
    121      * 32-bit signed integers are marked with the 16-bit tag '0xFFFF'.  The tag '0x0000'
     153     * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.  The tag 0x0000
    122154     * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
    123155     * values are encoded in the same manner as the default format.
     
    156188
    157189#if USE(ALTERNATE_JSIMMEDIATE)
    158         static const intptr_t TagTypeInteger = 0xffff000000000000ll; // bottom bit set indicates integer, this dominates the following bit
    159 #else
    160         static const intptr_t TagTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit
     190        // If all bits in the mask are set, this indicates an integer number,
     191        // if any but not all are set this value is a double precision number.
     192        static const intptr_t TagTypeNumber = 0xffff000000000000ll;
     193        // This value is 2^48, used to encode doubles such that the encoded value will begin
     194        // with a 16-bit pattern within the range 0x0001..0xFFFE.
     195        static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
     196#else
     197        static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
    161198#endif
    162199        static const intptr_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
    163         static const intptr_t TagMask           = TagTypeInteger | TagBitTypeOther;
     200        static const intptr_t TagMask           = TagTypeNumber | TagBitTypeOther;
    164201
    165202        static const intptr_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
     
    190227        static ALWAYS_INLINE bool isNumber(JSValuePtr v)
    191228        {
    192             return rawValue(v) & TagTypeInteger;
    193         }
    194 
    195         static ALWAYS_INLINE bool isPositiveNumber(JSValuePtr v)
     229            return rawValue(v) & TagTypeNumber;
     230        }
     231
     232        static ALWAYS_INLINE bool isIntegerNumber(JSValuePtr v)
     233        {
     234#if USE(ALTERNATE_JSIMMEDIATE)
     235            return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
     236#else
     237            return isNumber(v);
     238#endif
     239        }
     240
     241#if USE(ALTERNATE_JSIMMEDIATE)
     242        static ALWAYS_INLINE bool isDoubleNumber(JSValuePtr v)
     243        {
     244            return isNumber(v) && !isIntegerNumber(v);
     245        }
     246#endif
     247
     248        static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValuePtr v)
    196249        {
    197250            // A single mask to check for the sign bit and the number tag all at once.
    198             return (rawValue(v) & (signBit | TagTypeInteger)) == TagTypeInteger;
     251            return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
    199252        }
    200253       
     
    208261            // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
    209262            return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
    210         }
    211 
    212         static bool isNegative(JSValuePtr v)
    213         {
    214             ASSERT(isNumber(v));
    215             return rawValue(v) & signBit;
    216263        }
    217264
     
    239286        }
    240287
    241         static ALWAYS_INLINE bool areBothImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
    242         {
    243             return rawValue(v1) & rawValue(v2) & TagTypeInteger;
     288        static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValuePtr v1, JSValuePtr v2)
     289        {
     290#if USE(ALTERNATE_JSIMMEDIATE)
     291            return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
     292#else
     293            return rawValue(v1) & rawValue(v2) & TagTypeNumber;
     294#endif
    244295        }
    245296
     
    283334        }
    284335
     336        // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the
     337        // integer doesn't interfere with the tag bits in the upper word.  In the default encoding,
     338        // if intptr_t id larger then int32_t we sign extend the value through the upper word.
    285339#if USE(ALTERNATE_JSIMMEDIATE)
    286340        static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value)
     
    289343#endif
    290344        {
    291             return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeInteger);
    292         }
     345            return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
     346        }
     347       
     348#if USE(ALTERNATE_JSIMMEDIATE)
     349        static ALWAYS_INLINE JSValuePtr makeDouble(double value)
     350        {
     351            return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
     352        }
     353#endif
    293354       
    294355        static ALWAYS_INLINE JSValuePtr makeBool(bool b)
     
    306367            return makeValue(FullTagTypeNull);
    307368        }
    308        
     369
     370        template<typename T>
     371        static JSValuePtr fromNumberOutsideIntegerRange(T);
     372
     373#if USE(ALTERNATE_JSIMMEDIATE)
     374        static ALWAYS_INLINE double doubleValue(JSValuePtr v)
     375        {
     376            return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
     377        }
     378#endif
     379
    309380        static ALWAYS_INLINE int32_t intValue(JSValuePtr v)
    310381        {
     
    340411    ALWAYS_INLINE JSValuePtr JSImmediate::impossibleValue() { return makeValue(0x4); }
    341412
     413#if USE(ALTERNATE_JSIMMEDIATE)
     414    inline bool doubleToBoolean(double value)
     415    {
     416        return value < 0.0 || value > 0.0;
     417    }
     418
    342419    ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
    343420    {
    344421        ASSERT(isImmediate(v));
    345         intptr_t bits = rawValue(v);
    346         return (bits & TagTypeInteger)
    347             ? bits != TagTypeInteger // !0 ints
    348             : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
    349     }
     422        return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
     423            : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
     424    }
     425#else
     426    ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
     427    {
     428        ASSERT(isImmediate(v));
     429        return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
     430    }
     431#endif
    350432
    351433    ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v)
    352434    {
    353         ASSERT(isNumber(v));
     435        // FIXME: should probably be asserting isPositiveIntegerNumber here.
     436        ASSERT(isIntegerNumber(v));
    354437        return intValue(v);
    355438    }
    356439
     440#if USE(ALTERNATE_JSIMMEDIATE)
     441    template<typename T>
     442    inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T value)
     443    {
     444        return makeDouble(static_cast<double>(value));
     445    }
     446#else
     447    template<typename T>
     448    inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T)
     449    {
     450        return noValue();
     451    }
     452#endif
     453
    357454    ALWAYS_INLINE JSValuePtr JSImmediate::from(char i)
    358455    {
     
    382479    ALWAYS_INLINE JSValuePtr JSImmediate::from(int i)
    383480    {
     481#if !USE(ALTERNATE_JSIMMEDIATE)
    384482        if ((i < minImmediateInt) | (i > maxImmediateInt))
    385             return noValue();
     483            return fromNumberOutsideIntegerRange(i);
     484#endif
    386485        return makeInt(i);
    387486    }
     
    390489    {
    391490        if (i > maxImmediateUInt)
    392             return noValue();
     491            return fromNumberOutsideIntegerRange(i);
    393492        return makeInt(i);
    394493    }
     
    397496    {
    398497        if ((i < minImmediateInt) | (i > maxImmediateInt))
    399             return noValue();
     498            return fromNumberOutsideIntegerRange(i);
    400499        return makeInt(i);
    401500    }
     
    404503    {
    405504        if (i > maxImmediateUInt)
    406             return noValue();
     505            return fromNumberOutsideIntegerRange(i);
    407506        return makeInt(i);
    408507    }
     
    418517    {
    419518        if (i > maxImmediateUInt)
    420             return noValue();
     519            return fromNumberOutsideIntegerRange(i);
    421520        return makeInt(static_cast<intptr_t>(i));
    422521    }
     
    425524    {
    426525        const int intVal = static_cast<int>(d);
    427 
    428         if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
    429             return noValue();
    430526
    431527        // Check for data loss from conversion to int.
    432528        if (intVal != d || (!intVal && signbit(d)))
    433             return noValue();
    434 
    435         return makeInt(intVal);
     529            return fromNumberOutsideIntegerRange(d);
     530
     531        return from(intVal);
    436532    }
    437533
    438534    ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v)
    439535    {
    440         ASSERT(isNumber(v));
     536        ASSERT(isIntegerNumber(v));
    441537        return intValue(v);
    442538    }
     
    445541    {
    446542        ASSERT(isImmediate(v));
    447         int i;
    448         if (isNumber(v))
    449             i = intValue(v);
    450         else if (rawValue(v) == FullTagTypeUndefined)
     543
     544        if (isIntegerNumber(v))
     545            return intValue(v);
     546
     547#if USE(ALTERNATE_JSIMMEDIATE)
     548        if (isNumber(v)) {
     549            ASSERT(isDoubleNumber(v));
     550            return doubleValue(v);
     551        }
     552#else
     553        ASSERT(!isNumber(v));
     554#endif
     555
     556        if (rawValue(v) == FullTagTypeUndefined)
    451557            return nonInlineNaN();
    452         else
    453             i = rawValue(v) >> ExtendedPayloadShift;
    454         return i;
     558
     559        ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
     560        return rawValue(v) >> ExtendedPayloadShift;
    455561    }
    456562
     
    458564    {
    459565        i = uintValue(v);
    460         return isPositiveNumber(v);
     566        return isPositiveIntegerNumber(v);
    461567    }
    462568
     
    464570    {
    465571        i = intValue(v);
    466         return isNumber(v);
     572        return isIntegerNumber(v);
    467573    }
    468574
     
    601707    inline bool JSValuePtr::isInt32Fast() const
    602708    {
    603         return JSImmediate::isNumber(asValue());
     709        return JSImmediate::isIntegerNumber(asValue());
    604710    }
    605711
     
    612718    inline bool JSValuePtr::isUInt32Fast() const
    613719    {
    614         return JSImmediate::isPositiveNumber(asValue());
     720        return JSImmediate::isPositiveIntegerNumber(asValue());
    615721    }
    616722
     
    628734    inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1, JSValuePtr v2)
    629735    {
    630         return JSImmediate::areBothImmediateNumbers(v1, v2);
     736        return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
    631737    }
    632738
     
    635741        static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValuePtr v1, JSValuePtr v2)
    636742        {
    637             return JSImmediate::areBothImmediateNumbers(v1, v2);
     743            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
    638744        }
    639745
     
    659765        {
    660766            ASSERT(canDoFastBitwiseOperations(v1, v2));
    661             return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeInteger);
     767            return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
    662768        }
    663769
     
    670776        static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2)
    671777        {
    672             return JSImmediate::areBothImmediateNumbers(v1, v2);
     778            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
    673779        }
    674780
    675781        static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2)
    676782        {
    677             return JSImmediate::areBothImmediateNumbers(v1, v2) && !JSImmediate::isNegative(v1);
     783            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
    678784        }
    679785
     
    682788            ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
    683789#if USE(ALTERNATE_JSIMMEDIATE)
    684             return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeInteger);
    685 #else
    686             return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeInteger);
     790            return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber);
     791#else
     792            return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
    687793#endif
    688794        }
     
    692798            // Number is non-negative and an operation involving two of these can't overflow.
    693799            // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
    694             return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeInteger + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeInteger;
     800            return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber;
    695801        }
    696802
     
    705811        {
    706812            ASSERT(canDoFastAdditiveOperations(v1, v2));
    707             return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeInteger);
     813            return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
    708814        }
    709815
     
    711817        {
    712818            ASSERT(canDoFastAdditiveOperations(v1, v2));
    713             return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeInteger);
     819            return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
    714820        }
    715821
  • trunk/JavaScriptCore/runtime/JSNumberCell.cpp

    r39670 r39958  
    2828
    2929namespace JSC {
     30
     31#if !USE(ALTERNATE_JSIMMEDIATE)
    3032
    3133JSValuePtr JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
     
    102104}
    103105
    104 NEVER_INLINE JSValuePtr jsNumberCell(ExecState* exec, double d)
     106JSValuePtr jsNumberCell(ExecState* exec, double d)
    105107{
    106108    return new (exec) JSNumberCell(exec, d);
    107109}
    108110
    109 NEVER_INLINE JSValuePtr jsNaN(ExecState* exec)
    110 {
    111     return new (exec) JSNumberCell(exec, NaN);
    112 }
    113 
    114 NEVER_INLINE JSValuePtr jsNumberCell(JSGlobalData* globalData, double d)
     111JSValuePtr jsNumberCell(JSGlobalData* globalData, double d)
    115112{
    116113    return new (globalData) JSNumberCell(globalData, d);
    117114}
    118115
    119 NEVER_INLINE JSValuePtr jsNaN(JSGlobalData* globalData)
     116#else
     117
     118JSValuePtr jsNumberCell(ExecState*, double)
    120119{
    121     return new (globalData) JSNumberCell(globalData, NaN);
     120    ASSERT_NOT_REACHED();
     121    return noValue();
    122122}
    123123
     124#endif
     125
    124126} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSNumberCell.h

    r39851 r39958  
    3333namespace JSC {
    3434
     35    extern const double NaN;
     36    extern const double Inf;
     37
     38#if !USE(ALTERNATE_JSIMMEDIATE)
     39
    3540    class Identifier;
    3641    class JSCell;
     
    4550        friend class JIT;
    4651        friend JSValuePtr jsNumberCell(JSGlobalData*, double);
    47         friend JSValuePtr jsNaN(JSGlobalData*);
    4852        friend JSValuePtr jsNumberCell(ExecState*, double);
    49         friend JSValuePtr jsNaN(ExecState*);
    5053    public:
    5154        double value() const { return m_value; }
     
    6164        virtual JSObject* toThisObject(ExecState*) const;
    6265        virtual JSValuePtr getJSNumber();
    63 
    64         int32_t toInt32() const;
    65         uint32_t toUInt32() const;
    6666
    6767        void* operator new(size_t size, ExecState* exec)
     
    105105    };
    106106
    107     extern const double NaN;
    108     extern const double Inf;
    109 
    110107    JSValuePtr jsNumberCell(JSGlobalData*, double);
    111     JSValuePtr jsNaN(JSGlobalData*);
    112108    JSValuePtr jsNumberCell(ExecState*, double);
    113     JSValuePtr jsNaN(ExecState*);
    114 
    115     inline JSNumberCell* JSValuePtr::asNumberCell() const
    116     {
    117         ASSERT(isNumberCell());
    118         return static_cast<JSNumberCell*>(asCell());
     109
     110    inline bool isNumberCell(JSValuePtr v)
     111    {
     112        return v.isCell() && v.asCell()->isNumber();
     113    }
     114
     115    inline JSNumberCell* asNumberCell(JSValuePtr v)
     116    {
     117        ASSERT(isNumberCell(v));
     118        return static_cast<JSNumberCell*>(v.asCell());
    119119    }
    120120
     
    125125    }
    126126
    127     ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, char i)
    128     {
    129         ASSERT(JSImmediate::from(i));
    130         return JSImmediate::from(i);
    131     }
    132 
    133     ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned char i)
    134     {
    135         ASSERT(JSImmediate::from(i));
    136         return JSImmediate::from(i);
    137     }
    138 
    139     ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, short i)
    140     {
    141         ASSERT(JSImmediate::from(i));
    142         return JSImmediate::from(i);
    143     }
    144 
    145     ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned short i)
    146     {
    147         ASSERT(JSImmediate::from(i));
    148         return JSImmediate::from(i);
    149     }
    150 
    151127    ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, int i)
    152128    {
     
    191167    }
    192168
    193     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, short i)
     169    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i)
    194170    {
    195171        JSValuePtr v = JSImmediate::from(i);
     
    197173    }
    198174
    199     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i)
     175    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i)
    200176    {
    201177        JSValuePtr v = JSImmediate::from(i);
     
    203179    }
    204180
    205     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i)
     181    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i)
    206182    {
    207183        JSValuePtr v = JSImmediate::from(i);
     
    209185    }
    210186
    211     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i)
     187    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i)
    212188    {
    213189        JSValuePtr v = JSImmediate::from(i);
     
    215191    }
    216192
    217     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i)
    218     {
    219         JSValuePtr v = JSImmediate::from(i);
    220         return v ? v : jsNumberCell(globalData, i);
    221     }
    222 
    223     ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i)
    224     {
    225         JSValuePtr v = JSImmediate::from(i);
    226         return v ? v : jsNumberCell(globalData, i);
    227     }
    228 
    229193    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long long i)
    230194    {
     
    239203    }
    240204
     205    inline bool JSValuePtr::isDoubleNumber() const
     206    {
     207        return isNumberCell(asValue());
     208    }
     209
     210    inline double JSValuePtr::getDoubleNumber() const
     211    {
     212        return asNumberCell(asValue())->value();
     213    }
     214
     215    inline bool JSValuePtr::isNumber() const
     216    {
     217        return JSImmediate::isNumber(asValue()) || isDoubleNumber();
     218    }
     219
     220    inline double JSValuePtr::uncheckedGetNumber() const
     221    {
     222        ASSERT(isNumber());
     223        return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber();
     224    }
     225
     226#else
     227
     228    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, double d)
     229    {
     230        JSValuePtr v = JSImmediate::from(d);
     231        ASSERT(v);
     232        return v;
     233    }
     234
     235    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, int i)
     236    {
     237        JSValuePtr v = JSImmediate::from(i);
     238        ASSERT(v);
     239        return v;
     240    }
     241
     242    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned i)
     243    {
     244        JSValuePtr v = JSImmediate::from(i);
     245        ASSERT(v);
     246        return v;
     247    }
     248
     249    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long i)
     250    {
     251        JSValuePtr v = JSImmediate::from(i);
     252        ASSERT(v);
     253        return v;
     254    }
     255
     256    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long i)
     257    {
     258        JSValuePtr v = JSImmediate::from(i);
     259        ASSERT(v);
     260        return v;
     261    }
     262
     263    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long long i)
     264    {
     265        JSValuePtr v = JSImmediate::from(static_cast<double>(i));
     266        ASSERT(v);
     267        return v;
     268    }
     269
     270    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long long i)
     271    {
     272        JSValuePtr v = JSImmediate::from(static_cast<double>(i));
     273        ASSERT(v);
     274        return v;
     275    }
     276
     277    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, double d)
     278    {
     279        JSValuePtr v = JSImmediate::from(d);
     280        ASSERT(v);
     281        return v;
     282    }
     283
     284    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, int i)
     285    {
     286        JSValuePtr v = JSImmediate::from(i);
     287        ASSERT(v);
     288        return v;
     289    }
     290
     291    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned i)
     292    {
     293        JSValuePtr v = JSImmediate::from(i);
     294        ASSERT(v);
     295        return v;
     296    }
     297
     298    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long i)
     299    {
     300        JSValuePtr v = JSImmediate::from(i);
     301        ASSERT(v);
     302        return v;
     303    }
     304
     305    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long i)
     306    {
     307        JSValuePtr v = JSImmediate::from(i);
     308        ASSERT(v);
     309        return v;
     310    }
     311
     312    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long long i)
     313    {
     314        JSValuePtr v = JSImmediate::from(static_cast<double>(i));
     315        ASSERT(v);
     316        return v;
     317    }
     318
     319    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long long i)
     320    {
     321        JSValuePtr v = JSImmediate::from(static_cast<double>(i));
     322        ASSERT(v);
     323        return v;
     324    }
     325
     326    inline bool JSValuePtr::isDoubleNumber() const
     327    {
     328        return JSImmediate::isDoubleNumber(asValue());
     329    }
     330
     331    inline double JSValuePtr::getDoubleNumber() const
     332    {
     333        return JSImmediate::doubleValue(asValue());
     334    }
     335
     336    inline bool JSValuePtr::isNumber() const
     337    {
     338        return JSImmediate::isNumber(asValue());
     339    }
     340
     341    inline double JSValuePtr::uncheckedGetNumber() const
     342    {
     343        ASSERT(isNumber());
     344        return JSImmediate::toDouble(asValue());
     345    }
     346
     347#endif
     348
     349    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, char i)
     350    {
     351        ASSERT(JSImmediate::from(i));
     352        return JSImmediate::from(i);
     353    }
     354
     355    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned char i)
     356    {
     357        ASSERT(JSImmediate::from(i));
     358        return JSImmediate::from(i);
     359    }
     360
     361    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, short i)
     362    {
     363        ASSERT(JSImmediate::from(i));
     364        return JSImmediate::from(i);
     365    }
     366
     367    ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned short i)
     368    {
     369        ASSERT(JSImmediate::from(i));
     370        return JSImmediate::from(i);
     371    }
     372
     373    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, short i)
     374    {
     375        ASSERT(JSImmediate::from(i));
     376        return JSImmediate::from(i);
     377    }
     378
     379    ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned short i)
     380    {
     381        ASSERT(JSImmediate::from(i));
     382        return JSImmediate::from(i);
     383    }
     384
     385    inline JSValuePtr jsNaN(ExecState* exec)
     386    {
     387        return jsNumber(exec, NaN);
     388    }
     389
     390    inline JSValuePtr jsNaN(JSGlobalData* globalData)
     391    {
     392        return jsNumber(globalData, NaN);
     393    }
     394
    241395    // --- JSValue inlines ----------------------------
    242 
    243     inline double JSValuePtr::uncheckedGetNumber() const
    244     {
    245         ASSERT(isNumber());
    246         return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asNumberCell()->value();
    247     }
    248 
    249     inline int32_t JSNumberCell::toInt32() const
    250     {
    251         if (m_value >= -2147483648.0 && m_value < 2147483648.0)
    252             return static_cast<int32_t>(m_value);
    253         bool ignored;
    254         return toInt32SlowCase(m_value, ignored);
    255     }
    256 
    257     inline uint32_t JSNumberCell::toUInt32() const
    258     {
    259         if (m_value >= 0.0 && m_value < 4294967296.0)
    260             return static_cast<uint32_t>(m_value);
    261         bool ignored;
    262         return toUInt32SlowCase(m_value, ignored);
    263     }
    264396
    265397    ALWAYS_INLINE JSValuePtr JSValuePtr::toJSNumber(ExecState* exec) const
     
    272404        if (isInt32Fast())
    273405            result = getInt32Fast();
    274         else if (LIKELY(isNumberCell()))
    275             result = asNumberCell()->value();
     406        else if (LIKELY(isDoubleNumber()))
     407            result = getDoubleNumber();
    276408        else {
    277409            ASSERT(!isNumber());
     
    285417        if (isInt32Fast())
    286418            arg = getInt32Fast();
    287         else if (LIKELY(isNumberCell()))
    288             arg = asNumberCell()->toInt32();
     419        else if (LIKELY(isDoubleNumber()))
     420            arg = JSC::toInt32(getDoubleNumber());
    289421        else {
    290422            ASSERT(!isNumber());
     
    298430        if (isUInt32Fast())
    299431            arg = getUInt32Fast();
    300         else if (LIKELY(isNumberCell()))
    301             arg = asNumberCell()->toUInt32();
     432        else if (LIKELY(isDoubleNumber()))
     433            arg = JSC::toUInt32(getDoubleNumber());
    302434        else if (isInt32Fast()) {
    303435            // FIXME: I think this case can be merged with the uint case; toUInt32SlowCase
  • trunk/JavaScriptCore/runtime/JSValue.h

    r39851 r39958  
    3434    class Identifier;
    3535    class JSCell;
    36     class JSNumberCell;
    3736    class JSObject;
    3837    class JSString;
     
    207206        inline const JSValuePtr asValue() const { return *this; }
    208207
    209         bool isNumberCell() const;
    210         JSNumberCell* asNumberCell() const;
     208        bool isDoubleNumber() const;
     209        double getDoubleNumber() const;
    211210
    212211        JSCell* m_ptr;
  • trunk/JavaScriptCore/runtime/NumberConstructor.cpp

    r39670 r39958  
    7676JSValuePtr numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
    7777{
    78     return jsNumberCell(exec, -Inf);
     78    return jsNumber(exec, -Inf);
    7979}
    8080
    8181JSValuePtr numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
    8282{
    83     return jsNumberCell(exec, Inf);
     83    return jsNumber(exec, Inf);
    8484}
    8585
    8686JSValuePtr numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&)
    8787{
    88     return jsNumberCell(exec, 1.7976931348623157E+308);
     88    return jsNumber(exec, 1.7976931348623157E+308);
    8989}
    9090
    9191JSValuePtr numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&)
    9292{
    93     return jsNumberCell(exec, 5E-324);
     93    return jsNumber(exec, 5E-324);
    9494}
    9595
  • trunk/JavaScriptCore/runtime/NumberObject.cpp

    r39670 r39958  
    4242}
    4343
    44 NumberObject* constructNumber(ExecState* exec, JSNumberCell* number)
     44NumberObject* constructNumber(ExecState* exec, JSValuePtr number)
    4545{
    4646    NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
     
    4949}
    5050
    51 NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValuePtr value)
    52 {
    53     NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
    54     object->setInternalValue(value);
    55     return object;
    56 }
    57 
    5851} // namespace JSC
  • trunk/JavaScriptCore/runtime/NumberObject.h

    r39670 r39958  
    2626namespace JSC {
    2727
    28     class JSNumberCell;
    29 
    3028    class NumberObject : public JSWrapperObject {
    3129    public:
     
    4038    };
    4139
    42     NumberObject* constructNumber(ExecState*, JSNumberCell*);
    43     NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValuePtr);
     40    NumberObject* constructNumber(ExecState*, JSValuePtr);
    4441
    4542} // namespace JSC
  • trunk/JavaScriptCore/runtime/Operations.h

    r39851 r39958  
    3232    inline bool JSValuePtr::equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
    3333    {
    34         if (JSImmediate::areBothImmediateNumbers(v1, v2))
     34        if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
    3535            return v1 == v2;
    3636
     
    4040    ALWAYS_INLINE bool JSValuePtr::equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
    4141    {
    42         ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2));
     42        ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2));
    4343
    4444        do {
     
    7272                    return false;
    7373                v1 = p1;
    74                 if (JSImmediate::areBothImmediateNumbers(v1, v2))
     74                if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
    7575                    return v1 == v2;
    7676                continue;
     
    8282                    return false;
    8383                v2 = p2;
    84                 if (JSImmediate::areBothImmediateNumbers(v1, v2))
     84                if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
    8585                    return v1 == v2;
    8686                continue;
     
    108108    inline bool JSValuePtr::strictEqual(JSValuePtr v1, JSValuePtr v2)
    109109    {
    110         if (JSImmediate::areBothImmediate(v1, v2))
     110        if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
    111111            return v1 == v2;
    112112
    113         if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != js0()) & (v2 != js0()))
    114             return false;
     113        if (v1->isNumber() && v2->isNumber())
     114            return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
     115
     116        if (JSImmediate::isEitherImmediate(v1, v2))
     117            return v1 == v2;
    115118
    116119        return strictEqualSlowCase(v1, v2);
     
    119122    ALWAYS_INLINE bool JSValuePtr::strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2)
    120123    {
    121         ASSERT(!JSImmediate::areBothImmediate(v1, v2));
     124        ASSERT(!JSImmediate::isEitherImmediate(v1, v2));
    122125
    123         if (JSImmediate::isEitherImmediate(v1, v2)) {
    124             ASSERT(v1 == js0() || v2 == js0());
    125             ASSERT(v1 != v2);
    126 
    127             // The reason we can't just return false here is that 0 === -0,
    128             // and while the former is an immediate number, the latter is not.
    129             if (v1 == js0())
    130                 return v2->asCell()->isNumber() && v2->asNumberCell()->value() == 0;
    131             return v1->asCell()->isNumber() && v1->asNumberCell()->value() == 0;
    132         }
    133 
    134         if (v1->asCell()->isNumber()) {
    135             return v2->asCell()->isNumber()
    136                 && v1->asNumberCell()->value() == v2->asNumberCell()->value();
    137         }
    138 
    139         if (v1->asCell()->isString()) {
    140             return v2->asCell()->isString()
    141                 && asString(v1)->value() == asString(v2)->value();
    142         }
     126        if (v1->asCell()->isString() && v2->asCell()->isString())
     127            return asString(v1)->value() == asString(v2)->value();
    143128
    144129        return v1 == v2;
Note: See TracChangeset for help on using the changeset viewer.