Reduce the verbosity of referring to QNaN in JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSValueInlineMethods.h
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef JSValueInlineMethods_h
27 #define JSValueInlineMethods_h
28
29 #include "JSValue.h"
30
31 namespace JSC {
32
33     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
34     {
35         if (isInt32())
36             return asInt32();
37         return JSC::toInt32(toNumber(exec));
38     }
39
40     inline uint32_t JSValue::toUInt32(ExecState* exec) const
41     {
42         // See comment on JSC::toUInt32, above.
43         return toInt32(exec);
44     }
45
46     inline bool JSValue::isUInt32() const
47     {
48         return isInt32() && asInt32() >= 0;
49     }
50
51     inline uint32_t JSValue::asUInt32() const
52     {
53         ASSERT(isUInt32());
54         return asInt32();
55     }
56
57     inline double JSValue::asNumber() const
58     {
59         ASSERT(isNumber());
60         return isInt32() ? asInt32() : asDouble();
61     }
62
63     inline JSValue jsNaN()
64     {
65         return JSValue(QNaN);
66     }
67
68     inline JSValue::JSValue(char i)
69     {
70         *this = JSValue(static_cast<int32_t>(i));
71     }
72
73     inline JSValue::JSValue(unsigned char i)
74     {
75         *this = JSValue(static_cast<int32_t>(i));
76     }
77
78     inline JSValue::JSValue(short i)
79     {
80         *this = JSValue(static_cast<int32_t>(i));
81     }
82
83     inline JSValue::JSValue(unsigned short i)
84     {
85         *this = JSValue(static_cast<int32_t>(i));
86     }
87
88     inline JSValue::JSValue(unsigned i)
89     {
90         if (static_cast<int32_t>(i) < 0) {
91             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
92             return;
93         }
94         *this = JSValue(static_cast<int32_t>(i));
95     }
96
97     inline JSValue::JSValue(long i)
98     {
99         if (static_cast<int32_t>(i) != i) {
100             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
101             return;
102         }
103         *this = JSValue(static_cast<int32_t>(i));
104     }
105
106     inline JSValue::JSValue(unsigned long i)
107     {
108         if (static_cast<uint32_t>(i) != i) {
109             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
110             return;
111         }
112         *this = JSValue(static_cast<uint32_t>(i));
113     }
114
115     inline JSValue::JSValue(long long i)
116     {
117         if (static_cast<int32_t>(i) != i) {
118             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
119             return;
120         }
121         *this = JSValue(static_cast<int32_t>(i));
122     }
123
124     inline JSValue::JSValue(unsigned long long i)
125     {
126         if (static_cast<uint32_t>(i) != i) {
127             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
128             return;
129         }
130         *this = JSValue(static_cast<uint32_t>(i));
131     }
132
133     inline JSValue::JSValue(double d)
134     {
135         const int32_t asInt32 = static_cast<int32_t>(d);
136         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
137             *this = JSValue(EncodeAsDouble, d);
138             return;
139         }
140         *this = JSValue(static_cast<int32_t>(d));
141     }
142
143     inline EncodedJSValue JSValue::encode(JSValue value)
144     {
145         return value.u.asInt64;
146     }
147
148     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
149     {
150         JSValue v;
151         v.u.asInt64 = encodedJSValue;
152         return v;
153     }
154
155 #if USE(JSVALUE32_64)
156     inline JSValue::JSValue()
157     {
158         u.asBits.tag = EmptyValueTag;
159         u.asBits.payload = 0;
160     }
161
162     inline JSValue::JSValue(JSNullTag)
163     {
164         u.asBits.tag = NullTag;
165         u.asBits.payload = 0;
166     }
167     
168     inline JSValue::JSValue(JSUndefinedTag)
169     {
170         u.asBits.tag = UndefinedTag;
171         u.asBits.payload = 0;
172     }
173     
174     inline JSValue::JSValue(JSTrueTag)
175     {
176         u.asBits.tag = BooleanTag;
177         u.asBits.payload = 1;
178     }
179     
180     inline JSValue::JSValue(JSFalseTag)
181     {
182         u.asBits.tag = BooleanTag;
183         u.asBits.payload = 0;
184     }
185
186     inline JSValue::JSValue(HashTableDeletedValueTag)
187     {
188         u.asBits.tag = DeletedValueTag;
189         u.asBits.payload = 0;
190     }
191
192     inline JSValue::JSValue(JSCell* ptr)
193     {
194         if (ptr)
195             u.asBits.tag = CellTag;
196         else
197             u.asBits.tag = EmptyValueTag;
198         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
199     }
200
201     inline JSValue::JSValue(const JSCell* ptr)
202     {
203         if (ptr)
204             u.asBits.tag = CellTag;
205         else
206             u.asBits.tag = EmptyValueTag;
207         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
208     }
209
210     inline JSValue::operator bool() const
211     {
212         ASSERT(tag() != DeletedValueTag);
213         return tag() != EmptyValueTag;
214     }
215
216     inline bool JSValue::operator==(const JSValue& other) const
217     {
218         return u.asInt64 == other.u.asInt64;
219     }
220
221     inline bool JSValue::operator!=(const JSValue& other) const
222     {
223         return u.asInt64 != other.u.asInt64;
224     }
225
226     inline bool JSValue::isEmpty() const
227     {
228         return tag() == EmptyValueTag;
229     }
230
231     inline bool JSValue::isUndefined() const
232     {
233         return tag() == UndefinedTag;
234     }
235
236     inline bool JSValue::isNull() const
237     {
238         return tag() == NullTag;
239     }
240
241     inline bool JSValue::isUndefinedOrNull() const
242     {
243         return isUndefined() || isNull();
244     }
245
246     inline bool JSValue::isCell() const
247     {
248         return tag() == CellTag;
249     }
250
251     inline bool JSValue::isInt32() const
252     {
253         return tag() == Int32Tag;
254     }
255
256     inline bool JSValue::isDouble() const
257     {
258         return tag() < LowestTag;
259     }
260
261     inline bool JSValue::isTrue() const
262     {
263         return tag() == BooleanTag && payload();
264     }
265
266     inline bool JSValue::isFalse() const
267     {
268         return tag() == BooleanTag && !payload();
269     }
270
271     inline uint32_t JSValue::tag() const
272     {
273         return u.asBits.tag;
274     }
275     
276     inline int32_t JSValue::payload() const
277     {
278         return u.asBits.payload;
279     }
280     
281     inline int32_t JSValue::asInt32() const
282     {
283         ASSERT(isInt32());
284         return u.asBits.payload;
285     }
286     
287     inline double JSValue::asDouble() const
288     {
289         ASSERT(isDouble());
290         return u.asDouble;
291     }
292     
293     ALWAYS_INLINE JSCell* JSValue::asCell() const
294     {
295         ASSERT(isCell());
296         return reinterpret_cast<JSCell*>(u.asBits.payload);
297     }
298
299     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
300     {
301         u.asDouble = d;
302     }
303
304     inline JSValue::JSValue(int i)
305     {
306         u.asBits.tag = Int32Tag;
307         u.asBits.payload = i;
308     }
309
310 #if ENABLE(LLINT_C_LOOP)
311     inline JSValue::JSValue(int32_t tag, int32_t payload)
312     {
313         u.asBits.tag = tag;
314         u.asBits.payload = payload;
315     }
316 #endif
317
318     inline bool JSValue::isNumber() const
319     {
320         return isInt32() || isDouble();
321     }
322
323     inline bool JSValue::isBoolean() const
324     {
325         return isTrue() || isFalse();
326     }
327
328     inline bool JSValue::asBoolean() const
329     {
330         ASSERT(isBoolean());
331         return payload();
332     }
333
334 #else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
335
336     // 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.
337     inline JSValue::JSValue()
338     {
339         u.asInt64 = ValueEmpty;
340     }
341
342     // 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.
343     inline JSValue::JSValue(HashTableDeletedValueTag)
344     {
345         u.asInt64 = ValueDeleted;
346     }
347
348     inline JSValue::JSValue(JSCell* ptr)
349     {
350         u.asInt64 = reinterpret_cast<uintptr_t>(ptr);
351     }
352
353     inline JSValue::JSValue(const JSCell* ptr)
354     {
355         u.asInt64 = reinterpret_cast<uintptr_t>(const_cast<JSCell*>(ptr));
356     }
357
358     inline JSValue::operator bool() const
359     {
360         return u.asInt64;
361     }
362
363     inline bool JSValue::operator==(const JSValue& other) const
364     {
365         return u.asInt64 == other.u.asInt64;
366     }
367
368     inline bool JSValue::operator!=(const JSValue& other) const
369     {
370         return u.asInt64 != other.u.asInt64;
371     }
372
373     inline bool JSValue::isEmpty() const
374     {
375         return u.asInt64 == ValueEmpty;
376     }
377
378     inline bool JSValue::isUndefined() const
379     {
380         return asValue() == JSValue(JSUndefined);
381     }
382
383     inline bool JSValue::isNull() const
384     {
385         return asValue() == JSValue(JSNull);
386     }
387
388     inline bool JSValue::isTrue() const
389     {
390         return asValue() == JSValue(JSTrue);
391     }
392
393     inline bool JSValue::isFalse() const
394     {
395         return asValue() == JSValue(JSFalse);
396     }
397
398     inline bool JSValue::asBoolean() const
399     {
400         ASSERT(isBoolean());
401         return asValue() == JSValue(JSTrue);
402     }
403
404     inline int32_t JSValue::asInt32() const
405     {
406         ASSERT(isInt32());
407         return static_cast<int32_t>(u.asInt64);
408     }
409
410     inline bool JSValue::isDouble() const
411     {
412         return isNumber() && !isInt32();
413     }
414
415     inline JSValue::JSValue(JSNullTag)
416     {
417         u.asInt64 = ValueNull;
418     }
419     
420     inline JSValue::JSValue(JSUndefinedTag)
421     {
422         u.asInt64 = ValueUndefined;
423     }
424
425     inline JSValue::JSValue(JSTrueTag)
426     {
427         u.asInt64 = ValueTrue;
428     }
429
430     inline JSValue::JSValue(JSFalseTag)
431     {
432         u.asInt64 = ValueFalse;
433     }
434
435     inline bool JSValue::isUndefinedOrNull() const
436     {
437         // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
438         return (u.asInt64 & ~TagBitUndefined) == ValueNull;
439     }
440
441     inline bool JSValue::isBoolean() const
442     {
443         return (u.asInt64 & ~1) == ValueFalse;
444     }
445
446     inline bool JSValue::isCell() const
447     {
448         return !(u.asInt64 & TagMask);
449     }
450
451     inline bool JSValue::isInt32() const
452     {
453         return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
454     }
455
456     inline int64_t reinterpretDoubleToInt64(double value)
457     {
458         return bitwise_cast<int64_t>(value);
459     }
460     inline double reinterpretInt64ToDouble(int64_t value)
461     {
462         return bitwise_cast<double>(value);
463     }
464
465     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
466     {
467         u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
468     }
469
470     inline JSValue::JSValue(int i)
471     {
472         u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
473     }
474
475     inline double JSValue::asDouble() const
476     {
477         ASSERT(isDouble());
478         return reinterpretInt64ToDouble(u.asInt64 - DoubleEncodeOffset);
479     }
480
481     inline bool JSValue::isNumber() const
482     {
483         return u.asInt64 & TagTypeNumber;
484     }
485
486     ALWAYS_INLINE JSCell* JSValue::asCell() const
487     {
488         ASSERT(isCell());
489         return u.ptr;
490     }
491
492 #endif // USE(JSVALUE64)
493
494 } // namespace JSC
495
496 #endif // JSValueInlineMethods_h