05aea6ff6a5c4fae117ab7f6c315abf020d7fec2
[WebKit-https.git] / JavaScriptCore / 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 "JSValue.h"
29 #include <limits>
30 #include <limits.h>
31 #include <stdarg.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34
35 namespace JSC {
36
37     class ExecState;
38     class JSCell;
39     class JSFastMath;
40     class JSGlobalData;
41     class JSObject;
42     class UString;
43
44     JSValuePtr js0();
45     JSValuePtr jsNull();
46     JSValuePtr jsBoolean(bool b);
47     JSValuePtr jsUndefined();
48     JSValuePtr jsImpossibleValue();
49     JSValuePtr jsNumber(ExecState* exec, double d);
50     JSValuePtr jsNumber(ExecState*, char i);
51     JSValuePtr jsNumber(ExecState*, unsigned char i);
52     JSValuePtr jsNumber(ExecState*, short i);
53     JSValuePtr jsNumber(ExecState*, unsigned short i);
54     JSValuePtr jsNumber(ExecState* exec, int i);
55     JSValuePtr jsNumber(ExecState* exec, unsigned i);
56     JSValuePtr jsNumber(ExecState* exec, long i);
57     JSValuePtr jsNumber(ExecState* exec, unsigned long i);
58     JSValuePtr jsNumber(ExecState* exec, long long i);
59     JSValuePtr jsNumber(ExecState* exec, unsigned long long i);
60     JSValuePtr jsNumber(JSGlobalData* globalData, double d);
61     JSValuePtr jsNumber(JSGlobalData* globalData, short i);
62     JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i);
63     JSValuePtr jsNumber(JSGlobalData* globalData, int i);
64     JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i);
65     JSValuePtr jsNumber(JSGlobalData* globalData, long i);
66     JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i);
67     JSValuePtr jsNumber(JSGlobalData* globalData, long long i);
68     JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i);
69
70     /*
71      * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 
72      * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
73      * because allocator alignment guarantees they will be 00 in cell pointers.
74      *
75      * For example, on a 32 bit system:
76      *
77      * JSCell*:             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     00
78      *                      [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
79      * JSImmediate:         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     TT
80      *                      [ high 30 bits: 'payload' ]             [ low 2 bits -- tag ]
81      *
82      * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
83      * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
84      * tag used to indicate the exact type.
85      *
86      * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
87      * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
88      * two bits will form an extended tag.
89      *
90      * 31 bit signed int:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     X1
91      *                      [ high 30 bits of the value ]      [ high bit part of value ]
92      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      ZZ               10
93      *                      [ extended 'payload' ]  [  extended tag  ]  [  tag 'other'  ]
94      *
95      * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
96      * bit would flag the value as undefined.  If neither bits are set, the value is null.
97      *
98      * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      UB               10
99      *                      [ extended 'payload' ]  [ undefined | bool ]  [ tag 'other' ]
100      *
101      * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
102      * For undefined or null immediates the payload is zero.
103      *
104      * Boolean:             000000000000000000000000000V      01               10
105      *                      [ boolean value ]              [ bool ]       [ tag 'other' ]
106      * Undefined:           0000000000000000000000000000      10               10
107      *                      [ zero ]                    [ undefined ]     [ tag 'other' ]
108      * Null:                0000000000000000000000000000      00               10
109      *                      [ zero ]                       [ zero ]       [ tag 'other' ]
110      */
111
112     /*
113      * On 64-bit platforms, we support an alternative encoding form for immediates, if
114      * USE(ALTERNATE_JSIMMEDIATE) is defined.
115      *
116      * The top 16-bits denote the type:
117      *
118      * Pointer: 0000:PPPP:PPPP:PPPP
119      * Integer: FFFF:0000:IIII:IIII
120      *
121      * 32-bit signed integers are marked with the 16-bit tag '0xFFFF'.  The tag '0x0000'
122      * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
123      * values are encoded in the same manner as the default format.
124      */
125
126     class JSImmediate {
127     private:
128         friend class JIT;
129         friend class JSValuePtr;
130         friend class JSFastMath;
131         friend JSValuePtr js0();
132         friend JSValuePtr jsNull();
133         friend JSValuePtr jsBoolean(bool b);
134         friend JSValuePtr jsUndefined();
135         friend JSValuePtr jsImpossibleValue();
136         friend JSValuePtr jsNumber(ExecState* exec, double d);
137         friend JSValuePtr jsNumber(ExecState*, char i);
138         friend JSValuePtr jsNumber(ExecState*, unsigned char i);
139         friend JSValuePtr jsNumber(ExecState*, short i);
140         friend JSValuePtr jsNumber(ExecState*, unsigned short i);
141         friend JSValuePtr jsNumber(ExecState* exec, int i);
142         friend JSValuePtr jsNumber(ExecState* exec, unsigned i);
143         friend JSValuePtr jsNumber(ExecState* exec, long i);
144         friend JSValuePtr jsNumber(ExecState* exec, unsigned long i);
145         friend JSValuePtr jsNumber(ExecState* exec, long long i);
146         friend JSValuePtr jsNumber(ExecState* exec, unsigned long long i);
147         friend JSValuePtr jsNumber(JSGlobalData* globalData, double d);
148         friend JSValuePtr jsNumber(JSGlobalData* globalData, short i);
149         friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i);
150         friend JSValuePtr jsNumber(JSGlobalData* globalData, int i);
151         friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i);
152         friend JSValuePtr jsNumber(JSGlobalData* globalData, long i);
153         friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i);
154         friend JSValuePtr jsNumber(JSGlobalData* globalData, long long i);
155         friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i);
156
157 #if USE(ALTERNATE_JSIMMEDIATE)
158         static const intptr_t TagTypeInteger = 0xffff000000000000ll; // bottom bit set indicates integer, this dominates the following bit
159 #else
160         static const intptr_t TagTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit
161 #endif
162         static const intptr_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
163         static const intptr_t TagMask           = TagTypeInteger | TagBitTypeOther;
164
165         static const intptr_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
166         static const intptr_t ExtendedTagBitBool      = 0x4;
167         static const intptr_t ExtendedTagBitUndefined = 0x8;
168
169         static const intptr_t FullTagTypeMask      = TagMask | ExtendedTagMask;
170         static const intptr_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
171         static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
172         static const intptr_t FullTagTypeNull      = TagBitTypeOther;
173
174 #if USE(ALTERNATE_JSIMMEDIATE)
175         static const int32_t IntegerPayloadShift  = 0;
176 #else
177         static const int32_t IntegerPayloadShift  = 1;
178 #endif
179         static const int32_t ExtendedPayloadShift = 4;
180
181         static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
182
183         static const int32_t signBit = 0x80000000;
184  
185         static ALWAYS_INLINE bool isImmediate(JSValuePtr v)
186         {
187             return rawValue(v) & TagMask;
188         }
189         
190         static ALWAYS_INLINE bool isNumber(JSValuePtr v)
191         {
192             return rawValue(v) & TagTypeInteger;
193         }
194
195         static ALWAYS_INLINE bool isPositiveNumber(JSValuePtr v)
196         {
197             // A single mask to check for the sign bit and the number tag all at once.
198             return (rawValue(v) & (signBit | TagTypeInteger)) == TagTypeInteger;
199         }
200         
201         static ALWAYS_INLINE bool isBoolean(JSValuePtr v)
202         {
203             return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
204         }
205         
206         static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v)
207         {
208             // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
209             return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
210         }
211
212         static bool isNegative(JSValuePtr v)
213         {
214             ASSERT(isNumber(v));
215             return rawValue(v) & signBit;
216         }
217
218         static JSValuePtr from(char);
219         static JSValuePtr from(signed char);
220         static JSValuePtr from(unsigned char);
221         static JSValuePtr from(short);
222         static JSValuePtr from(unsigned short);
223         static JSValuePtr from(int);
224         static JSValuePtr from(unsigned);
225         static JSValuePtr from(long);
226         static JSValuePtr from(unsigned long);
227         static JSValuePtr from(long long);
228         static JSValuePtr from(unsigned long long);
229         static JSValuePtr from(double);
230
231         static ALWAYS_INLINE bool isEitherImmediate(JSValuePtr v1, JSValuePtr v2)
232         {
233             return (rawValue(v1) | rawValue(v2)) & TagMask;
234         }
235
236         static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2)
237         {
238             return isImmediate(v1) & isImmediate(v2);
239         }
240
241         static ALWAYS_INLINE bool areBothImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
242         {
243             return rawValue(v1) & rawValue(v2) & TagTypeInteger;
244         }
245
246         static double toDouble(JSValuePtr);
247         static bool toBoolean(JSValuePtr);
248         static JSObject* toObject(JSValuePtr, ExecState*);
249         static JSObject* toThisObject(JSValuePtr, ExecState*);
250         static UString toString(JSValuePtr);
251
252         static bool getUInt32(JSValuePtr, uint32_t&);
253         static bool getTruncatedInt32(JSValuePtr, int32_t&);
254         static bool getTruncatedUInt32(JSValuePtr, uint32_t&);
255
256         static int32_t getTruncatedInt32(JSValuePtr);
257         static uint32_t getTruncatedUInt32(JSValuePtr);
258
259         static JSValuePtr trueImmediate();
260         static JSValuePtr falseImmediate();
261         static JSValuePtr undefinedImmediate();
262         static JSValuePtr nullImmediate();
263         static JSValuePtr zeroImmediate();
264         static JSValuePtr oneImmediate();
265
266         static JSValuePtr impossibleValue();
267         
268         static JSObject* prototype(JSValuePtr, ExecState*);
269
270     private:
271 #if USE(ALTERNATE_JSIMMEDIATE)
272         static const int minImmediateInt = ((-INT_MAX) - 1);
273         static const int maxImmediateInt = INT_MAX;
274 #else
275         static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
276         static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
277 #endif
278         static const unsigned maxImmediateUInt = maxImmediateInt;
279
280         static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer)
281         {
282             return JSValuePtr::makeImmediate(integer);
283         }
284
285 #if USE(ALTERNATE_JSIMMEDIATE)
286         static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value)
287 #else
288         static ALWAYS_INLINE JSValuePtr makeInt(int32_t value)
289 #endif
290         {
291             return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeInteger);
292         }
293         
294         static ALWAYS_INLINE JSValuePtr makeBool(bool b)
295         {
296             return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
297         }
298         
299         static ALWAYS_INLINE JSValuePtr makeUndefined()
300         {
301             return makeValue(FullTagTypeUndefined);
302         }
303         
304         static ALWAYS_INLINE JSValuePtr makeNull()
305         {
306             return makeValue(FullTagTypeNull);
307         }
308         
309         static ALWAYS_INLINE int32_t intValue(JSValuePtr v)
310         {
311             return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
312         }
313         
314         static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v)
315         {
316             return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
317         }
318         
319         static ALWAYS_INLINE bool boolValue(JSValuePtr v)
320         {
321             return rawValue(v) & ExtendedPayloadBitBoolValue;
322         }
323         
324         static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v)
325         {
326             return v.immediateValue();
327         }
328
329         static double nonInlineNaN();
330     };
331
332     ALWAYS_INLINE JSValuePtr JSImmediate::trueImmediate() { return makeBool(true); }
333     ALWAYS_INLINE JSValuePtr JSImmediate::falseImmediate() { return makeBool(false); }
334     ALWAYS_INLINE JSValuePtr JSImmediate::undefinedImmediate() { return makeUndefined(); }
335     ALWAYS_INLINE JSValuePtr JSImmediate::nullImmediate() { return makeNull(); }
336     ALWAYS_INLINE JSValuePtr JSImmediate::zeroImmediate() { return makeInt(0); }
337     ALWAYS_INLINE JSValuePtr JSImmediate::oneImmediate() { return makeInt(1); }
338
339     // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
340     ALWAYS_INLINE JSValuePtr JSImmediate::impossibleValue() { return makeValue(0x4); }
341
342     ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
343     {
344         ASSERT(isImmediate(v));
345         intptr_t bits = rawValue(v);
346         return (bits & TagTypeInteger)
347             ? bits != TagTypeInteger // !0 ints
348             : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
349     }
350
351     ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v)
352     {
353         ASSERT(isNumber(v));
354         return intValue(v);
355     }
356
357     ALWAYS_INLINE JSValuePtr JSImmediate::from(char i)
358     {
359         return makeInt(i);
360     }
361
362     ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i)
363     {
364         return makeInt(i);
365     }
366
367     ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i)
368     {
369         return makeInt(i);
370     }
371
372     ALWAYS_INLINE JSValuePtr JSImmediate::from(short i)
373     {
374         return makeInt(i);
375     }
376
377     ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i)
378     {
379         return makeInt(i);
380     }
381
382     ALWAYS_INLINE JSValuePtr JSImmediate::from(int i)
383     {
384         if ((i < minImmediateInt) | (i > maxImmediateInt))
385             return noValue();
386         return makeInt(i);
387     }
388
389     ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i)
390     {
391         if (i > maxImmediateUInt)
392             return noValue();
393         return makeInt(i);
394     }
395
396     ALWAYS_INLINE JSValuePtr JSImmediate::from(long i)
397     {
398         if ((i < minImmediateInt) | (i > maxImmediateInt))
399             return noValue();
400         return makeInt(i);
401     }
402
403     ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i)
404     {
405         if (i > maxImmediateUInt)
406             return noValue();
407         return makeInt(i);
408     }
409
410     ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i)
411     {
412         if ((i < minImmediateInt) | (i > maxImmediateInt))
413             return noValue();
414         return makeInt(static_cast<intptr_t>(i));
415     }
416
417     ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i)
418     {
419         if (i > maxImmediateUInt)
420             return noValue();
421         return makeInt(static_cast<intptr_t>(i));
422     }
423
424     ALWAYS_INLINE JSValuePtr JSImmediate::from(double d)
425     {
426         const int intVal = static_cast<int>(d);
427
428         if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
429             return noValue();
430
431         // Check for data loss from conversion to int.
432         if (intVal != d || (!intVal && signbit(d)))
433             return noValue();
434
435         return makeInt(intVal);
436     }
437
438     ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v)
439     {
440         ASSERT(isNumber(v));
441         return intValue(v);
442     }
443
444     ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v)
445     {
446         ASSERT(isImmediate(v));
447         int i;
448         if (isNumber(v))
449             i = intValue(v);
450         else if (rawValue(v) == FullTagTypeUndefined)
451             return nonInlineNaN();
452         else
453             i = rawValue(v) >> ExtendedPayloadShift;
454         return i;
455     }
456
457     ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i)
458     {
459         i = uintValue(v);
460         return isPositiveNumber(v);
461     }
462
463     ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i)
464     {
465         i = intValue(v);
466         return isNumber(v);
467     }
468
469     ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i)
470     {
471         return getUInt32(v, i);
472     }
473
474     inline JSValuePtr js0()
475     {
476         return JSImmediate::zeroImmediate();
477     }
478
479     inline JSValuePtr jsNull()
480     {
481         return JSImmediate::nullImmediate();
482     }
483
484     inline JSValuePtr jsBoolean(bool b)
485     {
486         return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
487     }
488
489     inline JSValuePtr jsUndefined()
490     {
491         return JSImmediate::undefinedImmediate();
492     }
493
494     inline JSValuePtr jsImpossibleValue()
495     {
496         return JSImmediate::impossibleValue();
497     }
498
499     // These are identical logic to the JSValue functions above, and faster than jsNumber(number)->toInt32().
500     int32_t toInt32(double);
501     uint32_t toUInt32(double);
502     int32_t toInt32SlowCase(double, bool& ok);
503     uint32_t toUInt32SlowCase(double, bool& ok);
504
505     inline bool JSValuePtr::isUndefined() const
506     {
507         return asValue() == jsUndefined();
508     }
509
510     inline bool JSValuePtr::isNull() const
511     {
512         return asValue() == jsNull();
513     }
514
515     inline bool JSValuePtr::isUndefinedOrNull() const
516     {
517         return JSImmediate::isUndefinedOrNull(asValue());
518     }
519
520     inline bool JSValuePtr::isBoolean() const
521     {
522         return JSImmediate::isBoolean(asValue());
523     }
524
525     inline bool JSValuePtr::getBoolean(bool& v) const
526     {
527         if (JSImmediate::isBoolean(asValue())) {
528             v = JSImmediate::toBoolean(asValue());
529             return true;
530         }
531         
532         return false;
533     }
534
535     inline bool JSValuePtr::getBoolean() const
536     {
537         return asValue() == jsBoolean(true);
538     }
539
540     ALWAYS_INLINE int32_t JSValuePtr::toInt32(ExecState* exec) const
541     {
542         int32_t i;
543         if (getTruncatedInt32(i))
544             return i;
545         bool ignored;
546         return toInt32SlowCase(toNumber(exec), ignored);
547     }
548
549     inline uint32_t JSValuePtr::toUInt32(ExecState* exec) const
550     {
551         uint32_t i;
552         if (getTruncatedUInt32(i))
553             return i;
554         bool ignored;
555         return toUInt32SlowCase(toNumber(exec), ignored);
556     }
557
558     inline int32_t toInt32(double val)
559     {
560         if (!(val >= -2147483648.0 && val < 2147483648.0)) {
561             bool ignored;
562             return toInt32SlowCase(val, ignored);
563         }
564         return static_cast<int32_t>(val);
565     }
566
567     inline uint32_t toUInt32(double val)
568     {
569         if (!(val >= 0.0 && val < 4294967296.0)) {
570             bool ignored;
571             return toUInt32SlowCase(val, ignored);
572         }
573         return static_cast<uint32_t>(val);
574     }
575
576     inline int32_t JSValuePtr::toInt32(ExecState* exec, bool& ok) const
577     {
578         int32_t i;
579         if (getTruncatedInt32(i)) {
580             ok = true;
581             return i;
582         }
583         return toInt32SlowCase(toNumber(exec), ok);
584     }
585
586     inline uint32_t JSValuePtr::toUInt32(ExecState* exec, bool& ok) const
587     {
588         uint32_t i;
589         if (getTruncatedUInt32(i)) {
590             ok = true;
591             return i;
592         }
593         return toUInt32SlowCase(toNumber(exec), ok);
594     }
595
596     inline bool JSValuePtr::isCell() const
597     {
598         return !JSImmediate::isImmediate(asValue());
599     }
600
601     inline bool JSValuePtr::isInt32Fast() const
602     {
603         return JSImmediate::isNumber(asValue());
604     }
605
606     inline int32_t JSValuePtr::getInt32Fast() const
607     {
608         ASSERT(isInt32Fast());
609         return JSImmediate::getTruncatedInt32(asValue());
610     }
611
612     inline bool JSValuePtr::isUInt32Fast() const
613     {
614         return JSImmediate::isPositiveNumber(asValue());
615     }
616
617     inline uint32_t JSValuePtr::getUInt32Fast() const
618     {
619         ASSERT(isUInt32Fast());
620         return JSImmediate::getTruncatedUInt32(asValue());
621     }
622
623     inline JSValuePtr JSValuePtr::makeInt32Fast(int32_t i)
624     {
625         return JSImmediate::from(i);
626     }
627
628     inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1, JSValuePtr v2)
629     {
630         return JSImmediate::areBothImmediateNumbers(v1, v2);
631     }
632
633     class JSFastMath {
634     public:
635         static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValuePtr v1, JSValuePtr v2)
636         {
637             return JSImmediate::areBothImmediateNumbers(v1, v2);
638         }
639
640         static ALWAYS_INLINE JSValuePtr equal(JSValuePtr v1, JSValuePtr v2)
641         {
642             ASSERT(canDoFastBitwiseOperations(v1, v2));
643             return jsBoolean(v1 == v2);
644         }
645
646         static ALWAYS_INLINE JSValuePtr notEqual(JSValuePtr v1, JSValuePtr v2)
647         {
648             ASSERT(canDoFastBitwiseOperations(v1, v2));
649             return jsBoolean(v1 != v2);
650         }
651
652         static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
653         {
654             ASSERT(canDoFastBitwiseOperations(v1, v2));
655             return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
656         }
657
658         static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
659         {
660             ASSERT(canDoFastBitwiseOperations(v1, v2));
661             return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeInteger);
662         }
663
664         static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
665         {
666             ASSERT(canDoFastBitwiseOperations(v1, v2));
667             return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
668         }
669
670         static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2)
671         {
672             return JSImmediate::areBothImmediateNumbers(v1, v2);
673         }
674
675         static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2)
676         {
677             return JSImmediate::areBothImmediateNumbers(v1, v2) && !JSImmediate::isNegative(v1);
678         }
679
680         static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift)
681         {
682             ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
683 #if USE(ALTERNATE_JSIMMEDIATE)
684             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::TagTypeInteger);
685 #else
686             return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeInteger);
687 #endif
688         }
689
690         static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v)
691         {
692             // Number is non-negative and an operation involving two of these can't overflow.
693             // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
694             return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeInteger + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeInteger;
695         }
696
697         static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v1, JSValuePtr v2)
698         {
699             // Number is non-negative and an operation involving two of these can't overflow.
700             // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
701             return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2);
702         }
703
704         static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
705         {
706             ASSERT(canDoFastAdditiveOperations(v1, v2));
707             return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeInteger);
708         }
709
710         static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
711         {
712             ASSERT(canDoFastAdditiveOperations(v1, v2));
713             return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeInteger);
714         }
715
716         static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v)
717         {
718             ASSERT(canDoFastAdditiveOperations(v));
719             return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
720         }
721
722         static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v)
723         {
724             ASSERT(canDoFastAdditiveOperations(v));
725             return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
726         }
727     };
728
729 } // namespace JSC
730
731 #endif // JSImmediate_h