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