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 <math.h> |
29 | #include <stddef.h> // for size_t |
30 | #include <stdint.h> |
31 | #include <wtf/AlwaysInline.h> |
32 | #include <wtf/Assertions.h> |
33 | #include <wtf/HashTraits.h> |
34 | #include <wtf/MathExtras.h> |
35 | |
36 | namespace JSC { |
37 | |
38 | class Identifier; |
39 | class JSCell; |
40 | class JSGlobalData; |
41 | class JSImmediate; |
42 | class JSObject; |
43 | class JSString; |
44 | class PropertySlot; |
45 | class PutPropertySlot; |
46 | class UString; |
47 | |
48 | struct ClassInfo; |
49 | struct Instruction; |
50 | |
51 | enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; |
52 | |
53 | #if USE(JSVALUE32_64) |
54 | typedef int64_t EncodedJSValue; |
55 | #else |
56 | typedef void* EncodedJSValue; |
57 | #endif |
58 | |
59 | double nonInlineNaN(); |
60 | int32_t toInt32SlowCase(double, bool& ok); |
61 | uint32_t toUInt32SlowCase(double, bool& ok); |
62 | |
63 | class JSValue { |
64 | friend class JSImmediate; |
65 | friend struct EncodedJSValueHashTraits; |
66 | friend class JIT; |
67 | friend class JITStubs; |
68 | friend class JITStubCall; |
69 | |
70 | public: |
71 | static EncodedJSValue encode(JSValue value); |
72 | static JSValue decode(EncodedJSValue ptr); |
73 | #if !USE(JSVALUE32_64) |
74 | private: |
75 | static JSValue makeImmediate(intptr_t value); |
76 | intptr_t immediateValue(); |
77 | public: |
78 | #endif |
79 | enum JSNullTag { JSNull }; |
80 | enum JSUndefinedTag { JSUndefined }; |
81 | enum JSTrueTag { JSTrue }; |
82 | enum JSFalseTag { JSFalse }; |
83 | enum EncodeAsDoubleTag { EncodeAsDouble }; |
84 | |
85 | JSValue(); |
86 | JSValue(JSNullTag); |
87 | JSValue(JSUndefinedTag); |
88 | JSValue(JSTrueTag); |
89 | JSValue(JSFalseTag); |
90 | JSValue(JSCell* ptr); |
91 | JSValue(const JSCell* ptr); |
92 | |
93 | // Numbers |
94 | JSValue(EncodeAsDoubleTag, ExecState*, double); |
95 | JSValue(ExecState*, double); |
96 | JSValue(ExecState*, char); |
97 | JSValue(ExecState*, unsigned char); |
98 | JSValue(ExecState*, short); |
99 | JSValue(ExecState*, unsigned short); |
100 | JSValue(ExecState*, int); |
101 | JSValue(ExecState*, unsigned); |
102 | JSValue(ExecState*, long); |
103 | JSValue(ExecState*, unsigned long); |
104 | JSValue(ExecState*, long long); |
105 | JSValue(ExecState*, unsigned long long); |
106 | JSValue(JSGlobalData*, double); |
107 | JSValue(JSGlobalData*, int); |
108 | JSValue(JSGlobalData*, unsigned); |
109 | |
110 | operator bool() const; |
111 | bool operator==(const JSValue& other) const; |
112 | bool operator!=(const JSValue& other) const; |
113 | |
114 | bool isInt32() const; |
115 | bool isUInt32() const; |
116 | bool isDouble() const; |
117 | bool isTrue() const; |
118 | bool isFalse() const; |
119 | |
120 | int32_t asInt32() const; |
121 | uint32_t asUInt32() const; |
122 | double asDouble() const; |
123 | |
124 | // Querying the type. |
125 | bool isUndefined() const; |
126 | bool isNull() const; |
127 | bool isUndefinedOrNull() const; |
128 | bool isBoolean() const; |
129 | bool isNumber() const; |
130 | bool isString() const; |
131 | bool isGetterSetter() const; |
132 | bool isObject() const; |
133 | bool inherits(const ClassInfo*) const; |
134 | |
135 | // Extracting the value. |
136 | bool getBoolean(bool&) const; |
137 | bool getBoolean() const; // false if not a boolean |
138 | bool getNumber(double&) const; |
139 | double uncheckedGetNumber() const; |
140 | bool getString(ExecState* exec, UString&) const; |
141 | UString getString(ExecState* exec) const; // null string if not a string |
142 | JSObject* getObject() const; // 0 if not an object |
143 | |
144 | CallType getCallData(CallData&); |
145 | ConstructType getConstructData(ConstructData&); |
146 | |
147 | // Extracting integer values. |
148 | bool getUInt32(uint32_t&) const; |
149 | |
150 | // Basic conversions. |
151 | JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; |
152 | bool getPrimitiveNumber(ExecState*, double& number, JSValue&); |
153 | |
154 | bool toBoolean(ExecState*) const; |
155 | |
156 | // toNumber conversion is expected to be side effect free if an exception has |
157 | // been set in the ExecState already. |
158 | double toNumber(ExecState*) const; |
159 | JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. |
160 | UString toString(ExecState*) const; |
161 | UString toPrimitiveString(ExecState*) const; |
162 | JSObject* toObject(ExecState*) const; |
163 | |
164 | // Integer conversions. |
165 | double toInteger(ExecState*) const; |
166 | double toIntegerPreserveNaN(ExecState*) const; |
167 | int32_t toInt32(ExecState*) const; |
168 | int32_t toInt32(ExecState*, bool& ok) const; |
169 | uint32_t toUInt32(ExecState*) const; |
170 | uint32_t toUInt32(ExecState*, bool& ok) const; |
171 | |
172 | #if ENABLE(JSC_ZOMBIES) |
173 | bool isZombie() const; |
174 | #endif |
175 | |
176 | // Floating point conversions (this is a convenience method for webcore; |
177 | // signle precision float is not a representation used in JS or JSC). |
178 | float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } |
179 | |
180 | // Object operations, with the toObject operation included. |
181 | JSValue get(ExecState*, const Identifier& propertyName) const; |
182 | JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const; |
183 | JSValue get(ExecState*, unsigned propertyName) const; |
184 | JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; |
185 | void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); |
186 | void put(ExecState*, unsigned propertyName, JSValue); |
187 | |
188 | bool needsThisConversion() const; |
189 | JSObject* toThisObject(ExecState*) const; |
190 | UString toThisString(ExecState*) const; |
191 | JSString* toThisJSString(ExecState*); |
192 | |
193 | static bool equal(ExecState* exec, JSValue v1, JSValue v2); |
194 | static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); |
195 | static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); |
196 | static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2); |
197 | static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2); |
198 | static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); |
199 | |
200 | JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object |
201 | |
202 | bool isCell() const; |
203 | JSCell* asCell() const; |
204 | |
205 | #ifndef NDEBUG |
206 | char* description(); |
207 | #endif |
208 | |
209 | private: |
210 | enum HashTableDeletedValueTag { HashTableDeletedValue }; |
211 | JSValue(HashTableDeletedValueTag); |
212 | |
213 | inline const JSValue asValue() const { return *this; } |
214 | JSObject* toObjectSlowCase(ExecState*) const; |
215 | JSObject* toThisObjectSlowCase(ExecState*) const; |
216 | |
217 | enum { Int32Tag = 0xffffffff }; |
218 | enum { CellTag = 0xfffffffe }; |
219 | enum { TrueTag = 0xfffffffd }; |
220 | enum { FalseTag = 0xfffffffc }; |
221 | enum { NullTag = 0xfffffffb }; |
222 | enum { UndefinedTag = 0xfffffffa }; |
223 | enum { EmptyValueTag = 0xfffffff9 }; |
224 | enum { DeletedValueTag = 0xfffffff8 }; |
225 | |
226 | enum { LowestTag = DeletedValueTag }; |
227 | |
228 | uint32_t tag() const; |
229 | int32_t payload() const; |
230 | |
231 | JSObject* synthesizePrototype(ExecState*) const; |
232 | JSObject* synthesizeObject(ExecState*) const; |
233 | |
234 | #if USE(JSVALUE32_64) |
235 | union { |
236 | EncodedJSValue asEncodedJSValue; |
237 | double asDouble; |
238 | #if CPU(BIG_ENDIAN) |
239 | struct { |
240 | int32_t tag; |
241 | int32_t payload; |
242 | } asBits; |
243 | #else |
244 | struct { |
245 | int32_t payload; |
246 | int32_t tag; |
247 | } asBits; |
248 | #endif |
249 | } u; |
250 | #else // USE(JSVALUE32_64) |
251 | JSCell* m_ptr; |
252 | #endif // USE(JSVALUE32_64) |
253 | }; |
254 | |
255 | #if USE(JSVALUE32_64) |
256 | typedef IntHash<EncodedJSValue> EncodedJSValueHash; |
257 | |
258 | struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> { |
259 | static const bool emptyValueIsZero = false; |
260 | static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); } |
261 | static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } |
262 | static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } |
263 | }; |
264 | #else |
265 | typedef PtrHash<EncodedJSValue> EncodedJSValueHash; |
266 | |
267 | struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> { |
268 | static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } |
269 | static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } |
270 | }; |
271 | #endif |
272 | |
273 | // Stand-alone helper functions. |
274 | inline JSValue jsNull() |
275 | { |
276 | return JSValue(JSValue::JSNull); |
277 | } |
278 | |
279 | inline JSValue jsUndefined() |
280 | { |
281 | return JSValue(JSValue::JSUndefined); |
282 | } |
283 | |
284 | inline JSValue jsBoolean(bool b) |
285 | { |
286 | return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse); |
287 | } |
288 | |
289 | ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d) |
290 | { |
291 | return JSValue(JSValue::EncodeAsDouble, exec, d); |
292 | } |
293 | |
294 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d) |
295 | { |
296 | return JSValue(exec, d); |
297 | } |
298 | |
299 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i) |
300 | { |
301 | return JSValue(exec, i); |
302 | } |
303 | |
304 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i) |
305 | { |
306 | return JSValue(exec, i); |
307 | } |
308 | |
309 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i) |
310 | { |
311 | return JSValue(exec, i); |
312 | } |
313 | |
314 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i) |
315 | { |
316 | return JSValue(exec, i); |
317 | } |
318 | |
319 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i) |
320 | { |
321 | return JSValue(exec, i); |
322 | } |
323 | |
324 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i) |
325 | { |
326 | return JSValue(exec, i); |
327 | } |
328 | |
329 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i) |
330 | { |
331 | return JSValue(exec, i); |
332 | } |
333 | |
334 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i) |
335 | { |
336 | return JSValue(exec, i); |
337 | } |
338 | |
339 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i) |
340 | { |
341 | return JSValue(exec, i); |
342 | } |
343 | |
344 | ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i) |
345 | { |
346 | return JSValue(exec, i); |
347 | } |
348 | |
349 | ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d) |
350 | { |
351 | return JSValue(globalData, d); |
352 | } |
353 | |
354 | ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i) |
355 | { |
356 | return JSValue(globalData, i); |
357 | } |
358 | |
359 | ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i) |
360 | { |
361 | return JSValue(globalData, i); |
362 | } |
363 | |
364 | inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); } |
365 | inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; } |
366 | |
367 | inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } |
368 | inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } |
369 | |
370 | inline int32_t toInt32(double val) |
371 | { |
372 | if (!(val >= -2147483648.0 && val < 2147483648.0)) { |
373 | bool ignored; |
374 | return toInt32SlowCase(val, ignored); |
375 | } |
376 | return static_cast<int32_t>(val); |
377 | } |
378 | |
379 | inline uint32_t toUInt32(double val) |
380 | { |
381 | if (!(val >= 0.0 && val < 4294967296.0)) { |
382 | bool ignored; |
383 | return toUInt32SlowCase(val, ignored); |
384 | } |
385 | return static_cast<uint32_t>(val); |
386 | } |
387 | |
388 | // FIXME: We should deprecate this and just use JSValue::asCell() instead. |
389 | JSCell* asCell(JSValue); |
390 | |
391 | inline JSCell* asCell(JSValue value) |
392 | { |
393 | return value.asCell(); |
394 | } |
395 | |
396 | ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const |
397 | { |
398 | if (isInt32()) |
399 | return asInt32(); |
400 | bool ignored; |
401 | return toInt32SlowCase(toNumber(exec), ignored); |
402 | } |
403 | |
404 | inline uint32_t JSValue::toUInt32(ExecState* exec) const |
405 | { |
406 | if (isUInt32()) |
407 | return asInt32(); |
408 | bool ignored; |
409 | return toUInt32SlowCase(toNumber(exec), ignored); |
410 | } |
411 | |
412 | inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const |
413 | { |
414 | if (isInt32()) { |
415 | ok = true; |
416 | return asInt32(); |
417 | } |
418 | return toInt32SlowCase(toNumber(exec), ok); |
419 | } |
420 | |
421 | inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const |
422 | { |
423 | if (isUInt32()) { |
424 | ok = true; |
425 | return asInt32(); |
426 | } |
427 | return toUInt32SlowCase(toNumber(exec), ok); |
428 | } |
429 | |
430 | #if USE(JSVALUE32_64) |
431 | inline JSValue jsNaN(ExecState* exec) |
432 | { |
433 | return JSValue(exec, nonInlineNaN()); |
434 | } |
435 | |
436 | // JSValue member functions. |
437 | inline EncodedJSValue JSValue::encode(JSValue value) |
438 | { |
439 | return value.u.asEncodedJSValue; |
440 | } |
441 | |
442 | inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) |
443 | { |
444 | JSValue v; |
445 | v.u.asEncodedJSValue = encodedJSValue; |
446 | #if ENABLE(JSC_ZOMBIES) |
447 | ASSERT(!v.isZombie()); |
448 | #endif |
449 | return v; |
450 | } |
451 | |
452 | inline JSValue::JSValue() |
453 | { |
454 | u.asBits.tag = EmptyValueTag; |
455 | u.asBits.payload = 0; |
456 | } |
457 | |
458 | inline JSValue::JSValue(JSNullTag) |
459 | { |
460 | u.asBits.tag = NullTag; |
461 | u.asBits.payload = 0; |
462 | } |
463 | |
464 | inline JSValue::JSValue(JSUndefinedTag) |
465 | { |
466 | u.asBits.tag = UndefinedTag; |
467 | u.asBits.payload = 0; |
468 | } |
469 | |
470 | inline JSValue::JSValue(JSTrueTag) |
471 | { |
472 | u.asBits.tag = TrueTag; |
473 | u.asBits.payload = 0; |
474 | } |
475 | |
476 | inline JSValue::JSValue(JSFalseTag) |
477 | { |
478 | u.asBits.tag = FalseTag; |
479 | u.asBits.payload = 0; |
480 | } |
481 | |
482 | inline JSValue::JSValue(HashTableDeletedValueTag) |
483 | { |
484 | u.asBits.tag = DeletedValueTag; |
485 | u.asBits.payload = 0; |
486 | } |
487 | |
488 | inline JSValue::JSValue(JSCell* ptr) |
489 | { |
490 | if (ptr) |
491 | u.asBits.tag = CellTag; |
492 | else |
493 | u.asBits.tag = EmptyValueTag; |
494 | u.asBits.payload = reinterpret_cast<int32_t>(ptr); |
495 | #if ENABLE(JSC_ZOMBIES) |
496 | ASSERT(!isZombie()); |
497 | #endif |
498 | } |
499 | |
500 | inline JSValue::JSValue(const JSCell* ptr) |
501 | { |
502 | if (ptr) |
503 | u.asBits.tag = CellTag; |
504 | else |
505 | u.asBits.tag = EmptyValueTag; |
506 | u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); |
507 | #if ENABLE(JSC_ZOMBIES) |
508 | ASSERT(!isZombie()); |
509 | #endif |
510 | } |
511 | |
512 | inline JSValue::operator bool() const |
513 | { |
514 | ASSERT(tag() != DeletedValueTag); |
515 | return tag() != EmptyValueTag; |
516 | } |
517 | |
518 | inline bool JSValue::operator==(const JSValue& other) const |
519 | { |
520 | return u.asEncodedJSValue == other.u.asEncodedJSValue; |
521 | } |
522 | |
523 | inline bool JSValue::operator!=(const JSValue& other) const |
524 | { |
525 | return u.asEncodedJSValue != other.u.asEncodedJSValue; |
526 | } |
527 | |
528 | inline bool JSValue::isUndefined() const |
529 | { |
530 | return tag() == UndefinedTag; |
531 | } |
532 | |
533 | inline bool JSValue::isNull() const |
534 | { |
535 | return tag() == NullTag; |
536 | } |
537 | |
538 | inline bool JSValue::isUndefinedOrNull() const |
539 | { |
540 | return isUndefined() || isNull(); |
541 | } |
542 | |
543 | inline bool JSValue::isCell() const |
544 | { |
545 | return tag() == CellTag; |
546 | } |
547 | |
548 | inline bool JSValue::isInt32() const |
549 | { |
550 | return tag() == Int32Tag; |
551 | } |
552 | |
553 | inline bool JSValue::isUInt32() const |
554 | { |
555 | return tag() == Int32Tag && asInt32() > -1; |
556 | } |
557 | |
558 | inline bool JSValue::isDouble() const |
559 | { |
560 | return tag() < LowestTag; |
561 | } |
562 | |
563 | inline bool JSValue::isTrue() const |
564 | { |
565 | return tag() == TrueTag; |
566 | } |
567 | |
568 | inline bool JSValue::isFalse() const |
569 | { |
570 | return tag() == FalseTag; |
571 | } |
572 | |
573 | inline uint32_t JSValue::tag() const |
574 | { |
575 | return u.asBits.tag; |
576 | } |
577 | |
578 | inline int32_t JSValue::payload() const |
579 | { |
580 | return u.asBits.payload; |
581 | } |
582 | |
583 | inline int32_t JSValue::asInt32() const |
584 | { |
585 | ASSERT(isInt32()); |
586 | return u.asBits.payload; |
587 | } |
588 | |
589 | inline uint32_t JSValue::asUInt32() const |
590 | { |
591 | ASSERT(isUInt32()); |
592 | return u.asBits.payload; |
593 | } |
594 | |
595 | inline double JSValue::asDouble() const |
596 | { |
597 | ASSERT(isDouble()); |
598 | return u.asDouble; |
599 | } |
600 | |
601 | ALWAYS_INLINE JSCell* JSValue::asCell() const |
602 | { |
603 | ASSERT(isCell()); |
604 | return reinterpret_cast<JSCell*>(u.asBits.payload); |
605 | } |
606 | |
607 | ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) |
608 | { |
609 | u.asDouble = d; |
610 | } |
611 | |
612 | inline JSValue::JSValue(ExecState* exec, double d) |
613 | { |
614 | const int32_t asInt32 = static_cast<int32_t>(d); |
615 | if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 |
616 | u.asDouble = d; |
617 | return; |
618 | } |
619 | *this = JSValue(exec, static_cast<int32_t>(d)); |
620 | } |
621 | |
622 | inline JSValue::JSValue(ExecState* exec, char i) |
623 | { |
624 | *this = JSValue(exec, static_cast<int32_t>(i)); |
625 | } |
626 | |
627 | inline JSValue::JSValue(ExecState* exec, unsigned char i) |
628 | { |
629 | *this = JSValue(exec, static_cast<int32_t>(i)); |
630 | } |
631 | |
632 | inline JSValue::JSValue(ExecState* exec, short i) |
633 | { |
634 | *this = JSValue(exec, static_cast<int32_t>(i)); |
635 | } |
636 | |
637 | inline JSValue::JSValue(ExecState* exec, unsigned short i) |
638 | { |
639 | *this = JSValue(exec, static_cast<int32_t>(i)); |
640 | } |
641 | |
642 | inline JSValue::JSValue(ExecState*, int i) |
643 | { |
644 | u.asBits.tag = Int32Tag; |
645 | u.asBits.payload = i; |
646 | } |
647 | |
648 | inline JSValue::JSValue(ExecState* exec, unsigned i) |
649 | { |
650 | if (static_cast<int32_t>(i) < 0) { |
651 | *this = JSValue(exec, static_cast<double>(i)); |
652 | return; |
653 | } |
654 | *this = JSValue(exec, static_cast<int32_t>(i)); |
655 | } |
656 | |
657 | inline JSValue::JSValue(ExecState* exec, long i) |
658 | { |
659 | if (static_cast<int32_t>(i) != i) { |
660 | *this = JSValue(exec, static_cast<double>(i)); |
661 | return; |
662 | } |
663 | *this = JSValue(exec, static_cast<int32_t>(i)); |
664 | } |
665 | |
666 | inline JSValue::JSValue(ExecState* exec, unsigned long i) |
667 | { |
668 | if (static_cast<uint32_t>(i) != i) { |
669 | *this = JSValue(exec, static_cast<double>(i)); |
670 | return; |
671 | } |
672 | *this = JSValue(exec, static_cast<uint32_t>(i)); |
673 | } |
674 | |
675 | inline JSValue::JSValue(ExecState* exec, long long i) |
676 | { |
677 | if (static_cast<int32_t>(i) != i) { |
678 | *this = JSValue(exec, static_cast<double>(i)); |
679 | return; |
680 | } |
681 | *this = JSValue(exec, static_cast<int32_t>(i)); |
682 | } |
683 | |
684 | inline JSValue::JSValue(ExecState* exec, unsigned long long i) |
685 | { |
686 | if (static_cast<uint32_t>(i) != i) { |
687 | *this = JSValue(exec, static_cast<double>(i)); |
688 | return; |
689 | } |
690 | *this = JSValue(exec, static_cast<uint32_t>(i)); |
691 | } |
692 | |
693 | inline JSValue::JSValue(JSGlobalData* globalData, double d) |
694 | { |
695 | const int32_t asInt32 = static_cast<int32_t>(d); |
696 | if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 |
697 | u.asDouble = d; |
698 | return; |
699 | } |
700 | *this = JSValue(globalData, static_cast<int32_t>(d)); |
701 | } |
702 | |
703 | inline JSValue::JSValue(JSGlobalData*, int i) |
704 | { |
705 | u.asBits.tag = Int32Tag; |
706 | u.asBits.payload = i; |
707 | } |
708 | |
709 | inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) |
710 | { |
711 | if (static_cast<int32_t>(i) < 0) { |
712 | *this = JSValue(globalData, static_cast<double>(i)); |
713 | return; |
714 | } |
715 | *this = JSValue(globalData, static_cast<int32_t>(i)); |
716 | } |
717 | |
718 | inline bool JSValue::isNumber() const |
719 | { |
720 | return isInt32() || isDouble(); |
721 | } |
722 | |
723 | inline bool JSValue::isBoolean() const |
724 | { |
725 | return isTrue() || isFalse(); |
726 | } |
727 | |
728 | inline bool JSValue::getBoolean(bool& v) const |
729 | { |
730 | if (isTrue()) { |
731 | v = true; |
732 | return true; |
733 | } |
734 | if (isFalse()) { |
735 | v = false; |
736 | return true; |
737 | } |
738 | |
739 | return false; |
740 | } |
741 | |
742 | inline bool JSValue::getBoolean() const |
743 | { |
744 | ASSERT(isBoolean()); |
745 | return tag() == TrueTag; |
746 | } |
747 | |
748 | inline double JSValue::uncheckedGetNumber() const |
749 | { |
750 | ASSERT(isNumber()); |
751 | return isInt32() ? asInt32() : asDouble(); |
752 | } |
753 | |
754 | ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const |
755 | { |
756 | return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec)); |
757 | } |
758 | |
759 | inline bool JSValue::getNumber(double& result) const |
760 | { |
761 | if (isInt32()) { |
762 | result = asInt32(); |
763 | return true; |
764 | } |
765 | if (isDouble()) { |
766 | result = asDouble(); |
767 | return true; |
768 | } |
769 | return false; |
770 | } |
771 | |
772 | #else // USE(JSVALUE32_64) |
773 | |
774 | // JSValue member functions. |
775 | inline EncodedJSValue JSValue::encode(JSValue value) |
776 | { |
777 | return reinterpret_cast<EncodedJSValue>(value.m_ptr); |
778 | } |
779 | |
780 | inline JSValue JSValue::decode(EncodedJSValue ptr) |
781 | { |
782 | return JSValue(reinterpret_cast<JSCell*>(ptr)); |
783 | } |
784 | |
785 | inline JSValue JSValue::makeImmediate(intptr_t value) |
786 | { |
787 | return JSValue(reinterpret_cast<JSCell*>(value)); |
788 | } |
789 | |
790 | inline intptr_t JSValue::immediateValue() |
791 | { |
792 | return reinterpret_cast<intptr_t>(m_ptr); |
793 | } |
794 | |
795 | // 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. |
796 | inline JSValue::JSValue() |
797 | : m_ptr(0) |
798 | { |
799 | } |
800 | |
801 | // 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. |
802 | inline JSValue::JSValue(HashTableDeletedValueTag) |
803 | : m_ptr(reinterpret_cast<JSCell*>(0x4)) |
804 | { |
805 | } |
806 | |
807 | inline JSValue::JSValue(JSCell* ptr) |
808 | : m_ptr(ptr) |
809 | { |
810 | #if ENABLE(JSC_ZOMBIES) |
811 | ASSERT(!isZombie()); |
812 | #endif |
813 | } |
814 | |
815 | inline JSValue::JSValue(const JSCell* ptr) |
816 | : m_ptr(const_cast<JSCell*>(ptr)) |
817 | { |
818 | #if ENABLE(JSC_ZOMBIES) |
819 | ASSERT(!isZombie()); |
820 | #endif |
821 | } |
822 | |
823 | inline JSValue::operator bool() const |
824 | { |
825 | return m_ptr; |
826 | } |
827 | |
828 | inline bool JSValue::operator==(const JSValue& other) const |
829 | { |
830 | return m_ptr == other.m_ptr; |
831 | } |
832 | |
833 | inline bool JSValue::operator!=(const JSValue& other) const |
834 | { |
835 | return m_ptr != other.m_ptr; |
836 | } |
837 | |
838 | inline bool JSValue::isUndefined() const |
839 | { |
840 | return asValue() == jsUndefined(); |
841 | } |
842 | |
843 | inline bool JSValue::isNull() const |
844 | { |
845 | return asValue() == jsNull(); |
846 | } |
847 | #endif // USE(JSVALUE32_64) |
848 | |
849 | } // namespace JSC |
850 | |
851 | #endif // JSValue_h |
852 | |