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