Changeset 35027 in webkit for trunk/JavaScriptCore/kjs/JSImmediate.h
- Timestamp:
- Jul 6, 2008, 7:49:29 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSImmediate.h
r34943 r35027 34 34 namespace KJS { 35 35 36 class ExecState; 37 class JSObject; 38 class JSValue; 39 class UString; 40 41 /* 42 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 43 * signed int masquerading as a pointer). The low two bits in a JSValue* are available 44 * for type tagging because allocator alignment guarantees they will be 00 in cell pointers. 45 * 46 * For example, on a 32 bit system: 47 * 48 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00 49 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ] 50 * 51 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT 52 * [ high 30 bits: signed int ] [ low 2 bits -- type tag ] 53 * 54 * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false 55 * and undefined/null. 56 * 57 * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits 58 * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has 59 * to sort them out. 60 */ 61 62 class JSImmediate { 63 public: 64 static ALWAYS_INLINE bool isImmediate(const JSValue* v) 65 { 66 return getTag(v) != 0; 67 } 68 69 static ALWAYS_INLINE bool isNumber(const JSValue* v) 70 { 71 return (getTag(v) == NumberType); 72 } 73 74 static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v) 75 { 76 // A single mask to check for the sign bit and the number tag all at once. 77 return (reinterpret_cast<uintptr_t>(v) & (0x80000000 | NumberType)) == NumberType; 78 } 79 80 static ALWAYS_INLINE bool isBoolean(const JSValue* v) 81 { 82 return (getTag(v) == BooleanType); 83 } 84 85 // Since we have room for only 3 unique tags, null and undefined have to share. 86 static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v) 87 { 88 return (getTag(v) == UndefinedType); 89 } 90 91 static bool isNegative(const JSValue* v) 36 class ExecState; 37 class JSObject; 38 class JSValue; 39 class UString; 40 41 /* 42 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 43 * signed int masquerading as a pointer). The low two bits in a JSValue* are available 44 * for type tagging because allocator alignment guarantees they will be 00 in cell pointers. 45 * 46 * For example, on a 32 bit system: 47 * 48 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00 49 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ] 50 * 51 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT 52 * [ high 30 bits: signed int ] [ low 2 bits -- type tag ] 53 * 54 * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false 55 * and undefined/null. 56 * 57 * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits 58 * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has 59 * to sort them out. 60 */ 61 62 class JSImmediate { 63 public: 64 static ALWAYS_INLINE bool isImmediate(const JSValue* v) 65 { 66 return getTag(v) != 0; 67 } 68 69 static ALWAYS_INLINE bool isNumber(const JSValue* v) 70 { 71 return (getTag(v) == NumberType); 72 } 73 74 static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v) 75 { 76 // A single mask to check for the sign bit and the number tag all at once. 77 return (reinterpret_cast<uintptr_t>(v) & (0x80000000 | NumberType)) == NumberType; 78 } 79 80 static ALWAYS_INLINE bool isBoolean(const JSValue* v) 81 { 82 return (getTag(v) == BooleanType); 83 } 84 85 // Since we have room for only 3 unique tags, null and undefined have to share. 86 static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v) 87 { 88 return (getTag(v) == UndefinedType); 89 } 90 91 static bool isNegative(const JSValue* v) 92 { 93 ASSERT(isNumber(v)); 94 return reinterpret_cast<uintptr_t>(v) & 0x80000000; 95 } 96 97 static JSValue* from(char); 98 static JSValue* from(signed char); 99 static JSValue* from(unsigned char); 100 static JSValue* from(short); 101 static JSValue* from(unsigned short); 102 static JSValue* from(int); 103 static JSValue* from(unsigned); 104 static JSValue* from(long); 105 static JSValue* from(unsigned long); 106 static JSValue* from(long long); 107 static JSValue* from(unsigned long long); 108 static JSValue* from(double); 109 110 static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2) 111 { 112 return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType; 113 } 114 115 static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2) 116 { 117 ASSERT(areBothImmediateNumbers(v1, v2)); 118 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2)); 119 } 120 121 static ALWAYS_INLINE JSValue* xorImmediateNumbers(const JSValue* v1, const JSValue* v2) 122 { 123 ASSERT(areBothImmediateNumbers(v1, v2)); 124 return tag(reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2), NumberType); 125 } 126 127 static ALWAYS_INLINE JSValue* orImmediateNumbers(const JSValue* v1, const JSValue* v2) 128 { 129 ASSERT(areBothImmediateNumbers(v1, v2)); 130 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)); 131 } 132 133 static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(const JSValue* val, const JSValue* shift) 134 { 135 ASSERT(areBothImmediateNumbers(val, shift)); 136 return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> 2) & 0x1f)) | NumberType); 137 } 138 139 static ALWAYS_INLINE bool canDoFastAdditiveOperations(const JSValue* v) 140 { 141 // Number is non-negative and an operation involving two of these can't overflow. 142 // Checking for allowed negative numbers takes more time than it's worth on SunSpider. 143 return (reinterpret_cast<uintptr_t>(v) & (NumberType + (3 << 30))) == NumberType; 144 } 145 146 static ALWAYS_INLINE JSValue* addImmediateNumbers(const JSValue* v1, const JSValue* v2) 147 { 148 ASSERT(canDoFastAdditiveOperations(v1)); 149 ASSERT(canDoFastAdditiveOperations(v2)); 150 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 151 } 152 153 static ALWAYS_INLINE JSValue* subImmediateNumbers(const JSValue* v1, const JSValue* v2) 154 { 155 ASSERT(canDoFastAdditiveOperations(v1)); 156 ASSERT(canDoFastAdditiveOperations(v2)); 157 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 158 } 159 160 static ALWAYS_INLINE JSValue* incImmediateNumber(const JSValue* v) 161 { 162 ASSERT(canDoFastAdditiveOperations(v)); 163 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + TagMask + 1); 164 } 165 166 static ALWAYS_INLINE JSValue* decImmediateNumber(const JSValue* v) 167 { 168 ASSERT(canDoFastAdditiveOperations(v)); 169 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (TagMask + 1)); 170 } 171 172 static double toDouble(const JSValue*); 173 static bool toBoolean(const JSValue*); 174 static JSObject* toObject(const JSValue*, ExecState*); 175 static UString toString(const JSValue*); 176 static uint32_t toTruncatedUInt32(const JSValue*); 177 static JSType type(const JSValue*); 178 179 static bool getUInt32(const JSValue*, uint32_t&); 180 static bool getTruncatedInt32(const JSValue*, int32_t&); 181 static bool getTruncatedUInt32(const JSValue*, uint32_t&); 182 183 static int32_t getTruncatedInt32(const JSValue*); 184 185 static JSValue* trueImmediate(); 186 static JSValue* falseImmediate(); 187 static JSValue* undefinedImmediate(); 188 static JSValue* nullImmediate(); 189 190 static JSValue* impossibleValue(); 191 192 static JSObject* prototype(const JSValue*, ExecState*); 193 194 private: 195 static const uintptr_t TagMask = 3; // type tags are 2 bits long 196 197 // Immediate values are restricted to a 30 bit signed value. 198 static const int minImmediateInt = -(1 << 29); 199 static const int maxImmediateInt = (1 << 29) - 1; 200 static const unsigned maxImmediateUInt = maxImmediateInt; 201 202 static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag) 203 { 204 return reinterpret_cast<JSValue*>(bits | tag); 205 } 206 207 static ALWAYS_INLINE uintptr_t unTag(const JSValue* v) 208 { 209 return reinterpret_cast<uintptr_t>(v) & ~TagMask; 210 } 211 212 static ALWAYS_INLINE uintptr_t getTag(const JSValue* v) 213 { 214 return reinterpret_cast<uintptr_t>(v) & TagMask; 215 } 216 }; 217 218 ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); } 219 ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); } 220 ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); } 221 ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); } 222 223 // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate 224 ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return tag(1 << 2, 0); } 225 226 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v) 227 { 228 ASSERT(isImmediate(v)); 229 uintptr_t bits = unTag(v); 230 return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType); 231 } 232 233 ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v) 234 { 235 ASSERT(isImmediate(v)); 236 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(v) >> 2); 237 } 238 239 ALWAYS_INLINE JSValue* JSImmediate::from(char i) 240 { 241 return tag(i << 2, NumberType); 242 } 243 244 ALWAYS_INLINE JSValue* JSImmediate::from(signed char i) 245 { 246 return tag(i << 2, NumberType); 247 } 248 249 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i) 250 { 251 return tag(i << 2, NumberType); 252 } 253 254 ALWAYS_INLINE JSValue* JSImmediate::from(short i) 255 { 256 return tag(i << 2, NumberType); 257 } 258 259 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i) 260 { 261 return tag(i << 2, NumberType); 262 } 263 264 ALWAYS_INLINE JSValue* JSImmediate::from(int i) 265 { 266 if ((i < minImmediateInt) | (i > maxImmediateInt)) 267 return 0; 268 return tag(i << 2, NumberType); 269 } 270 271 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i) 272 { 273 if (i > maxImmediateUInt) 274 return 0; 275 return tag(i << 2, NumberType); 276 } 277 278 ALWAYS_INLINE JSValue* JSImmediate::from(long i) 279 { 280 if ((i < minImmediateInt) | (i > maxImmediateInt)) 281 return 0; 282 return tag(i << 2, NumberType); 283 } 284 285 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i) 286 { 287 if (i > maxImmediateUInt) 288 return 0; 289 return tag(i << 2, NumberType); 290 } 291 292 ALWAYS_INLINE JSValue* JSImmediate::from(long long i) 293 { 294 if ((i < minImmediateInt) | (i > maxImmediateInt)) 295 return 0; 296 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 297 } 298 299 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i) 300 { 301 if (i > maxImmediateUInt) 302 return 0; 303 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 304 } 305 306 ALWAYS_INLINE JSValue* JSImmediate::from(double d) 307 { 308 const int intVal = static_cast<int>(d); 309 310 if ((intVal < minImmediateInt) | (intVal > maxImmediateInt)) 311 return 0; 312 313 // Check for data loss from conversion to int. 314 if ((intVal != d) || (!intVal && signbit(d))) 315 return 0; 316 317 return tag(intVal << 2, NumberType); 318 } 319 320 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v) 92 321 { 93 322 ASSERT(isNumber(v)); 94 return reinterpret_cast<uintptr_t>(v) & 0x80000000; 95 } 96 97 static JSValue* from(char); 98 static JSValue* from(signed char); 99 static JSValue* from(unsigned char); 100 static JSValue* from(short); 101 static JSValue* from(unsigned short); 102 static JSValue* from(int); 103 static JSValue* from(unsigned); 104 static JSValue* from(long); 105 static JSValue* from(unsigned long); 106 static JSValue* from(long long); 107 static JSValue* from(unsigned long long); 108 static JSValue* from(double); 109 110 static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2) 111 { 112 return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType; 113 } 114 115 static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2) 116 { 117 ASSERT(areBothImmediateNumbers(v1, v2)); 118 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2)); 119 } 120 121 static ALWAYS_INLINE JSValue* xorImmediateNumbers(const JSValue* v1, const JSValue* v2) 122 { 123 ASSERT(areBothImmediateNumbers(v1, v2)); 124 return tag(reinterpret_cast<uintptr_t>(v1) ^ reinterpret_cast<uintptr_t>(v2), NumberType); 125 } 126 127 static ALWAYS_INLINE JSValue* orImmediateNumbers(const JSValue* v1, const JSValue* v2) 128 { 129 ASSERT(areBothImmediateNumbers(v1, v2)); 130 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)); 131 } 132 133 static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(const JSValue* val, const JSValue* shift) 134 { 135 ASSERT(areBothImmediateNumbers(val, shift)); 136 return reinterpret_cast<JSValue*>((reinterpret_cast<intptr_t>(val) >> ((reinterpret_cast<uintptr_t>(shift) >> 2) & 0x1f)) | NumberType); 137 } 138 139 static ALWAYS_INLINE bool canDoFastAdditiveOperations(const JSValue* v) 140 { 141 // Number is non-negative and an operation involving two of these can't overflow. 142 // Checking for allowed negative numbers takes more time than it's worth on SunSpider. 143 return (reinterpret_cast<uintptr_t>(v) & (NumberType + (3 << 30))) == NumberType; 144 } 145 146 static ALWAYS_INLINE JSValue* addImmediateNumbers(const JSValue* v1, const JSValue* v2) 147 { 148 ASSERT(canDoFastAdditiveOperations(v1)); 149 ASSERT(canDoFastAdditiveOperations(v2)); 150 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) + (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 151 } 152 153 static ALWAYS_INLINE JSValue* subImmediateNumbers(const JSValue* v1, const JSValue* v2) 154 { 155 ASSERT(canDoFastAdditiveOperations(v1)); 156 ASSERT(canDoFastAdditiveOperations(v2)); 157 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) - (reinterpret_cast<uintptr_t>(v2) & ~NumberType)); 158 } 159 160 static ALWAYS_INLINE JSValue* incImmediateNumber(const JSValue* v) 161 { 162 ASSERT(canDoFastAdditiveOperations(v)); 163 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) + TagMask + 1); 164 } 165 166 static ALWAYS_INLINE JSValue* decImmediateNumber(const JSValue* v) 167 { 168 ASSERT(canDoFastAdditiveOperations(v)); 169 return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v) - (TagMask + 1)); 170 } 171 172 static double toDouble(const JSValue*); 173 static bool toBoolean(const JSValue*); 174 static JSObject* toObject(const JSValue*, ExecState*); 175 static UString toString(const JSValue*); 176 static uint32_t toTruncatedUInt32(const JSValue*); 177 static JSType type(const JSValue*); 178 179 static bool getUInt32(const JSValue*, uint32_t&); 180 static bool getTruncatedInt32(const JSValue*, int32_t&); 181 static bool getTruncatedUInt32(const JSValue*, uint32_t&); 182 183 static int32_t getTruncatedInt32(const JSValue*); 184 185 static JSValue* trueImmediate(); 186 static JSValue* falseImmediate(); 187 static JSValue* undefinedImmediate(); 188 static JSValue* nullImmediate(); 189 190 static JSValue* impossibleValue(); 191 192 static JSObject* prototype(const JSValue*, ExecState*); 193 194 private: 195 static const uintptr_t TagMask = 3; // type tags are 2 bits long 196 197 // Immediate values are restricted to a 30 bit signed value. 198 static const int minImmediateInt = -(1 << 29); 199 static const int maxImmediateInt = (1 << 29) - 1; 200 static const unsigned maxImmediateUInt = maxImmediateInt; 201 202 static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag) 203 { 204 return reinterpret_cast<JSValue*>(bits | tag); 205 } 206 207 static ALWAYS_INLINE uintptr_t unTag(const JSValue* v) 208 { 209 return reinterpret_cast<uintptr_t>(v) & ~TagMask; 210 } 211 212 static ALWAYS_INLINE uintptr_t getTag(const JSValue* v) 213 { 214 return reinterpret_cast<uintptr_t>(v) & TagMask; 215 } 216 }; 217 218 ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); } 219 ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); } 220 ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); } 221 ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); } 222 223 // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate 224 ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return tag(1 << 2, 0); } 225 226 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v) 227 { 228 ASSERT(isImmediate(v)); 229 uintptr_t bits = unTag(v); 230 return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType); 231 } 232 233 ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v) 234 { 235 ASSERT(isImmediate(v)); 236 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(v) >> 2); 237 } 238 239 ALWAYS_INLINE JSValue* JSImmediate::from(char i) 240 { 241 return tag(i << 2, NumberType); 242 } 243 244 ALWAYS_INLINE JSValue* JSImmediate::from(signed char i) 245 { 246 return tag(i << 2, NumberType); 247 } 248 249 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i) 250 { 251 return tag(i << 2, NumberType); 252 } 253 254 ALWAYS_INLINE JSValue* JSImmediate::from(short i) 255 { 256 return tag(i << 2, NumberType); 257 } 258 259 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i) 260 { 261 return tag(i << 2, NumberType); 262 } 263 264 ALWAYS_INLINE JSValue* JSImmediate::from(int i) 265 { 266 if ((i < minImmediateInt) | (i > maxImmediateInt)) 267 return 0; 268 return tag(i << 2, NumberType); 269 } 270 271 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i) 272 { 273 if (i > maxImmediateUInt) 274 return 0; 275 return tag(i << 2, NumberType); 276 } 277 278 ALWAYS_INLINE JSValue* JSImmediate::from(long i) 279 { 280 if ((i < minImmediateInt) | (i > maxImmediateInt)) 281 return 0; 282 return tag(i << 2, NumberType); 283 } 284 285 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i) 286 { 287 if (i > maxImmediateUInt) 288 return 0; 289 return tag(i << 2, NumberType); 290 } 291 292 ALWAYS_INLINE JSValue* JSImmediate::from(long long i) 293 { 294 if ((i < minImmediateInt) | (i > maxImmediateInt)) 295 return 0; 296 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 297 } 298 299 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i) 300 { 301 if (i > maxImmediateUInt) 302 return 0; 303 return tag(static_cast<uintptr_t>(i) << 2, NumberType); 304 } 305 306 ALWAYS_INLINE JSValue* JSImmediate::from(double d) 307 { 308 const int intVal = static_cast<int>(d); 309 310 if ((intVal < minImmediateInt) | (intVal > maxImmediateInt)) 311 return 0; 312 313 // Check for data loss from conversion to int. 314 if ((intVal != d) || (!intVal && signbit(d))) 315 return 0; 316 317 return tag(intVal << 2, NumberType); 318 } 319 320 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v) 321 { 322 ASSERT(isNumber(v)); 323 return static_cast<int32_t>(unTag(v)) >> 2; 324 } 325 326 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v) 327 { 328 ASSERT(isImmediate(v)); 329 const int32_t i = static_cast<int32_t>(unTag(v)) >> 2; 330 if (JSImmediate::getTag(v) == UndefinedType && i) 331 return std::numeric_limits<double>::quiet_NaN(); 332 return i; 333 } 334 335 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i) 336 { 337 i = static_cast<uintptr_t>(unTag(v)) >> 2; 338 return isPositiveNumber(v); 339 } 340 341 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i) 342 { 343 i = static_cast<int32_t>(unTag(v)) >> 2; 344 return isNumber(v); 345 } 346 347 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i) 348 { 349 return getUInt32(v, i); 350 } 351 352 ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v) 353 { 354 ASSERT(isImmediate(v)); 355 356 uintptr_t tag = getTag(v); 357 if (tag == UndefinedType) 358 return v == undefinedImmediate() ? UndefinedType : NullType; 359 return static_cast<JSType>(tag); 360 } 361 362 ALWAYS_INLINE JSValue* jsUndefined() 363 { 364 return JSImmediate::undefinedImmediate(); 365 } 366 367 inline JSValue* jsNull() 368 { 369 return JSImmediate::nullImmediate(); 370 } 371 372 inline JSValue* jsBoolean(bool b) 373 { 374 return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate(); 375 } 323 return static_cast<int32_t>(unTag(v)) >> 2; 324 } 325 326 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v) 327 { 328 ASSERT(isImmediate(v)); 329 const int32_t i = static_cast<int32_t>(unTag(v)) >> 2; 330 if (JSImmediate::getTag(v) == UndefinedType && i) 331 return std::numeric_limits<double>::quiet_NaN(); 332 return i; 333 } 334 335 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i) 336 { 337 i = static_cast<uintptr_t>(unTag(v)) >> 2; 338 return isPositiveNumber(v); 339 } 340 341 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i) 342 { 343 i = static_cast<int32_t>(unTag(v)) >> 2; 344 return isNumber(v); 345 } 346 347 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i) 348 { 349 return getUInt32(v, i); 350 } 351 352 ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v) 353 { 354 ASSERT(isImmediate(v)); 355 356 uintptr_t tag = getTag(v); 357 if (tag == UndefinedType) 358 return v == undefinedImmediate() ? UndefinedType : NullType; 359 return static_cast<JSType>(tag); 360 } 361 362 ALWAYS_INLINE JSValue* jsUndefined() 363 { 364 return JSImmediate::undefinedImmediate(); 365 } 366 367 inline JSValue* jsNull() 368 { 369 return JSImmediate::nullImmediate(); 370 } 371 372 inline JSValue* jsBoolean(bool b) 373 { 374 return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate(); 375 } 376 376 377 377 } // namespace KJS
Note:
See TracChangeset
for help on using the changeset viewer.