Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef JSValueInlineMethods_h
     27 #define JSValueInlineMethods_h
     28 
     29 #include "JSValue.h"
     30 
     31 namespace JSC {
     32 
     33     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
     34     {
     35         if (isInt32())
     36             return asInt32();
     37         return JSC::toInt32(toNumber(exec));
     38     }
     39 
     40     inline uint32_t JSValue::toUInt32(ExecState* exec) const
     41     {
     42         // See comment on JSC::toUInt32, above.
     43         return toInt32(exec);
     44     }
     45 
     46     inline bool JSValue::isUInt32() const
     47     {
     48         return isInt32() && asInt32() >= 0;
     49     }
     50 
     51     inline uint32_t JSValue::asUInt32() const
     52     {
     53         ASSERT(isUInt32());
     54         return asInt32();
     55     }
     56 
     57     inline double JSValue::uncheckedGetNumber() const
     58     {
     59         ASSERT(isNumber());
     60         return isInt32() ? asInt32() : asDouble();
     61     }
     62 
     63     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
     64     {
     65         return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
     66     }
     67 
     68     inline JSValue jsNaN()
     69     {
     70         return JSValue(nonInlineNaN());
     71     }
     72 
     73     inline bool JSValue::getNumber(double& result) const
     74     {
     75         if (isInt32()) {
     76             result = asInt32();
     77             return true;
     78         }
     79         if (isDouble()) {
     80             result = asDouble();
     81             return true;
     82         }
     83         return false;
     84     }
     85 
     86     inline bool JSValue::getBoolean(bool& v) const
     87     {
     88         if (isTrue()) {
     89             v = true;
     90             return true;
     91         }
     92         if (isFalse()) {
     93             v = false;
     94             return true;
     95         }
     96 
     97         return false;
     98     }
     99 
    100     inline JSValue::JSValue(char i)
    101     {
    102         *this = JSValue(static_cast<int32_t>(i));
    103     }
    104 
    105     inline JSValue::JSValue(unsigned char i)
    106     {
    107         *this = JSValue(static_cast<int32_t>(i));
    108     }
    109 
    110     inline JSValue::JSValue(short i)
    111     {
    112         *this = JSValue(static_cast<int32_t>(i));
    113     }
    114 
    115     inline JSValue::JSValue(unsigned short i)
    116     {
    117         *this = JSValue(static_cast<int32_t>(i));
    118     }
    119 
    120     inline JSValue::JSValue(unsigned i)
    121     {
    122         if (static_cast<int32_t>(i) < 0) {
    123             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
    124             return;
    125         }
    126         *this = JSValue(static_cast<int32_t>(i));
    127     }
    128 
    129     inline JSValue::JSValue(long i)
    130     {
    131         if (static_cast<int32_t>(i) != i) {
    132             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
    133             return;
    134         }
    135         *this = JSValue(static_cast<int32_t>(i));
    136     }
    137 
    138     inline JSValue::JSValue(unsigned long i)
    139     {
    140         if (static_cast<uint32_t>(i) != i) {
    141             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
    142             return;
    143         }
    144         *this = JSValue(static_cast<uint32_t>(i));
    145     }
    146 
    147     inline JSValue::JSValue(long long i)
    148     {
    149         if (static_cast<int32_t>(i) != i) {
    150             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
    151             return;
    152         }
    153         *this = JSValue(static_cast<int32_t>(i));
    154     }
    155 
    156     inline JSValue::JSValue(unsigned long long i)
    157     {
    158         if (static_cast<uint32_t>(i) != i) {
    159             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
    160             return;
    161         }
    162         *this = JSValue(static_cast<uint32_t>(i));
    163     }
    164 
    165     inline JSValue::JSValue(double d)
    166     {
    167         const int32_t asInt32 = static_cast<int32_t>(d);
    168         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
    169             *this = JSValue(EncodeAsDouble, d);
    170             return;
    171         }
    172         *this = JSValue(static_cast<int32_t>(d));
    173     }
    174 
    175 #if USE(JSVALUE32_64)
    176     inline EncodedJSValue JSValue::encode(JSValue value)
    177     {
    178         return value.u.asInt64;
    179     }
    180 
    181     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
    182     {
    183         JSValue v;
    184         v.u.asInt64 = encodedJSValue;
    185         return v;
    186     }
    187 
    188     inline JSValue::JSValue()
    189     {
    190         u.asBits.tag = EmptyValueTag;
    191         u.asBits.payload = 0;
    192     }
    193 
    194     inline JSValue::JSValue(JSNullTag)
    195     {
    196         u.asBits.tag = NullTag;
    197         u.asBits.payload = 0;
    198     }
    199 
    200     inline JSValue::JSValue(JSUndefinedTag)
    201     {
    202         u.asBits.tag = UndefinedTag;
    203         u.asBits.payload = 0;
    204     }
    205 
    206     inline JSValue::JSValue(JSTrueTag)
    207     {
    208         u.asBits.tag = BooleanTag;
    209         u.asBits.payload = 1;
    210     }
    211 
    212     inline JSValue::JSValue(JSFalseTag)
    213     {
    214         u.asBits.tag = BooleanTag;
    215         u.asBits.payload = 0;
    216     }
    217 
    218     inline JSValue::JSValue(HashTableDeletedValueTag)
    219     {
    220         u.asBits.tag = DeletedValueTag;
    221         u.asBits.payload = 0;
    222     }
    223 
    224     inline JSValue::JSValue(JSCell* ptr)
    225     {
    226         if (ptr)
    227             u.asBits.tag = CellTag;
    228         else
    229             u.asBits.tag = EmptyValueTag;
    230         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
    231 #if ENABLE(JSC_ZOMBIES)
    232         ASSERT(!isZombie());
    233 #endif
    234     }
    235 
    236     inline JSValue::JSValue(const JSCell* ptr)
    237     {
    238         if (ptr)
    239             u.asBits.tag = CellTag;
    240         else
    241             u.asBits.tag = EmptyValueTag;
    242         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
    243 #if ENABLE(JSC_ZOMBIES)
    244         ASSERT(!isZombie());
    245 #endif
    246     }
    247 
    248     inline JSValue::operator bool() const
    249     {
    250         ASSERT(tag() != DeletedValueTag);
    251         return tag() != EmptyValueTag;
    252     }
    253 
    254     inline bool JSValue::operator==(const JSValue& other) const
    255     {
    256         return u.asInt64 == other.u.asInt64;
    257     }
    258 
    259     inline bool JSValue::operator!=(const JSValue& other) const
    260     {
    261         return u.asInt64 != other.u.asInt64;
    262     }
    263 
    264     inline bool JSValue::isUndefined() const
    265     {
    266         return tag() == UndefinedTag;
    267     }
    268 
    269     inline bool JSValue::isNull() const
    270     {
    271         return tag() == NullTag;
    272     }
    273 
    274     inline bool JSValue::isUndefinedOrNull() const
    275     {
    276         return isUndefined() || isNull();
    277     }
    278 
    279     inline bool JSValue::isCell() const
    280     {
    281         return tag() == CellTag;
    282     }
    283 
    284     inline bool JSValue::isInt32() const
    285     {
    286         return tag() == Int32Tag;
    287     }
    288 
    289     inline bool JSValue::isDouble() const
    290     {
    291         return tag() < LowestTag;
    292     }
    293 
    294     inline bool JSValue::isTrue() const
    295     {
    296         return tag() == BooleanTag && payload();
    297     }
    298 
    299     inline bool JSValue::isFalse() const
    300     {
    301         return tag() == BooleanTag && !payload();
    302     }
    303 
    304     inline uint32_t JSValue::tag() const
    305     {
    306         return u.asBits.tag;
    307     }
    308 
    309     inline int32_t JSValue::payload() const
    310     {
    311         return u.asBits.payload;
    312     }
    313 
    314     inline int32_t JSValue::asInt32() const
    315     {
    316         ASSERT(isInt32());
    317         return u.asBits.payload;
    318     }
    319 
    320     inline double JSValue::asDouble() const
    321     {
    322         ASSERT(isDouble());
    323         return u.asDouble;
    324     }
    325 
    326     ALWAYS_INLINE JSCell* JSValue::asCell() const
    327     {
    328         ASSERT(isCell());
    329         return reinterpret_cast<JSCell*>(u.asBits.payload);
    330     }
    331 
    332     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
    333     {
    334         u.asDouble = d;
    335     }
    336 
    337     inline JSValue::JSValue(int i)
    338     {
    339         u.asBits.tag = Int32Tag;
    340         u.asBits.payload = i;
    341     }
    342 
    343     inline bool JSValue::isNumber() const
    344     {
    345         return isInt32() || isDouble();
    346     }
    347 
    348     inline bool JSValue::isBoolean() const
    349     {
    350         return isTrue() || isFalse();
    351     }
    352 
    353     inline bool JSValue::getBoolean() const
    354     {
    355         ASSERT(isBoolean());
    356         return payload();
    357     }
    358 
    359 #else // USE(JSVALUE32_64)
    360 
    361     // JSValue member functions.
    362     inline EncodedJSValue JSValue::encode(JSValue value)
    363     {
    364         return value.u.ptr;
    365     }
    366 
    367     inline JSValue JSValue::decode(EncodedJSValue ptr)
    368     {
    369         return JSValue(reinterpret_cast<JSCell*>(ptr));
    370     }
    371 
    372     // 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.
    373     inline JSValue::JSValue()
    374     {
    375         u.asInt64 = ValueEmpty;
    376     }
    377 
    378     // 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.
    379     inline JSValue::JSValue(HashTableDeletedValueTag)
    380     {
    381         u.asInt64 = ValueDeleted;
    382     }
    383 
    384     inline JSValue::JSValue(JSCell* ptr)
    385     {
    386         u.ptr = ptr;
    387 #if ENABLE(JSC_ZOMBIES)
    388         ASSERT(!isZombie());
    389 #endif
    390     }
    391 
    392     inline JSValue::JSValue(const JSCell* ptr)
    393     {
    394         u.ptr = const_cast<JSCell*>(ptr);
    395 #if ENABLE(JSC_ZOMBIES)
    396         ASSERT(!isZombie());
    397 #endif
    398     }
    399 
    400     inline JSValue::operator bool() const
    401     {
    402         return u.ptr;
    403     }
    404 
    405     inline bool JSValue::operator==(const JSValue& other) const
    406     {
    407         return u.ptr == other.u.ptr;
    408     }
    409 
    410     inline bool JSValue::operator!=(const JSValue& other) const
    411     {
    412         return u.ptr != other.u.ptr;
    413     }
    414 
    415     inline bool JSValue::isUndefined() const
    416     {
    417         return asValue() == jsUndefined();
    418     }
    419 
    420     inline bool JSValue::isNull() const
    421     {
    422         return asValue() == jsNull();
    423     }
    424 
    425     inline bool JSValue::isTrue() const
    426     {
    427         return asValue() == JSValue(JSTrue);
    428     }
    429 
    430     inline bool JSValue::isFalse() const
    431     {
    432         return asValue() == JSValue(JSFalse);
    433     }
    434 
    435     inline bool JSValue::getBoolean() const
    436     {
    437         ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
    438         return asValue() == jsBoolean(true);
    439     }
    440 
    441     inline int32_t JSValue::asInt32() const
    442     {
    443         ASSERT(isInt32());
    444         return static_cast<int32_t>(u.asInt64);
    445     }
    446 
    447     inline bool JSValue::isDouble() const
    448     {
    449         return isNumber() && !isInt32();
    450     }
    451 
    452     inline JSValue::JSValue(JSNullTag)
    453     {
    454         u.asInt64 = ValueNull;
    455     }
    456 
    457     inline JSValue::JSValue(JSUndefinedTag)
    458     {
    459         u.asInt64 = ValueUndefined;
    460     }
    461 
    462     inline JSValue::JSValue(JSTrueTag)
    463     {
    464         u.asInt64 = ValueTrue;
    465     }
    466 
    467     inline JSValue::JSValue(JSFalseTag)
    468     {
    469         u.asInt64 = ValueFalse;
    470     }
    471 
    472     inline bool JSValue::isUndefinedOrNull() const
    473     {
    474         // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
    475         return (u.asInt64 & ~TagBitUndefined) == ValueNull;
    476     }
    477 
    478     inline bool JSValue::isBoolean() const
    479     {
    480         return (u.asInt64 & ~1) == ValueFalse;
    481     }
    482 
    483     inline bool JSValue::isCell() const
    484     {
    485         return !(u.asInt64 & TagMask);
    486     }
    487 
    488     inline bool JSValue::isInt32() const
    489     {
    490         return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
    491     }
    492 
    493     inline intptr_t reinterpretDoubleToIntptr(double value)
    494     {
    495         return bitwise_cast<intptr_t>(value);
    496     }
    497     inline double reinterpretIntptrToDouble(intptr_t value)
    498     {
    499         return bitwise_cast<double>(value);
    500     }
    501 
    502     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
    503     {
    504         u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
    505     }
    506 
    507     inline JSValue::JSValue(int i)
    508     {
    509         u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
    510     }
    511 
    512     inline double JSValue::asDouble() const
    513     {
    514         return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
    515     }
    516 
    517     inline bool JSValue::isNumber() const
    518     {
    519         return u.asInt64 & TagTypeNumber;
    520     }
    521 
    522     ALWAYS_INLINE JSCell* JSValue::asCell() const
    523     {
    524         ASSERT(isCell());
    525         return u.ptr;
    526     }
    527 
    528 #endif // USE(JSVALUE64)
    529 
    530 } // namespace JSC
    531 
    532 #endif // JSValueInlineMethods_h
    533