1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef JSValueInlineMethods_h 27 #define JSValueInlineMethods_h 28 29 #include "JSValue.h" 30 31 namespace JSC { 32 toInt32(ExecState * exec)33 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const 34 { 35 if (isInt32()) 36 return asInt32(); 37 return JSC::toInt32(toNumber(exec)); 38 } 39 toUInt32(ExecState * exec)40 inline uint32_t JSValue::toUInt32(ExecState* exec) const 41 { 42 // See comment on JSC::toUInt32, above. 43 return toInt32(exec); 44 } 45 isUInt32()46 inline bool JSValue::isUInt32() const 47 { 48 return isInt32() && asInt32() >= 0; 49 } 50 asUInt32()51 inline uint32_t JSValue::asUInt32() const 52 { 53 ASSERT(isUInt32()); 54 return asInt32(); 55 } 56 uncheckedGetNumber()57 inline double JSValue::uncheckedGetNumber() const 58 { 59 ASSERT(isNumber()); 60 return isInt32() ? asInt32() : asDouble(); 61 } 62 toJSNumber(ExecState * exec)63 ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const 64 { 65 return isNumber() ? asValue() : jsNumber(this->toNumber(exec)); 66 } 67 jsNaN()68 inline JSValue jsNaN() 69 { 70 return JSValue(nonInlineNaN()); 71 } 72 getNumber(double & result)73 inline bool JSValue::getNumber(double& result) const 74 { 75 if (isInt32()) { 76 result = asInt32(); 77 return true; 78 } 79 if (isDouble()) { 80 result = asDouble(); 81 return true; 82 } 83 return false; 84 } 85 getBoolean(bool & v)86 inline bool JSValue::getBoolean(bool& v) const 87 { 88 if (isTrue()) { 89 v = true; 90 return true; 91 } 92 if (isFalse()) { 93 v = false; 94 return true; 95 } 96 97 return false; 98 } 99 JSValue(char i)100 inline JSValue::JSValue(char i) 101 { 102 *this = JSValue(static_cast<int32_t>(i)); 103 } 104 JSValue(unsigned char i)105 inline JSValue::JSValue(unsigned char i) 106 { 107 *this = JSValue(static_cast<int32_t>(i)); 108 } 109 JSValue(short i)110 inline JSValue::JSValue(short i) 111 { 112 *this = JSValue(static_cast<int32_t>(i)); 113 } 114 JSValue(unsigned short i)115 inline JSValue::JSValue(unsigned short i) 116 { 117 *this = JSValue(static_cast<int32_t>(i)); 118 } 119 JSValue(unsigned i)120 inline JSValue::JSValue(unsigned i) 121 { 122 if (static_cast<int32_t>(i) < 0) { 123 *this = JSValue(EncodeAsDouble, static_cast<double>(i)); 124 return; 125 } 126 *this = JSValue(static_cast<int32_t>(i)); 127 } 128 JSValue(long i)129 inline JSValue::JSValue(long i) 130 { 131 if (static_cast<int32_t>(i) != i) { 132 *this = JSValue(EncodeAsDouble, static_cast<double>(i)); 133 return; 134 } 135 *this = JSValue(static_cast<int32_t>(i)); 136 } 137 JSValue(unsigned long i)138 inline JSValue::JSValue(unsigned long i) 139 { 140 if (static_cast<uint32_t>(i) != i) { 141 *this = JSValue(EncodeAsDouble, static_cast<double>(i)); 142 return; 143 } 144 *this = JSValue(static_cast<uint32_t>(i)); 145 } 146 JSValue(long long i)147 inline JSValue::JSValue(long long i) 148 { 149 if (static_cast<int32_t>(i) != i) { 150 *this = JSValue(EncodeAsDouble, static_cast<double>(i)); 151 return; 152 } 153 *this = JSValue(static_cast<int32_t>(i)); 154 } 155 JSValue(unsigned long long i)156 inline JSValue::JSValue(unsigned long long i) 157 { 158 if (static_cast<uint32_t>(i) != i) { 159 *this = JSValue(EncodeAsDouble, static_cast<double>(i)); 160 return; 161 } 162 *this = JSValue(static_cast<uint32_t>(i)); 163 } 164 JSValue(double d)165 inline JSValue::JSValue(double d) 166 { 167 const int32_t asInt32 = static_cast<int32_t>(d); 168 if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 169 *this = JSValue(EncodeAsDouble, d); 170 return; 171 } 172 *this = JSValue(static_cast<int32_t>(d)); 173 } 174 175 #if USE(JSVALUE32_64) encode(JSValue value)176 inline EncodedJSValue JSValue::encode(JSValue value) 177 { 178 return value.u.asInt64; 179 } 180 decode(EncodedJSValue encodedJSValue)181 inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) 182 { 183 JSValue v; 184 v.u.asInt64 = encodedJSValue; 185 return v; 186 } 187 JSValue()188 inline JSValue::JSValue() 189 { 190 u.asBits.tag = EmptyValueTag; 191 u.asBits.payload = 0; 192 } 193 JSValue(JSNullTag)194 inline JSValue::JSValue(JSNullTag) 195 { 196 u.asBits.tag = NullTag; 197 u.asBits.payload = 0; 198 } 199 JSValue(JSUndefinedTag)200 inline JSValue::JSValue(JSUndefinedTag) 201 { 202 u.asBits.tag = UndefinedTag; 203 u.asBits.payload = 0; 204 } 205 JSValue(JSTrueTag)206 inline JSValue::JSValue(JSTrueTag) 207 { 208 u.asBits.tag = BooleanTag; 209 u.asBits.payload = 1; 210 } 211 JSValue(JSFalseTag)212 inline JSValue::JSValue(JSFalseTag) 213 { 214 u.asBits.tag = BooleanTag; 215 u.asBits.payload = 0; 216 } 217 JSValue(HashTableDeletedValueTag)218 inline JSValue::JSValue(HashTableDeletedValueTag) 219 { 220 u.asBits.tag = DeletedValueTag; 221 u.asBits.payload = 0; 222 } 223 JSValue(JSCell * ptr)224 inline JSValue::JSValue(JSCell* ptr) 225 { 226 if (ptr) 227 u.asBits.tag = CellTag; 228 else 229 u.asBits.tag = EmptyValueTag; 230 u.asBits.payload = reinterpret_cast<int32_t>(ptr); 231 #if ENABLE(JSC_ZOMBIES) 232 ASSERT(!isZombie()); 233 #endif 234 } 235 JSValue(const JSCell * ptr)236 inline JSValue::JSValue(const JSCell* ptr) 237 { 238 if (ptr) 239 u.asBits.tag = CellTag; 240 else 241 u.asBits.tag = EmptyValueTag; 242 u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); 243 #if ENABLE(JSC_ZOMBIES) 244 ASSERT(!isZombie()); 245 #endif 246 } 247 248 inline JSValue::operator bool() const 249 { 250 ASSERT(tag() != DeletedValueTag); 251 return tag() != EmptyValueTag; 252 } 253 254 inline bool JSValue::operator==(const JSValue& other) const 255 { 256 return u.asInt64 == other.u.asInt64; 257 } 258 259 inline bool JSValue::operator!=(const JSValue& other) const 260 { 261 return u.asInt64 != other.u.asInt64; 262 } 263 isUndefined()264 inline bool JSValue::isUndefined() const 265 { 266 return tag() == UndefinedTag; 267 } 268 isNull()269 inline bool JSValue::isNull() const 270 { 271 return tag() == NullTag; 272 } 273 isUndefinedOrNull()274 inline bool JSValue::isUndefinedOrNull() const 275 { 276 return isUndefined() || isNull(); 277 } 278 isCell()279 inline bool JSValue::isCell() const 280 { 281 return tag() == CellTag; 282 } 283 isInt32()284 inline bool JSValue::isInt32() const 285 { 286 return tag() == Int32Tag; 287 } 288 isDouble()289 inline bool JSValue::isDouble() const 290 { 291 return tag() < LowestTag; 292 } 293 isTrue()294 inline bool JSValue::isTrue() const 295 { 296 return tag() == BooleanTag && payload(); 297 } 298 isFalse()299 inline bool JSValue::isFalse() const 300 { 301 return tag() == BooleanTag && !payload(); 302 } 303 tag()304 inline uint32_t JSValue::tag() const 305 { 306 return u.asBits.tag; 307 } 308 payload()309 inline int32_t JSValue::payload() const 310 { 311 return u.asBits.payload; 312 } 313 asInt32()314 inline int32_t JSValue::asInt32() const 315 { 316 ASSERT(isInt32()); 317 return u.asBits.payload; 318 } 319 asDouble()320 inline double JSValue::asDouble() const 321 { 322 ASSERT(isDouble()); 323 return u.asDouble; 324 } 325 asCell()326 ALWAYS_INLINE JSCell* JSValue::asCell() const 327 { 328 ASSERT(isCell()); 329 return reinterpret_cast<JSCell*>(u.asBits.payload); 330 } 331 JSValue(EncodeAsDoubleTag,double d)332 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) 333 { 334 u.asDouble = d; 335 } 336 JSValue(int i)337 inline JSValue::JSValue(int i) 338 { 339 u.asBits.tag = Int32Tag; 340 u.asBits.payload = i; 341 } 342 isNumber()343 inline bool JSValue::isNumber() const 344 { 345 return isInt32() || isDouble(); 346 } 347 isBoolean()348 inline bool JSValue::isBoolean() const 349 { 350 return isTrue() || isFalse(); 351 } 352 getBoolean()353 inline bool JSValue::getBoolean() const 354 { 355 ASSERT(isBoolean()); 356 return payload(); 357 } 358 359 #else // USE(JSVALUE32_64) 360 361 // JSValue member functions. encode(JSValue value)362 inline EncodedJSValue JSValue::encode(JSValue value) 363 { 364 return value.u.ptr; 365 } 366 decode(EncodedJSValue ptr)367 inline JSValue JSValue::decode(EncodedJSValue ptr) 368 { 369 return JSValue(reinterpret_cast<JSCell*>(ptr)); 370 } 371 372 // 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()373 inline JSValue::JSValue() 374 { 375 u.asInt64 = ValueEmpty; 376 } 377 378 // 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)379 inline JSValue::JSValue(HashTableDeletedValueTag) 380 { 381 u.asInt64 = ValueDeleted; 382 } 383 JSValue(JSCell * ptr)384 inline JSValue::JSValue(JSCell* ptr) 385 { 386 u.ptr = ptr; 387 #if ENABLE(JSC_ZOMBIES) 388 ASSERT(!isZombie()); 389 #endif 390 } 391 JSValue(const JSCell * ptr)392 inline JSValue::JSValue(const JSCell* ptr) 393 { 394 u.ptr = const_cast<JSCell*>(ptr); 395 #if ENABLE(JSC_ZOMBIES) 396 ASSERT(!isZombie()); 397 #endif 398 } 399 400 inline JSValue::operator bool() const 401 { 402 return u.ptr; 403 } 404 405 inline bool JSValue::operator==(const JSValue& other) const 406 { 407 return u.ptr == other.u.ptr; 408 } 409 410 inline bool JSValue::operator!=(const JSValue& other) const 411 { 412 return u.ptr != other.u.ptr; 413 } 414 isUndefined()415 inline bool JSValue::isUndefined() const 416 { 417 return asValue() == jsUndefined(); 418 } 419 isNull()420 inline bool JSValue::isNull() const 421 { 422 return asValue() == jsNull(); 423 } 424 isTrue()425 inline bool JSValue::isTrue() const 426 { 427 return asValue() == JSValue(JSTrue); 428 } 429 isFalse()430 inline bool JSValue::isFalse() const 431 { 432 return asValue() == JSValue(JSFalse); 433 } 434 getBoolean()435 inline bool JSValue::getBoolean() const 436 { 437 ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false)); 438 return asValue() == jsBoolean(true); 439 } 440 asInt32()441 inline int32_t JSValue::asInt32() const 442 { 443 ASSERT(isInt32()); 444 return static_cast<int32_t>(u.asInt64); 445 } 446 isDouble()447 inline bool JSValue::isDouble() const 448 { 449 return isNumber() && !isInt32(); 450 } 451 JSValue(JSNullTag)452 inline JSValue::JSValue(JSNullTag) 453 { 454 u.asInt64 = ValueNull; 455 } 456 JSValue(JSUndefinedTag)457 inline JSValue::JSValue(JSUndefinedTag) 458 { 459 u.asInt64 = ValueUndefined; 460 } 461 JSValue(JSTrueTag)462 inline JSValue::JSValue(JSTrueTag) 463 { 464 u.asInt64 = ValueTrue; 465 } 466 JSValue(JSFalseTag)467 inline JSValue::JSValue(JSFalseTag) 468 { 469 u.asInt64 = ValueFalse; 470 } 471 isUndefinedOrNull()472 inline bool JSValue::isUndefinedOrNull() const 473 { 474 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. 475 return (u.asInt64 & ~TagBitUndefined) == ValueNull; 476 } 477 isBoolean()478 inline bool JSValue::isBoolean() const 479 { 480 return (u.asInt64 & ~1) == ValueFalse; 481 } 482 isCell()483 inline bool JSValue::isCell() const 484 { 485 return !(u.asInt64 & TagMask); 486 } 487 isInt32()488 inline bool JSValue::isInt32() const 489 { 490 return (u.asInt64 & TagTypeNumber) == TagTypeNumber; 491 } 492 reinterpretDoubleToIntptr(double value)493 inline intptr_t reinterpretDoubleToIntptr(double value) 494 { 495 return bitwise_cast<intptr_t>(value); 496 } reinterpretIntptrToDouble(intptr_t value)497 inline double reinterpretIntptrToDouble(intptr_t value) 498 { 499 return bitwise_cast<double>(value); 500 } 501 JSValue(EncodeAsDoubleTag,double d)502 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) 503 { 504 u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset; 505 } 506 JSValue(int i)507 inline JSValue::JSValue(int i) 508 { 509 u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i); 510 } 511 asDouble()512 inline double JSValue::asDouble() const 513 { 514 return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset); 515 } 516 isNumber()517 inline bool JSValue::isNumber() const 518 { 519 return u.asInt64 & TagTypeNumber; 520 } 521 asCell()522 ALWAYS_INLINE JSCell* JSValue::asCell() const 523 { 524 ASSERT(isCell()); 525 return u.ptr; 526 } 527 528 #endif // USE(JSVALUE64) 529 530 } // namespace JSC 531 532 #endif // JSValueInlineMethods_h 533