1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef JSValue_h
24 #define JSValue_h
25 
26 #include "CallData.h"
27 #include "ConstructData.h"
28 #include <stddef.h> // for size_t
29 #include <stdint.h>
30 #include <wtf/AlwaysInline.h>
31 #include <wtf/Assertions.h>
32 #include <wtf/HashTraits.h>
33 #include <wtf/MathExtras.h>
34 
35 namespace JSC {
36 
37     class Identifier;
38     class JSCell;
39     class JSGlobalData;
40     class JSImmediate;
41     class JSObject;
42     class JSString;
43     class PropertySlot;
44     class PutPropertySlot;
45     class UString;
46 
47     struct ClassInfo;
48     struct Instruction;
49 
50     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
51 
52 #if USE(JSVALUE32_64)
53     typedef int64_t EncodedJSValue;
54 #else
55     typedef void* EncodedJSValue;
56 #endif
57 
58     double nonInlineNaN();
59     int32_t toInt32SlowCase(double, bool& ok);
60     uint32_t toUInt32SlowCase(double, bool& ok);
61 
62     class JSValue {
63         friend class JSImmediate;
64         friend struct EncodedJSValueHashTraits;
65         friend class JIT;
66         friend class JITStubs;
67         friend class JITStubCall;
68 
69     public:
70         static EncodedJSValue encode(JSValue value);
71         static JSValue decode(EncodedJSValue ptr);
72 #if !USE(JSVALUE32_64)
73     private:
74         static JSValue makeImmediate(intptr_t value);
75         intptr_t immediateValue();
76     public:
77 #endif
78         enum JSNullTag { JSNull };
79         enum JSUndefinedTag { JSUndefined };
80         enum JSTrueTag { JSTrue };
81         enum JSFalseTag { JSFalse };
82         enum EncodeAsDoubleTag { EncodeAsDouble };
83 
84         JSValue();
85         JSValue(JSNullTag);
86         JSValue(JSUndefinedTag);
87         JSValue(JSTrueTag);
88         JSValue(JSFalseTag);
89         JSValue(JSCell* ptr);
90         JSValue(const JSCell* ptr);
91 
92         // Numbers
93         JSValue(EncodeAsDoubleTag, ExecState*, double);
94         JSValue(ExecState*, double);
95         JSValue(ExecState*, char);
96         JSValue(ExecState*, unsigned char);
97         JSValue(ExecState*, short);
98         JSValue(ExecState*, unsigned short);
99         JSValue(ExecState*, int);
100         JSValue(ExecState*, unsigned);
101         JSValue(ExecState*, long);
102         JSValue(ExecState*, unsigned long);
103         JSValue(ExecState*, long long);
104         JSValue(ExecState*, unsigned long long);
105         JSValue(JSGlobalData*, double);
106         JSValue(JSGlobalData*, int);
107         JSValue(JSGlobalData*, unsigned);
108 
109         operator bool() const;
110         bool operator==(const JSValue& other) const;
111         bool operator!=(const JSValue& other) const;
112 
113         bool isInt32() const;
114         bool isUInt32() const;
115         bool isDouble() const;
116         bool isTrue() const;
117         bool isFalse() const;
118 
119         int32_t asInt32() const;
120         uint32_t asUInt32() const;
121         double asDouble() const;
122 
123         // Querying the type.
124         bool isUndefined() const;
125         bool isNull() const;
126         bool isUndefinedOrNull() const;
127         bool isBoolean() const;
128         bool isNumber() const;
129         bool isString() const;
130         bool isGetterSetter() const;
131         bool isObject() const;
132         bool inherits(const ClassInfo*) const;
133 
134         // Extracting the value.
135         bool getBoolean(bool&) const;
136         bool getBoolean() const; // false if not a boolean
137         bool getNumber(double&) const;
138         double uncheckedGetNumber() const;
139         bool getString(ExecState* exec, UString&) const;
140         UString getString(ExecState* exec) const; // null string if not a string
141         JSObject* getObject() const; // 0 if not an object
142 
143         CallType getCallData(CallData&);
144         ConstructType getConstructData(ConstructData&);
145 
146         // Extracting integer values.
147         bool getUInt32(uint32_t&) const;
148 
149         // Basic conversions.
150         JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
151         bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
152 
153         bool toBoolean(ExecState*) const;
154 
155         // toNumber conversion is expected to be side effect free if an exception has
156         // been set in the ExecState already.
157         double toNumber(ExecState*) const;
158         JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
159         UString toString(ExecState*) const;
160         UString toPrimitiveString(ExecState*) const;
161         JSObject* toObject(ExecState*) const;
162 
163         // Integer conversions.
164         double toInteger(ExecState*) const;
165         double toIntegerPreserveNaN(ExecState*) const;
166         int32_t toInt32(ExecState*) const;
167         int32_t toInt32(ExecState*, bool& ok) const;
168         uint32_t toUInt32(ExecState*) const;
169         uint32_t toUInt32(ExecState*, bool& ok) const;
170 
171 #if ENABLE(JSC_ZOMBIES)
172         bool isZombie() const;
173 #endif
174 
175         // Floating point conversions (this is a convenience method for webcore;
176         // signle precision float is not a representation used in JS or JSC).
toFloat(ExecState * exec)177         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
178 
179         // Object operations, with the toObject operation included.
180         JSValue get(ExecState*, const Identifier& propertyName) const;
181         JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
182         JSValue get(ExecState*, unsigned propertyName) const;
183         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
184         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
185         void put(ExecState*, unsigned propertyName, JSValue);
186 
187         bool needsThisConversion() const;
188         JSObject* toThisObject(ExecState*) const;
189         UString toThisString(ExecState*) const;
190         JSString* toThisJSString(ExecState*);
191 
192         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
193         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
194         static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
195         static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
196         static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
197         static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
198 
199         JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
200 
201         bool isCell() const;
202         JSCell* asCell() const;
203 
204 #ifndef NDEBUG
205         char* description();
206 #endif
207 
208     private:
209         enum HashTableDeletedValueTag { HashTableDeletedValue };
210         JSValue(HashTableDeletedValueTag);
211 
asValue()212         inline const JSValue asValue() const { return *this; }
213         JSObject* toObjectSlowCase(ExecState*) const;
214         JSObject* toThisObjectSlowCase(ExecState*) const;
215 
216         enum { Int32Tag =        0xffffffff };
217         enum { CellTag =         0xfffffffe };
218         enum { TrueTag =         0xfffffffd };
219         enum { FalseTag =        0xfffffffc };
220         enum { NullTag =         0xfffffffb };
221         enum { UndefinedTag =    0xfffffffa };
222         enum { EmptyValueTag =   0xfffffff9 };
223         enum { DeletedValueTag = 0xfffffff8 };
224 
225         enum { LowestTag =  DeletedValueTag };
226 
227         uint32_t tag() const;
228         int32_t payload() const;
229 
230         JSObject* synthesizePrototype(ExecState*) const;
231         JSObject* synthesizeObject(ExecState*) const;
232 
233 #if USE(JSVALUE32_64)
234         union {
235             EncodedJSValue asEncodedJSValue;
236             double asDouble;
237 #if CPU(BIG_ENDIAN)
238             struct {
239                 int32_t tag;
240                 int32_t payload;
241             } asBits;
242 #else
243             struct {
244                 int32_t payload;
245                 int32_t tag;
246             } asBits;
247 #endif
248         } u;
249 #else // USE(JSVALUE32_64)
250         JSCell* m_ptr;
251 #endif // USE(JSVALUE32_64)
252     };
253 
254 #if USE(JSVALUE32_64)
255     typedef IntHash<EncodedJSValue> EncodedJSValueHash;
256 
257     struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
258         static const bool emptyValueIsZero = false;
emptyValueEncodedJSValueHashTraits259         static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
constructDeletedValueEncodedJSValueHashTraits260         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
isDeletedValueEncodedJSValueHashTraits261         static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
262     };
263 #else
264     typedef PtrHash<EncodedJSValue> EncodedJSValueHash;
265 
266     struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
constructDeletedValueEncodedJSValueHashTraits267         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
isDeletedValueEncodedJSValueHashTraits268         static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
269     };
270 #endif
271 
272     // Stand-alone helper functions.
jsNull()273     inline JSValue jsNull()
274     {
275         return JSValue(JSValue::JSNull);
276     }
277 
jsUndefined()278     inline JSValue jsUndefined()
279     {
280         return JSValue(JSValue::JSUndefined);
281     }
282 
jsBoolean(bool b)283     inline JSValue jsBoolean(bool b)
284     {
285         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
286     }
287 
jsDoubleNumber(ExecState * exec,double d)288     ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d)
289     {
290         return JSValue(JSValue::EncodeAsDouble, exec, d);
291     }
292 
jsNumber(ExecState * exec,double d)293     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
294     {
295         return JSValue(exec, d);
296     }
297 
jsNumber(ExecState * exec,char i)298     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
299     {
300         return JSValue(exec, i);
301     }
302 
jsNumber(ExecState * exec,unsigned char i)303     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
304     {
305         return JSValue(exec, i);
306     }
307 
jsNumber(ExecState * exec,short i)308     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
309     {
310         return JSValue(exec, i);
311     }
312 
jsNumber(ExecState * exec,unsigned short i)313     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
314     {
315         return JSValue(exec, i);
316     }
317 
jsNumber(ExecState * exec,int i)318     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
319     {
320         return JSValue(exec, i);
321     }
322 
jsNumber(ExecState * exec,unsigned i)323     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
324     {
325         return JSValue(exec, i);
326     }
327 
jsNumber(ExecState * exec,long i)328     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
329     {
330         return JSValue(exec, i);
331     }
332 
jsNumber(ExecState * exec,unsigned long i)333     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
334     {
335         return JSValue(exec, i);
336     }
337 
jsNumber(ExecState * exec,long long i)338     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
339     {
340         return JSValue(exec, i);
341     }
342 
jsNumber(ExecState * exec,unsigned long long i)343     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
344     {
345         return JSValue(exec, i);
346     }
347 
jsNumber(JSGlobalData * globalData,double d)348     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
349     {
350         return JSValue(globalData, d);
351     }
352 
jsNumber(JSGlobalData * globalData,int i)353     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
354     {
355         return JSValue(globalData, i);
356     }
357 
jsNumber(JSGlobalData * globalData,unsigned i)358     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
359     {
360         return JSValue(globalData, i);
361     }
362 
363     inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
364     inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
365 
366     inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
367     inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
368 
toInt32(double val)369     inline int32_t toInt32(double val)
370     {
371         if (!(val >= -2147483648.0 && val < 2147483648.0)) {
372             bool ignored;
373             return toInt32SlowCase(val, ignored);
374         }
375         return static_cast<int32_t>(val);
376     }
377 
toUInt32(double val)378     inline uint32_t toUInt32(double val)
379     {
380         if (!(val >= 0.0 && val < 4294967296.0)) {
381             bool ignored;
382             return toUInt32SlowCase(val, ignored);
383         }
384         return static_cast<uint32_t>(val);
385     }
386 
387     // FIXME: We should deprecate this and just use JSValue::asCell() instead.
388     JSCell* asCell(JSValue);
389 
asCell(JSValue value)390     inline JSCell* asCell(JSValue value)
391     {
392         return value.asCell();
393     }
394 
toInt32(ExecState * exec)395     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
396     {
397         if (isInt32())
398             return asInt32();
399         bool ignored;
400         return toInt32SlowCase(toNumber(exec), ignored);
401     }
402 
toUInt32(ExecState * exec)403     inline uint32_t JSValue::toUInt32(ExecState* exec) const
404     {
405         if (isUInt32())
406             return asInt32();
407         bool ignored;
408         return toUInt32SlowCase(toNumber(exec), ignored);
409     }
410 
toInt32(ExecState * exec,bool & ok)411     inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
412     {
413         if (isInt32()) {
414             ok = true;
415             return asInt32();
416         }
417         return toInt32SlowCase(toNumber(exec), ok);
418     }
419 
toUInt32(ExecState * exec,bool & ok)420     inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
421     {
422         if (isUInt32()) {
423             ok = true;
424             return asInt32();
425         }
426         return toUInt32SlowCase(toNumber(exec), ok);
427     }
428 
429 #if USE(JSVALUE32_64)
jsNaN(ExecState * exec)430     inline JSValue jsNaN(ExecState* exec)
431     {
432         return JSValue(exec, nonInlineNaN());
433     }
434 
435     // JSValue member functions.
encode(JSValue value)436     inline EncodedJSValue JSValue::encode(JSValue value)
437     {
438         return value.u.asEncodedJSValue;
439     }
440 
decode(EncodedJSValue encodedJSValue)441     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
442     {
443         JSValue v;
444         v.u.asEncodedJSValue = encodedJSValue;
445 #if ENABLE(JSC_ZOMBIES)
446         ASSERT(!v.isZombie());
447 #endif
448         return v;
449     }
450 
JSValue()451     inline JSValue::JSValue()
452     {
453         u.asBits.tag = EmptyValueTag;
454         u.asBits.payload = 0;
455     }
456 
JSValue(JSNullTag)457     inline JSValue::JSValue(JSNullTag)
458     {
459         u.asBits.tag = NullTag;
460         u.asBits.payload = 0;
461     }
462 
JSValue(JSUndefinedTag)463     inline JSValue::JSValue(JSUndefinedTag)
464     {
465         u.asBits.tag = UndefinedTag;
466         u.asBits.payload = 0;
467     }
468 
JSValue(JSTrueTag)469     inline JSValue::JSValue(JSTrueTag)
470     {
471         u.asBits.tag = TrueTag;
472         u.asBits.payload = 0;
473     }
474 
JSValue(JSFalseTag)475     inline JSValue::JSValue(JSFalseTag)
476     {
477         u.asBits.tag = FalseTag;
478         u.asBits.payload = 0;
479     }
480 
JSValue(HashTableDeletedValueTag)481     inline JSValue::JSValue(HashTableDeletedValueTag)
482     {
483         u.asBits.tag = DeletedValueTag;
484         u.asBits.payload = 0;
485     }
486 
JSValue(JSCell * ptr)487     inline JSValue::JSValue(JSCell* ptr)
488     {
489         if (ptr)
490             u.asBits.tag = CellTag;
491         else
492             u.asBits.tag = EmptyValueTag;
493 #if defined(__sparc64__)
494         u.asBits.payload = reinterpret_cast<int64_t>(ptr);
495 #else
496         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
497 #endif
498 #if ENABLE(JSC_ZOMBIES)
499         ASSERT(!isZombie());
500 #endif
501     }
502 
JSValue(const JSCell * ptr)503     inline JSValue::JSValue(const JSCell* ptr)
504     {
505         if (ptr)
506             u.asBits.tag = CellTag;
507         else
508             u.asBits.tag = EmptyValueTag;
509 #if defined(__sparc64__)
510         u.asBits.payload = reinterpret_cast<int64_t>(const_cast<JSCell*>(ptr));
511 #else
512         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
513 #endif
514 #if ENABLE(JSC_ZOMBIES)
515         ASSERT(!isZombie());
516 #endif
517     }
518 
519     inline JSValue::operator bool() const
520     {
521         ASSERT(tag() != DeletedValueTag);
522         return tag() != EmptyValueTag;
523     }
524 
525     inline bool JSValue::operator==(const JSValue& other) const
526     {
527         return u.asEncodedJSValue == other.u.asEncodedJSValue;
528     }
529 
530     inline bool JSValue::operator!=(const JSValue& other) const
531     {
532         return u.asEncodedJSValue != other.u.asEncodedJSValue;
533     }
534 
isUndefined()535     inline bool JSValue::isUndefined() const
536     {
537         return tag() == UndefinedTag;
538     }
539 
isNull()540     inline bool JSValue::isNull() const
541     {
542         return tag() == NullTag;
543     }
544 
isUndefinedOrNull()545     inline bool JSValue::isUndefinedOrNull() const
546     {
547         return isUndefined() || isNull();
548     }
549 
isCell()550     inline bool JSValue::isCell() const
551     {
552         return tag() == CellTag;
553     }
554 
isInt32()555     inline bool JSValue::isInt32() const
556     {
557         return tag() == Int32Tag;
558     }
559 
isUInt32()560     inline bool JSValue::isUInt32() const
561     {
562         return tag() == Int32Tag && asInt32() > -1;
563     }
564 
isDouble()565     inline bool JSValue::isDouble() const
566     {
567         return tag() < LowestTag;
568     }
569 
isTrue()570     inline bool JSValue::isTrue() const
571     {
572         return tag() == TrueTag;
573     }
574 
isFalse()575     inline bool JSValue::isFalse() const
576     {
577         return tag() == FalseTag;
578     }
579 
tag()580     inline uint32_t JSValue::tag() const
581     {
582         return u.asBits.tag;
583     }
584 
payload()585     inline int32_t JSValue::payload() const
586     {
587         return u.asBits.payload;
588     }
589 
asInt32()590     inline int32_t JSValue::asInt32() const
591     {
592         ASSERT(isInt32());
593         return u.asBits.payload;
594     }
595 
asUInt32()596     inline uint32_t JSValue::asUInt32() const
597     {
598         ASSERT(isUInt32());
599         return u.asBits.payload;
600     }
601 
asDouble()602     inline double JSValue::asDouble() const
603     {
604         ASSERT(isDouble());
605         return u.asDouble;
606     }
607 
asCell()608     ALWAYS_INLINE JSCell* JSValue::asCell() const
609     {
610         ASSERT(isCell());
611         return reinterpret_cast<JSCell*>(u.asBits.payload);
612     }
613 
JSValue(EncodeAsDoubleTag,ExecState *,double d)614     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
615     {
616         u.asDouble = d;
617     }
618 
JSValue(ExecState * exec,double d)619     inline JSValue::JSValue(ExecState* exec, double d)
620     {
621         const int32_t asInt32 = static_cast<int32_t>(d);
622         if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
623             u.asDouble = d;
624             return;
625         }
626         *this = JSValue(exec, static_cast<int32_t>(d));
627     }
628 
JSValue(ExecState * exec,char i)629     inline JSValue::JSValue(ExecState* exec, char i)
630     {
631         *this = JSValue(exec, static_cast<int32_t>(i));
632     }
633 
JSValue(ExecState * exec,unsigned char i)634     inline JSValue::JSValue(ExecState* exec, unsigned char i)
635     {
636         *this = JSValue(exec, static_cast<int32_t>(i));
637     }
638 
JSValue(ExecState * exec,short i)639     inline JSValue::JSValue(ExecState* exec, short i)
640     {
641         *this = JSValue(exec, static_cast<int32_t>(i));
642     }
643 
JSValue(ExecState * exec,unsigned short i)644     inline JSValue::JSValue(ExecState* exec, unsigned short i)
645     {
646         *this = JSValue(exec, static_cast<int32_t>(i));
647     }
648 
JSValue(ExecState *,int i)649     inline JSValue::JSValue(ExecState*, int i)
650     {
651         u.asBits.tag = Int32Tag;
652         u.asBits.payload = i;
653     }
654 
JSValue(ExecState * exec,unsigned i)655     inline JSValue::JSValue(ExecState* exec, unsigned i)
656     {
657         if (static_cast<int32_t>(i) < 0) {
658             *this = JSValue(exec, static_cast<double>(i));
659             return;
660         }
661         *this = JSValue(exec, static_cast<int32_t>(i));
662     }
663 
JSValue(ExecState * exec,long i)664     inline JSValue::JSValue(ExecState* exec, long i)
665     {
666         if (static_cast<int32_t>(i) != i) {
667             *this = JSValue(exec, static_cast<double>(i));
668             return;
669         }
670         *this = JSValue(exec, static_cast<int32_t>(i));
671     }
672 
JSValue(ExecState * exec,unsigned long i)673     inline JSValue::JSValue(ExecState* exec, unsigned long i)
674     {
675         if (static_cast<uint32_t>(i) != i) {
676             *this = JSValue(exec, static_cast<double>(i));
677             return;
678         }
679         *this = JSValue(exec, static_cast<uint32_t>(i));
680     }
681 
JSValue(ExecState * exec,long long i)682     inline JSValue::JSValue(ExecState* exec, long long i)
683     {
684         if (static_cast<int32_t>(i) != i) {
685             *this = JSValue(exec, static_cast<double>(i));
686             return;
687         }
688         *this = JSValue(exec, static_cast<int32_t>(i));
689     }
690 
JSValue(ExecState * exec,unsigned long long i)691     inline JSValue::JSValue(ExecState* exec, unsigned long long i)
692     {
693         if (static_cast<uint32_t>(i) != i) {
694             *this = JSValue(exec, static_cast<double>(i));
695             return;
696         }
697         *this = JSValue(exec, static_cast<uint32_t>(i));
698     }
699 
JSValue(JSGlobalData * globalData,double d)700     inline JSValue::JSValue(JSGlobalData* globalData, double d)
701     {
702         const int32_t asInt32 = static_cast<int32_t>(d);
703         if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
704             u.asDouble = d;
705             return;
706         }
707         *this = JSValue(globalData, static_cast<int32_t>(d));
708     }
709 
JSValue(JSGlobalData *,int i)710     inline JSValue::JSValue(JSGlobalData*, int i)
711     {
712         u.asBits.tag = Int32Tag;
713         u.asBits.payload = i;
714     }
715 
JSValue(JSGlobalData * globalData,unsigned i)716     inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
717     {
718         if (static_cast<int32_t>(i) < 0) {
719             *this = JSValue(globalData, static_cast<double>(i));
720             return;
721         }
722         *this = JSValue(globalData, static_cast<int32_t>(i));
723     }
724 
isNumber()725     inline bool JSValue::isNumber() const
726     {
727         return isInt32() || isDouble();
728     }
729 
isBoolean()730     inline bool JSValue::isBoolean() const
731     {
732         return isTrue() || isFalse();
733     }
734 
getBoolean(bool & v)735     inline bool JSValue::getBoolean(bool& v) const
736     {
737         if (isTrue()) {
738             v = true;
739             return true;
740         }
741         if (isFalse()) {
742             v = false;
743             return true;
744         }
745 
746         return false;
747     }
748 
getBoolean()749     inline bool JSValue::getBoolean() const
750     {
751         ASSERT(isBoolean());
752         return tag() == TrueTag;
753     }
754 
uncheckedGetNumber()755     inline double JSValue::uncheckedGetNumber() const
756     {
757         ASSERT(isNumber());
758         return isInt32() ? asInt32() : asDouble();
759     }
760 
toJSNumber(ExecState * exec)761     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
762     {
763         return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
764     }
765 
getNumber(double & result)766     inline bool JSValue::getNumber(double& result) const
767     {
768         if (isInt32()) {
769             result = asInt32();
770             return true;
771         }
772         if (isDouble()) {
773             result = asDouble();
774             return true;
775         }
776         return false;
777     }
778 
779 #else // USE(JSVALUE32_64)
780 
781     // JSValue member functions.
encode(JSValue value)782     inline EncodedJSValue JSValue::encode(JSValue value)
783     {
784         EncodedJSValue r;
785         memcpy(&r, &value.m_ptr, sizeof(r));
786         return r;
787     }
788 
decode(EncodedJSValue ptr)789     inline JSValue JSValue::decode(EncodedJSValue ptr)
790     {
791         JSCell *cellPtr;
792         memcpy(&cellPtr, &ptr, sizeof(cellPtr));
793         return JSValue(cellPtr);
794     }
795 
makeImmediate(intptr_t value)796     inline JSValue JSValue::makeImmediate(intptr_t value)
797     {
798         JSCell *cellPtr;
799         memcpy(&cellPtr, &value, sizeof(cellPtr));
800         return JSValue(cellPtr);
801     }
802 
immediateValue()803     inline intptr_t JSValue::immediateValue()
804     {
805         intptr_t v;
806         memcpy(&v, &m_ptr, sizeof(v));
807         return v;
808     }
809 
810     // 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.
JSValue()811     inline JSValue::JSValue()
812         : m_ptr(0)
813     {
814     }
815 
816     // 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.
JSValue(HashTableDeletedValueTag)817     inline JSValue::JSValue(HashTableDeletedValueTag)
818         : m_ptr(reinterpret_cast<JSCell*>(0x4))
819     {
820     }
821 
JSValue(JSCell * ptr)822     inline JSValue::JSValue(JSCell* ptr)
823         : m_ptr(ptr)
824     {
825 #if ENABLE(JSC_ZOMBIES)
826         ASSERT(!isZombie());
827 #endif
828     }
829 
JSValue(const JSCell * ptr)830     inline JSValue::JSValue(const JSCell* ptr)
831         : m_ptr(const_cast<JSCell*>(ptr))
832     {
833 #if ENABLE(JSC_ZOMBIES)
834         ASSERT(!isZombie());
835 #endif
836     }
837 
838     inline JSValue::operator bool() const
839     {
840         return m_ptr;
841     }
842 
843     inline bool JSValue::operator==(const JSValue& other) const
844     {
845         return m_ptr == other.m_ptr;
846     }
847 
848     inline bool JSValue::operator!=(const JSValue& other) const
849     {
850         return m_ptr != other.m_ptr;
851     }
852 
isUndefined()853     inline bool JSValue::isUndefined() const
854     {
855         return asValue() == jsUndefined();
856     }
857 
isNull()858     inline bool JSValue::isNull() const
859     {
860         return asValue() == jsNull();
861     }
862 #endif // USE(JSVALUE32_64)
863 
864 } // namespace JSC
865 
866 #endif // JSValue_h
867