]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSValueInlineMethods.h
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / runtime / JSValueInlineMethods.h
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
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
40 inline uint32_t JSValue::toUInt32(ExecState* exec) const
41 {
42 // See comment on JSC::toUInt32, above.
43 return toInt32(exec);
44 }
45
46 inline bool JSValue::isUInt32() const
47 {
48 return isInt32() && asInt32() >= 0;
49 }
50
51 inline uint32_t JSValue::asUInt32() const
52 {
53 ASSERT(isUInt32());
54 return asInt32();
55 }
56
57 inline double JSValue::uncheckedGetNumber() const
58 {
59 ASSERT(isNumber());
60 return isInt32() ? asInt32() : asDouble();
61 }
62
63 ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
64 {
65 return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
66 }
67
68 inline JSValue jsNaN()
69 {
70 return JSValue(nonInlineNaN());
71 }
72
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
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
100 inline JSValue::JSValue(char i)
101 {
102 *this = JSValue(static_cast<int32_t>(i));
103 }
104
105 inline JSValue::JSValue(unsigned char i)
106 {
107 *this = JSValue(static_cast<int32_t>(i));
108 }
109
110 inline JSValue::JSValue(short i)
111 {
112 *this = JSValue(static_cast<int32_t>(i));
113 }
114
115 inline JSValue::JSValue(unsigned short i)
116 {
117 *this = JSValue(static_cast<int32_t>(i));
118 }
119
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
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
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
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
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
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)
176 inline EncodedJSValue JSValue::encode(JSValue value)
177 {
178 return value.u.asInt64;
179 }
180
181 inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
182 {
183 JSValue v;
184 v.u.asInt64 = encodedJSValue;
185 return v;
186 }
187
188 inline JSValue::JSValue()
189 {
190 u.asBits.tag = EmptyValueTag;
191 u.asBits.payload = 0;
192 }
193
194 inline JSValue::JSValue(JSNullTag)
195 {
196 u.asBits.tag = NullTag;
197 u.asBits.payload = 0;
198 }
199
200 inline JSValue::JSValue(JSUndefinedTag)
201 {
202 u.asBits.tag = UndefinedTag;
203 u.asBits.payload = 0;
204 }
205
206 inline JSValue::JSValue(JSTrueTag)
207 {
208 u.asBits.tag = BooleanTag;
209 u.asBits.payload = 1;
210 }
211
212 inline JSValue::JSValue(JSFalseTag)
213 {
214 u.asBits.tag = BooleanTag;
215 u.asBits.payload = 0;
216 }
217
218 inline JSValue::JSValue(HashTableDeletedValueTag)
219 {
220 u.asBits.tag = DeletedValueTag;
221 u.asBits.payload = 0;
222 }
223
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
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
264 inline bool JSValue::isUndefined() const
265 {
266 return tag() == UndefinedTag;
267 }
268
269 inline bool JSValue::isNull() const
270 {
271 return tag() == NullTag;
272 }
273
274 inline bool JSValue::isUndefinedOrNull() const
275 {
276 return isUndefined() || isNull();
277 }
278
279 inline bool JSValue::isCell() const
280 {
281 return tag() == CellTag;
282 }
283
284 inline bool JSValue::isInt32() const
285 {
286 return tag() == Int32Tag;
287 }
288
289 inline bool JSValue::isDouble() const
290 {
291 return tag() < LowestTag;
292 }
293
294 inline bool JSValue::isTrue() const
295 {
296 return tag() == BooleanTag && payload();
297 }
298
299 inline bool JSValue::isFalse() const
300 {
301 return tag() == BooleanTag && !payload();
302 }
303
304 inline uint32_t JSValue::tag() const
305 {
306 return u.asBits.tag;
307 }
308
309 inline int32_t JSValue::payload() const
310 {
311 return u.asBits.payload;
312 }
313
314 inline int32_t JSValue::asInt32() const
315 {
316 ASSERT(isInt32());
317 return u.asBits.payload;
318 }
319
320 inline double JSValue::asDouble() const
321 {
322 ASSERT(isDouble());
323 return u.asDouble;
324 }
325
326 ALWAYS_INLINE JSCell* JSValue::asCell() const
327 {
328 ASSERT(isCell());
329 return reinterpret_cast<JSCell*>(u.asBits.payload);
330 }
331
332 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
333 {
334 u.asDouble = d;
335 }
336
337 inline JSValue::JSValue(int i)
338 {
339 u.asBits.tag = Int32Tag;
340 u.asBits.payload = i;
341 }
342
343 inline bool JSValue::isNumber() const
344 {
345 return isInt32() || isDouble();
346 }
347
348 inline bool JSValue::isBoolean() const
349 {
350 return isTrue() || isFalse();
351 }
352
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.
362 inline EncodedJSValue JSValue::encode(JSValue value)
363 {
364 return value.u.ptr;
365 }
366
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.
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.
379 inline JSValue::JSValue(HashTableDeletedValueTag)
380 {
381 u.asInt64 = ValueDeleted;
382 }
383
384 inline JSValue::JSValue(JSCell* ptr)
385 {
386 u.ptr = ptr;
387 #if ENABLE(JSC_ZOMBIES)
388 ASSERT(!isZombie());
389 #endif
390 }
391
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
415 inline bool JSValue::isUndefined() const
416 {
417 return asValue() == jsUndefined();
418 }
419
420 inline bool JSValue::isNull() const
421 {
422 return asValue() == jsNull();
423 }
424
425 inline bool JSValue::isTrue() const
426 {
427 return asValue() == JSValue(JSTrue);
428 }
429
430 inline bool JSValue::isFalse() const
431 {
432 return asValue() == JSValue(JSFalse);
433 }
434
435 inline bool JSValue::getBoolean() const
436 {
437 ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
438 return asValue() == jsBoolean(true);
439 }
440
441 inline int32_t JSValue::asInt32() const
442 {
443 ASSERT(isInt32());
444 return static_cast<int32_t>(u.asInt64);
445 }
446
447 inline bool JSValue::isDouble() const
448 {
449 return isNumber() && !isInt32();
450 }
451
452 inline JSValue::JSValue(JSNullTag)
453 {
454 u.asInt64 = ValueNull;
455 }
456
457 inline JSValue::JSValue(JSUndefinedTag)
458 {
459 u.asInt64 = ValueUndefined;
460 }
461
462 inline JSValue::JSValue(JSTrueTag)
463 {
464 u.asInt64 = ValueTrue;
465 }
466
467 inline JSValue::JSValue(JSFalseTag)
468 {
469 u.asInt64 = ValueFalse;
470 }
471
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
478 inline bool JSValue::isBoolean() const
479 {
480 return (u.asInt64 & ~1) == ValueFalse;
481 }
482
483 inline bool JSValue::isCell() const
484 {
485 return !(u.asInt64 & TagMask);
486 }
487
488 inline bool JSValue::isInt32() const
489 {
490 return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
491 }
492
493 inline intptr_t reinterpretDoubleToIntptr(double value)
494 {
495 return bitwise_cast<intptr_t>(value);
496 }
497 inline double reinterpretIntptrToDouble(intptr_t value)
498 {
499 return bitwise_cast<double>(value);
500 }
501
502 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
503 {
504 u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
505 }
506
507 inline JSValue::JSValue(int i)
508 {
509 u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
510 }
511
512 inline double JSValue::asDouble() const
513 {
514 return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
515 }
516
517 inline bool JSValue::isNumber() const
518 {
519 return u.asInt64 & TagTypeNumber;
520 }
521
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