| /* |
| * Copyright (C) 2011 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef JSValueInlineMethods_h |
| #define JSValueInlineMethods_h |
| |
| #include "JSValue.h" |
| |
| namespace JSC { |
| |
| ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const |
| { |
| if (isInt32()) |
| return asInt32(); |
| return JSC::toInt32(toNumber(exec)); |
| } |
| |
| inline uint32_t JSValue::toUInt32(ExecState* exec) const |
| { |
| // See comment on JSC::toUInt32, above. |
| return toInt32(exec); |
| } |
| |
| inline bool JSValue::isUInt32() const |
| { |
| return isInt32() && asInt32() >= 0; |
| } |
| |
| inline uint32_t JSValue::asUInt32() const |
| { |
| ASSERT(isUInt32()); |
| return asInt32(); |
| } |
| |
| inline double JSValue::uncheckedGetNumber() const |
| { |
| ASSERT(isNumber()); |
| return isInt32() ? asInt32() : asDouble(); |
| } |
| |
| ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const |
| { |
| return isNumber() ? asValue() : jsNumber(this->toNumber(exec)); |
| } |
| |
| inline JSValue jsNaN() |
| { |
| return JSValue(nonInlineNaN()); |
| } |
| |
| inline bool JSValue::getNumber(double& result) const |
| { |
| if (isInt32()) { |
| result = asInt32(); |
| return true; |
| } |
| if (isDouble()) { |
| result = asDouble(); |
| return true; |
| } |
| return false; |
| } |
| |
| inline bool JSValue::getBoolean(bool& v) const |
| { |
| if (isTrue()) { |
| v = true; |
| return true; |
| } |
| if (isFalse()) { |
| v = false; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| inline JSValue::JSValue(char i) |
| { |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(unsigned char i) |
| { |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(short i) |
| { |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(unsigned short i) |
| { |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(unsigned i) |
| { |
| if (static_cast<int32_t>(i) < 0) { |
| *this = JSValue(EncodeAsDouble, static_cast<double>(i)); |
| return; |
| } |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(long i) |
| { |
| if (static_cast<int32_t>(i) != i) { |
| *this = JSValue(EncodeAsDouble, static_cast<double>(i)); |
| return; |
| } |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(unsigned long i) |
| { |
| if (static_cast<uint32_t>(i) != i) { |
| *this = JSValue(EncodeAsDouble, static_cast<double>(i)); |
| return; |
| } |
| *this = JSValue(static_cast<uint32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(long long i) |
| { |
| if (static_cast<int32_t>(i) != i) { |
| *this = JSValue(EncodeAsDouble, static_cast<double>(i)); |
| return; |
| } |
| *this = JSValue(static_cast<int32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(unsigned long long i) |
| { |
| if (static_cast<uint32_t>(i) != i) { |
| *this = JSValue(EncodeAsDouble, static_cast<double>(i)); |
| return; |
| } |
| *this = JSValue(static_cast<uint32_t>(i)); |
| } |
| |
| inline JSValue::JSValue(double d) |
| { |
| const int32_t asInt32 = static_cast<int32_t>(d); |
| if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 |
| *this = JSValue(EncodeAsDouble, d); |
| return; |
| } |
| *this = JSValue(static_cast<int32_t>(d)); |
| } |
| |
| #if USE(JSVALUE32_64) |
| inline EncodedJSValue JSValue::encode(JSValue value) |
| { |
| return value.u.asInt64; |
| } |
| |
| inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) |
| { |
| JSValue v; |
| v.u.asInt64 = encodedJSValue; |
| return v; |
| } |
| |
| inline JSValue::JSValue() |
| { |
| u.asBits.tag = EmptyValueTag; |
| u.asBits.payload = 0; |
| } |
| |
| inline JSValue::JSValue(JSNullTag) |
| { |
| u.asBits.tag = NullTag; |
| u.asBits.payload = 0; |
| } |
| |
| inline JSValue::JSValue(JSUndefinedTag) |
| { |
| u.asBits.tag = UndefinedTag; |
| u.asBits.payload = 0; |
| } |
| |
| inline JSValue::JSValue(JSTrueTag) |
| { |
| u.asBits.tag = BooleanTag; |
| u.asBits.payload = 1; |
| } |
| |
| inline JSValue::JSValue(JSFalseTag) |
| { |
| u.asBits.tag = BooleanTag; |
| u.asBits.payload = 0; |
| } |
| |
| inline JSValue::JSValue(HashTableDeletedValueTag) |
| { |
| u.asBits.tag = DeletedValueTag; |
| u.asBits.payload = 0; |
| } |
| |
| inline JSValue::JSValue(JSCell* ptr) |
| { |
| if (ptr) |
| u.asBits.tag = CellTag; |
| else |
| u.asBits.tag = EmptyValueTag; |
| u.asBits.payload = reinterpret_cast<int32_t>(ptr); |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!isZombie()); |
| #endif |
| } |
| |
| inline JSValue::JSValue(const JSCell* ptr) |
| { |
| if (ptr) |
| u.asBits.tag = CellTag; |
| else |
| u.asBits.tag = EmptyValueTag; |
| u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!isZombie()); |
| #endif |
| } |
| |
| inline JSValue::operator bool() const |
| { |
| ASSERT(tag() != DeletedValueTag); |
| return tag() != EmptyValueTag; |
| } |
| |
| inline bool JSValue::operator==(const JSValue& other) const |
| { |
| return u.asInt64 == other.u.asInt64; |
| } |
| |
| inline bool JSValue::operator!=(const JSValue& other) const |
| { |
| return u.asInt64 != other.u.asInt64; |
| } |
| |
| inline bool JSValue::isUndefined() const |
| { |
| return tag() == UndefinedTag; |
| } |
| |
| inline bool JSValue::isNull() const |
| { |
| return tag() == NullTag; |
| } |
| |
| inline bool JSValue::isUndefinedOrNull() const |
| { |
| return isUndefined() || isNull(); |
| } |
| |
| inline bool JSValue::isCell() const |
| { |
| return tag() == CellTag; |
| } |
| |
| inline bool JSValue::isInt32() const |
| { |
| return tag() == Int32Tag; |
| } |
| |
| inline bool JSValue::isDouble() const |
| { |
| return tag() < LowestTag; |
| } |
| |
| inline bool JSValue::isTrue() const |
| { |
| return tag() == BooleanTag && payload(); |
| } |
| |
| inline bool JSValue::isFalse() const |
| { |
| return tag() == BooleanTag && !payload(); |
| } |
| |
| inline uint32_t JSValue::tag() const |
| { |
| return u.asBits.tag; |
| } |
| |
| inline int32_t JSValue::payload() const |
| { |
| return u.asBits.payload; |
| } |
| |
| inline int32_t JSValue::asInt32() const |
| { |
| ASSERT(isInt32()); |
| return u.asBits.payload; |
| } |
| |
| inline double JSValue::asDouble() const |
| { |
| ASSERT(isDouble()); |
| return u.asDouble; |
| } |
| |
| ALWAYS_INLINE JSCell* JSValue::asCell() const |
| { |
| ASSERT(isCell()); |
| return reinterpret_cast<JSCell*>(u.asBits.payload); |
| } |
| |
| ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) |
| { |
| u.asDouble = d; |
| } |
| |
| inline JSValue::JSValue(int i) |
| { |
| u.asBits.tag = Int32Tag; |
| u.asBits.payload = i; |
| } |
| |
| inline bool JSValue::isNumber() const |
| { |
| return isInt32() || isDouble(); |
| } |
| |
| inline bool JSValue::isBoolean() const |
| { |
| return isTrue() || isFalse(); |
| } |
| |
| inline bool JSValue::getBoolean() const |
| { |
| ASSERT(isBoolean()); |
| return payload(); |
| } |
| |
| #else // USE(JSVALUE32_64) |
| |
| // JSValue member functions. |
| inline EncodedJSValue JSValue::encode(JSValue value) |
| { |
| return value.u.ptr; |
| } |
| |
| inline JSValue JSValue::decode(EncodedJSValue ptr) |
| { |
| return JSValue(reinterpret_cast<JSCell*>(ptr)); |
| } |
| |
| // 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. |
| inline JSValue::JSValue() |
| { |
| u.asInt64 = ValueEmpty; |
| } |
| |
| // 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. |
| inline JSValue::JSValue(HashTableDeletedValueTag) |
| { |
| u.asInt64 = ValueDeleted; |
| } |
| |
| inline JSValue::JSValue(JSCell* ptr) |
| { |
| u.ptr = ptr; |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!isZombie()); |
| #endif |
| } |
| |
| inline JSValue::JSValue(const JSCell* ptr) |
| { |
| u.ptr = const_cast<JSCell*>(ptr); |
| #if ENABLE(JSC_ZOMBIES) |
| ASSERT(!isZombie()); |
| #endif |
| } |
| |
| inline JSValue::operator bool() const |
| { |
| return u.ptr; |
| } |
| |
| inline bool JSValue::operator==(const JSValue& other) const |
| { |
| return u.ptr == other.u.ptr; |
| } |
| |
| inline bool JSValue::operator!=(const JSValue& other) const |
| { |
| return u.ptr != other.u.ptr; |
| } |
| |
| inline bool JSValue::isUndefined() const |
| { |
| return asValue() == jsUndefined(); |
| } |
| |
| inline bool JSValue::isNull() const |
| { |
| return asValue() == jsNull(); |
| } |
| |
| inline bool JSValue::isTrue() const |
| { |
| return asValue() == JSValue(JSTrue); |
| } |
| |
| inline bool JSValue::isFalse() const |
| { |
| return asValue() == JSValue(JSFalse); |
| } |
| |
| inline bool JSValue::getBoolean() const |
| { |
| ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false)); |
| return asValue() == jsBoolean(true); |
| } |
| |
| inline int32_t JSValue::asInt32() const |
| { |
| ASSERT(isInt32()); |
| return static_cast<int32_t>(u.asInt64); |
| } |
| |
| inline bool JSValue::isDouble() const |
| { |
| return isNumber() && !isInt32(); |
| } |
| |
| inline JSValue::JSValue(JSNullTag) |
| { |
| u.asInt64 = ValueNull; |
| } |
| |
| inline JSValue::JSValue(JSUndefinedTag) |
| { |
| u.asInt64 = ValueUndefined; |
| } |
| |
| inline JSValue::JSValue(JSTrueTag) |
| { |
| u.asInt64 = ValueTrue; |
| } |
| |
| inline JSValue::JSValue(JSFalseTag) |
| { |
| u.asInt64 = ValueFalse; |
| } |
| |
| inline bool JSValue::isUndefinedOrNull() const |
| { |
| // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. |
| return (u.asInt64 & ~TagBitUndefined) == ValueNull; |
| } |
| |
| inline bool JSValue::isBoolean() const |
| { |
| return (u.asInt64 & ~1) == ValueFalse; |
| } |
| |
| inline bool JSValue::isCell() const |
| { |
| return !(u.asInt64 & TagMask); |
| } |
| |
| inline bool JSValue::isInt32() const |
| { |
| return (u.asInt64 & TagTypeNumber) == TagTypeNumber; |
| } |
| |
| inline intptr_t reinterpretDoubleToIntptr(double value) |
| { |
| return bitwise_cast<intptr_t>(value); |
| } |
| inline double reinterpretIntptrToDouble(intptr_t value) |
| { |
| return bitwise_cast<double>(value); |
| } |
| |
| ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) |
| { |
| u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset; |
| } |
| |
| inline JSValue::JSValue(int i) |
| { |
| u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i); |
| } |
| |
| inline double JSValue::asDouble() const |
| { |
| return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset); |
| } |
| |
| inline bool JSValue::isNumber() const |
| { |
| return u.asInt64 & TagTypeNumber; |
| } |
| |
| ALWAYS_INLINE JSCell* JSValue::asCell() const |
| { |
| ASSERT(isCell()); |
| return u.ptr; |
| } |
| |
| #endif // USE(JSVALUE64) |
| |
| } // namespace JSC |
| |
| #endif // JSValueInlineMethods_h |