2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include <wtf/Assertions.h>
26 #include <wtf/AlwaysInline.h>
27 #include <wtf/MathExtras.h>
28 #include <wtf/StdLibExtras.h>
47 JSValuePtr
jsBoolean(bool b
);
48 JSValuePtr
jsUndefined();
49 JSValuePtr
jsImpossibleValue();
50 JSValuePtr
jsNumber(ExecState
* exec
, double d
);
51 JSValuePtr
jsNumber(ExecState
*, char i
);
52 JSValuePtr
jsNumber(ExecState
*, unsigned char i
);
53 JSValuePtr
jsNumber(ExecState
*, short i
);
54 JSValuePtr
jsNumber(ExecState
*, unsigned short i
);
55 JSValuePtr
jsNumber(ExecState
* exec
, int i
);
56 JSValuePtr
jsNumber(ExecState
* exec
, unsigned i
);
57 JSValuePtr
jsNumber(ExecState
* exec
, long i
);
58 JSValuePtr
jsNumber(ExecState
* exec
, unsigned long i
);
59 JSValuePtr
jsNumber(ExecState
* exec
, long long i
);
60 JSValuePtr
jsNumber(ExecState
* exec
, unsigned long long i
);
61 JSValuePtr
jsNumber(JSGlobalData
* globalData
, double d
);
62 JSValuePtr
jsNumber(JSGlobalData
* globalData
, short i
);
63 JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned short i
);
64 JSValuePtr
jsNumber(JSGlobalData
* globalData
, int i
);
65 JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned i
);
66 JSValuePtr
jsNumber(JSGlobalData
* globalData
, long i
);
67 JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned long i
);
68 JSValuePtr
jsNumber(JSGlobalData
* globalData
, long long i
);
69 JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned long long i
);
71 #if USE(ALTERNATE_JSIMMEDIATE)
72 inline intptr_t reinterpretDoubleToIntptr(double value
)
74 return WTF::bitwise_cast
<intptr_t>(value
);
77 inline double reinterpretIntptrToDouble(intptr_t value
)
79 return WTF::bitwise_cast
<double>(value
);
84 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
85 * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
86 * because allocator alignment guarantees they will be 00 in cell pointers.
88 * For example, on a 32 bit system:
90 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
91 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
92 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
93 * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ]
95 * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
96 * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
97 * tag used to indicate the exact type.
99 * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
100 * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
101 * two bits will form an extended tag.
103 * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1
104 * [ high 30 bits of the value ] [ high bit part of value ]
105 * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10
106 * [ extended 'payload' ] [ extended tag ] [ tag 'other' ]
108 * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
109 * bit would flag the value as undefined. If neither bits are set, the value is null.
111 * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
112 * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
114 * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
115 * For undefined or null immediates the payload is zero.
117 * Boolean: 000000000000000000000000000V 01 10
118 * [ boolean value ] [ bool ] [ tag 'other' ]
119 * Undefined: 0000000000000000000000000000 10 10
120 * [ zero ] [ undefined ] [ tag 'other' ]
121 * Null: 0000000000000000000000000000 00 10
122 * [ zero ] [ zero ] [ tag 'other' ]
126 * On 64-bit platforms, we support an alternative encoding form for immediates, if
127 * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision
128 * floating point values may also be encoded as JSImmediates.
130 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
131 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
132 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
133 * have a payload of zero. We assume that non-zero payloads are available to encode
134 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
135 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
136 * ranges to encode other values (however there are also other ranges of NaN space that
137 * could have been selected). This range of NaN space is represented by 64-bit numbers
138 * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
139 * valid double-precision numbers will begin fall in these ranges.
141 * The scheme we have implemented encodes double precision values by adding 2^48 to the
142 * 64-bit integer representation of the number. After this manipulation, no encoded
143 * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
145 * The top 16-bits denote the type of the encoded JSImmediate:
147 * Pointer: 0000:PPPP:PPPP:PPPP
148 * 0001:****:****:****
150 * FFFE:****:****:****
151 * Integer: FFFF:0000:IIII:IIII
153 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000
154 * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined
155 * values are encoded in the same manner as the default format.
161 friend class JSValuePtr
;
162 friend class JSFastMath
;
163 friend JSValuePtr
js0();
164 friend JSValuePtr
jsNull();
165 friend JSValuePtr
jsBoolean(bool b
);
166 friend JSValuePtr
jsUndefined();
167 friend JSValuePtr
jsImpossibleValue();
168 friend JSValuePtr
jsNumber(ExecState
* exec
, double d
);
169 friend JSValuePtr
jsNumber(ExecState
*, char i
);
170 friend JSValuePtr
jsNumber(ExecState
*, unsigned char i
);
171 friend JSValuePtr
jsNumber(ExecState
*, short i
);
172 friend JSValuePtr
jsNumber(ExecState
*, unsigned short i
);
173 friend JSValuePtr
jsNumber(ExecState
* exec
, int i
);
174 friend JSValuePtr
jsNumber(ExecState
* exec
, unsigned i
);
175 friend JSValuePtr
jsNumber(ExecState
* exec
, long i
);
176 friend JSValuePtr
jsNumber(ExecState
* exec
, unsigned long i
);
177 friend JSValuePtr
jsNumber(ExecState
* exec
, long long i
);
178 friend JSValuePtr
jsNumber(ExecState
* exec
, unsigned long long i
);
179 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, double d
);
180 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, short i
);
181 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned short i
);
182 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, int i
);
183 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned i
);
184 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, long i
);
185 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned long i
);
186 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, long long i
);
187 friend JSValuePtr
jsNumber(JSGlobalData
* globalData
, unsigned long long i
);
189 #if USE(ALTERNATE_JSIMMEDIATE)
190 // If all bits in the mask are set, this indicates an integer number,
191 // if any but not all are set this value is a double precision number.
192 static const intptr_t TagTypeNumber
= 0xffff000000000000ll
;
193 // This value is 2^48, used to encode doubles such that the encoded value will begin
194 // with a 16-bit pattern within the range 0x0001..0xFFFE.
195 static const intptr_t DoubleEncodeOffset
= 0x1000000000000ll
;
197 static const intptr_t TagTypeNumber
= 0x1; // bottom bit set indicates integer, this dominates the following bit
199 static const intptr_t TagBitTypeOther
= 0x2; // second bit set indicates immediate other than an integer
200 static const intptr_t TagMask
= TagTypeNumber
| TagBitTypeOther
;
202 static const intptr_t ExtendedTagMask
= 0xC; // extended tag holds a further two bits
203 static const intptr_t ExtendedTagBitBool
= 0x4;
204 static const intptr_t ExtendedTagBitUndefined
= 0x8;
206 static const intptr_t FullTagTypeMask
= TagMask
| ExtendedTagMask
;
207 static const intptr_t FullTagTypeBool
= TagBitTypeOther
| ExtendedTagBitBool
;
208 static const intptr_t FullTagTypeUndefined
= TagBitTypeOther
| ExtendedTagBitUndefined
;
209 static const intptr_t FullTagTypeNull
= TagBitTypeOther
;
211 #if USE(ALTERNATE_JSIMMEDIATE)
212 static const int32_t IntegerPayloadShift
= 0;
214 static const int32_t IntegerPayloadShift
= 1;
216 static const int32_t ExtendedPayloadShift
= 4;
218 static const intptr_t ExtendedPayloadBitBoolValue
= 1 << ExtendedPayloadShift
;
220 static const int32_t signBit
= 0x80000000;
222 static ALWAYS_INLINE
bool isImmediate(JSValuePtr v
)
224 return rawValue(v
) & TagMask
;
227 static ALWAYS_INLINE
bool isNumber(JSValuePtr v
)
229 return rawValue(v
) & TagTypeNumber
;
232 static ALWAYS_INLINE
bool isIntegerNumber(JSValuePtr v
)
234 #if USE(ALTERNATE_JSIMMEDIATE)
235 return (rawValue(v
) & TagTypeNumber
) == TagTypeNumber
;
241 #if USE(ALTERNATE_JSIMMEDIATE)
242 static ALWAYS_INLINE
bool isDoubleNumber(JSValuePtr v
)
244 return isNumber(v
) && !isIntegerNumber(v
);
248 static ALWAYS_INLINE
bool isPositiveIntegerNumber(JSValuePtr v
)
250 // A single mask to check for the sign bit and the number tag all at once.
251 return (rawValue(v
) & (signBit
| TagTypeNumber
)) == TagTypeNumber
;
254 static ALWAYS_INLINE
bool isBoolean(JSValuePtr v
)
256 return (rawValue(v
) & FullTagTypeMask
) == FullTagTypeBool
;
259 static ALWAYS_INLINE
bool isUndefinedOrNull(JSValuePtr v
)
261 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
262 return (rawValue(v
) & ~ExtendedTagBitUndefined
) == FullTagTypeNull
;
265 static JSValuePtr
from(char);
266 static JSValuePtr
from(signed char);
267 static JSValuePtr
from(unsigned char);
268 static JSValuePtr
from(short);
269 static JSValuePtr
from(unsigned short);
270 static JSValuePtr
from(int);
271 static JSValuePtr
from(unsigned);
272 static JSValuePtr
from(long);
273 static JSValuePtr
from(unsigned long);
274 static JSValuePtr
from(long long);
275 static JSValuePtr
from(unsigned long long);
276 static JSValuePtr
from(double);
278 static ALWAYS_INLINE
bool isEitherImmediate(JSValuePtr v1
, JSValuePtr v2
)
280 return (rawValue(v1
) | rawValue(v2
)) & TagMask
;
283 static ALWAYS_INLINE
bool areBothImmediate(JSValuePtr v1
, JSValuePtr v2
)
285 return isImmediate(v1
) & isImmediate(v2
);
288 static ALWAYS_INLINE
bool areBothImmediateIntegerNumbers(JSValuePtr v1
, JSValuePtr v2
)
290 #if USE(ALTERNATE_JSIMMEDIATE)
291 return (rawValue(v1
) & rawValue(v2
) & TagTypeNumber
) == TagTypeNumber
;
293 return rawValue(v1
) & rawValue(v2
) & TagTypeNumber
;
297 static double toDouble(JSValuePtr
);
298 static bool toBoolean(JSValuePtr
);
299 static JSObject
* toObject(JSValuePtr
, ExecState
*);
300 static JSObject
* toThisObject(JSValuePtr
, ExecState
*);
301 static UString
toString(JSValuePtr
);
303 static bool getUInt32(JSValuePtr
, uint32_t&);
304 static bool getTruncatedInt32(JSValuePtr
, int32_t&);
305 static bool getTruncatedUInt32(JSValuePtr
, uint32_t&);
307 static int32_t getTruncatedInt32(JSValuePtr
);
308 static uint32_t getTruncatedUInt32(JSValuePtr
);
310 static JSValuePtr
trueImmediate();
311 static JSValuePtr
falseImmediate();
312 static JSValuePtr
undefinedImmediate();
313 static JSValuePtr
nullImmediate();
314 static JSValuePtr
zeroImmediate();
315 static JSValuePtr
oneImmediate();
317 static JSValuePtr
impossibleValue();
319 static JSObject
* prototype(JSValuePtr
, ExecState
*);
322 #if USE(ALTERNATE_JSIMMEDIATE)
323 static const int minImmediateInt
= ((-INT_MAX
) - 1);
324 static const int maxImmediateInt
= INT_MAX
;
326 static const int minImmediateInt
= ((-INT_MAX
) - 1) >> IntegerPayloadShift
;
327 static const int maxImmediateInt
= INT_MAX
>> IntegerPayloadShift
;
329 static const unsigned maxImmediateUInt
= maxImmediateInt
;
331 static ALWAYS_INLINE JSValuePtr
makeValue(intptr_t integer
)
333 return JSValuePtr::makeImmediate(integer
);
336 // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the
337 // integer doesn't interfere with the tag bits in the upper word. In the default encoding,
338 // if intptr_t id larger then int32_t we sign extend the value through the upper word.
339 #if USE(ALTERNATE_JSIMMEDIATE)
340 static ALWAYS_INLINE JSValuePtr
makeInt(uint32_t value
)
342 static ALWAYS_INLINE JSValuePtr
makeInt(int32_t value
)
345 return makeValue((static_cast<intptr_t>(value
) << IntegerPayloadShift
) | TagTypeNumber
);
348 #if USE(ALTERNATE_JSIMMEDIATE)
349 static ALWAYS_INLINE JSValuePtr
makeDouble(double value
)
351 return makeValue(reinterpretDoubleToIntptr(value
) + DoubleEncodeOffset
);
355 static ALWAYS_INLINE JSValuePtr
makeBool(bool b
)
357 return makeValue((static_cast<intptr_t>(b
) << ExtendedPayloadShift
) | FullTagTypeBool
);
360 static ALWAYS_INLINE JSValuePtr
makeUndefined()
362 return makeValue(FullTagTypeUndefined
);
365 static ALWAYS_INLINE JSValuePtr
makeNull()
367 return makeValue(FullTagTypeNull
);
371 static JSValuePtr
fromNumberOutsideIntegerRange(T
);
373 #if USE(ALTERNATE_JSIMMEDIATE)
374 static ALWAYS_INLINE
double doubleValue(JSValuePtr v
)
376 return reinterpretIntptrToDouble(rawValue(v
) - DoubleEncodeOffset
);
380 static ALWAYS_INLINE
int32_t intValue(JSValuePtr v
)
382 return static_cast<int32_t>(rawValue(v
) >> IntegerPayloadShift
);
385 static ALWAYS_INLINE
uint32_t uintValue(JSValuePtr v
)
387 return static_cast<uint32_t>(rawValue(v
) >> IntegerPayloadShift
);
390 static ALWAYS_INLINE
bool boolValue(JSValuePtr v
)
392 return rawValue(v
) & ExtendedPayloadBitBoolValue
;
395 static ALWAYS_INLINE
intptr_t rawValue(JSValuePtr v
)
397 return v
.immediateValue();
400 static double nonInlineNaN();
403 ALWAYS_INLINE JSValuePtr
JSImmediate::trueImmediate() { return makeBool(true); }
404 ALWAYS_INLINE JSValuePtr
JSImmediate::falseImmediate() { return makeBool(false); }
405 ALWAYS_INLINE JSValuePtr
JSImmediate::undefinedImmediate() { return makeUndefined(); }
406 ALWAYS_INLINE JSValuePtr
JSImmediate::nullImmediate() { return makeNull(); }
407 ALWAYS_INLINE JSValuePtr
JSImmediate::zeroImmediate() { return makeInt(0); }
408 ALWAYS_INLINE JSValuePtr
JSImmediate::oneImmediate() { return makeInt(1); }
410 // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
411 ALWAYS_INLINE JSValuePtr
JSImmediate::impossibleValue() { return makeValue(0x4); }
413 #if USE(ALTERNATE_JSIMMEDIATE)
414 inline bool doubleToBoolean(double value
)
416 return value
< 0.0 || value
> 0.0;
419 ALWAYS_INLINE
bool JSImmediate::toBoolean(JSValuePtr v
)
421 ASSERT(isImmediate(v
));
422 return isNumber(v
) ? isIntegerNumber(v
) ? v
!= zeroImmediate()
423 : doubleToBoolean(doubleValue(v
)) : v
== trueImmediate();
426 ALWAYS_INLINE
bool JSImmediate::toBoolean(JSValuePtr v
)
428 ASSERT(isImmediate(v
));
429 return isIntegerNumber(v
) ? v
!= zeroImmediate() : v
== trueImmediate();
433 ALWAYS_INLINE
uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v
)
435 // FIXME: should probably be asserting isPositiveIntegerNumber here.
436 ASSERT(isIntegerNumber(v
));
440 #if USE(ALTERNATE_JSIMMEDIATE)
442 inline JSValuePtr
JSImmediate::fromNumberOutsideIntegerRange(T value
)
444 return makeDouble(static_cast<double>(value
));
448 inline JSValuePtr
JSImmediate::fromNumberOutsideIntegerRange(T
)
454 ALWAYS_INLINE JSValuePtr
JSImmediate::from(char i
)
459 ALWAYS_INLINE JSValuePtr
JSImmediate::from(signed char i
)
464 ALWAYS_INLINE JSValuePtr
JSImmediate::from(unsigned char i
)
469 ALWAYS_INLINE JSValuePtr
JSImmediate::from(short i
)
474 ALWAYS_INLINE JSValuePtr
JSImmediate::from(unsigned short i
)
479 ALWAYS_INLINE JSValuePtr
JSImmediate::from(int i
)
481 #if !USE(ALTERNATE_JSIMMEDIATE)
482 if ((i
< minImmediateInt
) | (i
> maxImmediateInt
))
483 return fromNumberOutsideIntegerRange(i
);
488 ALWAYS_INLINE JSValuePtr
JSImmediate::from(unsigned i
)
490 if (i
> maxImmediateUInt
)
491 return fromNumberOutsideIntegerRange(i
);
495 ALWAYS_INLINE JSValuePtr
JSImmediate::from(long i
)
497 if ((i
< minImmediateInt
) | (i
> maxImmediateInt
))
498 return fromNumberOutsideIntegerRange(i
);
502 ALWAYS_INLINE JSValuePtr
JSImmediate::from(unsigned long i
)
504 if (i
> maxImmediateUInt
)
505 return fromNumberOutsideIntegerRange(i
);
509 ALWAYS_INLINE JSValuePtr
JSImmediate::from(long long i
)
511 if ((i
< minImmediateInt
) | (i
> maxImmediateInt
))
513 return makeInt(static_cast<intptr_t>(i
));
516 ALWAYS_INLINE JSValuePtr
JSImmediate::from(unsigned long long i
)
518 if (i
> maxImmediateUInt
)
519 return fromNumberOutsideIntegerRange(i
);
520 return makeInt(static_cast<intptr_t>(i
));
523 ALWAYS_INLINE JSValuePtr
JSImmediate::from(double d
)
525 const int intVal
= static_cast<int>(d
);
527 // Check for data loss from conversion to int.
528 if (intVal
!= d
|| (!intVal
&& signbit(d
)))
529 return fromNumberOutsideIntegerRange(d
);
534 ALWAYS_INLINE
int32_t JSImmediate::getTruncatedInt32(JSValuePtr v
)
536 ASSERT(isIntegerNumber(v
));
540 ALWAYS_INLINE
double JSImmediate::toDouble(JSValuePtr v
)
542 ASSERT(isImmediate(v
));
544 if (isIntegerNumber(v
))
547 #if USE(ALTERNATE_JSIMMEDIATE)
549 ASSERT(isDoubleNumber(v
));
550 return doubleValue(v
);
553 ASSERT(!isNumber(v
));
556 if (rawValue(v
) == FullTagTypeUndefined
)
557 return nonInlineNaN();
559 ASSERT(JSImmediate::isBoolean(v
) || (v
== JSImmediate::nullImmediate()));
560 return rawValue(v
) >> ExtendedPayloadShift
;
563 ALWAYS_INLINE
bool JSImmediate::getUInt32(JSValuePtr v
, uint32_t& i
)
566 return isPositiveIntegerNumber(v
);
569 ALWAYS_INLINE
bool JSImmediate::getTruncatedInt32(JSValuePtr v
, int32_t& i
)
572 return isIntegerNumber(v
);
575 ALWAYS_INLINE
bool JSImmediate::getTruncatedUInt32(JSValuePtr v
, uint32_t& i
)
577 return getUInt32(v
, i
);
580 inline JSValuePtr
js0()
582 return JSImmediate::zeroImmediate();
585 inline JSValuePtr
jsNull()
587 return JSImmediate::nullImmediate();
590 inline JSValuePtr
jsBoolean(bool b
)
592 return b
? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
595 inline JSValuePtr
jsUndefined()
597 return JSImmediate::undefinedImmediate();
600 inline JSValuePtr
jsImpossibleValue()
602 return JSImmediate::impossibleValue();
605 // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32().
606 int32_t toInt32(double);
607 uint32_t toUInt32(double);
608 int32_t toInt32SlowCase(double, bool& ok
);
609 uint32_t toUInt32SlowCase(double, bool& ok
);
611 inline bool JSValuePtr::isUndefined() const
613 return asValue() == jsUndefined();
616 inline bool JSValuePtr::isNull() const
618 return asValue() == jsNull();
621 inline bool JSValuePtr::isUndefinedOrNull() const
623 return JSImmediate::isUndefinedOrNull(asValue());
626 inline bool JSValuePtr::isBoolean() const
628 return JSImmediate::isBoolean(asValue());
631 inline bool JSValuePtr::getBoolean(bool& v
) const
633 if (JSImmediate::isBoolean(asValue())) {
634 v
= JSImmediate::toBoolean(asValue());
641 inline bool JSValuePtr::getBoolean() const
643 return asValue() == jsBoolean(true);
646 ALWAYS_INLINE
int32_t JSValuePtr::toInt32(ExecState
* exec
) const
649 if (getTruncatedInt32(i
))
652 return toInt32SlowCase(toNumber(exec
), ignored
);
655 inline uint32_t JSValuePtr::toUInt32(ExecState
* exec
) const
658 if (getTruncatedUInt32(i
))
661 return toUInt32SlowCase(toNumber(exec
), ignored
);
664 inline int32_t toInt32(double val
)
666 if (!(val
>= -2147483648.0 && val
< 2147483648.0)) {
668 return toInt32SlowCase(val
, ignored
);
670 return static_cast<int32_t>(val
);
673 inline uint32_t toUInt32(double val
)
675 if (!(val
>= 0.0 && val
< 4294967296.0)) {
677 return toUInt32SlowCase(val
, ignored
);
679 return static_cast<uint32_t>(val
);
682 inline int32_t JSValuePtr::toInt32(ExecState
* exec
, bool& ok
) const
685 if (getTruncatedInt32(i
)) {
689 return toInt32SlowCase(toNumber(exec
), ok
);
692 inline uint32_t JSValuePtr::toUInt32(ExecState
* exec
, bool& ok
) const
695 if (getTruncatedUInt32(i
)) {
699 return toUInt32SlowCase(toNumber(exec
), ok
);
702 inline bool JSValuePtr::isCell() const
704 return !JSImmediate::isImmediate(asValue());
707 inline bool JSValuePtr::isInt32Fast() const
709 return JSImmediate::isIntegerNumber(asValue());
712 inline int32_t JSValuePtr::getInt32Fast() const
714 ASSERT(isInt32Fast());
715 return JSImmediate::getTruncatedInt32(asValue());
718 inline bool JSValuePtr::isUInt32Fast() const
720 return JSImmediate::isPositiveIntegerNumber(asValue());
723 inline uint32_t JSValuePtr::getUInt32Fast() const
725 ASSERT(isUInt32Fast());
726 return JSImmediate::getTruncatedUInt32(asValue());
729 inline JSValuePtr
JSValuePtr::makeInt32Fast(int32_t i
)
731 return JSImmediate::from(i
);
734 inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1
, JSValuePtr v2
)
736 return JSImmediate::areBothImmediateIntegerNumbers(v1
, v2
);
741 static ALWAYS_INLINE
bool canDoFastBitwiseOperations(JSValuePtr v1
, JSValuePtr v2
)
743 return JSImmediate::areBothImmediateIntegerNumbers(v1
, v2
);
746 static ALWAYS_INLINE JSValuePtr
equal(JSValuePtr v1
, JSValuePtr v2
)
748 ASSERT(canDoFastBitwiseOperations(v1
, v2
));
749 return jsBoolean(v1
== v2
);
752 static ALWAYS_INLINE JSValuePtr
notEqual(JSValuePtr v1
, JSValuePtr v2
)
754 ASSERT(canDoFastBitwiseOperations(v1
, v2
));
755 return jsBoolean(v1
!= v2
);
758 static ALWAYS_INLINE JSValuePtr
andImmediateNumbers(JSValuePtr v1
, JSValuePtr v2
)
760 ASSERT(canDoFastBitwiseOperations(v1
, v2
));
761 return JSImmediate::makeValue(JSImmediate::rawValue(v1
) & JSImmediate::rawValue(v2
));
764 static ALWAYS_INLINE JSValuePtr
xorImmediateNumbers(JSValuePtr v1
, JSValuePtr v2
)
766 ASSERT(canDoFastBitwiseOperations(v1
, v2
));
767 return JSImmediate::makeValue((JSImmediate::rawValue(v1
) ^ JSImmediate::rawValue(v2
)) | JSImmediate::TagTypeNumber
);
770 static ALWAYS_INLINE JSValuePtr
orImmediateNumbers(JSValuePtr v1
, JSValuePtr v2
)
772 ASSERT(canDoFastBitwiseOperations(v1
, v2
));
773 return JSImmediate::makeValue(JSImmediate::rawValue(v1
) | JSImmediate::rawValue(v2
));
776 static ALWAYS_INLINE
bool canDoFastRshift(JSValuePtr v1
, JSValuePtr v2
)
778 return JSImmediate::areBothImmediateIntegerNumbers(v1
, v2
);
781 static ALWAYS_INLINE
bool canDoFastUrshift(JSValuePtr v1
, JSValuePtr v2
)
783 return JSImmediate::areBothImmediateIntegerNumbers(v1
, v2
) && !(JSImmediate::rawValue(v1
) & JSImmediate::signBit
);
786 static ALWAYS_INLINE JSValuePtr
rightShiftImmediateNumbers(JSValuePtr val
, JSValuePtr shift
)
788 ASSERT(canDoFastRshift(val
, shift
) || canDoFastUrshift(val
, shift
));
789 #if USE(ALTERNATE_JSIMMEDIATE)
790 return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val
)) >> ((JSImmediate::rawValue(shift
) >> JSImmediate::IntegerPayloadShift
) & 0x1f))) | JSImmediate::TagTypeNumber
);
792 return JSImmediate::makeValue((JSImmediate::rawValue(val
) >> ((JSImmediate::rawValue(shift
) >> JSImmediate::IntegerPayloadShift
) & 0x1f)) | JSImmediate::TagTypeNumber
);
796 static ALWAYS_INLINE
bool canDoFastAdditiveOperations(JSValuePtr v
)
798 // Number is non-negative and an operation involving two of these can't overflow.
799 // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
800 return (JSImmediate::rawValue(v
) & (JSImmediate::TagTypeNumber
+ (JSImmediate::signBit
| (JSImmediate::signBit
>> 1)))) == JSImmediate::TagTypeNumber
;
803 static ALWAYS_INLINE
bool canDoFastAdditiveOperations(JSValuePtr v1
, JSValuePtr v2
)
805 // Number is non-negative and an operation involving two of these can't overflow.
806 // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
807 return canDoFastAdditiveOperations(v1
) && canDoFastAdditiveOperations(v2
);
810 static ALWAYS_INLINE JSValuePtr
addImmediateNumbers(JSValuePtr v1
, JSValuePtr v2
)
812 ASSERT(canDoFastAdditiveOperations(v1
, v2
));
813 return JSImmediate::makeValue(JSImmediate::rawValue(v1
) + JSImmediate::rawValue(v2
) - JSImmediate::TagTypeNumber
);
816 static ALWAYS_INLINE JSValuePtr
subImmediateNumbers(JSValuePtr v1
, JSValuePtr v2
)
818 ASSERT(canDoFastAdditiveOperations(v1
, v2
));
819 return JSImmediate::makeValue(JSImmediate::rawValue(v1
) - JSImmediate::rawValue(v2
) + JSImmediate::TagTypeNumber
);
822 static ALWAYS_INLINE JSValuePtr
incImmediateNumber(JSValuePtr v
)
824 ASSERT(canDoFastAdditiveOperations(v
));
825 return JSImmediate::makeValue(JSImmediate::rawValue(v
) + (1 << JSImmediate::IntegerPayloadShift
));
828 static ALWAYS_INLINE JSValuePtr
decImmediateNumber(JSValuePtr v
)
830 ASSERT(canDoFastAdditiveOperations(v
));
831 return JSImmediate::makeValue(JSImmediate::rawValue(v
) - (1 << JSImmediate::IntegerPayloadShift
));
837 #endif // JSImmediate_h