2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
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.
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.
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.
23 #include <stddef.h> // for size_t
30 #include "ConstructData.h"
32 #include <wtf/AlwaysInline.h>
33 #include <wtf/Assertions.h>
34 #include <wtf/HashTraits.h>
35 #include <wtf/MathExtras.h>
46 class PutPropertySlot
;
52 enum PreferredPrimitiveType
{ NoPreference
, PreferNumber
, PreferString
};
55 typedef int64_t EncodedJSValue
;
57 typedef void* EncodedJSValue
;
60 double nonInlineNaN();
61 int32_t toInt32SlowCase(double, bool& ok
);
62 uint32_t toUInt32SlowCase(double, bool& ok
);
65 friend class JSImmediate
;
66 friend struct EncodedJSValueHashTraits
;
68 friend class JITStubs
;
69 friend class JITStubCall
;
72 static EncodedJSValue
encode(JSValue value
);
73 static JSValue
decode(EncodedJSValue ptr
);
74 #if !USE(JSVALUE32_64)
76 static JSValue
makeImmediate(intptr_t value
);
77 intptr_t immediateValue();
80 enum JSNullTag
{ JSNull
};
81 enum JSUndefinedTag
{ JSUndefined
};
82 enum JSTrueTag
{ JSTrue
};
83 enum JSFalseTag
{ JSFalse
};
87 JSValue(JSUndefinedTag
);
91 JSValue(const JSCell
* ptr
);
94 JSValue(ExecState
*, double);
95 JSValue(ExecState
*, char);
96 JSValue(ExecState
*, unsigned char);
97 JSValue(ExecState
*, short);
98 JSValue(ExecState
*, unsigned short);
99 JSValue(ExecState
*, int);
100 JSValue(ExecState
*, unsigned);
101 JSValue(ExecState
*, long);
102 JSValue(ExecState
*, unsigned long);
103 JSValue(ExecState
*, long long);
104 JSValue(ExecState
*, unsigned long long);
105 JSValue(JSGlobalData
*, double);
106 JSValue(JSGlobalData
*, int);
107 JSValue(JSGlobalData
*, unsigned);
109 operator bool() const;
110 bool operator==(const JSValue
& other
) const;
111 bool operator!=(const JSValue
& other
) const;
113 bool isInt32() const;
114 bool isUInt32() const;
115 bool isDouble() const;
117 bool isFalse() const;
119 int32_t asInt32() const;
120 uint32_t asUInt32() const;
121 double asDouble() const;
123 // Querying the type.
124 bool isUndefined() const;
126 bool isUndefinedOrNull() const;
127 bool isBoolean() const;
128 bool isNumber() const;
129 bool isString() const;
130 bool isGetterSetter() const;
131 bool isObject() const;
132 bool isObject(const ClassInfo
*) const;
134 // Extracting the value.
135 bool getBoolean(bool&) const;
136 bool getBoolean() const; // false if not a boolean
137 bool getNumber(double&) const;
138 double uncheckedGetNumber() const;
139 bool getString(UString
&) const;
140 UString
getString() const; // null string if not a string
141 JSObject
* getObject() const; // 0 if not an object
143 CallType
getCallData(CallData
&);
144 ConstructType
getConstructData(ConstructData
&);
146 // Extracting integer values.
147 bool getUInt32(uint32_t&) const;
149 // Basic conversions.
150 JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
151 bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
&);
153 bool toBoolean(ExecState
*) const;
155 // toNumber conversion is expected to be side effect free if an exception has
156 // been set in the ExecState already.
157 double toNumber(ExecState
*) const;
158 JSValue
toJSNumber(ExecState
*) const; // Fast path for when you expect that the value is an immediate number.
159 UString
toString(ExecState
*) const;
160 JSObject
* toObject(ExecState
*) const;
162 // Integer conversions.
163 double toInteger(ExecState
*) const;
164 double toIntegerPreserveNaN(ExecState
*) const;
165 int32_t toInt32(ExecState
*) const;
166 int32_t toInt32(ExecState
*, bool& ok
) const;
167 uint32_t toUInt32(ExecState
*) const;
168 uint32_t toUInt32(ExecState
*, bool& ok
) const;
170 // Floating point conversions (this is a convenience method for webcore;
171 // signle precision float is not a representation used in JS or JSC).
172 float toFloat(ExecState
* exec
) const { return static_cast<float>(toNumber(exec
)); }
174 // Garbage collection.
178 // Object operations, with the toObject operation included.
179 JSValue
get(ExecState
*, const Identifier
& propertyName
) const;
180 JSValue
get(ExecState
*, const Identifier
& propertyName
, PropertySlot
&) const;
181 JSValue
get(ExecState
*, unsigned propertyName
) const;
182 JSValue
get(ExecState
*, unsigned propertyName
, PropertySlot
&) const;
183 void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
184 void put(ExecState
*, unsigned propertyName
, JSValue
);
186 bool needsThisConversion() const;
187 JSObject
* toThisObject(ExecState
*) const;
188 UString
toThisString(ExecState
*) const;
189 JSString
* toThisJSString(ExecState
*);
191 static bool equal(ExecState
* exec
, JSValue v1
, JSValue v2
);
192 static bool equalSlowCase(ExecState
* exec
, JSValue v1
, JSValue v2
);
193 static bool equalSlowCaseInline(ExecState
* exec
, JSValue v1
, JSValue v2
);
194 static bool strictEqual(JSValue v1
, JSValue v2
);
195 static bool strictEqualSlowCase(JSValue v1
, JSValue v2
);
196 static bool strictEqualSlowCaseInline(JSValue v1
, JSValue v2
);
198 JSValue
getJSNumber(); // JSValue() if this is not a JSNumber or number object
201 JSCell
* asCell() const;
208 enum HashTableDeletedValueTag
{ HashTableDeletedValue
};
209 JSValue(HashTableDeletedValueTag
);
211 inline const JSValue
asValue() const { return *this; }
212 JSObject
* toObjectSlowCase(ExecState
*) const;
213 JSObject
* toThisObjectSlowCase(ExecState
*) const;
215 enum { Int32Tag
= 0xffffffff };
216 enum { CellTag
= 0xfffffffe };
217 enum { TrueTag
= 0xfffffffd };
218 enum { FalseTag
= 0xfffffffc };
219 enum { NullTag
= 0xfffffffb };
220 enum { UndefinedTag
= 0xfffffffa };
221 enum { DeletedValueTag
= 0xfffffff9 };
223 enum { LowestTag
= DeletedValueTag
};
225 uint32_t tag() const;
226 int32_t payload() const;
228 JSObject
* synthesizePrototype(ExecState
*) const;
229 JSObject
* synthesizeObject(ExecState
*) const;
231 #if USE(JSVALUE32_64)
233 EncodedJSValue asEncodedJSValue
;
235 #if PLATFORM(BIG_ENDIAN)
247 #else // USE(JSVALUE32_64)
249 #endif // USE(JSVALUE32_64)
252 #if USE(JSVALUE32_64)
253 typedef IntHash
<EncodedJSValue
> EncodedJSValueHash
;
255 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
256 static const bool emptyValueIsZero
= false;
257 static EncodedJSValue
emptyValue() { return JSValue::encode(JSValue()); }
258 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
259 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
262 typedef PtrHash
<EncodedJSValue
> EncodedJSValueHash
;
264 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
265 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
266 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
270 // Stand-alone helper functions.
271 inline JSValue
jsNull()
273 return JSValue(JSValue::JSNull
);
276 inline JSValue
jsUndefined()
278 return JSValue(JSValue::JSUndefined
);
281 inline JSValue
jsBoolean(bool b
)
283 return b
? JSValue(JSValue::JSTrue
) : JSValue(JSValue::JSFalse
);
286 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, double d
)
288 return JSValue(exec
, d
);
291 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, char i
)
293 return JSValue(exec
, i
);
296 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned char i
)
298 return JSValue(exec
, i
);
301 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, short i
)
303 return JSValue(exec
, i
);
306 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned short i
)
308 return JSValue(exec
, i
);
311 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, int i
)
313 return JSValue(exec
, i
);
316 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned i
)
318 return JSValue(exec
, i
);
321 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, long i
)
323 return JSValue(exec
, i
);
326 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned long i
)
328 return JSValue(exec
, i
);
331 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, long long i
)
333 return JSValue(exec
, i
);
336 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned long long i
)
338 return JSValue(exec
, i
);
341 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, double d
)
343 return JSValue(globalData
, d
);
346 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, int i
)
348 return JSValue(globalData
, i
);
351 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, unsigned i
)
353 return JSValue(globalData
, i
);
356 inline bool operator==(const JSValue a
, const JSCell
* b
) { return a
== JSValue(b
); }
357 inline bool operator==(const JSCell
* a
, const JSValue b
) { return JSValue(a
) == b
; }
359 inline bool operator!=(const JSValue a
, const JSCell
* b
) { return a
!= JSValue(b
); }
360 inline bool operator!=(const JSCell
* a
, const JSValue b
) { return JSValue(a
) != b
; }
362 inline int32_t toInt32(double val
)
364 if (!(val
>= -2147483648.0 && val
< 2147483648.0)) {
366 return toInt32SlowCase(val
, ignored
);
368 return static_cast<int32_t>(val
);
371 inline uint32_t toUInt32(double val
)
373 if (!(val
>= 0.0 && val
< 4294967296.0)) {
375 return toUInt32SlowCase(val
, ignored
);
377 return static_cast<uint32_t>(val
);
380 ALWAYS_INLINE
int32_t JSValue::toInt32(ExecState
* exec
) const
385 return toInt32SlowCase(toNumber(exec
), ignored
);
388 inline uint32_t JSValue::toUInt32(ExecState
* exec
) const
393 return toUInt32SlowCase(toNumber(exec
), ignored
);
396 inline int32_t JSValue::toInt32(ExecState
* exec
, bool& ok
) const
402 return toInt32SlowCase(toNumber(exec
), ok
);
405 inline uint32_t JSValue::toUInt32(ExecState
* exec
, bool& ok
) const
411 return toUInt32SlowCase(toNumber(exec
), ok
);
414 #if USE(JSVALUE32_64)
415 inline JSValue
jsNaN(ExecState
* exec
)
417 return JSValue(exec
, nonInlineNaN());
420 // JSValue member functions.
421 inline EncodedJSValue
JSValue::encode(JSValue value
)
423 return value
.u
.asEncodedJSValue
;
426 inline JSValue
JSValue::decode(EncodedJSValue encodedJSValue
)
429 v
.u
.asEncodedJSValue
= encodedJSValue
;
433 inline JSValue::JSValue()
435 u
.asBits
.tag
= CellTag
;
436 u
.asBits
.payload
= 0;
439 inline JSValue::JSValue(JSNullTag
)
441 u
.asBits
.tag
= NullTag
;
442 u
.asBits
.payload
= 0;
445 inline JSValue::JSValue(JSUndefinedTag
)
447 u
.asBits
.tag
= UndefinedTag
;
448 u
.asBits
.payload
= 0;
451 inline JSValue::JSValue(JSTrueTag
)
453 u
.asBits
.tag
= TrueTag
;
454 u
.asBits
.payload
= 0;
457 inline JSValue::JSValue(JSFalseTag
)
459 u
.asBits
.tag
= FalseTag
;
460 u
.asBits
.payload
= 0;
463 inline JSValue::JSValue(HashTableDeletedValueTag
)
465 u
.asBits
.tag
= DeletedValueTag
;
466 u
.asBits
.payload
= 0;
469 inline JSValue::JSValue(JSCell
* ptr
)
471 u
.asBits
.tag
= CellTag
;
472 u
.asBits
.payload
= reinterpret_cast<int32_t>(ptr
);
475 inline JSValue::JSValue(const JSCell
* ptr
)
477 u
.asBits
.tag
= CellTag
;
478 u
.asBits
.payload
= reinterpret_cast<int32_t>(const_cast<JSCell
*>(ptr
));
481 inline JSValue::operator bool() const
483 return u
.asBits
.payload
|| tag() != CellTag
;
486 inline bool JSValue::operator==(const JSValue
& other
) const
488 return u
.asEncodedJSValue
== other
.u
.asEncodedJSValue
;
491 inline bool JSValue::operator!=(const JSValue
& other
) const
493 return u
.asEncodedJSValue
!= other
.u
.asEncodedJSValue
;
496 inline bool JSValue::isUndefined() const
498 return tag() == UndefinedTag
;
501 inline bool JSValue::isNull() const
503 return tag() == NullTag
;
506 inline bool JSValue::isUndefinedOrNull() const
508 return isUndefined() || isNull();
511 inline bool JSValue::isCell() const
513 return tag() == CellTag
;
516 inline bool JSValue::isInt32() const
518 return tag() == Int32Tag
;
521 inline bool JSValue::isUInt32() const
523 return tag() == Int32Tag
&& asInt32() > -1;
526 inline bool JSValue::isDouble() const
528 return tag() < LowestTag
;
531 inline bool JSValue::isTrue() const
533 return tag() == TrueTag
;
536 inline bool JSValue::isFalse() const
538 return tag() == FalseTag
;
541 inline uint32_t JSValue::tag() const
546 inline int32_t JSValue::payload() const
548 return u
.asBits
.payload
;
551 inline int32_t JSValue::asInt32() const
554 return u
.asBits
.payload
;
557 inline uint32_t JSValue::asUInt32() const
560 return u
.asBits
.payload
;
563 inline double JSValue::asDouble() const
569 ALWAYS_INLINE JSCell
* JSValue::asCell() const
572 return reinterpret_cast<JSCell
*>(u
.asBits
.payload
);
575 inline JSValue::JSValue(ExecState
* exec
, double d
)
577 const int32_t asInt32
= static_cast<int32_t>(d
);
578 if (asInt32
!= d
|| (!asInt32
&& signbit(d
))) { // true for -0.0
582 *this = JSValue(exec
, static_cast<int32_t>(d
));
585 inline JSValue::JSValue(ExecState
* exec
, char i
)
587 *this = JSValue(exec
, static_cast<int32_t>(i
));
590 inline JSValue::JSValue(ExecState
* exec
, unsigned char i
)
592 *this = JSValue(exec
, static_cast<int32_t>(i
));
595 inline JSValue::JSValue(ExecState
* exec
, short i
)
597 *this = JSValue(exec
, static_cast<int32_t>(i
));
600 inline JSValue::JSValue(ExecState
* exec
, unsigned short i
)
602 *this = JSValue(exec
, static_cast<int32_t>(i
));
605 inline JSValue::JSValue(ExecState
*, int i
)
607 u
.asBits
.tag
= Int32Tag
;
608 u
.asBits
.payload
= i
;
611 inline JSValue::JSValue(ExecState
* exec
, unsigned i
)
613 if (static_cast<int32_t>(i
) < 0) {
614 *this = JSValue(exec
, static_cast<double>(i
));
617 *this = JSValue(exec
, static_cast<int32_t>(i
));
620 inline JSValue::JSValue(ExecState
* exec
, long i
)
622 if (static_cast<int32_t>(i
) != i
) {
623 *this = JSValue(exec
, static_cast<double>(i
));
626 *this = JSValue(exec
, static_cast<int32_t>(i
));
629 inline JSValue::JSValue(ExecState
* exec
, unsigned long i
)
631 if (static_cast<uint32_t>(i
) != i
) {
632 *this = JSValue(exec
, static_cast<double>(i
));
635 *this = JSValue(exec
, static_cast<uint32_t>(i
));
638 inline JSValue::JSValue(ExecState
* exec
, long long i
)
640 if (static_cast<int32_t>(i
) != i
) {
641 *this = JSValue(exec
, static_cast<double>(i
));
644 *this = JSValue(exec
, static_cast<int32_t>(i
));
647 inline JSValue::JSValue(ExecState
* exec
, unsigned long long i
)
649 if (static_cast<uint32_t>(i
) != i
) {
650 *this = JSValue(exec
, static_cast<double>(i
));
653 *this = JSValue(exec
, static_cast<uint32_t>(i
));
656 inline JSValue::JSValue(JSGlobalData
* globalData
, double d
)
658 const int32_t asInt32
= static_cast<int32_t>(d
);
659 if (asInt32
!= d
|| (!asInt32
&& signbit(d
))) { // true for -0.0
663 *this = JSValue(globalData
, static_cast<int32_t>(d
));
666 inline JSValue::JSValue(JSGlobalData
*, int i
)
668 u
.asBits
.tag
= Int32Tag
;
669 u
.asBits
.payload
= i
;
672 inline JSValue::JSValue(JSGlobalData
* globalData
, unsigned i
)
674 if (static_cast<int32_t>(i
) < 0) {
675 *this = JSValue(globalData
, static_cast<double>(i
));
678 *this = JSValue(globalData
, static_cast<int32_t>(i
));
681 inline bool JSValue::isNumber() const
683 return isInt32() || isDouble();
686 inline bool JSValue::isBoolean() const
688 return isTrue() || isFalse();
691 inline bool JSValue::getBoolean(bool& v
) const
705 inline bool JSValue::getBoolean() const
708 return tag() == TrueTag
;
711 inline double JSValue::uncheckedGetNumber() const
714 return isInt32() ? asInt32() : asDouble();
717 ALWAYS_INLINE JSValue
JSValue::toJSNumber(ExecState
* exec
) const
719 return isNumber() ? asValue() : jsNumber(exec
, this->toNumber(exec
));
722 inline bool JSValue::getNumber(double& result
) const
735 #else // USE(JSVALUE32_64)
737 // JSValue member functions.
738 inline EncodedJSValue
JSValue::encode(JSValue value
)
740 return reinterpret_cast<EncodedJSValue
>(value
.m_ptr
);
743 inline JSValue
JSValue::decode(EncodedJSValue ptr
)
745 return JSValue(reinterpret_cast<JSCell
*>(ptr
));
748 inline JSValue
JSValue::makeImmediate(intptr_t value
)
750 return JSValue(reinterpret_cast<JSCell
*>(value
));
753 inline intptr_t JSValue::immediateValue()
755 return reinterpret_cast<intptr_t>(m_ptr
);
758 // 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.
759 inline JSValue::JSValue()
764 // 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.
765 inline JSValue::JSValue(HashTableDeletedValueTag
)
766 : m_ptr(reinterpret_cast<JSCell
*>(0x4))
770 inline JSValue::JSValue(JSCell
* ptr
)
775 inline JSValue::JSValue(const JSCell
* ptr
)
776 : m_ptr(const_cast<JSCell
*>(ptr
))
780 inline JSValue::operator bool() const
785 inline bool JSValue::operator==(const JSValue
& other
) const
787 return m_ptr
== other
.m_ptr
;
790 inline bool JSValue::operator!=(const JSValue
& other
) const
792 return m_ptr
!= other
.m_ptr
;
795 inline bool JSValue::isUndefined() const
797 return asValue() == jsUndefined();
800 inline bool JSValue::isNull() const
802 return asValue() == jsNull();
804 #endif // USE(JSVALUE32_64)