Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  *  Copyright (C) 2006 Alexey Proskuryakov (ap (at) webkit.org)
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Library General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Library General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Library General Public License
     16  *  along with this library; see the file COPYING.LIB.  If not, write to
     17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  *  Boston, MA 02110-1301, USA.
     19  *
     20  */
     21 
     22 #ifndef JSImmediate_h
     23 #define JSImmediate_h
     24 
     25 #include <wtf/Platform.h>
     26 
     27 #if !USE(JSVALUE32_64)
     28 
     29 #include <wtf/Assertions.h>
     30 #include <wtf/AlwaysInline.h>
     31 #include <wtf/MathExtras.h>
     32 #include <wtf/StdLibExtras.h>
     33 #include "JSValue.h"
     34 #include <limits>
     35 #include <limits.h>
     36 #include <stdarg.h>
     37 #include <stdint.h>
     38 #include <stdlib.h>
     39 
     40 namespace JSC {
     41 
     42     class ExecState;
     43     class JSCell;
     44     class JSFastMath;
     45     class JSGlobalData;
     46     class JSObject;
     47     class UString;
     48 
     49 #if USE(JSVALUE64)
     50     inline intptr_t reinterpretDoubleToIntptr(double value)
     51     {
     52         return WTF::bitwise_cast<intptr_t>(value);
     53     }
     54 
     55     inline double reinterpretIntptrToDouble(intptr_t value)
     56     {
     57         return WTF::bitwise_cast<double>(value);
     58     }
     59 #endif
     60 
     61     /*
     62      * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
     63      * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
     64      * because allocator alignment guarantees they will be 00 in cell pointers.
     65      *
     66      * For example, on a 32 bit system:
     67      *
     68      * JSCell*:             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     00
     69      *                      [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
     70      * JSImmediate:         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     TT
     71      *                      [ high 30 bits: 'payload' ]             [ low 2 bits -- tag ]
     72      *
     73      * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
     74      * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
     75      * tag used to indicate the exact type.
     76      *
     77      * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
     78      * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
     79      * two bits will form an extended tag.
     80      *
     81      * 31 bit signed int:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     X1
     82      *                      [ high 30 bits of the value ]      [ high bit part of value ]
     83      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      ZZ               10
     84      *                      [ extended 'payload' ]  [  extended tag  ]  [  tag 'other'  ]
     85      *
     86      * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
     87      * bit would flag the value as undefined.  If neither bits are set, the value is null.
     88      *
     89      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      UB               10
     90      *                      [ extended 'payload' ]  [ undefined | bool ]  [ tag 'other' ]
     91      *
     92      * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
     93      * For undefined or null immediates the payload is zero.
     94      *
     95      * Boolean:             000000000000000000000000000V      01               10
     96      *                      [ boolean value ]              [ bool ]       [ tag 'other' ]
     97      * Undefined:           0000000000000000000000000000      10               10
     98      *                      [ zero ]                    [ undefined ]     [ tag 'other' ]
     99      * Null:                0000000000000000000000000000      00               10
    100      *                      [ zero ]                       [ zero ]       [ tag 'other' ]
    101      */
    102 
    103     /*
    104      * On 64-bit platforms, we support an alternative encoding form for immediates, if
    105      * USE(JSVALUE64) is defined.  When this format is used, double precision
    106      * floating point values may also be encoded as JSImmediates.
    107      *
    108      * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
    109      * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
    110      * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
    111      * have a payload of zero.  We assume that non-zero payloads are available to encode
    112      * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
    113      * all set represents a NaN with a non-zero payload, we can use this space in the NaN
    114      * ranges to encode other values (however there are also other ranges of NaN space that
    115      * could have been selected).  This range of NaN space is represented by 64-bit numbers
    116      * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
    117      * valid double-precision numbers will begin fall in these ranges.
    118      *
    119      * The scheme we have implemented encodes double precision values by adding 2^48 to the
    120      * 64-bit integer representation of the number.  After this manipulation, no encoded
    121      * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
    122      *
    123      * The top 16-bits denote the type of the encoded JSImmediate:
    124      *
    125      * Pointer: 0000:PPPP:PPPP:PPPP
    126      *          0001:****:****:****
    127      * Double:{         ...
    128      *          FFFE:****:****:****
    129      * Integer: FFFF:0000:IIII:IIII
    130      *
    131      * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.  The tag 0x0000
    132      * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
    133      * values are encoded in the same manner as the default format.
    134      */
    135 
    136     class JSImmediate {
    137     private:
    138         friend class JIT;
    139         friend class JSValue;
    140         friend class JSFastMath;
    141         friend JSValue jsNumber(ExecState* exec, double d);
    142         friend JSValue jsNumber(ExecState*, char i);
    143         friend JSValue jsNumber(ExecState*, unsigned char i);
    144         friend JSValue jsNumber(ExecState*, short i);
    145         friend JSValue jsNumber(ExecState*, unsigned short i);
    146         friend JSValue jsNumber(ExecState* exec, int i);
    147         friend JSValue jsNumber(ExecState* exec, unsigned i);
    148         friend JSValue jsNumber(ExecState* exec, long i);
    149         friend JSValue jsNumber(ExecState* exec, unsigned long i);
    150         friend JSValue jsNumber(ExecState* exec, long long i);
    151         friend JSValue jsNumber(ExecState* exec, unsigned long long i);
    152         friend JSValue jsNumber(JSGlobalData* globalData, double d);
    153         friend JSValue jsNumber(JSGlobalData* globalData, short i);
    154         friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i);
    155         friend JSValue jsNumber(JSGlobalData* globalData, int i);
    156         friend JSValue jsNumber(JSGlobalData* globalData, unsigned i);
    157         friend JSValue jsNumber(JSGlobalData* globalData, long i);
    158         friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i);
    159         friend JSValue jsNumber(JSGlobalData* globalData, long long i);
    160         friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i);
    161 
    162 #if USE(JSVALUE64)
    163         // If all bits in the mask are set, this indicates an integer number,
    164         // if any but not all are set this value is a double precision number.
    165         static const intptr_t TagTypeNumber = 0xffff000000000000ll;
    166         // This value is 2^48, used to encode doubles such that the encoded value will begin
    167         // with a 16-bit pattern within the range 0x0001..0xFFFE.
    168         static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
    169 #else
    170         static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
    171 #endif
    172         static const intptr_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
    173         static const intptr_t TagMask           = TagTypeNumber | TagBitTypeOther;
    174 
    175         static const intptr_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
    176         static const intptr_t ExtendedTagBitBool      = 0x4;
    177         static const intptr_t ExtendedTagBitUndefined = 0x8;
    178 
    179         static const intptr_t FullTagTypeMask      = TagMask | ExtendedTagMask;
    180         static const intptr_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
    181         static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
    182         static const intptr_t FullTagTypeNull      = TagBitTypeOther;
    183 
    184 #if USE(JSVALUE64)
    185         static const int32_t IntegerPayloadShift  = 0;
    186 #else
    187         static const int32_t IntegerPayloadShift  = 1;
    188 #endif
    189         static const int32_t ExtendedPayloadShift = 4;
    190 
    191         static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
    192 
    193         static const int32_t signBit = 0x80000000;
    194 
    195         static ALWAYS_INLINE bool isImmediate(JSValue v)
    196         {
    197             return rawValue(v) & TagMask;
    198         }
    199 
    200         static ALWAYS_INLINE bool isNumber(JSValue v)
    201         {
    202             return rawValue(v) & TagTypeNumber;
    203         }
    204 
    205         static ALWAYS_INLINE bool isIntegerNumber(JSValue v)
    206         {
    207 #if USE(JSVALUE64)
    208             return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
    209 #else
    210             return isNumber(v);
    211 #endif
    212         }
    213 
    214 #if USE(JSVALUE64)
    215         static ALWAYS_INLINE bool isDouble(JSValue v)
    216         {
    217             return isNumber(v) && !isIntegerNumber(v);
    218         }
    219 #endif
    220 
    221         static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v)
    222         {
    223             // A single mask to check for the sign bit and the number tag all at once.
    224             return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
    225         }
    226 
    227         static ALWAYS_INLINE bool isBoolean(JSValue v)
    228         {
    229             return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
    230         }
    231 
    232         static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v)
    233         {
    234             // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
    235             return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
    236         }
    237 
    238         static JSValue from(char);
    239         static JSValue from(signed char);
    240         static JSValue from(unsigned char);
    241         static JSValue from(short);
    242         static JSValue from(unsigned short);
    243         static JSValue from(int);
    244         static JSValue from(unsigned);
    245         static JSValue from(long);
    246         static JSValue from(unsigned long);
    247         static JSValue from(long long);
    248         static JSValue from(unsigned long long);
    249         static JSValue from(double);
    250 
    251         static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2)
    252         {
    253             return (rawValue(v1) | rawValue(v2)) & TagMask;
    254         }
    255 
    256         static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2)
    257         {
    258             return isImmediate(v1) & isImmediate(v2);
    259         }
    260 
    261         static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2)
    262         {
    263 #if USE(JSVALUE64)
    264             return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
    265 #else
    266             return rawValue(v1) & rawValue(v2) & TagTypeNumber;
    267 #endif
    268         }
    269 
    270         static double toDouble(JSValue);
    271         static bool toBoolean(JSValue);
    272 
    273         static bool getUInt32(JSValue, uint32_t&);
    274         static bool getTruncatedInt32(JSValue, int32_t&);
    275         static bool getTruncatedUInt32(JSValue, uint32_t&);
    276 
    277         static int32_t getTruncatedInt32(JSValue);
    278         static uint32_t getTruncatedUInt32(JSValue);
    279 
    280         static JSValue trueImmediate();
    281         static JSValue falseImmediate();
    282         static JSValue undefinedImmediate();
    283         static JSValue nullImmediate();
    284         static JSValue zeroImmediate();
    285         static JSValue oneImmediate();
    286 
    287     private:
    288 #if USE(JSVALUE64)
    289         static const int minImmediateInt = ((-INT_MAX) - 1);
    290         static const int maxImmediateInt = INT_MAX;
    291 #else
    292         static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
    293         static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
    294 #endif
    295         static const unsigned maxImmediateUInt = maxImmediateInt;
    296 
    297         static ALWAYS_INLINE JSValue makeValue(intptr_t integer)
    298         {
    299             return JSValue::makeImmediate(integer);
    300         }
    301 
    302         // With USE(JSVALUE64) we want the argument to be zero extended, so the
    303         // integer doesn't interfere with the tag bits in the upper word.  In the default encoding,
    304         // if intptr_t id larger then int32_t we sign extend the value through the upper word.
    305 #if USE(JSVALUE64)
    306         static ALWAYS_INLINE JSValue makeInt(uint32_t value)
    307 #else
    308         static ALWAYS_INLINE JSValue makeInt(int32_t value)
    309 #endif
    310         {
    311             return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
    312         }
    313 
    314 #if USE(JSVALUE64)
    315         static ALWAYS_INLINE JSValue makeDouble(double value)
    316         {
    317             return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
    318         }
    319 #endif
    320 
    321         static ALWAYS_INLINE JSValue makeBool(bool b)
    322         {
    323             return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
    324         }
    325 
    326         static ALWAYS_INLINE JSValue makeUndefined()
    327         {
    328             return makeValue(FullTagTypeUndefined);
    329         }
    330 
    331         static ALWAYS_INLINE JSValue makeNull()
    332         {
    333             return makeValue(FullTagTypeNull);
    334         }
    335 
    336         template<typename T>
    337         static JSValue fromNumberOutsideIntegerRange(T);
    338 
    339 #if USE(JSVALUE64)
    340         static ALWAYS_INLINE double doubleValue(JSValue v)
    341         {
    342             return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
    343         }
    344 #endif
    345 
    346         static ALWAYS_INLINE int32_t intValue(JSValue v)
    347         {
    348             return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
    349         }
    350 
    351         static ALWAYS_INLINE uint32_t uintValue(JSValue v)
    352         {
    353             return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
    354         }
    355 
    356         static ALWAYS_INLINE bool boolValue(JSValue v)
    357         {
    358             return rawValue(v) & ExtendedPayloadBitBoolValue;
    359         }
    360 
    361         static ALWAYS_INLINE intptr_t rawValue(JSValue v)
    362         {
    363             return v.immediateValue();
    364         }
    365     };
    366 
    367     ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); }
    368     ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); }
    369     ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); }
    370     ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); }
    371     ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); }
    372     ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); }
    373 
    374 #if USE(JSVALUE64)
    375     inline bool doubleToBoolean(double value)
    376     {
    377         return value < 0.0 || value > 0.0;
    378     }
    379 
    380     ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
    381     {
    382         ASSERT(isImmediate(v));
    383         return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
    384             : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
    385     }
    386 #else
    387     ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
    388     {
    389         ASSERT(isImmediate(v));
    390         return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
    391     }
    392 #endif
    393 
    394     ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v)
    395     {
    396         // FIXME: should probably be asserting isPositiveIntegerNumber here.
    397         ASSERT(isIntegerNumber(v));
    398         return intValue(v);
    399     }
    400 
    401 #if USE(JSVALUE64)
    402     template<typename T>
    403     inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value)
    404     {
    405         return makeDouble(static_cast<double>(value));
    406     }
    407 #else
    408     template<typename T>
    409     inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T)
    410     {
    411         return JSValue();
    412     }
    413 #endif
    414 
    415     ALWAYS_INLINE JSValue JSImmediate::from(char i)
    416     {
    417         return makeInt(i);
    418     }
    419 
    420     ALWAYS_INLINE JSValue JSImmediate::from(signed char i)
    421     {
    422         return makeInt(i);
    423     }
    424 
    425     ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i)
    426     {
    427         return makeInt(i);
    428     }
    429 
    430     ALWAYS_INLINE JSValue JSImmediate::from(short i)
    431     {
    432         return makeInt(i);
    433     }
    434 
    435     ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i)
    436     {
    437         return makeInt(i);
    438     }
    439 
    440     ALWAYS_INLINE JSValue JSImmediate::from(int i)
    441     {
    442 #if !USE(JSVALUE64)
    443         if ((i < minImmediateInt) | (i > maxImmediateInt))
    444             return fromNumberOutsideIntegerRange(i);
    445 #endif
    446         return makeInt(i);
    447     }
    448 
    449     ALWAYS_INLINE JSValue JSImmediate::from(unsigned i)
    450     {
    451         if (i > maxImmediateUInt)
    452             return fromNumberOutsideIntegerRange(i);
    453         return makeInt(i);
    454     }
    455 
    456     ALWAYS_INLINE JSValue JSImmediate::from(long i)
    457     {
    458         if ((i < minImmediateInt) | (i > maxImmediateInt))
    459             return fromNumberOutsideIntegerRange(i);
    460         return makeInt(i);
    461     }
    462 
    463     ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i)
    464     {
    465         if (i > maxImmediateUInt)
    466             return fromNumberOutsideIntegerRange(i);
    467         return makeInt(i);
    468     }
    469 
    470     ALWAYS_INLINE JSValue JSImmediate::from(long long i)
    471     {
    472         if ((i < minImmediateInt) | (i > maxImmediateInt))
    473             return JSValue();
    474         return makeInt(static_cast<intptr_t>(i));
    475     }
    476 
    477     ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i)
    478     {
    479         if (i > maxImmediateUInt)
    480             return fromNumberOutsideIntegerRange(i);
    481         return makeInt(static_cast<intptr_t>(i));
    482     }
    483 
    484     ALWAYS_INLINE JSValue JSImmediate::from(double d)
    485     {
    486         const int intVal = static_cast<int>(d);
    487 
    488         // Check for data loss from conversion to int.
    489         if (intVal != d || (!intVal && signbit(d)))
    490             return fromNumberOutsideIntegerRange(d);
    491 
    492         return from(intVal);
    493     }
    494 
    495     ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v)
    496     {
    497         ASSERT(isIntegerNumber(v));
    498         return intValue(v);
    499     }
    500 
    501     ALWAYS_INLINE double JSImmediate::toDouble(JSValue v)
    502     {
    503         ASSERT(isImmediate(v));
    504 
    505         if (isIntegerNumber(v))
    506             return intValue(v);
    507 
    508 #if USE(JSVALUE64)
    509         if (isNumber(v)) {
    510             ASSERT(isDouble(v));
    511             return doubleValue(v);
    512         }
    513 #else
    514         ASSERT(!isNumber(v));
    515 #endif
    516 
    517         if (rawValue(v) == FullTagTypeUndefined)
    518             return nonInlineNaN();
    519 
    520         ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
    521         return rawValue(v) >> ExtendedPayloadShift;
    522     }
    523 
    524     ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i)
    525     {
    526         i = uintValue(v);
    527         return isPositiveIntegerNumber(v);
    528     }
    529 
    530     ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i)
    531     {
    532         i = intValue(v);
    533         return isIntegerNumber(v);
    534     }
    535 
    536     ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i)
    537     {
    538         return getUInt32(v, i);
    539     }
    540 
    541     inline JSValue::JSValue(JSNullTag)
    542     {
    543         *this = JSImmediate::nullImmediate();
    544     }
    545 
    546     inline JSValue::JSValue(JSUndefinedTag)
    547     {
    548         *this = JSImmediate::undefinedImmediate();
    549     }
    550 
    551     inline JSValue::JSValue(JSTrueTag)
    552     {
    553         *this = JSImmediate::trueImmediate();
    554     }
    555 
    556     inline JSValue::JSValue(JSFalseTag)
    557     {
    558         *this = JSImmediate::falseImmediate();
    559     }
    560 
    561     inline bool JSValue::isUndefinedOrNull() const
    562     {
    563         return JSImmediate::isUndefinedOrNull(asValue());
    564     }
    565 
    566     inline bool JSValue::isBoolean() const
    567     {
    568         return JSImmediate::isBoolean(asValue());
    569     }
    570 
    571     inline bool JSValue::isTrue() const
    572     {
    573         return asValue() == JSImmediate::trueImmediate();
    574     }
    575 
    576     inline bool JSValue::isFalse() const
    577     {
    578         return asValue() == JSImmediate::falseImmediate();
    579     }
    580 
    581     inline bool JSValue::getBoolean(bool& v) const
    582     {
    583         if (JSImmediate::isBoolean(asValue())) {
    584             v = JSImmediate::toBoolean(asValue());
    585             return true;
    586         }
    587 
    588         return false;
    589     }
    590 
    591     inline bool JSValue::getBoolean() const
    592     {
    593         return asValue() == jsBoolean(true);
    594     }
    595 
    596     inline bool JSValue::isCell() const
    597     {
    598         return !JSImmediate::isImmediate(asValue());
    599     }
    600 
    601     inline bool JSValue::isInt32() const
    602     {
    603         return JSImmediate::isIntegerNumber(asValue());
    604     }
    605 
    606     inline int32_t JSValue::asInt32() const
    607     {
    608         ASSERT(isInt32());
    609         return JSImmediate::getTruncatedInt32(asValue());
    610     }
    611 
    612     inline bool JSValue::isUInt32() const
    613     {
    614         return JSImmediate::isPositiveIntegerNumber(asValue());
    615     }
    616 
    617     inline uint32_t JSValue::asUInt32() const
    618     {
    619         ASSERT(isUInt32());
    620         return JSImmediate::getTruncatedUInt32(asValue());
    621     }
    622 
    623     class JSFastMath {
    624     public:
    625         static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2)
    626         {
    627             return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
    628         }
    629 
    630         static ALWAYS_INLINE JSValue equal(JSValue v1, JSValue v2)
    631         {
    632             ASSERT(canDoFastBitwiseOperations(v1, v2));
    633             return jsBoolean(v1 == v2);
    634         }
    635 
    636         static ALWAYS_INLINE JSValue notEqual(JSValue v1, JSValue v2)
    637         {
    638             ASSERT(canDoFastBitwiseOperations(v1, v2));
    639             return jsBoolean(v1 != v2);
    640         }
    641 
    642         static ALWAYS_INLINE JSValue andImmediateNumbers(JSValue v1, JSValue v2)
    643         {
    644             ASSERT(canDoFastBitwiseOperations(v1, v2));
    645             return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
    646         }
    647 
    648         static ALWAYS_INLINE JSValue xorImmediateNumbers(JSValue v1, JSValue v2)
    649         {
    650             ASSERT(canDoFastBitwiseOperations(v1, v2));
    651             return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
    652         }
    653 
    654         static ALWAYS_INLINE JSValue orImmediateNumbers(JSValue v1, JSValue v2)
    655         {
    656             ASSERT(canDoFastBitwiseOperations(v1, v2));
    657             return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
    658         }
    659 
    660         static ALWAYS_INLINE bool canDoFastRshift(JSValue v1, JSValue v2)
    661         {
    662             return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
    663         }
    664 
    665         static ALWAYS_INLINE bool canDoFastUrshift(JSValue v1, JSValue v2)
    666         {
    667             return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
    668         }
    669 
    670         static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift)
    671         {
    672             ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
    673 #if USE(JSVALUE64)
    674             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);
    675 #else
    676             return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
    677 #endif
    678         }
    679 
    680         static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v)
    681         {
    682             // Number is non-negative and an operation involving two of these can't overflow.
    683             // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
    684             return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber;
    685         }
    686 
    687         static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v1, JSValue v2)
    688         {
    689             // Number is non-negative and an operation involving two of these can't overflow.
    690             // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
    691             return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2);
    692         }
    693 
    694         static ALWAYS_INLINE JSValue addImmediateNumbers(JSValue v1, JSValue v2)
    695         {
    696             ASSERT(canDoFastAdditiveOperations(v1, v2));
    697             return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
    698         }
    699 
    700         static ALWAYS_INLINE JSValue subImmediateNumbers(JSValue v1, JSValue v2)
    701         {
    702             ASSERT(canDoFastAdditiveOperations(v1, v2));
    703             return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
    704         }
    705 
    706         static ALWAYS_INLINE JSValue incImmediateNumber(JSValue v)
    707         {
    708             ASSERT(canDoFastAdditiveOperations(v));
    709             return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
    710         }
    711 
    712         static ALWAYS_INLINE JSValue decImmediateNumber(JSValue v)
    713         {
    714             ASSERT(canDoFastAdditiveOperations(v));
    715             return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
    716         }
    717     };
    718 
    719 } // namespace JSC
    720 
    721 #endif // !USE(JSVALUE32_64)
    722 
    723 #endif // JSImmediate_h
    724