/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
*
*/
-#include <stddef.h> // for size_t
-#include <stdint.h>
-
#ifndef JSValue_h
#define JSValue_h
-#include "CallData.h"
-#include "ConstructData.h"
#include <math.h>
+#include <stddef.h> // for size_t
+#include <stdint.h>
#include <wtf/AlwaysInline.h>
#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
#include <wtf/HashTraits.h>
#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
namespace JSC {
+ class ExecState;
class Identifier;
class JSCell;
class JSGlobalData;
- class JSImmediate;
+ class JSGlobalObject;
class JSObject;
class JSString;
class PropertySlot;
class PutPropertySlot;
class UString;
+#if ENABLE(DFG_JIT)
+ namespace DFG {
+ class AssemblyHelpers;
+ class JITCompiler;
+ class JITCodeGenerator;
+ class JSValueSource;
+ class OSRExitCompiler;
+ class SpeculativeJIT;
+ }
+#endif
+ namespace LLInt {
+ class Data;
+ }
struct ClassInfo;
struct Instruction;
+ struct MethodTable;
+
+ template <class T> class WriteBarrierBase;
enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
+
#if USE(JSVALUE32_64)
typedef int64_t EncodedJSValue;
#else
typedef void* EncodedJSValue;
#endif
+
+ union EncodedValueDescriptor {
+ int64_t asInt64;
+#if USE(JSVALUE32_64)
+ double asDouble;
+#elif USE(JSVALUE64)
+ JSCell* ptr;
+#endif
+
+#if CPU(BIG_ENDIAN)
+ struct {
+ int32_t tag;
+ int32_t payload;
+ } asBits;
+#else
+ struct {
+ int32_t payload;
+ int32_t tag;
+ } asBits;
+#endif
+ };
+
+ // This implements ToInt32, defined in ECMA-262 9.5.
+ JS_EXPORT_PRIVATE int32_t toInt32(double);
- double nonInlineNaN();
- int32_t toInt32SlowCase(double, bool& ok);
- uint32_t toUInt32SlowCase(double, bool& ok);
+ // This implements ToUInt32, defined in ECMA-262 9.6.
+ inline uint32_t toUInt32(double number)
+ {
+ // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
+ // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
+ return toInt32(number);
+ }
class JSValue {
- friend class JSImmediate;
friend struct EncodedJSValueHashTraits;
friend class JIT;
friend class JITStubs;
friend class JITStubCall;
+ friend class JSInterfaceJIT;
+ friend class SpecializedThunkJIT;
+#if ENABLE(DFG_JIT)
+ friend class DFG::AssemblyHelpers;
+ friend class DFG::JITCompiler;
+ friend class DFG::JITCodeGenerator;
+ friend class DFG::JSValueSource;
+ friend class DFG::OSRExitCompiler;
+ friend class DFG::SpeculativeJIT;
+#endif
+ friend class LLInt::Data;
public:
- static EncodedJSValue encode(JSValue value);
- static JSValue decode(EncodedJSValue ptr);
-#if !USE(JSVALUE32_64)
- private:
- static JSValue makeImmediate(intptr_t value);
- intptr_t immediateValue();
- public:
-#endif
+ static EncodedJSValue encode(JSValue);
+ static JSValue decode(EncodedJSValue);
+
enum JSNullTag { JSNull };
enum JSUndefinedTag { JSUndefined };
enum JSTrueTag { JSTrue };
enum JSFalseTag { JSFalse };
+ enum EncodeAsDoubleTag { EncodeAsDouble };
JSValue();
JSValue(JSNullTag);
JSValue(const JSCell* ptr);
// Numbers
- JSValue(ExecState*, double);
- JSValue(ExecState*, char);
- JSValue(ExecState*, unsigned char);
- JSValue(ExecState*, short);
- JSValue(ExecState*, unsigned short);
- JSValue(ExecState*, int);
- JSValue(ExecState*, unsigned);
- JSValue(ExecState*, long);
- JSValue(ExecState*, unsigned long);
- JSValue(ExecState*, long long);
- JSValue(ExecState*, unsigned long long);
- JSValue(JSGlobalData*, double);
- JSValue(JSGlobalData*, int);
- JSValue(JSGlobalData*, unsigned);
+ JSValue(EncodeAsDoubleTag, double);
+ explicit JSValue(double);
+ explicit JSValue(char);
+ explicit JSValue(unsigned char);
+ explicit JSValue(short);
+ explicit JSValue(unsigned short);
+ explicit JSValue(int);
+ explicit JSValue(unsigned);
+ explicit JSValue(long);
+ explicit JSValue(unsigned long);
+ explicit JSValue(long long);
+ explicit JSValue(unsigned long long);
operator bool() const;
bool operator==(const JSValue& other) const;
int32_t asInt32() const;
uint32_t asUInt32() const;
double asDouble() const;
+ bool asBoolean() const;
+ double asNumber() const;
// Querying the type.
+ bool isEmpty() const;
+ bool isFunction() const;
bool isUndefined() const;
bool isNull() const;
bool isUndefinedOrNull() const;
bool isBoolean() const;
bool isNumber() const;
bool isString() const;
+ bool isPrimitive() const;
bool isGetterSetter() const;
bool isObject() const;
- bool isObject(const ClassInfo*) const;
+ bool inherits(const ClassInfo*) const;
// Extracting the value.
- bool getBoolean(bool&) const;
- bool getBoolean() const; // false if not a boolean
- bool getNumber(double&) const;
- double uncheckedGetNumber() const;
- bool getString(UString&) const;
- UString getString() const; // null string if not a string
+ bool getString(ExecState* exec, UString&) const;
+ UString getString(ExecState* exec) const; // null string if not a string
JSObject* getObject() const; // 0 if not an object
- CallType getCallData(CallData&);
- ConstructType getConstructData(ConstructData&);
-
// Extracting integer values.
bool getUInt32(uint32_t&) const;
// toNumber conversion is expected to be side effect free if an exception has
// been set in the ExecState already.
double toNumber(ExecState*) const;
- JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
- UString toString(ExecState*) const;
+ JSString* toString(ExecState*) const;
+ UString toUString(ExecState*) const;
+ UString toUStringInline(ExecState*) const;
JSObject* toObject(ExecState*) const;
+ JSObject* toObject(ExecState*, JSGlobalObject*) const;
// Integer conversions.
- double toInteger(ExecState*) const;
+ JS_EXPORT_PRIVATE double toInteger(ExecState*) const;
double toIntegerPreserveNaN(ExecState*) const;
int32_t toInt32(ExecState*) const;
- int32_t toInt32(ExecState*, bool& ok) const;
uint32_t toUInt32(ExecState*) const;
- uint32_t toUInt32(ExecState*, bool& ok) const;
// Floating point conversions (this is a convenience method for webcore;
// signle precision float is not a representation used in JS or JSC).
float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
- // Garbage collection.
- void mark();
- bool marked() const;
-
// Object operations, with the toObject operation included.
JSValue get(ExecState*, const Identifier& propertyName) const;
JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
JSValue get(ExecState*, unsigned propertyName) const;
JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- void put(ExecState*, unsigned propertyName, JSValue);
+ void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
- bool needsThisConversion() const;
JSObject* toThisObject(ExecState*) const;
- UString toThisString(ExecState*) const;
- JSString* toThisJSString(ExecState*);
static bool equal(ExecState* exec, JSValue v1, JSValue v2);
static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
- static bool strictEqual(JSValue v1, JSValue v2);
- static bool strictEqualSlowCase(JSValue v1, JSValue v2);
- static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2);
-
- JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
+ static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
+ static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
+ static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
bool isCell() const;
JSCell* asCell() const;
+ JS_EXPORT_PRIVATE bool isValidCallee();
-#ifndef NDEBUG
char* description();
-#endif
+
+ JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
private:
+ template <class T> JSValue(WriteBarrierBase<T>);
+
enum HashTableDeletedValueTag { HashTableDeletedValue };
JSValue(HashTableDeletedValueTag);
inline const JSValue asValue() const { return *this; }
- JSObject* toObjectSlowCase(ExecState*) const;
- JSObject* toThisObjectSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
+ JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
+#if USE(JSVALUE32_64)
+ /*
+ * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
+ * form for immediates.
+ *
+ * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
+ * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
+ * can encode a 51-bit payload. Hardware produced and C-library payloads typically
+ * have a payload of zero. We assume that non-zero payloads are available to encode
+ * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
+ * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+ * ranges to encode other values (however there are also other ranges of NaN space that
+ * could have been selected).
+ *
+ * For JSValues that do not contain a double value, the high 32 bits contain the tag
+ * values listed in the enums below, which all correspond to NaN-space. In the case of
+ * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
+ * integer or boolean value; in the case of all other tags the payload is 0.
+ */
enum { Int32Tag = 0xffffffff };
- enum { CellTag = 0xfffffffe };
- enum { TrueTag = 0xfffffffd };
- enum { FalseTag = 0xfffffffc };
- enum { NullTag = 0xfffffffb };
- enum { UndefinedTag = 0xfffffffa };
+ enum { BooleanTag = 0xfffffffe };
+ enum { NullTag = 0xfffffffd };
+ enum { UndefinedTag = 0xfffffffc };
+ enum { CellTag = 0xfffffffb };
+ enum { EmptyValueTag = 0xfffffffa };
enum { DeletedValueTag = 0xfffffff9 };
enum { LowestTag = DeletedValueTag };
uint32_t tag() const;
int32_t payload() const;
-
- JSObject* synthesizePrototype(ExecState*) const;
- JSObject* synthesizeObject(ExecState*) const;
-
-#if USE(JSVALUE32_64)
- union {
- EncodedJSValue asEncodedJSValue;
- double asDouble;
-#if PLATFORM(BIG_ENDIAN)
- struct {
- int32_t tag;
- int32_t payload;
- } asBits;
-#else
- struct {
- int32_t payload;
- int32_t tag;
- } asBits;
+#elif USE(JSVALUE64)
+ /*
+ * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
+ * form for immediates.
+ *
+ * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
+ * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
+ * can encode a 51-bit payload. Hardware produced and C-library payloads typically
+ * have a payload of zero. We assume that non-zero payloads are available to encode
+ * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
+ * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+ * ranges to encode other values (however there are also other ranges of NaN space that
+ * could have been selected).
+ *
+ * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
+ * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
+ * numbers will begin fall in these ranges.
+ *
+ * The top 16-bits denote the type of the encoded JSValue:
+ *
+ * Pointer { 0000:PPPP:PPPP:PPPP
+ * / 0001:****:****:****
+ * Double { ...
+ * \ FFFE:****:****:****
+ * Integer { FFFF:0000:IIII:IIII
+ *
+ * The scheme we have implemented encodes double precision values by performing a
+ * 64-bit integer addition of the value 2^48 to the number. After this manipulation
+ * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
+ * Values must be decoded by reversing this operation before subsequent floating point
+ * operations my be peformed.
+ *
+ * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
+ *
+ * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
+ * null and undefined values are represented by specific, invalid pointer values:
+ *
+ * False: 0x06
+ * True: 0x07
+ * Undefined: 0x0a
+ * Null: 0x02
+ *
+ * These values have the following properties:
+ * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
+ * quickly distinguished from all immediate values, including these invalid pointers.
+ * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
+ * same value, allowing null & undefined to be quickly detected.
+ *
+ * No valid JSValue will have the bit pattern 0x0, this is used to represent array
+ * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
+ */
+
+ // These values are #defines since using static const integers here is a ~1% regression!
+
+ // This value is 2^48, used to encode doubles such that the encoded value will begin
+ // with a 16-bit pattern within the range 0x0001..0xFFFE.
+ #define DoubleEncodeOffset 0x1000000000000ll
+ // If all bits in the mask are set, this indicates an integer number,
+ // if any but not all are set this value is a double precision number.
+ #define TagTypeNumber 0xffff000000000000ll
+
+ // All non-numeric (bool, null, undefined) immediates have bit 2 set.
+ #define TagBitTypeOther 0x2ll
+ #define TagBitBool 0x4ll
+ #define TagBitUndefined 0x8ll
+ // Combined integer value for non-numeric immediates.
+ #define ValueFalse (TagBitTypeOther | TagBitBool | false)
+ #define ValueTrue (TagBitTypeOther | TagBitBool | true)
+ #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
+ #define ValueNull (TagBitTypeOther)
+
+ // TagMask is used to check for all types of immediate values (either number or 'other').
+ #define TagMask (TagTypeNumber | TagBitTypeOther)
+
+ // These special values are never visible to JavaScript code; Empty is used to represent
+ // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
+ // These values would map to cell types in the JSValue encoding, but not valid GC cell
+ // pointer should have either of these values (Empty is null, deleted is at an invalid
+ // alignment for a GC cell, and in the zero page).
+ #define ValueEmpty 0x0ll
+ #define ValueDeleted 0x4ll
#endif
- } u;
-#else // USE(JSVALUE32_64)
- JSCell* m_ptr;
-#endif // USE(JSVALUE32_64)
+
+ EncodedValueDescriptor u;
};
#if USE(JSVALUE32_64)
};
#endif
+ typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
+
// Stand-alone helper functions.
inline JSValue jsNull()
{
return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
- {
- return JSValue(exec, d);
- }
-
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
- {
- return JSValue(exec, i);
- }
-
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
+ ALWAYS_INLINE JSValue jsDoubleNumber(double d)
{
- return JSValue(exec, i);
+ ASSERT(JSValue(JSValue::EncodeAsDouble, d).isNumber());
+ return JSValue(JSValue::EncodeAsDouble, d);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
+ ALWAYS_INLINE JSValue jsNumber(double d)
{
- return JSValue(exec, i);
+ ASSERT(JSValue(d).isNumber());
+ return JSValue(d);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
+ ALWAYS_INLINE JSValue jsNumber(char i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
+ ALWAYS_INLINE JSValue jsNumber(unsigned char i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
+ ALWAYS_INLINE JSValue jsNumber(short i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
+ ALWAYS_INLINE JSValue jsNumber(unsigned short i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
+ ALWAYS_INLINE JSValue jsNumber(int i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
+ ALWAYS_INLINE JSValue jsNumber(unsigned i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
+ ALWAYS_INLINE JSValue jsNumber(long i)
{
- return JSValue(exec, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
+ ALWAYS_INLINE JSValue jsNumber(unsigned long i)
{
- return JSValue(globalData, d);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
+ ALWAYS_INLINE JSValue jsNumber(long long i)
{
- return JSValue(globalData, i);
+ return JSValue(i);
}
- ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
+ ALWAYS_INLINE JSValue jsNumber(unsigned long long i)
{
- return JSValue(globalData, i);
+ return JSValue(i);
}
inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
- inline int32_t toInt32(double val)
- {
- if (!(val >= -2147483648.0 && val < 2147483648.0)) {
- bool ignored;
- return toInt32SlowCase(val, ignored);
- }
- return static_cast<int32_t>(val);
- }
-
- inline uint32_t toUInt32(double val)
- {
- if (!(val >= 0.0 && val < 4294967296.0)) {
- bool ignored;
- return toUInt32SlowCase(val, ignored);
- }
- return static_cast<uint32_t>(val);
- }
-
- ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
- {
- if (isInt32())
- return asInt32();
- bool ignored;
- return toInt32SlowCase(toNumber(exec), ignored);
- }
-
- inline uint32_t JSValue::toUInt32(ExecState* exec) const
- {
- if (isUInt32())
- return asInt32();
- bool ignored;
- return toUInt32SlowCase(toNumber(exec), ignored);
- }
-
- inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
- {
- if (isInt32()) {
- ok = true;
- return asInt32();
- }
- return toInt32SlowCase(toNumber(exec), ok);
- }
-
- inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
- {
- if (isUInt32()) {
- ok = true;
- return asInt32();
- }
- return toUInt32SlowCase(toNumber(exec), ok);
- }
-
-#if USE(JSVALUE32_64)
- inline JSValue jsNaN(ExecState* exec)
- {
- return JSValue(exec, nonInlineNaN());
- }
-
- // JSValue member functions.
- inline EncodedJSValue JSValue::encode(JSValue value)
- {
- return value.u.asEncodedJSValue;
- }
-
- inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
- {
- JSValue v;
- v.u.asEncodedJSValue = encodedJSValue;
- return v;
- }
-
- inline JSValue::JSValue()
- {
- u.asBits.tag = CellTag;
- 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 = TrueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSFalseTag)
- {
- u.asBits.tag = FalseTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(HashTableDeletedValueTag)
- {
- u.asBits.tag = DeletedValueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- {
- u.asBits.tag = CellTag;
- u.asBits.payload = reinterpret_cast<int32_t>(ptr);
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- {
- u.asBits.tag = CellTag;
- u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
- }
-
- inline JSValue::operator bool() const
- {
- return u.asBits.payload || tag() != CellTag;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return u.asEncodedJSValue == other.u.asEncodedJSValue;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return u.asEncodedJSValue != other.u.asEncodedJSValue;
- }
-
- 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::isUInt32() const
- {
- return tag() == Int32Tag && asInt32() > -1;
- }
-
- inline bool JSValue::isDouble() const
- {
- return tag() < LowestTag;
- }
-
- inline bool JSValue::isTrue() const
- {
- return tag() == TrueTag;
- }
-
- inline bool JSValue::isFalse() const
- {
- return tag() == FalseTag;
- }
-
- 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 uint32_t JSValue::asUInt32() const
- {
- ASSERT(isUInt32());
- 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);
- }
-
- inline JSValue::JSValue(ExecState* exec, double d)
- {
- const int32_t asInt32 = static_cast<int32_t>(d);
- if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
- u.asDouble = d;
- return;
- }
- *this = JSValue(exec, static_cast<int32_t>(d));
- }
-
- inline JSValue::JSValue(ExecState* exec, char i)
- {
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, unsigned char i)
- {
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, short i)
- {
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, unsigned short i)
- {
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState*, int i)
- {
- u.asBits.tag = Int32Tag;
- u.asBits.payload = i;
- }
-
- inline JSValue::JSValue(ExecState* exec, unsigned i)
- {
- if (static_cast<int32_t>(i) < 0) {
- *this = JSValue(exec, static_cast<double>(i));
- return;
- }
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(exec, static_cast<double>(i));
- return;
- }
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, unsigned long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(exec, static_cast<double>(i));
- return;
- }
- *this = JSValue(exec, static_cast<uint32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, long long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(exec, static_cast<double>(i));
- return;
- }
- *this = JSValue(exec, static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(ExecState* exec, unsigned long long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(exec, static_cast<double>(i));
- return;
- }
- *this = JSValue(exec, static_cast<uint32_t>(i));
- }
-
- inline JSValue::JSValue(JSGlobalData* globalData, double d)
- {
- const int32_t asInt32 = static_cast<int32_t>(d);
- if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
- u.asDouble = d;
- return;
- }
- *this = JSValue(globalData, static_cast<int32_t>(d));
- }
-
- inline JSValue::JSValue(JSGlobalData*, int i)
- {
- u.asBits.tag = Int32Tag;
- u.asBits.payload = i;
- }
-
- inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
- {
- if (static_cast<int32_t>(i) < 0) {
- *this = JSValue(globalData, static_cast<double>(i));
- return;
- }
- *this = JSValue(globalData, static_cast<int32_t>(i));
- }
-
- inline bool JSValue::isNumber() const
- {
- return isInt32() || isDouble();
- }
-
- inline bool JSValue::isBoolean() const
- {
- return isTrue() || isFalse();
- }
-
- inline bool JSValue::getBoolean(bool& v) const
- {
- if (isTrue()) {
- v = true;
- return true;
- }
- if (isFalse()) {
- v = false;
- return true;
- }
-
- return false;
- }
-
- inline bool JSValue::getBoolean() const
- {
- ASSERT(isBoolean());
- return tag() == TrueTag;
- }
-
- inline double JSValue::uncheckedGetNumber() const
- {
- ASSERT(isNumber());
- return isInt32() ? asInt32() : asDouble();
- }
-
- ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
- {
- return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
- }
-
- inline bool JSValue::getNumber(double& result) const
- {
- if (isInt32()) {
- result = asInt32();
- return true;
- }
- if (isDouble()) {
- result = asDouble();
- return true;
- }
- return false;
- }
-
-#else // USE(JSVALUE32_64)
-
- // JSValue member functions.
- inline EncodedJSValue JSValue::encode(JSValue value)
- {
- return reinterpret_cast<EncodedJSValue>(value.m_ptr);
- }
-
- inline JSValue JSValue::decode(EncodedJSValue ptr)
- {
- return JSValue(reinterpret_cast<JSCell*>(ptr));
- }
-
- inline JSValue JSValue::makeImmediate(intptr_t value)
- {
- return JSValue(reinterpret_cast<JSCell*>(value));
- }
-
- inline intptr_t JSValue::immediateValue()
- {
- return reinterpret_cast<intptr_t>(m_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()
- : m_ptr(0)
- {
- }
-
- // 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)
- : m_ptr(reinterpret_cast<JSCell*>(0x4))
- {
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- : m_ptr(ptr)
- {
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- : m_ptr(const_cast<JSCell*>(ptr))
- {
- }
-
- inline JSValue::operator bool() const
- {
- return m_ptr;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return m_ptr == other.m_ptr;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return m_ptr != other.m_ptr;
- }
-
- inline bool JSValue::isUndefined() const
- {
- return asValue() == jsUndefined();
- }
-
- inline bool JSValue::isNull() const
- {
- return asValue() == jsNull();
- }
-#endif // USE(JSVALUE32_64)
-
} // namespace JSC
#endif // JSValue_h