• 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 #include <stddef.h> // for size_t
24 #include <stdint.h>
25 
26 #ifndef JSValue_h
27 #define JSValue_h
28 
29 #include "CallData.h"
30 #include "ConstructData.h"
31 #include <math.h>
32 #include <wtf/AlwaysInline.h>
33 #include <wtf/Assertions.h>
34 #include <wtf/HashTraits.h>
35 #include <wtf/MathExtras.h>
36 
37 namespace JSC {
38 
39     class Identifier;
40     class JSCell;
41     class JSGlobalData;
42     class JSImmediate;
43     class JSObject;
44     class JSString;
45     class MarkStack;
46     class PropertySlot;
47     class PutPropertySlot;
48     class UString;
49 
50     struct ClassInfo;
51     struct Instruction;
52 
53     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
54 
55 #if USE(JSVALUE32_64)
56     typedef int64_t EncodedJSValue;
57 #else
58     typedef void* EncodedJSValue;
59 #endif
60 
61     double nonInlineNaN();
62     int32_t toInt32SlowCase(double, bool& ok);
63     uint32_t toUInt32SlowCase(double, bool& ok);
64 
65     class JSValue {
66         friend class JSImmediate;
67         friend struct EncodedJSValueHashTraits;
68         friend class JIT;
69         friend class JITStubs;
70         friend class JITStubCall;
71 
72     public:
73         static EncodedJSValue encode(JSValue value);
74         static JSValue decode(EncodedJSValue ptr);
75 #if !USE(JSVALUE32_64)
76     private:
77         static JSValue makeImmediate(intptr_t value);
78         intptr_t immediateValue();
79     public:
80 #endif
81         enum JSNullTag { JSNull };
82         enum JSUndefinedTag { JSUndefined };
83         enum JSTrueTag { JSTrue };
84         enum JSFalseTag { JSFalse };
85 
86         JSValue();
87         JSValue(JSNullTag);
88         JSValue(JSUndefinedTag);
89         JSValue(JSTrueTag);
90         JSValue(JSFalseTag);
91         JSValue(JSCell* ptr);
92         JSValue(const JSCell* ptr);
93 
94         // Numbers
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 isObject(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(UString&) const;
141         UString getString() 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         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         // Floating point conversions (this is a convenience method for webcore;
172         // signle precision float is not a representation used in JS or JSC).
toFloat(ExecState * exec)173         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
174 
175         // Garbage collection.
176         void markChildren(MarkStack&);
177         bool hasChildren() const;
178         bool marked() const;
179         void markDirect();
180 
181         // Object operations, with the toObject operation included.
182         JSValue get(ExecState*, const Identifier& propertyName) const;
183         JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
184         JSValue get(ExecState*, unsigned propertyName) const;
185         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
186         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
187         void put(ExecState*, unsigned propertyName, JSValue);
188 
189         bool needsThisConversion() const;
190         JSObject* toThisObject(ExecState*) const;
191         UString toThisString(ExecState*) const;
192         JSString* toThisJSString(ExecState*);
193 
194         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
195         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
196         static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
197         static bool strictEqual(JSValue v1, JSValue v2);
198         static bool strictEqualSlowCase(JSValue v1, JSValue v2);
199         static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2);
200 
201         JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
202 
203         bool isCell() const;
204         JSCell* asCell() const;
205 
206 #ifndef NDEBUG
207         char* description();
208 #endif
209 
210     private:
211         enum HashTableDeletedValueTag { HashTableDeletedValue };
212         JSValue(HashTableDeletedValueTag);
213 
asValue()214         inline const JSValue asValue() const { return *this; }
215         JSObject* toObjectSlowCase(ExecState*) const;
216         JSObject* toThisObjectSlowCase(ExecState*) const;
217 
218         enum { Int32Tag =        0xffffffff };
219         enum { CellTag =         0xfffffffe };
220         enum { TrueTag =         0xfffffffd };
221         enum { FalseTag =        0xfffffffc };
222         enum { NullTag =         0xfffffffb };
223         enum { UndefinedTag =    0xfffffffa };
224         enum { DeletedValueTag = 0xfffffff9 };
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 PLATFORM(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 
jsNumber(ExecState * exec,double d)289     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
290     {
291         return JSValue(exec, d);
292     }
293 
jsNumber(ExecState * exec,char i)294     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
295     {
296         return JSValue(exec, i);
297     }
298 
jsNumber(ExecState * exec,unsigned char i)299     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
300     {
301         return JSValue(exec, i);
302     }
303 
jsNumber(ExecState * exec,short i)304     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
305     {
306         return JSValue(exec, i);
307     }
308 
jsNumber(ExecState * exec,unsigned short i)309     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
310     {
311         return JSValue(exec, i);
312     }
313 
jsNumber(ExecState * exec,int i)314     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
315     {
316         return JSValue(exec, i);
317     }
318 
jsNumber(ExecState * exec,unsigned i)319     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
320     {
321         return JSValue(exec, i);
322     }
323 
jsNumber(ExecState * exec,long i)324     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
325     {
326         return JSValue(exec, i);
327     }
328 
jsNumber(ExecState * exec,unsigned long i)329     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
330     {
331         return JSValue(exec, i);
332     }
333 
jsNumber(ExecState * exec,long long i)334     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
335     {
336         return JSValue(exec, i);
337     }
338 
jsNumber(ExecState * exec,unsigned long long i)339     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
340     {
341         return JSValue(exec, i);
342     }
343 
jsNumber(JSGlobalData * globalData,double d)344     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
345     {
346         return JSValue(globalData, d);
347     }
348 
jsNumber(JSGlobalData * globalData,int i)349     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
350     {
351         return JSValue(globalData, i);
352     }
353 
jsNumber(JSGlobalData * globalData,unsigned i)354     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
355     {
356         return JSValue(globalData, i);
357     }
358 
359     inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
360     inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
361 
362     inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
363     inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
364 
toInt32(double val)365     inline int32_t toInt32(double val)
366     {
367         if (!(val >= -2147483648.0 && val < 2147483648.0)) {
368             bool ignored;
369             return toInt32SlowCase(val, ignored);
370         }
371         return static_cast<int32_t>(val);
372     }
373 
toUInt32(double val)374     inline uint32_t toUInt32(double val)
375     {
376         if (!(val >= 0.0 && val < 4294967296.0)) {
377             bool ignored;
378             return toUInt32SlowCase(val, ignored);
379         }
380         return static_cast<uint32_t>(val);
381     }
382 
toInt32(ExecState * exec)383     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
384     {
385         if (isInt32())
386             return asInt32();
387         bool ignored;
388         return toInt32SlowCase(toNumber(exec), ignored);
389     }
390 
toUInt32(ExecState * exec)391     inline uint32_t JSValue::toUInt32(ExecState* exec) const
392     {
393         if (isUInt32())
394             return asInt32();
395         bool ignored;
396         return toUInt32SlowCase(toNumber(exec), ignored);
397     }
398 
toInt32(ExecState * exec,bool & ok)399     inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
400     {
401         if (isInt32()) {
402             ok = true;
403             return asInt32();
404         }
405         return toInt32SlowCase(toNumber(exec), ok);
406     }
407 
toUInt32(ExecState * exec,bool & ok)408     inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
409     {
410         if (isUInt32()) {
411             ok = true;
412             return asInt32();
413         }
414         return toUInt32SlowCase(toNumber(exec), ok);
415     }
416 
417 #if USE(JSVALUE32_64)
jsNaN(ExecState * exec)418     inline JSValue jsNaN(ExecState* exec)
419     {
420         return JSValue(exec, nonInlineNaN());
421     }
422 
423     // JSValue member functions.
encode(JSValue value)424     inline EncodedJSValue JSValue::encode(JSValue value)
425     {
426         return value.u.asEncodedJSValue;
427     }
428 
decode(EncodedJSValue encodedJSValue)429     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
430     {
431         JSValue v;
432         v.u.asEncodedJSValue = encodedJSValue;
433         return v;
434     }
435 
JSValue()436     inline JSValue::JSValue()
437     {
438         u.asBits.tag = CellTag;
439         u.asBits.payload = 0;
440     }
441 
JSValue(JSNullTag)442     inline JSValue::JSValue(JSNullTag)
443     {
444         u.asBits.tag = NullTag;
445         u.asBits.payload = 0;
446     }
447 
JSValue(JSUndefinedTag)448     inline JSValue::JSValue(JSUndefinedTag)
449     {
450         u.asBits.tag = UndefinedTag;
451         u.asBits.payload = 0;
452     }
453 
JSValue(JSTrueTag)454     inline JSValue::JSValue(JSTrueTag)
455     {
456         u.asBits.tag = TrueTag;
457         u.asBits.payload = 0;
458     }
459 
JSValue(JSFalseTag)460     inline JSValue::JSValue(JSFalseTag)
461     {
462         u.asBits.tag = FalseTag;
463         u.asBits.payload = 0;
464     }
465 
JSValue(HashTableDeletedValueTag)466     inline JSValue::JSValue(HashTableDeletedValueTag)
467     {
468         u.asBits.tag = DeletedValueTag;
469         u.asBits.payload = 0;
470     }
471 
JSValue(JSCell * ptr)472     inline JSValue::JSValue(JSCell* ptr)
473     {
474         u.asBits.tag = CellTag;
475         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
476     }
477 
JSValue(const JSCell * ptr)478     inline JSValue::JSValue(const JSCell* ptr)
479     {
480         u.asBits.tag = CellTag;
481         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
482     }
483 
484     inline JSValue::operator bool() const
485     {
486         return u.asBits.payload || tag() != CellTag;
487     }
488 
489     inline bool JSValue::operator==(const JSValue& other) const
490     {
491         return u.asEncodedJSValue == other.u.asEncodedJSValue;
492     }
493 
494     inline bool JSValue::operator!=(const JSValue& other) const
495     {
496         return u.asEncodedJSValue != other.u.asEncodedJSValue;
497     }
498 
isUndefined()499     inline bool JSValue::isUndefined() const
500     {
501         return tag() == UndefinedTag;
502     }
503 
isNull()504     inline bool JSValue::isNull() const
505     {
506         return tag() == NullTag;
507     }
508 
isUndefinedOrNull()509     inline bool JSValue::isUndefinedOrNull() const
510     {
511         return isUndefined() || isNull();
512     }
513 
isCell()514     inline bool JSValue::isCell() const
515     {
516         return tag() == CellTag;
517     }
518 
isInt32()519     inline bool JSValue::isInt32() const
520     {
521         return tag() == Int32Tag;
522     }
523 
isUInt32()524     inline bool JSValue::isUInt32() const
525     {
526         return tag() == Int32Tag && asInt32() > -1;
527     }
528 
isDouble()529     inline bool JSValue::isDouble() const
530     {
531         return tag() < LowestTag;
532     }
533 
isTrue()534     inline bool JSValue::isTrue() const
535     {
536         return tag() == TrueTag;
537     }
538 
isFalse()539     inline bool JSValue::isFalse() const
540     {
541         return tag() == FalseTag;
542     }
543 
tag()544     inline uint32_t JSValue::tag() const
545     {
546         return u.asBits.tag;
547     }
548 
payload()549     inline int32_t JSValue::payload() const
550     {
551         return u.asBits.payload;
552     }
553 
asInt32()554     inline int32_t JSValue::asInt32() const
555     {
556         ASSERT(isInt32());
557         return u.asBits.payload;
558     }
559 
asUInt32()560     inline uint32_t JSValue::asUInt32() const
561     {
562         ASSERT(isUInt32());
563         return u.asBits.payload;
564     }
565 
asDouble()566     inline double JSValue::asDouble() const
567     {
568         ASSERT(isDouble());
569         return u.asDouble;
570     }
571 
asCell()572     ALWAYS_INLINE JSCell* JSValue::asCell() const
573     {
574         ASSERT(isCell());
575         return reinterpret_cast<JSCell*>(u.asBits.payload);
576     }
577 
JSValue(ExecState * exec,double d)578     inline JSValue::JSValue(ExecState* exec, double d)
579     {
580         const int32_t asInt32 = static_cast<int32_t>(d);
581         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
582             u.asDouble = d;
583             return;
584         }
585         *this = JSValue(exec, static_cast<int32_t>(d));
586     }
587 
JSValue(ExecState * exec,char i)588     inline JSValue::JSValue(ExecState* exec, char i)
589     {
590         *this = JSValue(exec, static_cast<int32_t>(i));
591     }
592 
JSValue(ExecState * exec,unsigned char i)593     inline JSValue::JSValue(ExecState* exec, unsigned char i)
594     {
595         *this = JSValue(exec, static_cast<int32_t>(i));
596     }
597 
JSValue(ExecState * exec,short i)598     inline JSValue::JSValue(ExecState* exec, short i)
599     {
600         *this = JSValue(exec, static_cast<int32_t>(i));
601     }
602 
JSValue(ExecState * exec,unsigned short i)603     inline JSValue::JSValue(ExecState* exec, unsigned short i)
604     {
605         *this = JSValue(exec, static_cast<int32_t>(i));
606     }
607 
JSValue(ExecState *,int i)608     inline JSValue::JSValue(ExecState*, int i)
609     {
610         u.asBits.tag = Int32Tag;
611         u.asBits.payload = i;
612     }
613 
JSValue(ExecState * exec,unsigned i)614     inline JSValue::JSValue(ExecState* exec, unsigned i)
615     {
616         if (static_cast<int32_t>(i) < 0) {
617             *this = JSValue(exec, static_cast<double>(i));
618             return;
619         }
620         *this = JSValue(exec, static_cast<int32_t>(i));
621     }
622 
JSValue(ExecState * exec,long i)623     inline JSValue::JSValue(ExecState* exec, long i)
624     {
625         if (static_cast<int32_t>(i) != i) {
626             *this = JSValue(exec, static_cast<double>(i));
627             return;
628         }
629         *this = JSValue(exec, static_cast<int32_t>(i));
630     }
631 
JSValue(ExecState * exec,unsigned long i)632     inline JSValue::JSValue(ExecState* exec, unsigned long i)
633     {
634         if (static_cast<uint32_t>(i) != i) {
635             *this = JSValue(exec, static_cast<double>(i));
636             return;
637         }
638         *this = JSValue(exec, static_cast<uint32_t>(i));
639     }
640 
JSValue(ExecState * exec,long long i)641     inline JSValue::JSValue(ExecState* exec, long long i)
642     {
643         if (static_cast<int32_t>(i) != i) {
644             *this = JSValue(exec, static_cast<double>(i));
645             return;
646         }
647         *this = JSValue(exec, static_cast<int32_t>(i));
648     }
649 
JSValue(ExecState * exec,unsigned long long i)650     inline JSValue::JSValue(ExecState* exec, unsigned long long i)
651     {
652         if (static_cast<uint32_t>(i) != i) {
653             *this = JSValue(exec, static_cast<double>(i));
654             return;
655         }
656         *this = JSValue(exec, static_cast<uint32_t>(i));
657     }
658 
JSValue(JSGlobalData * globalData,double d)659     inline JSValue::JSValue(JSGlobalData* globalData, double d)
660     {
661         const int32_t asInt32 = static_cast<int32_t>(d);
662         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
663             u.asDouble = d;
664             return;
665         }
666         *this = JSValue(globalData, static_cast<int32_t>(d));
667     }
668 
JSValue(JSGlobalData *,int i)669     inline JSValue::JSValue(JSGlobalData*, int i)
670     {
671         u.asBits.tag = Int32Tag;
672         u.asBits.payload = i;
673     }
674 
JSValue(JSGlobalData * globalData,unsigned i)675     inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
676     {
677         if (static_cast<int32_t>(i) < 0) {
678             *this = JSValue(globalData, static_cast<double>(i));
679             return;
680         }
681         *this = JSValue(globalData, static_cast<int32_t>(i));
682     }
683 
isNumber()684     inline bool JSValue::isNumber() const
685     {
686         return isInt32() || isDouble();
687     }
688 
isBoolean()689     inline bool JSValue::isBoolean() const
690     {
691         return isTrue() || isFalse();
692     }
693 
getBoolean(bool & v)694     inline bool JSValue::getBoolean(bool& v) const
695     {
696         if (isTrue()) {
697             v = true;
698             return true;
699         }
700         if (isFalse()) {
701             v = false;
702             return true;
703         }
704 
705         return false;
706     }
707 
getBoolean()708     inline bool JSValue::getBoolean() const
709     {
710         ASSERT(isBoolean());
711         return tag() == TrueTag;
712     }
713 
uncheckedGetNumber()714     inline double JSValue::uncheckedGetNumber() const
715     {
716         ASSERT(isNumber());
717         return isInt32() ? asInt32() : asDouble();
718     }
719 
toJSNumber(ExecState * exec)720     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
721     {
722         return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
723     }
724 
getNumber(double & result)725     inline bool JSValue::getNumber(double& result) const
726     {
727         if (isInt32()) {
728             result = asInt32();
729             return true;
730         }
731         if (isDouble()) {
732             result = asDouble();
733             return true;
734         }
735         return false;
736     }
737 
738 #else // USE(JSVALUE32_64)
739 
740     // JSValue member functions.
encode(JSValue value)741     inline EncodedJSValue JSValue::encode(JSValue value)
742     {
743         return reinterpret_cast<EncodedJSValue>(value.m_ptr);
744     }
745 
decode(EncodedJSValue ptr)746     inline JSValue JSValue::decode(EncodedJSValue ptr)
747     {
748         return JSValue(reinterpret_cast<JSCell*>(ptr));
749     }
750 
makeImmediate(intptr_t value)751     inline JSValue JSValue::makeImmediate(intptr_t value)
752     {
753         return JSValue(reinterpret_cast<JSCell*>(value));
754     }
755 
immediateValue()756     inline intptr_t JSValue::immediateValue()
757     {
758         return reinterpret_cast<intptr_t>(m_ptr);
759     }
760 
761     // 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()762     inline JSValue::JSValue()
763         : m_ptr(0)
764     {
765     }
766 
767     // 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)768     inline JSValue::JSValue(HashTableDeletedValueTag)
769         : m_ptr(reinterpret_cast<JSCell*>(0x4))
770     {
771     }
772 
JSValue(JSCell * ptr)773     inline JSValue::JSValue(JSCell* ptr)
774         : m_ptr(ptr)
775     {
776     }
777 
JSValue(const JSCell * ptr)778     inline JSValue::JSValue(const JSCell* ptr)
779         : m_ptr(const_cast<JSCell*>(ptr))
780     {
781     }
782 
783     inline JSValue::operator bool() const
784     {
785         return m_ptr;
786     }
787 
788     inline bool JSValue::operator==(const JSValue& other) const
789     {
790         return m_ptr == other.m_ptr;
791     }
792 
793     inline bool JSValue::operator!=(const JSValue& other) const
794     {
795         return m_ptr != other.m_ptr;
796     }
797 
isUndefined()798     inline bool JSValue::isUndefined() const
799     {
800         return asValue() == jsUndefined();
801     }
802 
isNull()803     inline bool JSValue::isNull() const
804     {
805         return asValue() == jsNull();
806     }
807 #endif // USE(JSVALUE32_64)
808 
809 } // namespace JSC
810 
811 #endif // JSValue_h
812