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
36namespace 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).
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
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;
260        static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
261        static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
262        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> {
268        static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
269        static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
270    };
271#endif
272
273    // Stand-alone helper functions.
274    inline JSValue jsNull()
275    {
276        return JSValue(JSValue::JSNull);
277    }
278
279    inline JSValue jsUndefined()
280    {
281        return JSValue(JSValue::JSUndefined);
282    }
283
284    inline JSValue jsBoolean(bool b)
285    {
286        return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
287    }
288
289    ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d)
290    {
291        return JSValue(JSValue::EncodeAsDouble, exec, d);
292    }
293
294    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
295    {
296        return JSValue(exec, d);
297    }
298
299    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
300    {
301        return JSValue(exec, i);
302    }
303
304    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
305    {
306        return JSValue(exec, i);
307    }
308
309    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
310    {
311        return JSValue(exec, i);
312    }
313
314    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
315    {
316        return JSValue(exec, i);
317    }
318
319    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
320    {
321        return JSValue(exec, i);
322    }
323
324    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
325    {
326        return JSValue(exec, i);
327    }
328
329    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
330    {
331        return JSValue(exec, i);
332    }
333
334    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
335    {
336        return JSValue(exec, i);
337    }
338
339    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
340    {
341        return JSValue(exec, i);
342    }
343
344    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
345    {
346        return JSValue(exec, i);
347    }
348
349    ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
350    {
351        return JSValue(globalData, d);
352    }
353
354    ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
355    {
356        return JSValue(globalData, i);
357    }
358
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
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
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
391    inline JSCell* asCell(JSValue value)
392    {
393        return value.asCell();
394    }
395
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
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
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
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)
431    inline JSValue jsNaN(ExecState* exec)
432    {
433        return JSValue(exec, nonInlineNaN());
434    }
435
436    // JSValue member functions.
437    inline EncodedJSValue JSValue::encode(JSValue value)
438    {
439        return value.u.asEncodedJSValue;
440    }
441
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
452    inline JSValue::JSValue()
453    {
454        u.asBits.tag = EmptyValueTag;
455        u.asBits.payload = 0;
456    }
457
458    inline JSValue::JSValue(JSNullTag)
459    {
460        u.asBits.tag = NullTag;
461        u.asBits.payload = 0;
462    }
463
464    inline JSValue::JSValue(JSUndefinedTag)
465    {
466        u.asBits.tag = UndefinedTag;
467        u.asBits.payload = 0;
468    }
469
470    inline JSValue::JSValue(JSTrueTag)
471    {
472        u.asBits.tag = TrueTag;
473        u.asBits.payload = 0;
474    }
475
476    inline JSValue::JSValue(JSFalseTag)
477    {
478        u.asBits.tag = FalseTag;
479        u.asBits.payload = 0;
480    }
481
482    inline JSValue::JSValue(HashTableDeletedValueTag)
483    {
484        u.asBits.tag = DeletedValueTag;
485        u.asBits.payload = 0;
486    }
487
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
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
528    inline bool JSValue::isUndefined() const
529    {
530        return tag() == UndefinedTag;
531    }
532
533    inline bool JSValue::isNull() const
534    {
535        return tag() == NullTag;
536    }
537
538    inline bool JSValue::isUndefinedOrNull() const
539    {
540        return isUndefined() || isNull();
541    }
542
543    inline bool JSValue::isCell() const
544    {
545        return tag() == CellTag;
546    }
547
548    inline bool JSValue::isInt32() const
549    {
550        return tag() == Int32Tag;
551    }
552
553    inline bool JSValue::isUInt32() const
554    {
555        return tag() == Int32Tag && asInt32() > -1;
556    }
557
558    inline bool JSValue::isDouble() const
559    {
560        return tag() < LowestTag;
561    }
562
563    inline bool JSValue::isTrue() const
564    {
565        return tag() == TrueTag;
566    }
567
568    inline bool JSValue::isFalse() const
569    {
570        return tag() == FalseTag;
571    }
572
573    inline uint32_t JSValue::tag() const
574    {
575        return u.asBits.tag;
576    }
577
578    inline int32_t JSValue::payload() const
579    {
580        return u.asBits.payload;
581    }
582
583    inline int32_t JSValue::asInt32() const
584    {
585        ASSERT(isInt32());
586        return u.asBits.payload;
587    }
588
589    inline uint32_t JSValue::asUInt32() const
590    {
591        ASSERT(isUInt32());
592        return u.asBits.payload;
593    }
594
595    inline double JSValue::asDouble() const
596    {
597        ASSERT(isDouble());
598        return u.asDouble;
599    }
600
601    ALWAYS_INLINE JSCell* JSValue::asCell() const
602    {
603        ASSERT(isCell());
604        return reinterpret_cast<JSCell*>(u.asBits.payload);
605    }
606
607    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
608    {
609        u.asDouble = d;
610    }
611
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
622    inline JSValue::JSValue(ExecState* exec, char i)
623    {
624        *this = JSValue(exec, static_cast<int32_t>(i));
625    }
626
627    inline JSValue::JSValue(ExecState* exec, unsigned char i)
628    {
629        *this = JSValue(exec, static_cast<int32_t>(i));
630    }
631
632    inline JSValue::JSValue(ExecState* exec, short i)
633    {
634        *this = JSValue(exec, static_cast<int32_t>(i));
635    }
636
637    inline JSValue::JSValue(ExecState* exec, unsigned short i)
638    {
639        *this = JSValue(exec, static_cast<int32_t>(i));
640    }
641
642    inline JSValue::JSValue(ExecState*, int i)
643    {
644        u.asBits.tag = Int32Tag;
645        u.asBits.payload = i;
646    }
647
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
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
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
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
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
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
703    inline JSValue::JSValue(JSGlobalData*, int i)
704    {
705        u.asBits.tag = Int32Tag;
706        u.asBits.payload = i;
707    }
708
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
718    inline bool JSValue::isNumber() const
719    {
720        return isInt32() || isDouble();
721    }
722
723    inline bool JSValue::isBoolean() const
724    {
725        return isTrue() || isFalse();
726    }
727
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
742    inline bool JSValue::getBoolean() const
743    {
744        ASSERT(isBoolean());
745        return tag() == TrueTag;
746    }
747
748    inline double JSValue::uncheckedGetNumber() const
749    {
750        ASSERT(isNumber());
751        return isInt32() ? asInt32() : asDouble();
752    }
753
754    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
755    {
756        return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
757    }
758
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.
775    inline EncodedJSValue JSValue::encode(JSValue value)
776    {
777        return reinterpret_cast<EncodedJSValue>(value.m_ptr);
778    }
779
780    inline JSValue JSValue::decode(EncodedJSValue ptr)
781    {
782        return JSValue(reinterpret_cast<JSCell*>(ptr));
783    }
784
785    inline JSValue JSValue::makeImmediate(intptr_t value)
786    {
787        return JSValue(reinterpret_cast<JSCell*>(value));
788    }
789
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.
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.
802    inline JSValue::JSValue(HashTableDeletedValueTag)
803        : m_ptr(reinterpret_cast<JSCell*>(0x4))
804    {
805    }
806
807    inline JSValue::JSValue(JSCell* ptr)
808        : m_ptr(ptr)
809    {
810#if ENABLE(JSC_ZOMBIES)
811        ASSERT(!isZombie());
812#endif
813    }
814
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
838    inline bool JSValue::isUndefined() const
839    {
840        return asValue() == jsUndefined();
841    }
842
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