Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSCJSValueInlines.h
1 /*
2  * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef JSValueInlines_h
27 #define JSValueInlines_h
28
29 #include "InternalFunction.h"
30 #include "JSCJSValue.h"
31 #include "JSCellInlines.h"
32 #include "JSFunction.h"
33
34 namespace JSC {
35
36 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
37 {
38     if (isInt32())
39         return asInt32();
40     return JSC::toInt32(toNumber(exec));
41 }
42
43 inline uint32_t JSValue::toUInt32(ExecState* exec) const
44 {
45     // See comment on JSC::toUInt32, above.
46     return toInt32(exec);
47 }
48
49 inline bool JSValue::isUInt32() const
50 {
51     return isInt32() && asInt32() >= 0;
52 }
53
54 inline uint32_t JSValue::asUInt32() const
55 {
56     ASSERT(isUInt32());
57     return asInt32();
58 }
59
60 inline double JSValue::asNumber() const
61 {
62     ASSERT(isNumber());
63     return isInt32() ? asInt32() : asDouble();
64 }
65
66 inline JSValue jsNaN()
67 {
68     return JSValue(QNaN);
69 }
70
71 inline JSValue::JSValue(char i)
72 {
73     *this = JSValue(static_cast<int32_t>(i));
74 }
75
76 inline JSValue::JSValue(unsigned char i)
77 {
78     *this = JSValue(static_cast<int32_t>(i));
79 }
80
81 inline JSValue::JSValue(short i)
82 {
83     *this = JSValue(static_cast<int32_t>(i));
84 }
85
86 inline JSValue::JSValue(unsigned short i)
87 {
88     *this = JSValue(static_cast<int32_t>(i));
89 }
90
91 inline JSValue::JSValue(unsigned i)
92 {
93     if (static_cast<int32_t>(i) < 0) {
94         *this = JSValue(EncodeAsDouble, static_cast<double>(i));
95         return;
96     }
97     *this = JSValue(static_cast<int32_t>(i));
98 }
99
100 inline JSValue::JSValue(long i)
101 {
102     if (static_cast<int32_t>(i) != i) {
103         *this = JSValue(EncodeAsDouble, static_cast<double>(i));
104         return;
105     }
106     *this = JSValue(static_cast<int32_t>(i));
107 }
108
109 inline JSValue::JSValue(unsigned long i)
110 {
111     if (static_cast<uint32_t>(i) != i) {
112         *this = JSValue(EncodeAsDouble, static_cast<double>(i));
113         return;
114     }
115     *this = JSValue(static_cast<uint32_t>(i));
116 }
117
118 inline JSValue::JSValue(long long i)
119 {
120     if (static_cast<int32_t>(i) != i) {
121         *this = JSValue(EncodeAsDouble, static_cast<double>(i));
122         return;
123     }
124     *this = JSValue(static_cast<int32_t>(i));
125 }
126
127 inline JSValue::JSValue(unsigned long long i)
128 {
129     if (static_cast<uint32_t>(i) != i) {
130         *this = JSValue(EncodeAsDouble, static_cast<double>(i));
131         return;
132     }
133     *this = JSValue(static_cast<uint32_t>(i));
134 }
135
136 inline JSValue::JSValue(double d)
137 {
138     const int32_t asInt32 = static_cast<int32_t>(d);
139     if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
140         *this = JSValue(EncodeAsDouble, d);
141         return;
142     }
143     *this = JSValue(static_cast<int32_t>(d));
144 }
145
146 inline EncodedJSValue JSValue::encode(JSValue value)
147 {
148     return value.u.asInt64;
149 }
150
151 inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
152 {
153     JSValue v;
154     v.u.asInt64 = encodedJSValue;
155     return v;
156 }
157
158 #if USE(JSVALUE32_64)
159 inline JSValue::JSValue()
160 {
161     u.asBits.tag = EmptyValueTag;
162     u.asBits.payload = 0;
163 }
164
165 inline JSValue::JSValue(JSNullTag)
166 {
167     u.asBits.tag = NullTag;
168     u.asBits.payload = 0;
169 }
170     
171 inline JSValue::JSValue(JSUndefinedTag)
172 {
173     u.asBits.tag = UndefinedTag;
174     u.asBits.payload = 0;
175 }
176     
177 inline JSValue::JSValue(JSTrueTag)
178 {
179     u.asBits.tag = BooleanTag;
180     u.asBits.payload = 1;
181 }
182     
183 inline JSValue::JSValue(JSFalseTag)
184 {
185     u.asBits.tag = BooleanTag;
186     u.asBits.payload = 0;
187 }
188
189 inline JSValue::JSValue(HashTableDeletedValueTag)
190 {
191     u.asBits.tag = DeletedValueTag;
192     u.asBits.payload = 0;
193 }
194
195 inline JSValue::JSValue(JSCell* ptr)
196 {
197     if (ptr)
198         u.asBits.tag = CellTag;
199     else
200         u.asBits.tag = EmptyValueTag;
201     u.asBits.payload = reinterpret_cast<int32_t>(ptr);
202 }
203
204 inline JSValue::JSValue(const JSCell* ptr)
205 {
206     if (ptr)
207         u.asBits.tag = CellTag;
208     else
209         u.asBits.tag = EmptyValueTag;
210     u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
211 }
212
213 inline JSValue::operator bool() const
214 {
215     ASSERT(tag() != DeletedValueTag);
216     return tag() != EmptyValueTag;
217 }
218
219 inline bool JSValue::operator==(const JSValue& other) const
220 {
221     return u.asInt64 == other.u.asInt64;
222 }
223
224 inline bool JSValue::operator!=(const JSValue& other) const
225 {
226     return u.asInt64 != other.u.asInt64;
227 }
228
229 inline bool JSValue::isEmpty() const
230 {
231     return tag() == EmptyValueTag;
232 }
233
234 inline bool JSValue::isUndefined() const
235 {
236     return tag() == UndefinedTag;
237 }
238
239 inline bool JSValue::isNull() const
240 {
241     return tag() == NullTag;
242 }
243
244 inline bool JSValue::isUndefinedOrNull() const
245 {
246     return isUndefined() || isNull();
247 }
248
249 inline bool JSValue::isCell() const
250 {
251     return tag() == CellTag;
252 }
253
254 inline bool JSValue::isInt32() const
255 {
256     return tag() == Int32Tag;
257 }
258
259 inline bool JSValue::isDouble() const
260 {
261     return tag() < LowestTag;
262 }
263
264 inline bool JSValue::isTrue() const
265 {
266     return tag() == BooleanTag && payload();
267 }
268
269 inline bool JSValue::isFalse() const
270 {
271     return tag() == BooleanTag && !payload();
272 }
273
274 inline uint32_t JSValue::tag() const
275 {
276     return u.asBits.tag;
277 }
278     
279 inline int32_t JSValue::payload() const
280 {
281     return u.asBits.payload;
282 }
283     
284 inline int32_t JSValue::asInt32() const
285 {
286     ASSERT(isInt32());
287     return u.asBits.payload;
288 }
289     
290 inline double JSValue::asDouble() const
291 {
292     ASSERT(isDouble());
293     return u.asDouble;
294 }
295     
296 ALWAYS_INLINE JSCell* JSValue::asCell() const
297 {
298     ASSERT(isCell());
299     return reinterpret_cast<JSCell*>(u.asBits.payload);
300 }
301
302 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
303 {
304     u.asDouble = d;
305 }
306
307 inline JSValue::JSValue(int i)
308 {
309     u.asBits.tag = Int32Tag;
310     u.asBits.payload = i;
311 }
312
313 #if ENABLE(LLINT_C_LOOP)
314 inline JSValue::JSValue(int32_t tag, int32_t payload)
315 {
316     u.asBits.tag = tag;
317     u.asBits.payload = payload;
318 }
319 #endif
320
321 inline bool JSValue::isNumber() const
322 {
323     return isInt32() || isDouble();
324 }
325
326 inline bool JSValue::isBoolean() const
327 {
328     return isTrue() || isFalse();
329 }
330
331 inline bool JSValue::asBoolean() const
332 {
333     ASSERT(isBoolean());
334     return payload();
335 }
336
337 #else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
338
339 // 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.
340 inline JSValue::JSValue()
341 {
342     u.asInt64 = ValueEmpty;
343 }
344
345 // 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.
346 inline JSValue::JSValue(HashTableDeletedValueTag)
347 {
348     u.asInt64 = ValueDeleted;
349 }
350
351 inline JSValue::JSValue(JSCell* ptr)
352 {
353     u.asInt64 = reinterpret_cast<uintptr_t>(ptr);
354 }
355
356 inline JSValue::JSValue(const JSCell* ptr)
357 {
358     u.asInt64 = reinterpret_cast<uintptr_t>(const_cast<JSCell*>(ptr));
359 }
360
361 inline JSValue::operator bool() const
362 {
363     return u.asInt64;
364 }
365
366 inline bool JSValue::operator==(const JSValue& other) const
367 {
368     return u.asInt64 == other.u.asInt64;
369 }
370
371 inline bool JSValue::operator!=(const JSValue& other) const
372 {
373     return u.asInt64 != other.u.asInt64;
374 }
375
376 inline bool JSValue::isEmpty() const
377 {
378     return u.asInt64 == ValueEmpty;
379 }
380
381 inline bool JSValue::isUndefined() const
382 {
383     return asValue() == JSValue(JSUndefined);
384 }
385
386 inline bool JSValue::isNull() const
387 {
388     return asValue() == JSValue(JSNull);
389 }
390
391 inline bool JSValue::isTrue() const
392 {
393     return asValue() == JSValue(JSTrue);
394 }
395
396 inline bool JSValue::isFalse() const
397 {
398     return asValue() == JSValue(JSFalse);
399 }
400
401 inline bool JSValue::asBoolean() const
402 {
403     ASSERT(isBoolean());
404     return asValue() == JSValue(JSTrue);
405 }
406
407 inline int32_t JSValue::asInt32() const
408 {
409     ASSERT(isInt32());
410     return static_cast<int32_t>(u.asInt64);
411 }
412
413 inline bool JSValue::isDouble() const
414 {
415     return isNumber() && !isInt32();
416 }
417
418 inline JSValue::JSValue(JSNullTag)
419 {
420     u.asInt64 = ValueNull;
421 }
422     
423 inline JSValue::JSValue(JSUndefinedTag)
424 {
425     u.asInt64 = ValueUndefined;
426 }
427
428 inline JSValue::JSValue(JSTrueTag)
429 {
430     u.asInt64 = ValueTrue;
431 }
432
433 inline JSValue::JSValue(JSFalseTag)
434 {
435     u.asInt64 = ValueFalse;
436 }
437
438 inline bool JSValue::isUndefinedOrNull() const
439 {
440     // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
441     return (u.asInt64 & ~TagBitUndefined) == ValueNull;
442 }
443
444 inline bool JSValue::isBoolean() const
445 {
446     return (u.asInt64 & ~1) == ValueFalse;
447 }
448
449 inline bool JSValue::isCell() const
450 {
451     return !(u.asInt64 & TagMask);
452 }
453
454 inline bool JSValue::isInt32() const
455 {
456     return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
457 }
458
459 inline int64_t reinterpretDoubleToInt64(double value)
460 {
461     return bitwise_cast<int64_t>(value);
462 }
463 inline double reinterpretInt64ToDouble(int64_t value)
464 {
465     return bitwise_cast<double>(value);
466 }
467
468 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
469 {
470     u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
471 }
472
473 inline JSValue::JSValue(int i)
474 {
475     u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
476 }
477
478 inline double JSValue::asDouble() const
479 {
480     ASSERT(isDouble());
481     return reinterpretInt64ToDouble(u.asInt64 - DoubleEncodeOffset);
482 }
483
484 inline bool JSValue::isNumber() const
485 {
486     return u.asInt64 & TagTypeNumber;
487 }
488
489 ALWAYS_INLINE JSCell* JSValue::asCell() const
490 {
491     ASSERT(isCell());
492     return u.ptr;
493 }
494
495 #endif // USE(JSVALUE64)
496
497 inline bool JSValue::isString() const
498 {
499     return isCell() && asCell()->isString();
500 }
501
502 inline bool JSValue::isPrimitive() const
503 {
504     return !isCell() || asCell()->isString();
505 }
506
507 inline bool JSValue::isGetterSetter() const
508 {
509     return isCell() && asCell()->isGetterSetter();
510 }
511
512 inline bool JSValue::isObject() const
513 {
514     return isCell() && asCell()->isObject();
515 }
516
517 inline bool JSValue::getString(ExecState* exec, String& s) const
518 {
519     return isCell() && asCell()->getString(exec, s);
520 }
521
522 inline String JSValue::getString(ExecState* exec) const
523 {
524     return isCell() ? asCell()->getString(exec) : String();
525 }
526
527 template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
528 {
529     return jsValue().getString(exec);
530 }
531
532 inline JSObject* JSValue::getObject() const
533 {
534     return isCell() ? asCell()->getObject() : 0;
535 }
536
537 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
538 {
539     if (isInt32()) {
540         int32_t i = asInt32();
541         v = static_cast<uint32_t>(i);
542         return i >= 0;
543     }
544     if (isDouble()) {
545         double d = asDouble();
546         v = static_cast<uint32_t>(d);
547         return v == d;
548     }
549     return false;
550 }
551
552 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
553 {
554     return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
555 }
556
557 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
558 {
559     if (isInt32()) {
560         number = asInt32();
561         value = *this;
562         return true;
563     }
564     if (isDouble()) {
565         number = asDouble();
566         value = *this;
567         return true;
568     }
569     if (isCell())
570         return asCell()->getPrimitiveNumber(exec, number, value);
571     if (isTrue()) {
572         number = 1.0;
573         value = *this;
574         return true;
575     }
576     if (isFalse() || isNull()) {
577         number = 0.0;
578         value = *this;
579         return true;
580     }
581     ASSERT(isUndefined());
582     number = QNaN;
583     value = *this;
584     return true;
585 }
586
587 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
588 {
589     if (isInt32())
590         return asInt32();
591     if (isDouble())
592         return asDouble();
593     return toNumberSlowCase(exec);
594 }
595
596 inline JSObject* JSValue::toObject(ExecState* exec) const
597 {
598     return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
599 }
600
601 inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
602 {
603     return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
604 }
605
606 inline bool JSValue::isFunction() const
607 {
608     return isCell() && (asCell()->inherits(JSFunction::info()) || asCell()->inherits(InternalFunction::info()));
609 }
610
611 // this method is here to be after the inline declaration of JSCell::inherits
612 inline bool JSValue::inherits(const ClassInfo* classInfo) const
613 {
614     return isCell() && asCell()->inherits(classInfo);
615 }
616
617 inline JSValue JSValue::toThis(ExecState* exec, ECMAMode ecmaMode) const
618 {
619     return isCell() ? asCell()->methodTable()->toThis(asCell(), exec, ecmaMode) : toThisSlowCase(exec, ecmaMode);
620 }
621
622 inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const
623 {
624     PropertySlot slot(asValue());
625     return get(exec, propertyName, slot);
626 }
627
628 inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
629 {
630     // If this is a primitive, we'll need to synthesize the prototype -
631     // and if it's a string there are special properties to check first.
632     JSObject* object;
633     if (UNLIKELY(!isObject())) {
634         if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
635             return slot.getValue(exec, propertyName);
636         object = synthesizePrototype(exec);
637     } else
638         object = asObject(asCell());
639     
640     if (object->getPropertySlot(exec, propertyName, slot))
641         return slot.getValue(exec, propertyName);
642     return jsUndefined();
643 }
644
645 inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
646 {
647     PropertySlot slot(asValue());
648     return get(exec, propertyName, slot);
649 }
650
651 inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
652 {
653     // If this is a primitive, we'll need to synthesize the prototype -
654     // and if it's a string there are special properties to check first.
655     JSObject* object;
656     if (UNLIKELY(!isObject())) {
657         if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
658             return slot.getValue(exec, propertyName);
659         object = synthesizePrototype(exec);
660     } else
661         object = asObject(asCell());
662     
663     if (object->getPropertySlot(exec, propertyName, slot))
664         return slot.getValue(exec, propertyName);
665     return jsUndefined();
666 }
667
668 inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
669 {
670     if (UNLIKELY(!isCell())) {
671         putToPrimitive(exec, propertyName, value, slot);
672         return;
673     }
674     asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
675 }
676
677 inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
678 {
679     if (UNLIKELY(!isCell())) {
680         putToPrimitiveByIndex(exec, propertyName, value, shouldThrow);
681         return;
682     }
683     asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
684 }
685
686 inline JSValue JSValue::structureOrUndefined() const
687 {
688     if (isCell())
689         return JSValue(asCell()->structure());
690     return jsUndefined();
691 }
692
693 // ECMA 11.9.3
694 inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
695 {
696     if (v1.isInt32() && v2.isInt32())
697         return v1 == v2;
698
699     return equalSlowCase(exec, v1, v2);
700 }
701
702 ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
703 {
704     do {
705         if (v1.isNumber() && v2.isNumber())
706             return v1.asNumber() == v2.asNumber();
707
708         bool s1 = v1.isString();
709         bool s2 = v2.isString();
710         if (s1 && s2)
711             return asString(v1)->value(exec) == asString(v2)->value(exec);
712
713         if (v1.isUndefinedOrNull()) {
714             if (v2.isUndefinedOrNull())
715                 return true;
716             if (!v2.isCell())
717                 return false;
718             return v2.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
719         }
720
721         if (v2.isUndefinedOrNull()) {
722             if (!v1.isCell())
723                 return false;
724             return v1.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
725         }
726
727         if (v1.isObject()) {
728             if (v2.isObject())
729                 return v1 == v2;
730             JSValue p1 = v1.toPrimitive(exec);
731             if (exec->hadException())
732                 return false;
733             v1 = p1;
734             if (v1.isInt32() && v2.isInt32())
735                 return v1 == v2;
736             continue;
737         }
738
739         if (v2.isObject()) {
740             JSValue p2 = v2.toPrimitive(exec);
741             if (exec->hadException())
742                 return false;
743             v2 = p2;
744             if (v1.isInt32() && v2.isInt32())
745                 return v1 == v2;
746             continue;
747         }
748
749         if (s1 || s2) {
750             double d1 = v1.toNumber(exec);
751             double d2 = v2.toNumber(exec);
752             return d1 == d2;
753         }
754
755         if (v1.isBoolean()) {
756             if (v2.isNumber())
757                 return static_cast<double>(v1.asBoolean()) == v2.asNumber();
758         } else if (v2.isBoolean()) {
759             if (v1.isNumber())
760                 return v1.asNumber() == static_cast<double>(v2.asBoolean());
761         }
762
763         return v1 == v2;
764     } while (true);
765 }
766
767 // ECMA 11.9.3
768 ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
769 {
770     ASSERT(v1.isCell() && v2.isCell());
771
772     if (v1.asCell()->isString() && v2.asCell()->isString())
773         return asString(v1)->value(exec) == asString(v2)->value(exec);
774
775     return v1 == v2;
776 }
777
778 inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
779 {
780     if (v1.isInt32() && v2.isInt32())
781         return v1 == v2;
782
783     if (v1.isNumber() && v2.isNumber())
784         return v1.asNumber() == v2.asNumber();
785
786     if (!v1.isCell() || !v2.isCell())
787         return v1 == v2;
788
789     return strictEqualSlowCaseInline(exec, v1, v2);
790 }
791
792 inline TriState JSValue::pureStrictEqual(JSValue v1, JSValue v2)
793 {
794     if (v1.isInt32() && v2.isInt32())
795         return triState(v1 == v2);
796
797     if (v1.isNumber() && v2.isNumber())
798         return triState(v1.asNumber() == v2.asNumber());
799
800     if (!v1.isCell() || !v2.isCell())
801         return triState(v1 == v2);
802     
803     if (v1.asCell()->isString() && v2.asCell()->isString()) {
804         const StringImpl* v1String = asString(v1)->tryGetValueImpl();
805         const StringImpl* v2String = asString(v2)->tryGetValueImpl();
806         if (!v1String || !v2String)
807             return MixedTriState;
808         return triState(WTF::equal(v1String, v2String));
809     }
810     
811     return triState(v1 == v2);
812 }
813
814 inline TriState JSValue::pureToBoolean() const
815 {
816     if (isInt32())
817         return asInt32() ? TrueTriState : FalseTriState;
818     if (isDouble())
819         return isNotZeroAndOrdered(asDouble()) ? TrueTriState : FalseTriState; // false for NaN
820     if (isCell())
821         return asCell()->pureToBoolean();
822     return isTrue() ? TrueTriState : FalseTriState;
823 }
824
825 } // namespace JSC
826
827 #endif // JSValueInlines_h
828