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, 2009 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.
27 #include "ConstructData.h"
29 #include <stddef.h> // for size_t
31 #include <wtf/AlwaysInline.h>
32 #include <wtf/Assertions.h>
33 #include <wtf/HashTraits.h>
34 #include <wtf/MathExtras.h>
45 class PutPropertySlot
;
51 enum PreferredPrimitiveType
{ NoPreference
, PreferNumber
, PreferString
};
54 typedef int64_t EncodedJSValue
;
56 typedef void* EncodedJSValue
;
59 double nonInlineNaN();
60 int32_t toInt32SlowCase(double, bool& ok
);
61 uint32_t toUInt32SlowCase(double, bool& ok
);
64 friend class JSImmediate
;
65 friend struct EncodedJSValueHashTraits
;
67 friend class JITStubs
;
68 friend class JITStubCall
;
71 static EncodedJSValue
encode(JSValue value
);
72 static JSValue
decode(EncodedJSValue ptr
);
73 #if !USE(JSVALUE32_64)
75 static JSValue
makeImmediate(intptr_t value
);
76 intptr_t immediateValue();
79 enum JSNullTag
{ JSNull
};
80 enum JSUndefinedTag
{ JSUndefined
};
81 enum JSTrueTag
{ JSTrue
};
82 enum JSFalseTag
{ JSFalse
};
83 enum EncodeAsDoubleTag
{ EncodeAsDouble
};
87 JSValue(JSUndefinedTag
);
91 JSValue(const JSCell
* ptr
);
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);
110 operator bool() const;
111 bool operator==(const JSValue
& other
) const;
112 bool operator!=(const JSValue
& other
) const;
114 bool isInt32() const;
115 bool isUInt32() const;
116 bool isDouble() const;
118 bool isFalse() const;
120 int32_t asInt32() const;
121 uint32_t asUInt32() const;
122 double asDouble() const;
124 // Querying the type.
125 bool isUndefined() 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;
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
144 CallType
getCallData(CallData
&);
145 ConstructType
getConstructData(ConstructData
&);
147 // Extracting integer values.
148 bool getUInt32(uint32_t&) const;
150 // Basic conversions.
151 JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
152 bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
&);
154 bool toBoolean(ExecState
*) const;
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;
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;
172 #if ENABLE(JSC_ZOMBIES)
173 bool isZombie() const;
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
)); }
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
);
188 bool needsThisConversion() const;
189 JSObject
* toThisObject(ExecState
*) const;
190 UString
toThisString(ExecState
*) const;
191 JSString
* toThisJSString(ExecState
*);
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
);
200 JSValue
getJSNumber(); // JSValue() if this is not a JSNumber or number object
203 JSCell
* asCell() const;
210 enum HashTableDeletedValueTag
{ HashTableDeletedValue
};
211 JSValue(HashTableDeletedValueTag
);
213 inline const JSValue
asValue() const { return *this; }
214 JSObject
* toObjectSlowCase(ExecState
*) const;
215 JSObject
* toThisObjectSlowCase(ExecState
*) const;
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 };
226 enum { LowestTag
= DeletedValueTag
};
228 uint32_t tag() const;
229 int32_t payload() const;
231 JSObject
* synthesizePrototype(ExecState
*) const;
232 JSObject
* synthesizeObject(ExecState
*) const;
234 #if USE(JSVALUE32_64)
236 EncodedJSValue asEncodedJSValue
;
238 #if PLATFORM(BIG_ENDIAN)
250 #else // USE(JSVALUE32_64)
252 #endif // USE(JSVALUE32_64)
255 #if USE(JSVALUE32_64)
256 typedef IntHash
<EncodedJSValue
> EncodedJSValueHash
;
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
)); }
265 typedef PtrHash
<EncodedJSValue
> EncodedJSValueHash
;
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
)); }
273 // Stand-alone helper functions.
274 inline JSValue
jsNull()
276 return JSValue(JSValue::JSNull
);
279 inline JSValue
jsUndefined()
281 return JSValue(JSValue::JSUndefined
);
284 inline JSValue
jsBoolean(bool b
)
286 return b
? JSValue(JSValue::JSTrue
) : JSValue(JSValue::JSFalse
);
289 ALWAYS_INLINE JSValue
jsDoubleNumber(ExecState
* exec
, double d
)
291 return JSValue(JSValue::EncodeAsDouble
, exec
, d
);
294 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, double d
)
296 return JSValue(exec
, d
);
299 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, char i
)
301 return JSValue(exec
, i
);
304 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned char i
)
306 return JSValue(exec
, i
);
309 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, short i
)
311 return JSValue(exec
, i
);
314 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned short i
)
316 return JSValue(exec
, i
);
319 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, int i
)
321 return JSValue(exec
, i
);
324 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned i
)
326 return JSValue(exec
, i
);
329 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, long i
)
331 return JSValue(exec
, i
);
334 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned long i
)
336 return JSValue(exec
, i
);
339 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, long long i
)
341 return JSValue(exec
, i
);
344 ALWAYS_INLINE JSValue
jsNumber(ExecState
* exec
, unsigned long long i
)
346 return JSValue(exec
, i
);
349 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, double d
)
351 return JSValue(globalData
, d
);
354 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, int i
)
356 return JSValue(globalData
, i
);
359 ALWAYS_INLINE JSValue
jsNumber(JSGlobalData
* globalData
, unsigned i
)
361 return JSValue(globalData
, i
);
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
; }
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
; }
370 inline int32_t toInt32(double val
)
372 if (!(val
>= -2147483648.0 && val
< 2147483648.0)) {
374 return toInt32SlowCase(val
, ignored
);
376 return static_cast<int32_t>(val
);
379 inline uint32_t toUInt32(double val
)
381 if (!(val
>= 0.0 && val
< 4294967296.0)) {
383 return toUInt32SlowCase(val
, ignored
);
385 return static_cast<uint32_t>(val
);
388 // FIXME: We should deprecate this and just use JSValue::asCell() instead.
389 JSCell
* asCell(JSValue
);
391 inline JSCell
* asCell(JSValue value
)
393 return value
.asCell();
396 ALWAYS_INLINE
int32_t JSValue::toInt32(ExecState
* exec
) const
401 return toInt32SlowCase(toNumber(exec
), ignored
);
404 inline uint32_t JSValue::toUInt32(ExecState
* exec
) const
409 return toUInt32SlowCase(toNumber(exec
), ignored
);
412 inline int32_t JSValue::toInt32(ExecState
* exec
, bool& ok
) const
418 return toInt32SlowCase(toNumber(exec
), ok
);
421 inline uint32_t JSValue::toUInt32(ExecState
* exec
, bool& ok
) const
427 return toUInt32SlowCase(toNumber(exec
), ok
);
430 #if USE(JSVALUE32_64)
431 inline JSValue
jsNaN(ExecState
* exec
)
433 return JSValue(exec
, nonInlineNaN());
436 // JSValue member functions.
437 inline EncodedJSValue
JSValue::encode(JSValue value
)
439 return value
.u
.asEncodedJSValue
;
442 inline JSValue
JSValue::decode(EncodedJSValue encodedJSValue
)
445 v
.u
.asEncodedJSValue
= encodedJSValue
;
446 #if ENABLE(JSC_ZOMBIES)
447 ASSERT(!v
.isZombie());
452 inline JSValue::JSValue()
454 u
.asBits
.tag
= EmptyValueTag
;
455 u
.asBits
.payload
= 0;
458 inline JSValue::JSValue(JSNullTag
)
460 u
.asBits
.tag
= NullTag
;
461 u
.asBits
.payload
= 0;
464 inline JSValue::JSValue(JSUndefinedTag
)
466 u
.asBits
.tag
= UndefinedTag
;
467 u
.asBits
.payload
= 0;
470 inline JSValue::JSValue(JSTrueTag
)
472 u
.asBits
.tag
= TrueTag
;
473 u
.asBits
.payload
= 0;
476 inline JSValue::JSValue(JSFalseTag
)
478 u
.asBits
.tag
= FalseTag
;
479 u
.asBits
.payload
= 0;
482 inline JSValue::JSValue(HashTableDeletedValueTag
)
484 u
.asBits
.tag
= DeletedValueTag
;
485 u
.asBits
.payload
= 0;
488 inline JSValue::JSValue(JSCell
* ptr
)
491 u
.asBits
.tag
= CellTag
;
493 u
.asBits
.tag
= EmptyValueTag
;
494 u
.asBits
.payload
= reinterpret_cast<int32_t>(ptr
);
495 #if ENABLE(JSC_ZOMBIES)
500 inline JSValue::JSValue(const JSCell
* ptr
)
503 u
.asBits
.tag
= CellTag
;
505 u
.asBits
.tag
= EmptyValueTag
;
506 u
.asBits
.payload
= reinterpret_cast<int32_t>(const_cast<JSCell
*>(ptr
));
507 #if ENABLE(JSC_ZOMBIES)
512 inline JSValue::operator bool() const
514 ASSERT(tag() != DeletedValueTag
);
515 return tag() != EmptyValueTag
;
518 inline bool JSValue::operator==(const JSValue
& other
) const
520 return u
.asEncodedJSValue
== other
.u
.asEncodedJSValue
;
523 inline bool JSValue::operator!=(const JSValue
& other
) const
525 return u
.asEncodedJSValue
!= other
.u
.asEncodedJSValue
;
528 inline bool JSValue::isUndefined() const
530 return tag() == UndefinedTag
;
533 inline bool JSValue::isNull() const
535 return tag() == NullTag
;
538 inline bool JSValue::isUndefinedOrNull() const
540 return isUndefined() || isNull();
543 inline bool JSValue::isCell() const
545 return tag() == CellTag
;
548 inline bool JSValue::isInt32() const
550 return tag() == Int32Tag
;
553 inline bool JSValue::isUInt32() const
555 return tag() == Int32Tag
&& asInt32() > -1;
558 inline bool JSValue::isDouble() const
560 return tag() < LowestTag
;
563 inline bool JSValue::isTrue() const
565 return tag() == TrueTag
;
568 inline bool JSValue::isFalse() const
570 return tag() == FalseTag
;
573 inline uint32_t JSValue::tag() const
578 inline int32_t JSValue::payload() const
580 return u
.asBits
.payload
;
583 inline int32_t JSValue::asInt32() const
586 return u
.asBits
.payload
;
589 inline uint32_t JSValue::asUInt32() const
592 return u
.asBits
.payload
;
595 inline double JSValue::asDouble() const
601 ALWAYS_INLINE JSCell
* JSValue::asCell() const
604 return reinterpret_cast<JSCell
*>(u
.asBits
.payload
);
607 ALWAYS_INLINE
JSValue::JSValue(EncodeAsDoubleTag
, ExecState
*, double d
)
612 inline JSValue::JSValue(ExecState
* exec
, double d
)
614 const int32_t asInt32
= static_cast<int32_t>(d
);
615 if (asInt32
!= d
|| (!asInt32
&& signbit(d
))) { // true for -0.0
619 *this = JSValue(exec
, static_cast<int32_t>(d
));
622 inline JSValue::JSValue(ExecState
* exec
, char i
)
624 *this = JSValue(exec
, static_cast<int32_t>(i
));
627 inline JSValue::JSValue(ExecState
* exec
, unsigned char i
)
629 *this = JSValue(exec
, static_cast<int32_t>(i
));
632 inline JSValue::JSValue(ExecState
* exec
, short i
)
634 *this = JSValue(exec
, static_cast<int32_t>(i
));
637 inline JSValue::JSValue(ExecState
* exec
, unsigned short i
)
639 *this = JSValue(exec
, static_cast<int32_t>(i
));
642 inline JSValue::JSValue(ExecState
*, int i
)
644 u
.asBits
.tag
= Int32Tag
;
645 u
.asBits
.payload
= i
;
648 inline JSValue::JSValue(ExecState
* exec
, unsigned i
)
650 if (static_cast<int32_t>(i
) < 0) {
651 *this = JSValue(exec
, static_cast<double>(i
));
654 *this = JSValue(exec
, static_cast<int32_t>(i
));
657 inline JSValue::JSValue(ExecState
* exec
, long i
)
659 if (static_cast<int32_t>(i
) != i
) {
660 *this = JSValue(exec
, static_cast<double>(i
));
663 *this = JSValue(exec
, static_cast<int32_t>(i
));
666 inline JSValue::JSValue(ExecState
* exec
, unsigned long i
)
668 if (static_cast<uint32_t>(i
) != i
) {
669 *this = JSValue(exec
, static_cast<double>(i
));
672 *this = JSValue(exec
, static_cast<uint32_t>(i
));
675 inline JSValue::JSValue(ExecState
* exec
, long long i
)
677 if (static_cast<int32_t>(i
) != i
) {
678 *this = JSValue(exec
, static_cast<double>(i
));
681 *this = JSValue(exec
, static_cast<int32_t>(i
));
684 inline JSValue::JSValue(ExecState
* exec
, unsigned long long i
)
686 if (static_cast<uint32_t>(i
) != i
) {
687 *this = JSValue(exec
, static_cast<double>(i
));
690 *this = JSValue(exec
, static_cast<uint32_t>(i
));
693 inline JSValue::JSValue(JSGlobalData
* globalData
, double d
)
695 const int32_t asInt32
= static_cast<int32_t>(d
);
696 if (asInt32
!= d
|| (!asInt32
&& signbit(d
))) { // true for -0.0
700 *this = JSValue(globalData
, static_cast<int32_t>(d
));
703 inline JSValue::JSValue(JSGlobalData
*, int i
)
705 u
.asBits
.tag
= Int32Tag
;
706 u
.asBits
.payload
= i
;
709 inline JSValue::JSValue(JSGlobalData
* globalData
, unsigned i
)
711 if (static_cast<int32_t>(i
) < 0) {
712 *this = JSValue(globalData
, static_cast<double>(i
));
715 *this = JSValue(globalData
, static_cast<int32_t>(i
));
718 inline bool JSValue::isNumber() const
720 return isInt32() || isDouble();
723 inline bool JSValue::isBoolean() const
725 return isTrue() || isFalse();
728 inline bool JSValue::getBoolean(bool& v
) const
742 inline bool JSValue::getBoolean() const
745 return tag() == TrueTag
;
748 inline double JSValue::uncheckedGetNumber() const
751 return isInt32() ? asInt32() : asDouble();
754 ALWAYS_INLINE JSValue
JSValue::toJSNumber(ExecState
* exec
) const
756 return isNumber() ? asValue() : jsNumber(exec
, this->toNumber(exec
));
759 inline bool JSValue::getNumber(double& result
) const
772 #else // USE(JSVALUE32_64)
774 // JSValue member functions.
775 inline EncodedJSValue
JSValue::encode(JSValue value
)
777 return reinterpret_cast<EncodedJSValue
>(value
.m_ptr
);
780 inline JSValue
JSValue::decode(EncodedJSValue ptr
)
782 return JSValue(reinterpret_cast<JSCell
*>(ptr
));
785 inline JSValue
JSValue::makeImmediate(intptr_t value
)
787 return JSValue(reinterpret_cast<JSCell
*>(value
));
790 inline intptr_t JSValue::immediateValue()
792 return reinterpret_cast<intptr_t>(m_ptr
);
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()
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))
807 inline JSValue::JSValue(JSCell
* ptr
)
810 #if ENABLE(JSC_ZOMBIES)
815 inline JSValue::JSValue(const JSCell
* ptr
)
816 : m_ptr(const_cast<JSCell
*>(ptr
))
818 #if ENABLE(JSC_ZOMBIES)
823 inline JSValue::operator bool() const
828 inline bool JSValue::operator==(const JSValue
& other
) const
830 return m_ptr
== other
.m_ptr
;
833 inline bool JSValue::operator!=(const JSValue
& other
) const
835 return m_ptr
!= other
.m_ptr
;
838 inline bool JSValue::isUndefined() const
840 return asValue() == jsUndefined();
843 inline bool JSValue::isNull() const
845 return asValue() == jsNull();
847 #endif // USE(JSVALUE32_64)