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