JavaScriptCore/runtime/JSImmediate.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
       
     3  *  Copyright (C) 2006 Alexey Proskuryakov (ap@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 #if !USE(JSVALUE32_64)
       
    26 
       
    27 #include <wtf/Assertions.h>
       
    28 #include <wtf/AlwaysInline.h>
       
    29 #include <wtf/MathExtras.h>
       
    30 #include <wtf/StdLibExtras.h>
       
    31 #include "JSValue.h"
       
    32 #include <limits>
       
    33 #include <limits.h>
       
    34 #include <stdarg.h>
       
    35 #include <stdint.h>
       
    36 #include <stdlib.h>
       
    37 
       
    38 namespace JSC {
       
    39 
       
    40     class ExecState;
       
    41     class JSCell;
       
    42     class JSFastMath;
       
    43     class JSGlobalData;
       
    44     class JSObject;
       
    45     class UString;
       
    46 
       
    47 #if USE(JSVALUE64)
       
    48     inline intptr_t reinterpretDoubleToIntptr(double value)
       
    49     {
       
    50         return WTF::bitwise_cast<intptr_t>(value);
       
    51     }
       
    52 
       
    53     inline double reinterpretIntptrToDouble(intptr_t value)
       
    54     {
       
    55         return WTF::bitwise_cast<double>(value);
       
    56     }
       
    57 #endif
       
    58 
       
    59     /*
       
    60      * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 
       
    61      * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
       
    62      * because allocator alignment guarantees they will be 00 in cell pointers.
       
    63      *
       
    64      * For example, on a 32 bit system:
       
    65      *
       
    66      * JSCell*:             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     00
       
    67      *                      [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
       
    68      * JSImmediate:         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     TT
       
    69      *                      [ high 30 bits: 'payload' ]             [ low 2 bits -- tag ]
       
    70      *
       
    71      * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
       
    72      * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
       
    73      * tag used to indicate the exact type.
       
    74      *
       
    75      * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
       
    76      * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
       
    77      * two bits will form an extended tag.
       
    78      *
       
    79      * 31 bit signed int:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     X1
       
    80      *                      [ high 30 bits of the value ]      [ high bit part of value ]
       
    81      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      ZZ               10
       
    82      *                      [ extended 'payload' ]  [  extended tag  ]  [  tag 'other'  ]
       
    83      *
       
    84      * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
       
    85      * bit would flag the value as undefined.  If neither bits are set, the value is null.
       
    86      *
       
    87      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      UB               10
       
    88      *                      [ extended 'payload' ]  [ undefined | bool ]  [ tag 'other' ]
       
    89      *
       
    90      * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
       
    91      * For undefined or null immediates the payload is zero.
       
    92      *
       
    93      * Boolean:             000000000000000000000000000V      01               10
       
    94      *                      [ boolean value ]              [ bool ]       [ tag 'other' ]
       
    95      * Undefined:           0000000000000000000000000000      10               10
       
    96      *                      [ zero ]                    [ undefined ]     [ tag 'other' ]
       
    97      * Null:                0000000000000000000000000000      00               10
       
    98      *                      [ zero ]                       [ zero ]       [ tag 'other' ]
       
    99      */
       
   100 
       
   101     /*
       
   102      * On 64-bit platforms, we support an alternative encoding form for immediates, if
       
   103      * USE(JSVALUE64) is defined.  When this format is used, double precision
       
   104      * floating point values may also be encoded as JSImmediates.
       
   105      *
       
   106      * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
       
   107      * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
       
   108      * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
       
   109      * have a payload of zero.  We assume that non-zero payloads are available to encode
       
   110      * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
       
   111      * all set represents a NaN with a non-zero payload, we can use this space in the NaN
       
   112      * ranges to encode other values (however there are also other ranges of NaN space that
       
   113      * could have been selected).  This range of NaN space is represented by 64-bit numbers
       
   114      * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
       
   115      * valid double-precision numbers will begin fall in these ranges.
       
   116      *
       
   117      * The scheme we have implemented encodes double precision values by adding 2^48 to the
       
   118      * 64-bit integer representation of the number.  After this manipulation, no encoded
       
   119      * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
       
   120      *
       
   121      * The top 16-bits denote the type of the encoded JSImmediate:
       
   122      *
       
   123      * Pointer: 0000:PPPP:PPPP:PPPP
       
   124      *          0001:****:****:****
       
   125      * Double:{         ...
       
   126      *          FFFE:****:****:****
       
   127      * Integer: FFFF:0000:IIII:IIII
       
   128      *
       
   129      * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.  The tag 0x0000
       
   130      * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
       
   131      * values are encoded in the same manner as the default format.
       
   132      */
       
   133 
       
   134     class JSImmediate {
       
   135     private:
       
   136         friend class JIT;
       
   137         friend class JSValue;
       
   138         friend class JSFastMath;
       
   139         friend class JSInterfaceJIT;
       
   140         friend class SpecializedThunkJIT;
       
   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 #elif USE(JSVALUE32)
       
   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