]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSImmediate.h
JavaScriptCore-525.tar.gz
[apple/javascriptcore.git] / runtime / JSImmediate.h
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 *
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.
9 *
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.
14 *
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.
19 *
20 */
21
22 #ifndef JSImmediate_h
23 #define JSImmediate_h
24
25 #include <wtf/Assertions.h>
26 #include <wtf/AlwaysInline.h>
27 #include <wtf/MathExtras.h>
28 #include <wtf/StdLibExtras.h>
29 #include "JSValue.h"
30 #include <limits>
31 #include <limits.h>
32 #include <stdarg.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35
36 namespace JSC {
37
38 class ExecState;
39 class JSCell;
40 class JSFastMath;
41 class JSGlobalData;
42 class JSObject;
43 class UString;
44
45 JSValuePtr js0();
46 JSValuePtr jsNull();
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);
70
71 #if USE(ALTERNATE_JSIMMEDIATE)
72 inline intptr_t reinterpretDoubleToIntptr(double value)
73 {
74 return WTF::bitwise_cast<intptr_t>(value);
75 }
76
77 inline double reinterpretIntptrToDouble(intptr_t value)
78 {
79 return WTF::bitwise_cast<double>(value);
80 }
81 #endif
82
83 /*
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.
87 *
88 * For example, on a 32 bit system:
89 *
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 ]
94 *
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.
98 *
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.
102 *
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' ]
107 *
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.
110 *
111 * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
112 * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
113 *
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.
116 *
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' ]
123 */
124
125 /*
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.
129 *
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.
140 *
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.
144 *
145 * The top 16-bits denote the type of the encoded JSImmediate:
146 *
147 * Pointer: 0000:PPPP:PPPP:PPPP
148 * 0001:****:****:****
149 * Double:{ ...
150 * FFFE:****:****:****
151 * Integer: FFFF:0000:IIII:IIII
152 *
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.
156 */
157
158 class JSImmediate {
159 private:
160 friend class JIT;
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);
188
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;
196 #else
197 static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
198 #endif
199 static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer
200 static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther;
201
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;
205
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;
210
211 #if USE(ALTERNATE_JSIMMEDIATE)
212 static const int32_t IntegerPayloadShift = 0;
213 #else
214 static const int32_t IntegerPayloadShift = 1;
215 #endif
216 static const int32_t ExtendedPayloadShift = 4;
217
218 static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
219
220 static const int32_t signBit = 0x80000000;
221
222 static ALWAYS_INLINE bool isImmediate(JSValuePtr v)
223 {
224 return rawValue(v) & TagMask;
225 }
226
227 static ALWAYS_INLINE bool isNumber(JSValuePtr v)
228 {
229 return rawValue(v) & TagTypeNumber;
230 }
231
232 static ALWAYS_INLINE bool isIntegerNumber(JSValuePtr v)
233 {
234 #if USE(ALTERNATE_JSIMMEDIATE)
235 return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
236 #else
237 return isNumber(v);
238 #endif
239 }
240
241 #if USE(ALTERNATE_JSIMMEDIATE)
242 static ALWAYS_INLINE bool isDoubleNumber(JSValuePtr v)
243 {
244 return isNumber(v) && !isIntegerNumber(v);
245 }
246 #endif
247
248 static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValuePtr v)
249 {
250 // A single mask to check for the sign bit and the number tag all at once.
251 return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
252 }
253
254 static ALWAYS_INLINE bool isBoolean(JSValuePtr v)
255 {
256 return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
257 }
258
259 static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v)
260 {
261 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
262 return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
263 }
264
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);
277
278 static ALWAYS_INLINE bool isEitherImmediate(JSValuePtr v1, JSValuePtr v2)
279 {
280 return (rawValue(v1) | rawValue(v2)) & TagMask;
281 }
282
283 static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2)
284 {
285 return isImmediate(v1) & isImmediate(v2);
286 }
287
288 static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValuePtr v1, JSValuePtr v2)
289 {
290 #if USE(ALTERNATE_JSIMMEDIATE)
291 return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
292 #else
293 return rawValue(v1) & rawValue(v2) & TagTypeNumber;
294 #endif
295 }
296
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);
302
303 static bool getUInt32(JSValuePtr, uint32_t&);
304 static bool getTruncatedInt32(JSValuePtr, int32_t&);
305 static bool getTruncatedUInt32(JSValuePtr, uint32_t&);
306
307 static int32_t getTruncatedInt32(JSValuePtr);
308 static uint32_t getTruncatedUInt32(JSValuePtr);
309
310 static JSValuePtr trueImmediate();
311 static JSValuePtr falseImmediate();
312 static JSValuePtr undefinedImmediate();
313 static JSValuePtr nullImmediate();
314 static JSValuePtr zeroImmediate();
315 static JSValuePtr oneImmediate();
316
317 static JSValuePtr impossibleValue();
318
319 static JSObject* prototype(JSValuePtr, ExecState*);
320
321 private:
322 #if USE(ALTERNATE_JSIMMEDIATE)
323 static const int minImmediateInt = ((-INT_MAX) - 1);
324 static const int maxImmediateInt = INT_MAX;
325 #else
326 static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
327 static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
328 #endif
329 static const unsigned maxImmediateUInt = maxImmediateInt;
330
331 static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer)
332 {
333 return JSValuePtr::makeImmediate(integer);
334 }
335
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)
341 #else
342 static ALWAYS_INLINE JSValuePtr makeInt(int32_t value)
343 #endif
344 {
345 return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
346 }
347
348 #if USE(ALTERNATE_JSIMMEDIATE)
349 static ALWAYS_INLINE JSValuePtr makeDouble(double value)
350 {
351 return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
352 }
353 #endif
354
355 static ALWAYS_INLINE JSValuePtr makeBool(bool b)
356 {
357 return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
358 }
359
360 static ALWAYS_INLINE JSValuePtr makeUndefined()
361 {
362 return makeValue(FullTagTypeUndefined);
363 }
364
365 static ALWAYS_INLINE JSValuePtr makeNull()
366 {
367 return makeValue(FullTagTypeNull);
368 }
369
370 template<typename T>
371 static JSValuePtr fromNumberOutsideIntegerRange(T);
372
373 #if USE(ALTERNATE_JSIMMEDIATE)
374 static ALWAYS_INLINE double doubleValue(JSValuePtr v)
375 {
376 return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
377 }
378 #endif
379
380 static ALWAYS_INLINE int32_t intValue(JSValuePtr v)
381 {
382 return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
383 }
384
385 static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v)
386 {
387 return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
388 }
389
390 static ALWAYS_INLINE bool boolValue(JSValuePtr v)
391 {
392 return rawValue(v) & ExtendedPayloadBitBoolValue;
393 }
394
395 static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v)
396 {
397 return v.immediateValue();
398 }
399
400 static double nonInlineNaN();
401 };
402
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); }
409
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); }
412
413 #if USE(ALTERNATE_JSIMMEDIATE)
414 inline bool doubleToBoolean(double value)
415 {
416 return value < 0.0 || value > 0.0;
417 }
418
419 ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
420 {
421 ASSERT(isImmediate(v));
422 return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
423 : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
424 }
425 #else
426 ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
427 {
428 ASSERT(isImmediate(v));
429 return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
430 }
431 #endif
432
433 ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v)
434 {
435 // FIXME: should probably be asserting isPositiveIntegerNumber here.
436 ASSERT(isIntegerNumber(v));
437 return intValue(v);
438 }
439
440 #if USE(ALTERNATE_JSIMMEDIATE)
441 template<typename T>
442 inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T value)
443 {
444 return makeDouble(static_cast<double>(value));
445 }
446 #else
447 template<typename T>
448 inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T)
449 {
450 return noValue();
451 }
452 #endif
453
454 ALWAYS_INLINE JSValuePtr JSImmediate::from(char i)
455 {
456 return makeInt(i);
457 }
458
459 ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i)
460 {
461 return makeInt(i);
462 }
463
464 ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i)
465 {
466 return makeInt(i);
467 }
468
469 ALWAYS_INLINE JSValuePtr JSImmediate::from(short i)
470 {
471 return makeInt(i);
472 }
473
474 ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i)
475 {
476 return makeInt(i);
477 }
478
479 ALWAYS_INLINE JSValuePtr JSImmediate::from(int i)
480 {
481 #if !USE(ALTERNATE_JSIMMEDIATE)
482 if ((i < minImmediateInt) | (i > maxImmediateInt))
483 return fromNumberOutsideIntegerRange(i);
484 #endif
485 return makeInt(i);
486 }
487
488 ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i)
489 {
490 if (i > maxImmediateUInt)
491 return fromNumberOutsideIntegerRange(i);
492 return makeInt(i);
493 }
494
495 ALWAYS_INLINE JSValuePtr JSImmediate::from(long i)
496 {
497 if ((i < minImmediateInt) | (i > maxImmediateInt))
498 return fromNumberOutsideIntegerRange(i);
499 return makeInt(i);
500 }
501
502 ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i)
503 {
504 if (i > maxImmediateUInt)
505 return fromNumberOutsideIntegerRange(i);
506 return makeInt(i);
507 }
508
509 ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i)
510 {
511 if ((i < minImmediateInt) | (i > maxImmediateInt))
512 return noValue();
513 return makeInt(static_cast<intptr_t>(i));
514 }
515
516 ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i)
517 {
518 if (i > maxImmediateUInt)
519 return fromNumberOutsideIntegerRange(i);
520 return makeInt(static_cast<intptr_t>(i));
521 }
522
523 ALWAYS_INLINE JSValuePtr JSImmediate::from(double d)
524 {
525 const int intVal = static_cast<int>(d);
526
527 // Check for data loss from conversion to int.
528 if (intVal != d || (!intVal && signbit(d)))
529 return fromNumberOutsideIntegerRange(d);
530
531 return from(intVal);
532 }
533
534 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v)
535 {
536 ASSERT(isIntegerNumber(v));
537 return intValue(v);
538 }
539
540 ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v)
541 {
542 ASSERT(isImmediate(v));
543
544 if (isIntegerNumber(v))
545 return intValue(v);
546
547 #if USE(ALTERNATE_JSIMMEDIATE)
548 if (isNumber(v)) {
549 ASSERT(isDoubleNumber(v));
550 return doubleValue(v);
551 }
552 #else
553 ASSERT(!isNumber(v));
554 #endif
555
556 if (rawValue(v) == FullTagTypeUndefined)
557 return nonInlineNaN();
558
559 ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
560 return rawValue(v) >> ExtendedPayloadShift;
561 }
562
563 ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i)
564 {
565 i = uintValue(v);
566 return isPositiveIntegerNumber(v);
567 }
568
569 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i)
570 {
571 i = intValue(v);
572 return isIntegerNumber(v);
573 }
574
575 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i)
576 {
577 return getUInt32(v, i);
578 }
579
580 inline JSValuePtr js0()
581 {
582 return JSImmediate::zeroImmediate();
583 }
584
585 inline JSValuePtr jsNull()
586 {
587 return JSImmediate::nullImmediate();
588 }
589
590 inline JSValuePtr jsBoolean(bool b)
591 {
592 return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
593 }
594
595 inline JSValuePtr jsUndefined()
596 {
597 return JSImmediate::undefinedImmediate();
598 }
599
600 inline JSValuePtr jsImpossibleValue()
601 {
602 return JSImmediate::impossibleValue();
603 }
604
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);
610
611 inline bool JSValuePtr::isUndefined() const
612 {
613 return asValue() == jsUndefined();
614 }
615
616 inline bool JSValuePtr::isNull() const
617 {
618 return asValue() == jsNull();
619 }
620
621 inline bool JSValuePtr::isUndefinedOrNull() const
622 {
623 return JSImmediate::isUndefinedOrNull(asValue());
624 }
625
626 inline bool JSValuePtr::isBoolean() const
627 {
628 return JSImmediate::isBoolean(asValue());
629 }
630
631 inline bool JSValuePtr::getBoolean(bool& v) const
632 {
633 if (JSImmediate::isBoolean(asValue())) {
634 v = JSImmediate::toBoolean(asValue());
635 return true;
636 }
637
638 return false;
639 }
640
641 inline bool JSValuePtr::getBoolean() const
642 {
643 return asValue() == jsBoolean(true);
644 }
645
646 ALWAYS_INLINE int32_t JSValuePtr::toInt32(ExecState* exec) const
647 {
648 int32_t i;
649 if (getTruncatedInt32(i))
650 return i;
651 bool ignored;
652 return toInt32SlowCase(toNumber(exec), ignored);
653 }
654
655 inline uint32_t JSValuePtr::toUInt32(ExecState* exec) const
656 {
657 uint32_t i;
658 if (getTruncatedUInt32(i))
659 return i;
660 bool ignored;
661 return toUInt32SlowCase(toNumber(exec), ignored);
662 }
663
664 inline int32_t toInt32(double val)
665 {
666 if (!(val >= -2147483648.0 && val < 2147483648.0)) {
667 bool ignored;
668 return toInt32SlowCase(val, ignored);
669 }
670 return static_cast<int32_t>(val);
671 }
672
673 inline uint32_t toUInt32(double val)
674 {
675 if (!(val >= 0.0 && val < 4294967296.0)) {
676 bool ignored;
677 return toUInt32SlowCase(val, ignored);
678 }
679 return static_cast<uint32_t>(val);
680 }
681
682 inline int32_t JSValuePtr::toInt32(ExecState* exec, bool& ok) const
683 {
684 int32_t i;
685 if (getTruncatedInt32(i)) {
686 ok = true;
687 return i;
688 }
689 return toInt32SlowCase(toNumber(exec), ok);
690 }
691
692 inline uint32_t JSValuePtr::toUInt32(ExecState* exec, bool& ok) const
693 {
694 uint32_t i;
695 if (getTruncatedUInt32(i)) {
696 ok = true;
697 return i;
698 }
699 return toUInt32SlowCase(toNumber(exec), ok);
700 }
701
702 inline bool JSValuePtr::isCell() const
703 {
704 return !JSImmediate::isImmediate(asValue());
705 }
706
707 inline bool JSValuePtr::isInt32Fast() const
708 {
709 return JSImmediate::isIntegerNumber(asValue());
710 }
711
712 inline int32_t JSValuePtr::getInt32Fast() const
713 {
714 ASSERT(isInt32Fast());
715 return JSImmediate::getTruncatedInt32(asValue());
716 }
717
718 inline bool JSValuePtr::isUInt32Fast() const
719 {
720 return JSImmediate::isPositiveIntegerNumber(asValue());
721 }
722
723 inline uint32_t JSValuePtr::getUInt32Fast() const
724 {
725 ASSERT(isUInt32Fast());
726 return JSImmediate::getTruncatedUInt32(asValue());
727 }
728
729 inline JSValuePtr JSValuePtr::makeInt32Fast(int32_t i)
730 {
731 return JSImmediate::from(i);
732 }
733
734 inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1, JSValuePtr v2)
735 {
736 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
737 }
738
739 class JSFastMath {
740 public:
741 static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValuePtr v1, JSValuePtr v2)
742 {
743 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
744 }
745
746 static ALWAYS_INLINE JSValuePtr equal(JSValuePtr v1, JSValuePtr v2)
747 {
748 ASSERT(canDoFastBitwiseOperations(v1, v2));
749 return jsBoolean(v1 == v2);
750 }
751
752 static ALWAYS_INLINE JSValuePtr notEqual(JSValuePtr v1, JSValuePtr v2)
753 {
754 ASSERT(canDoFastBitwiseOperations(v1, v2));
755 return jsBoolean(v1 != v2);
756 }
757
758 static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
759 {
760 ASSERT(canDoFastBitwiseOperations(v1, v2));
761 return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
762 }
763
764 static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
765 {
766 ASSERT(canDoFastBitwiseOperations(v1, v2));
767 return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
768 }
769
770 static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
771 {
772 ASSERT(canDoFastBitwiseOperations(v1, v2));
773 return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
774 }
775
776 static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2)
777 {
778 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
779 }
780
781 static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2)
782 {
783 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
784 }
785
786 static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift)
787 {
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);
791 #else
792 return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
793 #endif
794 }
795
796 static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v)
797 {
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;
801 }
802
803 static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v1, JSValuePtr v2)
804 {
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);
808 }
809
810 static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
811 {
812 ASSERT(canDoFastAdditiveOperations(v1, v2));
813 return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
814 }
815
816 static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
817 {
818 ASSERT(canDoFastAdditiveOperations(v1, v2));
819 return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
820 }
821
822 static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v)
823 {
824 ASSERT(canDoFastAdditiveOperations(v));
825 return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
826 }
827
828 static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v)
829 {
830 ASSERT(canDoFastAdditiveOperations(v));
831 return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
832 }
833 };
834
835 } // namespace JSC
836
837 #endif // JSImmediate_h