| 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). | 
| 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 |  | 
| 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; | 
| 259 |         static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); } | 
| 260 |         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } | 
| 261 |         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> { | 
| 267 |         static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(value: JSValue(JSValue::HashTableDeletedValue)); } | 
| 268 |         static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(value: JSValue(JSValue::HashTableDeletedValue)); } | 
| 269 |     }; | 
| 270 | #endif | 
| 271 |  | 
| 272 |     // Stand-alone helper functions. | 
| 273 |     inline JSValue jsNull() | 
| 274 |     { | 
| 275 |         return JSValue(JSValue::JSNull); | 
| 276 |     } | 
| 277 |  | 
| 278 |     inline JSValue jsUndefined() | 
| 279 |     { | 
| 280 |         return JSValue(JSValue::JSUndefined); | 
| 281 |     } | 
| 282 |  | 
| 283 |     inline JSValue jsBoolean(bool b) | 
| 284 |     { | 
| 285 |         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse); | 
| 286 |     } | 
| 287 |  | 
| 288 |     ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d) | 
| 289 |     { | 
| 290 |         return JSValue(JSValue::EncodeAsDouble, exec, d); | 
| 291 |     } | 
| 292 |  | 
| 293 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d) | 
| 294 |     { | 
| 295 |         return JSValue(exec, d); | 
| 296 |     } | 
| 297 |  | 
| 298 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i) | 
| 299 |     { | 
| 300 |         return JSValue(exec, i); | 
| 301 |     } | 
| 302 |  | 
| 303 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i) | 
| 304 |     { | 
| 305 |         return JSValue(exec, i); | 
| 306 |     } | 
| 307 |  | 
| 308 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i) | 
| 309 |     { | 
| 310 |         return JSValue(exec, i); | 
| 311 |     } | 
| 312 |  | 
| 313 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i) | 
| 314 |     { | 
| 315 |         return JSValue(exec, i); | 
| 316 |     } | 
| 317 |  | 
| 318 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i) | 
| 319 |     { | 
| 320 |         return JSValue(exec, i); | 
| 321 |     } | 
| 322 |  | 
| 323 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i) | 
| 324 |     { | 
| 325 |         return JSValue(exec, i); | 
| 326 |     } | 
| 327 |  | 
| 328 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i) | 
| 329 |     { | 
| 330 |         return JSValue(exec, i); | 
| 331 |     } | 
| 332 |  | 
| 333 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i) | 
| 334 |     { | 
| 335 |         return JSValue(exec, i); | 
| 336 |     } | 
| 337 |  | 
| 338 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i) | 
| 339 |     { | 
| 340 |         return JSValue(exec, i); | 
| 341 |     } | 
| 342 |  | 
| 343 |     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i) | 
| 344 |     { | 
| 345 |         return JSValue(exec, i); | 
| 346 |     } | 
| 347 |  | 
| 348 |     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d) | 
| 349 |     { | 
| 350 |         return JSValue(globalData, d); | 
| 351 |     } | 
| 352 |  | 
| 353 |     ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i) | 
| 354 |     { | 
| 355 |         return JSValue(globalData, i); | 
| 356 |     } | 
| 357 |  | 
| 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 |  | 
| 369 |     inline int32_t toInt32(double val) | 
| 370 |     { | 
| 371 |         if (!(val >= -2147483648.0 && val < 2147483648.0)) { | 
| 372 |             bool ignored; | 
| 373 |             return toInt32SlowCase(val, ok&: ignored); | 
| 374 |         } | 
| 375 |         return static_cast<int32_t>(val); | 
| 376 |     } | 
| 377 |  | 
| 378 |     inline uint32_t toUInt32(double val) | 
| 379 |     { | 
| 380 |         if (!(val >= 0.0 && val < 4294967296.0)) { | 
| 381 |             bool ignored; | 
| 382 |             return toUInt32SlowCase(val, ok&: 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 |  | 
| 390 |     inline JSCell* asCell(JSValue value) | 
| 391 |     { | 
| 392 |         return value.asCell(); | 
| 393 |     } | 
| 394 |  | 
| 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), ok&: ignored); | 
| 401 |     } | 
| 402 |  | 
| 403 |     inline uint32_t JSValue::toUInt32(ExecState* exec) const | 
| 404 |     { | 
| 405 |         if (isUInt32()) | 
| 406 |             return asInt32(); | 
| 407 |         bool ignored; | 
| 408 |         return toUInt32SlowCase(toNumber(exec), ok&: ignored); | 
| 409 |     } | 
| 410 |  | 
| 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 |  | 
| 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) | 
| 430 |     inline JSValue jsNaN(ExecState* exec) | 
| 431 |     { | 
| 432 |         return JSValue(exec, nonInlineNaN()); | 
| 433 |     } | 
| 434 |  | 
| 435 |     // JSValue member functions. | 
| 436 |     inline EncodedJSValue JSValue::encode(JSValue value) | 
| 437 |     { | 
| 438 |         return value.u.asEncodedJSValue; | 
| 439 |     } | 
| 440 |  | 
| 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 |  | 
| 451 |     inline JSValue::JSValue() | 
| 452 |     { | 
| 453 |         u.asBits.tag = EmptyValueTag; | 
| 454 |         u.asBits.payload = 0; | 
| 455 |     } | 
| 456 |  | 
| 457 |     inline JSValue::JSValue(JSNullTag) | 
| 458 |     { | 
| 459 |         u.asBits.tag = NullTag; | 
| 460 |         u.asBits.payload = 0; | 
| 461 |     } | 
| 462 |      | 
| 463 |     inline JSValue::JSValue(JSUndefinedTag) | 
| 464 |     { | 
| 465 |         u.asBits.tag = UndefinedTag; | 
| 466 |         u.asBits.payload = 0; | 
| 467 |     } | 
| 468 |      | 
| 469 |     inline JSValue::JSValue(JSTrueTag) | 
| 470 |     { | 
| 471 |         u.asBits.tag = TrueTag; | 
| 472 |         u.asBits.payload = 0; | 
| 473 |     } | 
| 474 |      | 
| 475 |     inline JSValue::JSValue(JSFalseTag) | 
| 476 |     { | 
| 477 |         u.asBits.tag = FalseTag; | 
| 478 |         u.asBits.payload = 0; | 
| 479 |     } | 
| 480 |  | 
| 481 |     inline JSValue::JSValue(HashTableDeletedValueTag) | 
| 482 |     { | 
| 483 |         u.asBits.tag = DeletedValueTag; | 
| 484 |         u.asBits.payload = 0; | 
| 485 |     } | 
| 486 |  | 
| 487 |     inline JSValue::JSValue(JSCell* ptr) | 
| 488 |     { | 
| 489 |         if (ptr) | 
| 490 |             u.asBits.tag = CellTag; | 
| 491 |         else | 
| 492 |             u.asBits.tag = EmptyValueTag; | 
| 493 |         u.asBits.payload = reinterpret_cast<int32_t>(ptr); | 
| 494 | #if ENABLE(JSC_ZOMBIES) | 
| 495 |         ASSERT(!isZombie()); | 
| 496 | #endif | 
| 497 |     } | 
| 498 |  | 
| 499 |     inline JSValue::JSValue(const JSCell* ptr) | 
| 500 |     { | 
| 501 |         if (ptr) | 
| 502 |             u.asBits.tag = CellTag; | 
| 503 |         else | 
| 504 |             u.asBits.tag = EmptyValueTag; | 
| 505 |         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); | 
| 506 | #if ENABLE(JSC_ZOMBIES) | 
| 507 |         ASSERT(!isZombie()); | 
| 508 | #endif | 
| 509 |     } | 
| 510 |  | 
| 511 |     inline JSValue::operator bool() const | 
| 512 |     { | 
| 513 |         ASSERT(tag() != DeletedValueTag); | 
| 514 |         return tag() != EmptyValueTag; | 
| 515 |     } | 
| 516 |  | 
| 517 |     inline bool JSValue::operator==(const JSValue& other) const | 
| 518 |     { | 
| 519 |         return u.asEncodedJSValue == other.u.asEncodedJSValue; | 
| 520 |     } | 
| 521 |  | 
| 522 |     inline bool JSValue::operator!=(const JSValue& other) const | 
| 523 |     { | 
| 524 |         return u.asEncodedJSValue != other.u.asEncodedJSValue; | 
| 525 |     } | 
| 526 |  | 
| 527 |     inline bool JSValue::isUndefined() const | 
| 528 |     { | 
| 529 |         return tag() == UndefinedTag; | 
| 530 |     } | 
| 531 |  | 
| 532 |     inline bool JSValue::isNull() const | 
| 533 |     { | 
| 534 |         return tag() == NullTag; | 
| 535 |     } | 
| 536 |  | 
| 537 |     inline bool JSValue::isUndefinedOrNull() const | 
| 538 |     { | 
| 539 |         return isUndefined() || isNull(); | 
| 540 |     } | 
| 541 |  | 
| 542 |     inline bool JSValue::isCell() const | 
| 543 |     { | 
| 544 |         return tag() == CellTag; | 
| 545 |     } | 
| 546 |  | 
| 547 |     inline bool JSValue::isInt32() const | 
| 548 |     { | 
| 549 |         return tag() == Int32Tag; | 
| 550 |     } | 
| 551 |  | 
| 552 |     inline bool JSValue::isUInt32() const | 
| 553 |     { | 
| 554 |         return tag() == Int32Tag && asInt32() > -1; | 
| 555 |     } | 
| 556 |  | 
| 557 |     inline bool JSValue::isDouble() const | 
| 558 |     { | 
| 559 |         return tag() < LowestTag; | 
| 560 |     } | 
| 561 |  | 
| 562 |     inline bool JSValue::isTrue() const | 
| 563 |     { | 
| 564 |         return tag() == TrueTag; | 
| 565 |     } | 
| 566 |  | 
| 567 |     inline bool JSValue::isFalse() const | 
| 568 |     { | 
| 569 |         return tag() == FalseTag; | 
| 570 |     } | 
| 571 |  | 
| 572 |     inline uint32_t JSValue::tag() const | 
| 573 |     { | 
| 574 |         return u.asBits.tag; | 
| 575 |     } | 
| 576 |      | 
| 577 |     inline int32_t JSValue::payload() const | 
| 578 |     { | 
| 579 |         return u.asBits.payload; | 
| 580 |     } | 
| 581 |      | 
| 582 |     inline int32_t JSValue::asInt32() const | 
| 583 |     { | 
| 584 |         ASSERT(isInt32()); | 
| 585 |         return u.asBits.payload; | 
| 586 |     } | 
| 587 |      | 
| 588 |     inline uint32_t JSValue::asUInt32() const | 
| 589 |     { | 
| 590 |         ASSERT(isUInt32()); | 
| 591 |         return u.asBits.payload; | 
| 592 |     } | 
| 593 |      | 
| 594 |     inline double JSValue::asDouble() const | 
| 595 |     { | 
| 596 |         ASSERT(isDouble()); | 
| 597 |         return u.asDouble; | 
| 598 |     } | 
| 599 |      | 
| 600 |     ALWAYS_INLINE JSCell* JSValue::asCell() const | 
| 601 |     { | 
| 602 |         ASSERT(isCell()); | 
| 603 |         return reinterpret_cast<JSCell*>(u.asBits.payload); | 
| 604 |     } | 
| 605 |  | 
| 606 |     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) | 
| 607 |     { | 
| 608 |         u.asDouble = d; | 
| 609 |     } | 
| 610 |  | 
| 611 |     inline JSValue::JSValue(ExecState* exec, double d) | 
| 612 |     { | 
| 613 |         const int32_t asInt32 = static_cast<int32_t>(d); | 
| 614 |         if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0 | 
| 615 |             u.asDouble = d; | 
| 616 |             return; | 
| 617 |         } | 
| 618 |         *this = JSValue(exec, static_cast<int32_t>(d)); | 
| 619 |     } | 
| 620 |  | 
| 621 |     inline JSValue::JSValue(ExecState* exec, char i) | 
| 622 |     { | 
| 623 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 624 |     } | 
| 625 |  | 
| 626 |     inline JSValue::JSValue(ExecState* exec, unsigned char i) | 
| 627 |     { | 
| 628 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 629 |     } | 
| 630 |  | 
| 631 |     inline JSValue::JSValue(ExecState* exec, short i) | 
| 632 |     { | 
| 633 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 634 |     } | 
| 635 |  | 
| 636 |     inline JSValue::JSValue(ExecState* exec, unsigned short i) | 
| 637 |     { | 
| 638 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 639 |     } | 
| 640 |  | 
| 641 |     inline JSValue::JSValue(ExecState*, int i) | 
| 642 |     { | 
| 643 |         u.asBits.tag = Int32Tag; | 
| 644 |         u.asBits.payload = i; | 
| 645 |     } | 
| 646 |  | 
| 647 |     inline JSValue::JSValue(ExecState* exec, unsigned i) | 
| 648 |     { | 
| 649 |         if (static_cast<int32_t>(i) < 0) { | 
| 650 |             *this = JSValue(exec, static_cast<double>(i)); | 
| 651 |             return; | 
| 652 |         } | 
| 653 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 654 |     } | 
| 655 |  | 
| 656 |     inline JSValue::JSValue(ExecState* exec, long i) | 
| 657 |     { | 
| 658 |         if (static_cast<int32_t>(i) != i) { | 
| 659 |             *this = JSValue(exec, static_cast<double>(i)); | 
| 660 |             return; | 
| 661 |         } | 
| 662 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 663 |     } | 
| 664 |  | 
| 665 |     inline JSValue::JSValue(ExecState* exec, unsigned long i) | 
| 666 |     { | 
| 667 |         if (static_cast<uint32_t>(i) != i) { | 
| 668 |             *this = JSValue(exec, static_cast<double>(i)); | 
| 669 |             return; | 
| 670 |         } | 
| 671 |         *this = JSValue(exec, static_cast<uint32_t>(i)); | 
| 672 |     } | 
| 673 |  | 
| 674 |     inline JSValue::JSValue(ExecState* exec, long long i) | 
| 675 |     { | 
| 676 |         if (static_cast<int32_t>(i) != i) { | 
| 677 |             *this = JSValue(exec, static_cast<double>(i)); | 
| 678 |             return; | 
| 679 |         } | 
| 680 |         *this = JSValue(exec, static_cast<int32_t>(i)); | 
| 681 |     } | 
| 682 |  | 
| 683 |     inline JSValue::JSValue(ExecState* exec, unsigned long long i) | 
| 684 |     { | 
| 685 |         if (static_cast<uint32_t>(i) != i) { | 
| 686 |             *this = JSValue(exec, static_cast<double>(i)); | 
| 687 |             return; | 
| 688 |         } | 
| 689 |         *this = JSValue(exec, static_cast<uint32_t>(i)); | 
| 690 |     } | 
| 691 |  | 
| 692 |     inline JSValue::JSValue(JSGlobalData* globalData, double d) | 
| 693 |     { | 
| 694 |         const int32_t asInt32 = static_cast<int32_t>(d); | 
| 695 |         if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0 | 
| 696 |             u.asDouble = d; | 
| 697 |             return; | 
| 698 |         } | 
| 699 |         *this = JSValue(globalData, static_cast<int32_t>(d)); | 
| 700 |     } | 
| 701 |      | 
| 702 |     inline JSValue::JSValue(JSGlobalData*, int i) | 
| 703 |     { | 
| 704 |         u.asBits.tag = Int32Tag; | 
| 705 |         u.asBits.payload = i; | 
| 706 |     } | 
| 707 |      | 
| 708 |     inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) | 
| 709 |     { | 
| 710 |         if (static_cast<int32_t>(i) < 0) { | 
| 711 |             *this = JSValue(globalData, static_cast<double>(i)); | 
| 712 |             return; | 
| 713 |         } | 
| 714 |         *this = JSValue(globalData, static_cast<int32_t>(i)); | 
| 715 |     } | 
| 716 |  | 
| 717 |     inline bool JSValue::isNumber() const | 
| 718 |     { | 
| 719 |         return isInt32() || isDouble(); | 
| 720 |     } | 
| 721 |  | 
| 722 |     inline bool JSValue::isBoolean() const | 
| 723 |     { | 
| 724 |         return isTrue() || isFalse(); | 
| 725 |     } | 
| 726 |  | 
| 727 |     inline bool JSValue::getBoolean(bool& v) const | 
| 728 |     { | 
| 729 |         if (isTrue()) { | 
| 730 |             v = true; | 
| 731 |             return true; | 
| 732 |         } | 
| 733 |         if (isFalse()) { | 
| 734 |             v = false; | 
| 735 |             return true; | 
| 736 |         } | 
| 737 |          | 
| 738 |         return false; | 
| 739 |     } | 
| 740 |  | 
| 741 |     inline bool JSValue::getBoolean() const | 
| 742 |     { | 
| 743 |         ASSERT(isBoolean()); | 
| 744 |         return tag() == TrueTag; | 
| 745 |     } | 
| 746 |  | 
| 747 |     inline double JSValue::uncheckedGetNumber() const | 
| 748 |     { | 
| 749 |         ASSERT(isNumber()); | 
| 750 |         return isInt32() ? asInt32() : asDouble(); | 
| 751 |     } | 
| 752 |  | 
| 753 |     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const | 
| 754 |     { | 
| 755 |         return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec)); | 
| 756 |     } | 
| 757 |  | 
| 758 |     inline bool JSValue::getNumber(double& result) const | 
| 759 |     { | 
| 760 |         if (isInt32()) { | 
| 761 |             result = asInt32(); | 
| 762 |             return true; | 
| 763 |         } | 
| 764 |         if (isDouble()) { | 
| 765 |             result = asDouble(); | 
| 766 |             return true; | 
| 767 |         } | 
| 768 |         return false; | 
| 769 |     } | 
| 770 |  | 
| 771 | #else // USE(JSVALUE32_64) | 
| 772 |  | 
| 773 |     // JSValue member functions. | 
| 774 |     inline EncodedJSValue JSValue::encode(JSValue value) | 
| 775 |     { | 
| 776 |         EncodedJSValue r; | 
| 777 |         memcpy(dest: &r, src: &value.m_ptr, n: sizeof(r)); | 
| 778 |         return r; | 
| 779 |     } | 
| 780 |  | 
| 781 |     inline JSValue JSValue::decode(EncodedJSValue ptr) | 
| 782 |     { | 
| 783 |         JSCell *cellPtr; | 
| 784 |         memcpy(dest: &cellPtr, src: &ptr, n: sizeof(cellPtr)); | 
| 785 |         return JSValue(cellPtr); | 
| 786 |     } | 
| 787 |  | 
| 788 |     inline JSValue JSValue::makeImmediate(intptr_t value) | 
| 789 |     { | 
| 790 |         JSCell *cellPtr; | 
| 791 |         memcpy(dest: &cellPtr, src: &value, n: sizeof(cellPtr)); | 
| 792 |         return JSValue(cellPtr); | 
| 793 |     } | 
| 794 |  | 
| 795 |     inline intptr_t JSValue::immediateValue() | 
| 796 |     { | 
| 797 |         intptr_t v; | 
| 798 |         memcpy(dest: &v, src: &m_ptr, n: sizeof(v)); | 
| 799 |         return v; | 
| 800 |     } | 
| 801 |      | 
| 802 |     // 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. | 
| 803 |     inline JSValue::JSValue() | 
| 804 |         : m_ptr(0) | 
| 805 |     { | 
| 806 |     } | 
| 807 |  | 
| 808 |     // 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. | 
| 809 |     inline JSValue::JSValue(HashTableDeletedValueTag) | 
| 810 |         : m_ptr(reinterpret_cast<JSCell*>(0x4)) | 
| 811 |     { | 
| 812 |     } | 
| 813 |  | 
| 814 |     inline JSValue::JSValue(JSCell* ptr) | 
| 815 |         : m_ptr(ptr) | 
| 816 |     { | 
| 817 | #if ENABLE(JSC_ZOMBIES) | 
| 818 |         ASSERT(!isZombie()); | 
| 819 | #endif | 
| 820 |     } | 
| 821 |  | 
| 822 |     inline JSValue::JSValue(const JSCell* ptr) | 
| 823 |         : m_ptr(const_cast<JSCell*>(ptr)) | 
| 824 |     { | 
| 825 | #if ENABLE(JSC_ZOMBIES) | 
| 826 |         ASSERT(!isZombie()); | 
| 827 | #endif | 
| 828 |     } | 
| 829 |  | 
| 830 |     inline JSValue::operator bool() const | 
| 831 |     { | 
| 832 |         return m_ptr; | 
| 833 |     } | 
| 834 |  | 
| 835 |     inline bool JSValue::operator==(const JSValue& other) const | 
| 836 |     { | 
| 837 |         return m_ptr == other.m_ptr; | 
| 838 |     } | 
| 839 |  | 
| 840 |     inline bool JSValue::operator!=(const JSValue& other) const | 
| 841 |     { | 
| 842 |         return m_ptr != other.m_ptr; | 
| 843 |     } | 
| 844 |  | 
| 845 |     inline bool JSValue::isUndefined() const | 
| 846 |     { | 
| 847 |         return asValue() == jsUndefined(); | 
| 848 |     } | 
| 849 |  | 
| 850 |     inline bool JSValue::isNull() const | 
| 851 |     { | 
| 852 |         return asValue() == jsNull(); | 
| 853 |     } | 
| 854 | #endif // USE(JSVALUE32_64) | 
| 855 |  | 
| 856 | } // namespace JSC | 
| 857 |  | 
| 858 | #endif // JSValue_h | 
| 859 |  |