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