Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      4  *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
      5  *
      6  *  This library is free software; you can redistribute it and/or
      7  *  modify it under the terms of the GNU Library General Public
      8  *  License as published by the Free Software Foundation; either
      9  *  version 2 of the License, or (at your option) any later version.
     10  *
     11  *  This library is distributed in the hope that it will be useful,
     12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  *  Library General Public License for more details.
     15  *
     16  *  You should have received a copy of the GNU Library General Public License
     17  *  along with this library; see the file COPYING.LIB.  If not, write to
     18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  *  Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #ifndef JSValue_h
     24 #define JSValue_h
     25 
     26 #include "CallData.h"
     27 #include "ConstructData.h"
     28 #include <math.h>
     29 #include <stddef.h> // for size_t
     30 #include <stdint.h>
     31 #include <wtf/AlwaysInline.h>
     32 #include <wtf/Assertions.h>
     33 #include <wtf/HashTraits.h>
     34 #include <wtf/MathExtras.h>
     35 
     36 namespace JSC {
     37 
     38     class Identifier;
     39     class JSCell;
     40     class JSGlobalData;
     41     class JSImmediate;
     42     class JSObject;
     43     class JSString;
     44     class PropertySlot;
     45     class PutPropertySlot;
     46     class UString;
     47 
     48     struct ClassInfo;
     49     struct Instruction;
     50 
     51     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
     52 
     53 #if USE(JSVALUE32_64)
     54     typedef int64_t EncodedJSValue;
     55 #else
     56     typedef void* EncodedJSValue;
     57 #endif
     58 
     59     double nonInlineNaN();
     60     int32_t toInt32SlowCase(double, bool& ok);
     61     uint32_t toUInt32SlowCase(double, bool& ok);
     62 
     63     class JSValue {
     64         friend class JSImmediate;
     65         friend struct EncodedJSValueHashTraits;
     66         friend class JIT;
     67         friend class JITStubs;
     68         friend class JITStubCall;
     69 
     70     public:
     71         static EncodedJSValue encode(JSValue value);
     72         static JSValue decode(EncodedJSValue ptr);
     73 #if !USE(JSVALUE32_64)
     74     private:
     75         static JSValue makeImmediate(intptr_t value);
     76         intptr_t immediateValue();
     77     public:
     78 #endif
     79         enum JSNullTag { JSNull };
     80         enum JSUndefinedTag { JSUndefined };
     81         enum JSTrueTag { JSTrue };
     82         enum JSFalseTag { JSFalse };
     83         enum EncodeAsDoubleTag { EncodeAsDouble };
     84 
     85         JSValue();
     86         JSValue(JSNullTag);
     87         JSValue(JSUndefinedTag);
     88         JSValue(JSTrueTag);
     89         JSValue(JSFalseTag);
     90         JSValue(JSCell* ptr);
     91         JSValue(const JSCell* ptr);
     92 
     93         // Numbers
     94         JSValue(EncodeAsDoubleTag, ExecState*, double);
     95         JSValue(ExecState*, double);
     96         JSValue(ExecState*, char);
     97         JSValue(ExecState*, unsigned char);
     98         JSValue(ExecState*, short);
     99         JSValue(ExecState*, unsigned short);
    100         JSValue(ExecState*, int);
    101         JSValue(ExecState*, unsigned);
    102         JSValue(ExecState*, long);
    103         JSValue(ExecState*, unsigned long);
    104         JSValue(ExecState*, long long);
    105         JSValue(ExecState*, unsigned long long);
    106         JSValue(JSGlobalData*, double);
    107         JSValue(JSGlobalData*, int);
    108         JSValue(JSGlobalData*, unsigned);
    109 
    110         operator bool() const;
    111         bool operator==(const JSValue& other) const;
    112         bool operator!=(const JSValue& other) const;
    113 
    114         bool isInt32() const;
    115         bool isUInt32() const;
    116         bool isDouble() const;
    117         bool isTrue() const;
    118         bool isFalse() const;
    119 
    120         int32_t asInt32() const;
    121         uint32_t asUInt32() const;
    122         double asDouble() const;
    123 
    124         // Querying the type.
    125         bool isUndefined() const;
    126         bool isNull() const;
    127         bool isUndefinedOrNull() const;
    128         bool isBoolean() const;
    129         bool isNumber() const;
    130         bool isString() const;
    131         bool isGetterSetter() const;
    132         bool isObject() const;
    133         bool inherits(const ClassInfo*) const;
    134 
    135         // Extracting the value.
    136         bool getBoolean(bool&) const;
    137         bool getBoolean() const; // false if not a boolean
    138         bool getNumber(double&) const;
    139         double uncheckedGetNumber() const;
    140         bool getString(ExecState* exec, UString&) const;
    141         UString getString(ExecState* exec) const; // null string if not a string
    142         JSObject* getObject() const; // 0 if not an object
    143 
    144         CallType getCallData(CallData&);
    145         ConstructType getConstructData(ConstructData&);
    146 
    147         // Extracting integer values.
    148         bool getUInt32(uint32_t&) const;
    149 
    150         // Basic conversions.
    151         JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
    152         bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
    153 
    154         bool toBoolean(ExecState*) const;
    155 
    156         // toNumber conversion is expected to be side effect free if an exception has
    157         // been set in the ExecState already.
    158         double toNumber(ExecState*) const;
    159         JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
    160         UString toString(ExecState*) const;
    161         UString toPrimitiveString(ExecState*) const;
    162         JSObject* toObject(ExecState*) const;
    163 
    164         // Integer conversions.
    165         double toInteger(ExecState*) const;
    166         double toIntegerPreserveNaN(ExecState*) const;
    167         int32_t toInt32(ExecState*) const;
    168         int32_t toInt32(ExecState*, bool& ok) const;
    169         uint32_t toUInt32(ExecState*) const;
    170         uint32_t toUInt32(ExecState*, bool& ok) const;
    171 
    172 #if ENABLE(JSC_ZOMBIES)
    173         bool isZombie() const;
    174 #endif
    175 
    176         // Floating point conversions (this is a convenience method for webcore;
    177         // signle precision float is not a representation used in JS or JSC).
    178         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
    179 
    180         // Object operations, with the toObject operation included.
    181         JSValue get(ExecState*, const Identifier& propertyName) const;
    182         JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
    183         JSValue get(ExecState*, unsigned propertyName) const;
    184         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
    185         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    186         void put(ExecState*, unsigned propertyName, JSValue);
    187 
    188         bool needsThisConversion() const;
    189         JSObject* toThisObject(ExecState*) const;
    190         UString toThisString(ExecState*) const;
    191         JSString* toThisJSString(ExecState*);
    192 
    193         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
    194         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
    195         static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
    196         static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
    197         static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
    198         static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
    199 
    200         JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
    201 
    202         bool isCell() const;
    203         JSCell* asCell() const;
    204 
    205 #ifndef NDEBUG
    206         char* description();
    207 #endif
    208 
    209     private:
    210         enum HashTableDeletedValueTag { HashTableDeletedValue };
    211         JSValue(HashTableDeletedValueTag);
    212 
    213         inline const JSValue asValue() const { return *this; }
    214         JSObject* toObjectSlowCase(ExecState*) const;
    215         JSObject* toThisObjectSlowCase(ExecState*) const;
    216 
    217         enum { Int32Tag =        0xffffffff };
    218         enum { CellTag =         0xfffffffe };
    219         enum { TrueTag =         0xfffffffd };
    220         enum { FalseTag =        0xfffffffc };
    221         enum { NullTag =         0xfffffffb };
    222         enum { UndefinedTag =    0xfffffffa };
    223         enum { EmptyValueTag =   0xfffffff9 };
    224         enum { DeletedValueTag = 0xfffffff8 };
    225 
    226         enum { LowestTag =  DeletedValueTag };
    227 
    228         uint32_t tag() const;
    229         int32_t payload() const;
    230 
    231         JSObject* synthesizePrototype(ExecState*) const;
    232         JSObject* synthesizeObject(ExecState*) const;
    233 
    234 #if USE(JSVALUE32_64)
    235         union {
    236             EncodedJSValue asEncodedJSValue;
    237             double asDouble;
    238 #if CPU(BIG_ENDIAN)
    239             struct {
    240                 int32_t tag;
    241                 int32_t payload;
    242             } asBits;
    243 #else
    244             struct {
    245                 int32_t payload;
    246                 int32_t tag;
    247             } asBits;
    248 #endif
    249         } u;
    250 #else // USE(JSVALUE32_64)
    251         JSCell* m_ptr;
    252 #endif // USE(JSVALUE32_64)
    253     };
    254 
    255 #if USE(JSVALUE32_64)
    256     typedef IntHash<EncodedJSValue> EncodedJSValueHash;
    257 
    258     struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
    259         static const bool emptyValueIsZero = false;
    260         static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
    261         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
    262         static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
    263     };
    264 #else
    265     typedef PtrHash<EncodedJSValue> EncodedJSValueHash;
    266 
    267     struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
    268         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
    269         static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
    270     };
    271 #endif
    272 
    273     // Stand-alone helper functions.
    274     inline JSValue jsNull()
    275     {
    276         return JSValue(JSValue::JSNull);
    277     }
    278 
    279     inline JSValue jsUndefined()
    280     {
    281         return JSValue(JSValue::JSUndefined);
    282     }
    283 
    284     inline JSValue jsBoolean(bool b)
    285     {
    286         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
    287     }
    288 
    289     ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d)
    290     {
    291         return JSValue(JSValue::EncodeAsDouble, exec, d);
    292     }
    293 
    294     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
    295     {
    296         return JSValue(exec, d);
    297     }
    298 
    299     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
    300     {
    301         return JSValue(exec, i);
    302     }
    303 
    304     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
    305     {
    306         return JSValue(exec, i);
    307     }
    308 
    309     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
    310     {
    311         return JSValue(exec, i);
    312     }
    313 
    314     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
    315     {
    316         return JSValue(exec, i);
    317     }
    318 
    319     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
    320     {
    321         return JSValue(exec, i);
    322     }
    323 
    324     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
    325     {
    326         return JSValue(exec, i);
    327     }
    328 
    329     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
    330     {
    331         return JSValue(exec, i);
    332     }
    333 
    334     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
    335     {
    336         return JSValue(exec, i);
    337     }
    338 
    339     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
    340     {
    341         return JSValue(exec, i);
    342     }
    343 
    344     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
    345     {
    346         return JSValue(exec, i);
    347     }
    348 
    349     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
    350     {
    351         return JSValue(globalData, d);
    352     }
    353 
    354     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
    355     {
    356         return JSValue(globalData, i);
    357     }
    358 
    359     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
    360     {
    361         return JSValue(globalData, i);
    362     }
    363 
    364     inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
    365     inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
    366 
    367     inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
    368     inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
    369 
    370     inline int32_t toInt32(double val)
    371     {
    372         if (!(val >= -2147483648.0 && val < 2147483648.0)) {
    373             bool ignored;
    374             return toInt32SlowCase(val, ignored);
    375         }
    376         return static_cast<int32_t>(val);
    377     }
    378 
    379     inline uint32_t toUInt32(double val)
    380     {
    381         if (!(val >= 0.0 && val < 4294967296.0)) {
    382             bool ignored;
    383             return toUInt32SlowCase(val, ignored);
    384         }
    385         return static_cast<uint32_t>(val);
    386     }
    387 
    388     // FIXME: We should deprecate this and just use JSValue::asCell() instead.
    389     JSCell* asCell(JSValue);
    390 
    391     inline JSCell* asCell(JSValue value)
    392     {
    393         return value.asCell();
    394     }
    395 
    396     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
    397     {
    398         if (isInt32())
    399             return asInt32();
    400         bool ignored;
    401         return toInt32SlowCase(toNumber(exec), ignored);
    402     }
    403 
    404     inline uint32_t JSValue::toUInt32(ExecState* exec) const
    405     {
    406         if (isUInt32())
    407             return asInt32();
    408         bool ignored;
    409         return toUInt32SlowCase(toNumber(exec), ignored);
    410     }
    411 
    412     inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
    413     {
    414         if (isInt32()) {
    415             ok = true;
    416             return asInt32();
    417         }
    418         return toInt32SlowCase(toNumber(exec), ok);
    419     }
    420 
    421     inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
    422     {
    423         if (isUInt32()) {
    424             ok = true;
    425             return asInt32();
    426         }
    427         return toUInt32SlowCase(toNumber(exec), ok);
    428     }
    429 
    430 #if USE(JSVALUE32_64)
    431     inline JSValue jsNaN(ExecState* exec)
    432     {
    433         return JSValue(exec, nonInlineNaN());
    434     }
    435 
    436     // JSValue member functions.
    437     inline EncodedJSValue JSValue::encode(JSValue value)
    438     {
    439         return value.u.asEncodedJSValue;
    440     }
    441 
    442     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
    443     {
    444         JSValue v;
    445         v.u.asEncodedJSValue = encodedJSValue;
    446 #if ENABLE(JSC_ZOMBIES)
    447         ASSERT(!v.isZombie());
    448 #endif
    449         return v;
    450     }
    451 
    452     inline JSValue::JSValue()
    453     {
    454         u.asBits.tag = EmptyValueTag;
    455         u.asBits.payload = 0;
    456     }
    457 
    458     inline JSValue::JSValue(JSNullTag)
    459     {
    460         u.asBits.tag = NullTag;
    461         u.asBits.payload = 0;
    462     }
    463 
    464     inline JSValue::JSValue(JSUndefinedTag)
    465     {
    466         u.asBits.tag = UndefinedTag;
    467         u.asBits.payload = 0;
    468     }
    469 
    470     inline JSValue::JSValue(JSTrueTag)
    471     {
    472         u.asBits.tag = TrueTag;
    473         u.asBits.payload = 0;
    474     }
    475 
    476     inline JSValue::JSValue(JSFalseTag)
    477     {
    478         u.asBits.tag = FalseTag;
    479         u.asBits.payload = 0;
    480     }
    481 
    482     inline JSValue::JSValue(HashTableDeletedValueTag)
    483     {
    484         u.asBits.tag = DeletedValueTag;
    485         u.asBits.payload = 0;
    486     }
    487 
    488     inline JSValue::JSValue(JSCell* ptr)
    489     {
    490         if (ptr)
    491             u.asBits.tag = CellTag;
    492         else
    493             u.asBits.tag = EmptyValueTag;
    494         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
    495 #if ENABLE(JSC_ZOMBIES)
    496         ASSERT(!isZombie());
    497 #endif
    498     }
    499 
    500     inline JSValue::JSValue(const JSCell* ptr)
    501     {
    502         if (ptr)
    503             u.asBits.tag = CellTag;
    504         else
    505             u.asBits.tag = EmptyValueTag;
    506         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
    507 #if ENABLE(JSC_ZOMBIES)
    508         ASSERT(!isZombie());
    509 #endif
    510     }
    511 
    512     inline JSValue::operator bool() const
    513     {
    514         ASSERT(tag() != DeletedValueTag);
    515         return tag() != EmptyValueTag;
    516     }
    517 
    518     inline bool JSValue::operator==(const JSValue& other) const
    519     {
    520         return u.asEncodedJSValue == other.u.asEncodedJSValue;
    521     }
    522 
    523     inline bool JSValue::operator!=(const JSValue& other) const
    524     {
    525         return u.asEncodedJSValue != other.u.asEncodedJSValue;
    526     }
    527 
    528     inline bool JSValue::isUndefined() const
    529     {
    530         return tag() == UndefinedTag;
    531     }
    532 
    533     inline bool JSValue::isNull() const
    534     {
    535         return tag() == NullTag;
    536     }
    537 
    538     inline bool JSValue::isUndefinedOrNull() const
    539     {
    540         return isUndefined() || isNull();
    541     }
    542 
    543     inline bool JSValue::isCell() const
    544     {
    545         return tag() == CellTag;
    546     }
    547 
    548     inline bool JSValue::isInt32() const
    549     {
    550         return tag() == Int32Tag;
    551     }
    552 
    553     inline bool JSValue::isUInt32() const
    554     {
    555         return tag() == Int32Tag && asInt32() > -1;
    556     }
    557 
    558     inline bool JSValue::isDouble() const
    559     {
    560         return tag() < LowestTag;
    561     }
    562 
    563     inline bool JSValue::isTrue() const
    564     {
    565         return tag() == TrueTag;
    566     }
    567 
    568     inline bool JSValue::isFalse() const
    569     {
    570         return tag() == FalseTag;
    571     }
    572 
    573     inline uint32_t JSValue::tag() const
    574     {
    575         return u.asBits.tag;
    576     }
    577 
    578     inline int32_t JSValue::payload() const
    579     {
    580         return u.asBits.payload;
    581     }
    582 
    583     inline int32_t JSValue::asInt32() const
    584     {
    585         ASSERT(isInt32());
    586         return u.asBits.payload;
    587     }
    588 
    589     inline uint32_t JSValue::asUInt32() const
    590     {
    591         ASSERT(isUInt32());
    592         return u.asBits.payload;
    593     }
    594 
    595     inline double JSValue::asDouble() const
    596     {
    597         ASSERT(isDouble());
    598         return u.asDouble;
    599     }
    600 
    601     ALWAYS_INLINE JSCell* JSValue::asCell() const
    602     {
    603         ASSERT(isCell());
    604         return reinterpret_cast<JSCell*>(u.asBits.payload);
    605     }
    606 
    607     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
    608     {
    609         u.asDouble = d;
    610     }
    611 
    612     inline JSValue::JSValue(ExecState* exec, double d)
    613     {
    614         const int32_t asInt32 = static_cast<int32_t>(d);
    615         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
    616             u.asDouble = d;
    617             return;
    618         }
    619         *this = JSValue(exec, static_cast<int32_t>(d));
    620     }
    621 
    622     inline JSValue::JSValue(ExecState* exec, char i)
    623     {
    624         *this = JSValue(exec, static_cast<int32_t>(i));
    625     }
    626 
    627     inline JSValue::JSValue(ExecState* exec, unsigned char i)
    628     {
    629         *this = JSValue(exec, static_cast<int32_t>(i));
    630     }
    631 
    632     inline JSValue::JSValue(ExecState* exec, short i)
    633     {
    634         *this = JSValue(exec, static_cast<int32_t>(i));
    635     }
    636 
    637     inline JSValue::JSValue(ExecState* exec, unsigned short i)
    638     {
    639         *this = JSValue(exec, static_cast<int32_t>(i));
    640     }
    641 
    642     inline JSValue::JSValue(ExecState*, int i)
    643     {
    644         u.asBits.tag = Int32Tag;
    645         u.asBits.payload = i;
    646     }
    647 
    648     inline JSValue::JSValue(ExecState* exec, unsigned i)
    649     {
    650         if (static_cast<int32_t>(i) < 0) {
    651             *this = JSValue(exec, static_cast<double>(i));
    652             return;
    653         }
    654         *this = JSValue(exec, static_cast<int32_t>(i));
    655     }
    656 
    657     inline JSValue::JSValue(ExecState* exec, long i)
    658     {
    659         if (static_cast<int32_t>(i) != i) {
    660             *this = JSValue(exec, static_cast<double>(i));
    661             return;
    662         }
    663         *this = JSValue(exec, static_cast<int32_t>(i));
    664     }
    665 
    666     inline JSValue::JSValue(ExecState* exec, unsigned long i)
    667     {
    668         if (static_cast<uint32_t>(i) != i) {
    669             *this = JSValue(exec, static_cast<double>(i));
    670             return;
    671         }
    672         *this = JSValue(exec, static_cast<uint32_t>(i));
    673     }
    674 
    675     inline JSValue::JSValue(ExecState* exec, long long i)
    676     {
    677         if (static_cast<int32_t>(i) != i) {
    678             *this = JSValue(exec, static_cast<double>(i));
    679             return;
    680         }
    681         *this = JSValue(exec, static_cast<int32_t>(i));
    682     }
    683 
    684     inline JSValue::JSValue(ExecState* exec, unsigned long long i)
    685     {
    686         if (static_cast<uint32_t>(i) != i) {
    687             *this = JSValue(exec, static_cast<double>(i));
    688             return;
    689         }
    690         *this = JSValue(exec, static_cast<uint32_t>(i));
    691     }
    692 
    693     inline JSValue::JSValue(JSGlobalData* globalData, double d)
    694     {
    695         const int32_t asInt32 = static_cast<int32_t>(d);
    696         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
    697             u.asDouble = d;
    698             return;
    699         }
    700         *this = JSValue(globalData, static_cast<int32_t>(d));
    701     }
    702 
    703     inline JSValue::JSValue(JSGlobalData*, int i)
    704     {
    705         u.asBits.tag = Int32Tag;
    706         u.asBits.payload = i;
    707     }
    708 
    709     inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
    710     {
    711         if (static_cast<int32_t>(i) < 0) {
    712             *this = JSValue(globalData, static_cast<double>(i));
    713             return;
    714         }
    715         *this = JSValue(globalData, static_cast<int32_t>(i));
    716     }
    717 
    718     inline bool JSValue::isNumber() const
    719     {
    720         return isInt32() || isDouble();
    721     }
    722 
    723     inline bool JSValue::isBoolean() const
    724     {
    725         return isTrue() || isFalse();
    726     }
    727 
    728     inline bool JSValue::getBoolean(bool& v) const
    729     {
    730         if (isTrue()) {
    731             v = true;
    732             return true;
    733         }
    734         if (isFalse()) {
    735             v = false;
    736             return true;
    737         }
    738 
    739         return false;
    740     }
    741 
    742     inline bool JSValue::getBoolean() const
    743     {
    744         ASSERT(isBoolean());
    745         return tag() == TrueTag;
    746     }
    747 
    748     inline double JSValue::uncheckedGetNumber() const
    749     {
    750         ASSERT(isNumber());
    751         return isInt32() ? asInt32() : asDouble();
    752     }
    753 
    754     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
    755     {
    756         return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
    757     }
    758 
    759     inline bool JSValue::getNumber(double& result) const
    760     {
    761         if (isInt32()) {
    762             result = asInt32();
    763             return true;
    764         }
    765         if (isDouble()) {
    766             result = asDouble();
    767             return true;
    768         }
    769         return false;
    770     }
    771 
    772 #else // USE(JSVALUE32_64)
    773 
    774     // JSValue member functions.
    775     inline EncodedJSValue JSValue::encode(JSValue value)
    776     {
    777         return reinterpret_cast<EncodedJSValue>(value.m_ptr);
    778     }
    779 
    780     inline JSValue JSValue::decode(EncodedJSValue ptr)
    781     {
    782         return JSValue(reinterpret_cast<JSCell*>(ptr));
    783     }
    784 
    785     inline JSValue JSValue::makeImmediate(intptr_t value)
    786     {
    787         return JSValue(reinterpret_cast<JSCell*>(value));
    788     }
    789 
    790     inline intptr_t JSValue::immediateValue()
    791     {
    792         return reinterpret_cast<intptr_t>(m_ptr);
    793     }
    794 
    795     // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
    796     inline JSValue::JSValue()
    797         : m_ptr(0)
    798     {
    799     }
    800 
    801     // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
    802     inline JSValue::JSValue(HashTableDeletedValueTag)
    803         : m_ptr(reinterpret_cast<JSCell*>(0x4))
    804     {
    805     }
    806 
    807     inline JSValue::JSValue(JSCell* ptr)
    808         : m_ptr(ptr)
    809     {
    810 #if ENABLE(JSC_ZOMBIES)
    811         ASSERT(!isZombie());
    812 #endif
    813     }
    814 
    815     inline JSValue::JSValue(const JSCell* ptr)
    816         : m_ptr(const_cast<JSCell*>(ptr))
    817     {
    818 #if ENABLE(JSC_ZOMBIES)
    819         ASSERT(!isZombie());
    820 #endif
    821     }
    822 
    823     inline JSValue::operator bool() const
    824     {
    825         return m_ptr;
    826     }
    827 
    828     inline bool JSValue::operator==(const JSValue& other) const
    829     {
    830         return m_ptr == other.m_ptr;
    831     }
    832 
    833     inline bool JSValue::operator!=(const JSValue& other) const
    834     {
    835         return m_ptr != other.m_ptr;
    836     }
    837 
    838     inline bool JSValue::isUndefined() const
    839     {
    840         return asValue() == jsUndefined();
    841     }
    842 
    843     inline bool JSValue::isNull() const
    844     {
    845         return asValue() == jsNull();
    846     }
    847 #endif // USE(JSVALUE32_64)
    848 
    849 } // namespace JSC
    850 
    851 #endif // JSValue_h
    852