]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSValueInlineMethods.h
JavaScriptCore-1097.3.3.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::asNumber() const
58 {
59 ASSERT(isNumber());
60 return isInt32() ? asInt32() : asDouble();
61 }
62
63 inline JSValue jsNaN()
64 {
65 return JSValue(std::numeric_limits<double>::quiet_NaN());
66 }
67
68 inline JSValue::JSValue(char i)
69 {
70 *this = JSValue(static_cast<int32_t>(i));
71 }
72
73 inline JSValue::JSValue(unsigned char i)
74 {
75 *this = JSValue(static_cast<int32_t>(i));
76 }
77
78 inline JSValue::JSValue(short i)
79 {
80 *this = JSValue(static_cast<int32_t>(i));
81 }
82
83 inline JSValue::JSValue(unsigned short i)
84 {
85 *this = JSValue(static_cast<int32_t>(i));
86 }
87
88 inline JSValue::JSValue(unsigned i)
89 {
90 if (static_cast<int32_t>(i) < 0) {
91 *this = JSValue(EncodeAsDouble, static_cast<double>(i));
92 return;
93 }
94 *this = JSValue(static_cast<int32_t>(i));
95 }
96
97 inline JSValue::JSValue(long i)
98 {
99 if (static_cast<int32_t>(i) != i) {
100 *this = JSValue(EncodeAsDouble, static_cast<double>(i));
101 return;
102 }
103 *this = JSValue(static_cast<int32_t>(i));
104 }
105
106 inline JSValue::JSValue(unsigned long i)
107 {
108 if (static_cast<uint32_t>(i) != i) {
109 *this = JSValue(EncodeAsDouble, static_cast<double>(i));
110 return;
111 }
112 *this = JSValue(static_cast<uint32_t>(i));
113 }
114
115 inline JSValue::JSValue(long long i)
116 {
117 if (static_cast<int32_t>(i) != i) {
118 *this = JSValue(EncodeAsDouble, static_cast<double>(i));
119 return;
120 }
121 *this = JSValue(static_cast<int32_t>(i));
122 }
123
124 inline JSValue::JSValue(unsigned long long i)
125 {
126 if (static_cast<uint32_t>(i) != i) {
127 *this = JSValue(EncodeAsDouble, static_cast<double>(i));
128 return;
129 }
130 *this = JSValue(static_cast<uint32_t>(i));
131 }
132
133 inline JSValue::JSValue(double d)
134 {
135 const int32_t asInt32 = static_cast<int32_t>(d);
136 if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
137 *this = JSValue(EncodeAsDouble, d);
138 return;
139 }
140 *this = JSValue(static_cast<int32_t>(d));
141 }
142
143 #if USE(JSVALUE32_64)
144 inline EncodedJSValue JSValue::encode(JSValue value)
145 {
146 return value.u.asInt64;
147 }
148
149 inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
150 {
151 JSValue v;
152 v.u.asInt64 = encodedJSValue;
153 return v;
154 }
155
156 inline JSValue::JSValue()
157 {
158 u.asBits.tag = EmptyValueTag;
159 u.asBits.payload = 0;
160 }
161
162 inline JSValue::JSValue(JSNullTag)
163 {
164 u.asBits.tag = NullTag;
165 u.asBits.payload = 0;
166 }
167
168 inline JSValue::JSValue(JSUndefinedTag)
169 {
170 u.asBits.tag = UndefinedTag;
171 u.asBits.payload = 0;
172 }
173
174 inline JSValue::JSValue(JSTrueTag)
175 {
176 u.asBits.tag = BooleanTag;
177 u.asBits.payload = 1;
178 }
179
180 inline JSValue::JSValue(JSFalseTag)
181 {
182 u.asBits.tag = BooleanTag;
183 u.asBits.payload = 0;
184 }
185
186 inline JSValue::JSValue(HashTableDeletedValueTag)
187 {
188 u.asBits.tag = DeletedValueTag;
189 u.asBits.payload = 0;
190 }
191
192 inline JSValue::JSValue(JSCell* ptr)
193 {
194 if (ptr)
195 u.asBits.tag = CellTag;
196 else
197 u.asBits.tag = EmptyValueTag;
198 u.asBits.payload = reinterpret_cast<int32_t>(ptr);
199 }
200
201 inline JSValue::JSValue(const JSCell* ptr)
202 {
203 if (ptr)
204 u.asBits.tag = CellTag;
205 else
206 u.asBits.tag = EmptyValueTag;
207 u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
208 }
209
210 inline JSValue::operator bool() const
211 {
212 ASSERT(tag() != DeletedValueTag);
213 return tag() != EmptyValueTag;
214 }
215
216 inline bool JSValue::operator==(const JSValue& other) const
217 {
218 return u.asInt64 == other.u.asInt64;
219 }
220
221 inline bool JSValue::operator!=(const JSValue& other) const
222 {
223 return u.asInt64 != other.u.asInt64;
224 }
225
226 inline bool JSValue::isEmpty() const
227 {
228 return tag() == EmptyValueTag;
229 }
230
231 inline bool JSValue::isUndefined() const
232 {
233 return tag() == UndefinedTag;
234 }
235
236 inline bool JSValue::isNull() const
237 {
238 return tag() == NullTag;
239 }
240
241 inline bool JSValue::isUndefinedOrNull() const
242 {
243 return isUndefined() || isNull();
244 }
245
246 inline bool JSValue::isCell() const
247 {
248 return tag() == CellTag;
249 }
250
251 inline bool JSValue::isInt32() const
252 {
253 return tag() == Int32Tag;
254 }
255
256 inline bool JSValue::isDouble() const
257 {
258 return tag() < LowestTag;
259 }
260
261 inline bool JSValue::isTrue() const
262 {
263 return tag() == BooleanTag && payload();
264 }
265
266 inline bool JSValue::isFalse() const
267 {
268 return tag() == BooleanTag && !payload();
269 }
270
271 inline uint32_t JSValue::tag() const
272 {
273 return u.asBits.tag;
274 }
275
276 inline int32_t JSValue::payload() const
277 {
278 return u.asBits.payload;
279 }
280
281 inline int32_t JSValue::asInt32() const
282 {
283 ASSERT(isInt32());
284 return u.asBits.payload;
285 }
286
287 inline double JSValue::asDouble() const
288 {
289 ASSERT(isDouble());
290 return u.asDouble;
291 }
292
293 ALWAYS_INLINE JSCell* JSValue::asCell() const
294 {
295 ASSERT(isCell());
296 return reinterpret_cast<JSCell*>(u.asBits.payload);
297 }
298
299 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
300 {
301 u.asDouble = d;
302 }
303
304 inline JSValue::JSValue(int i)
305 {
306 u.asBits.tag = Int32Tag;
307 u.asBits.payload = i;
308 }
309
310 inline bool JSValue::isNumber() const
311 {
312 return isInt32() || isDouble();
313 }
314
315 inline bool JSValue::isBoolean() const
316 {
317 return isTrue() || isFalse();
318 }
319
320 inline bool JSValue::asBoolean() const
321 {
322 ASSERT(isBoolean());
323 return payload();
324 }
325
326 #else // USE(JSVALUE32_64)
327
328 // JSValue member functions.
329 inline EncodedJSValue JSValue::encode(JSValue value)
330 {
331 return value.u.ptr;
332 }
333
334 inline JSValue JSValue::decode(EncodedJSValue ptr)
335 {
336 return JSValue(reinterpret_cast<JSCell*>(ptr));
337 }
338
339 // 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.
340 inline JSValue::JSValue()
341 {
342 u.asInt64 = ValueEmpty;
343 }
344
345 // 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.
346 inline JSValue::JSValue(HashTableDeletedValueTag)
347 {
348 u.asInt64 = ValueDeleted;
349 }
350
351 inline JSValue::JSValue(JSCell* ptr)
352 {
353 u.ptr = ptr;
354 }
355
356 inline JSValue::JSValue(const JSCell* ptr)
357 {
358 u.ptr = const_cast<JSCell*>(ptr);
359 }
360
361 inline JSValue::operator bool() const
362 {
363 return u.ptr;
364 }
365
366 inline bool JSValue::operator==(const JSValue& other) const
367 {
368 return u.ptr == other.u.ptr;
369 }
370
371 inline bool JSValue::operator!=(const JSValue& other) const
372 {
373 return u.ptr != other.u.ptr;
374 }
375
376 inline bool JSValue::isEmpty() const
377 {
378 return u.asInt64 == ValueEmpty;
379 }
380
381 inline bool JSValue::isUndefined() const
382 {
383 return asValue() == JSValue(JSUndefined);
384 }
385
386 inline bool JSValue::isNull() const
387 {
388 return asValue() == JSValue(JSNull);
389 }
390
391 inline bool JSValue::isTrue() const
392 {
393 return asValue() == JSValue(JSTrue);
394 }
395
396 inline bool JSValue::isFalse() const
397 {
398 return asValue() == JSValue(JSFalse);
399 }
400
401 inline bool JSValue::asBoolean() const
402 {
403 ASSERT(isBoolean());
404 return asValue() == JSValue(JSTrue);
405 }
406
407 inline int32_t JSValue::asInt32() const
408 {
409 ASSERT(isInt32());
410 return static_cast<int32_t>(u.asInt64);
411 }
412
413 inline bool JSValue::isDouble() const
414 {
415 return isNumber() && !isInt32();
416 }
417
418 inline JSValue::JSValue(JSNullTag)
419 {
420 u.asInt64 = ValueNull;
421 }
422
423 inline JSValue::JSValue(JSUndefinedTag)
424 {
425 u.asInt64 = ValueUndefined;
426 }
427
428 inline JSValue::JSValue(JSTrueTag)
429 {
430 u.asInt64 = ValueTrue;
431 }
432
433 inline JSValue::JSValue(JSFalseTag)
434 {
435 u.asInt64 = ValueFalse;
436 }
437
438 inline bool JSValue::isUndefinedOrNull() const
439 {
440 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
441 return (u.asInt64 & ~TagBitUndefined) == ValueNull;
442 }
443
444 inline bool JSValue::isBoolean() const
445 {
446 return (u.asInt64 & ~1) == ValueFalse;
447 }
448
449 inline bool JSValue::isCell() const
450 {
451 return !(u.asInt64 & TagMask);
452 }
453
454 inline bool JSValue::isInt32() const
455 {
456 return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
457 }
458
459 inline intptr_t reinterpretDoubleToIntptr(double value)
460 {
461 return bitwise_cast<intptr_t>(value);
462 }
463 inline double reinterpretIntptrToDouble(intptr_t value)
464 {
465 return bitwise_cast<double>(value);
466 }
467
468 ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
469 {
470 u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
471 }
472
473 inline JSValue::JSValue(int i)
474 {
475 u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
476 }
477
478 inline double JSValue::asDouble() const
479 {
480 ASSERT(isDouble());
481 return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
482 }
483
484 inline bool JSValue::isNumber() const
485 {
486 return u.asInt64 & TagTypeNumber;
487 }
488
489 ALWAYS_INLINE JSCell* JSValue::asCell() const
490 {
491 ASSERT(isCell());
492 return u.ptr;
493 }
494
495 #endif // USE(JSVALUE64)
496
497 } // namespace JSC
498
499 #endif // JSValueInlineMethods_h