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