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