]>
Commit | Line | Data |
---|---|---|
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 |