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