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