|
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 <math.h> |
|
27 #include <stddef.h> // for size_t |
|
28 #include <stdint.h> |
|
29 #include <wtf/AlwaysInline.h> |
|
30 #include <wtf/Assertions.h> |
|
31 #include <wtf/HashTraits.h> |
|
32 #include <wtf/MathExtras.h> |
|
33 |
|
34 namespace JSC { |
|
35 |
|
36 class ExecState; |
|
37 class Identifier; |
|
38 class JSCell; |
|
39 class JSGlobalData; |
|
40 class JSImmediate; |
|
41 class JSObject; |
|
42 class JSString; |
|
43 class PropertySlot; |
|
44 class PutPropertySlot; |
|
45 class UString; |
|
46 |
|
47 struct ClassInfo; |
|
48 struct Instruction; |
|
49 |
|
50 enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; |
|
51 |
|
52 #if USE(JSVALUE32_64) |
|
53 typedef int64_t EncodedJSValue; |
|
54 #else |
|
55 typedef void* EncodedJSValue; |
|
56 #endif |
|
57 |
|
58 double nonInlineNaN(); |
|
59 int32_t toInt32SlowCase(double, bool& ok); |
|
60 uint32_t toUInt32SlowCase(double, bool& ok); |
|
61 |
|
62 class JSValue { |
|
63 friend class JSImmediate; |
|
64 friend struct EncodedJSValueHashTraits; |
|
65 friend class JIT; |
|
66 friend class JITStubs; |
|
67 friend class JITStubCall; |
|
68 friend class JSInterfaceJIT; |
|
69 friend class SpecializedThunkJIT; |
|
70 |
|
71 public: |
|
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 enum EncodeAsDoubleTag { EncodeAsDouble }; |
|
85 |
|
86 JSValue(); |
|
87 JSValue(JSNullTag); |
|
88 JSValue(JSUndefinedTag); |
|
89 JSValue(JSTrueTag); |
|
90 JSValue(JSFalseTag); |
|
91 JSValue(JSCell* ptr); |
|
92 JSValue(const JSCell* ptr); |
|
93 |
|
94 // Numbers |
|
95 JSValue(EncodeAsDoubleTag, ExecState*, double); |
|
96 JSValue(ExecState*, double); |
|
97 JSValue(ExecState*, char); |
|
98 JSValue(ExecState*, unsigned char); |
|
99 JSValue(ExecState*, short); |
|
100 JSValue(ExecState*, unsigned short); |
|
101 JSValue(ExecState*, int); |
|
102 JSValue(ExecState*, unsigned); |
|
103 JSValue(ExecState*, long); |
|
104 JSValue(ExecState*, unsigned long); |
|
105 JSValue(ExecState*, long long); |
|
106 JSValue(ExecState*, unsigned long long); |
|
107 JSValue(JSGlobalData*, double); |
|
108 JSValue(JSGlobalData*, int); |
|
109 JSValue(JSGlobalData*, unsigned); |
|
110 |
|
111 operator bool() const; |
|
112 bool operator==(const JSValue& other) const; |
|
113 bool operator!=(const JSValue& other) const; |
|
114 |
|
115 bool isInt32() const; |
|
116 bool isUInt32() const; |
|
117 bool isDouble() const; |
|
118 bool isTrue() const; |
|
119 bool isFalse() const; |
|
120 |
|
121 int32_t asInt32() const; |
|
122 uint32_t asUInt32() const; |
|
123 double asDouble() const; |
|
124 |
|
125 // Querying the type. |
|
126 bool isUndefined() const; |
|
127 bool isNull() const; |
|
128 bool isUndefinedOrNull() const; |
|
129 bool isBoolean() const; |
|
130 bool isNumber() const; |
|
131 bool isString() const; |
|
132 bool isGetterSetter() const; |
|
133 bool isObject() const; |
|
134 bool inherits(const ClassInfo*) const; |
|
135 |
|
136 // Extracting the value. |
|
137 bool getBoolean(bool&) const; |
|
138 bool getBoolean() const; // false if not a boolean |
|
139 bool getNumber(double&) const; |
|
140 double uncheckedGetNumber() const; |
|
141 bool getString(ExecState* exec, UString&) const; |
|
142 UString getString(ExecState* exec) const; // null string if not a string |
|
143 JSObject* getObject() const; // 0 if not an object |
|
144 |
|
145 // Extracting integer values. |
|
146 bool getUInt32(uint32_t&) const; |
|
147 |
|
148 // Basic conversions. |
|
149 JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; |
|
150 bool getPrimitiveNumber(ExecState*, double& number, JSValue&); |
|
151 |
|
152 bool toBoolean(ExecState*) const; |
|
153 |
|
154 // toNumber conversion is expected to be side effect free if an exception has |
|
155 // been set in the ExecState already. |
|
156 double toNumber(ExecState*) const; |
|
157 JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. |
|
158 UString toString(ExecState*) const; |
|
159 UString toPrimitiveString(ExecState*) const; |
|
160 JSObject* toObject(ExecState*) const; |
|
161 |
|
162 // Integer conversions. |
|
163 double toInteger(ExecState*) const; |
|
164 double toIntegerPreserveNaN(ExecState*) const; |
|
165 int32_t toInt32(ExecState*) const; |
|
166 int32_t toInt32(ExecState*, bool& ok) const; |
|
167 uint32_t toUInt32(ExecState*) const; |
|
168 uint32_t toUInt32(ExecState*, bool& ok) const; |
|
169 |
|
170 #if ENABLE(JSC_ZOMBIES) |
|
171 bool isZombie() const; |
|
172 #endif |
|
173 |
|
174 // Floating point conversions (this is a convenience method for webcore; |
|
175 // signle precision float is not a representation used in JS or JSC). |
|
176 float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } |
|
177 |
|
178 // Object operations, with the toObject operation included. |
|
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 putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); |
|
185 void put(ExecState*, unsigned propertyName, JSValue); |
|
186 |
|
187 bool needsThisConversion() const; |
|
188 JSObject* toThisObject(ExecState*) const; |
|
189 UString toThisString(ExecState*) const; |
|
190 JSString* toThisJSString(ExecState*) const; |
|
191 |
|
192 static bool equal(ExecState* exec, JSValue v1, JSValue v2); |
|
193 static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); |
|
194 static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); |
|
195 static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2); |
|
196 static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2); |
|
197 static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); |
|
198 |
|
199 JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object |
|
200 |
|
201 bool isCell() const; |
|
202 JSCell* asCell() const; |
|
203 bool isValidCallee(); |
|
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 JSObject* synthesizePrototype(ExecState*) const; |
|
218 JSObject* synthesizeObject(ExecState*) const; |
|
219 |
|
220 #if USE(JSVALUE32_64) |
|
221 enum { Int32Tag = 0xffffffff }; |
|
222 enum { CellTag = 0xfffffffe }; |
|
223 enum { TrueTag = 0xfffffffd }; |
|
224 enum { FalseTag = 0xfffffffc }; |
|
225 enum { NullTag = 0xfffffffb }; |
|
226 enum { UndefinedTag = 0xfffffffa }; |
|
227 enum { EmptyValueTag = 0xfffffff9 }; |
|
228 enum { DeletedValueTag = 0xfffffff8 }; |
|
229 |
|
230 enum { LowestTag = DeletedValueTag }; |
|
231 |
|
232 uint32_t tag() const; |
|
233 int32_t payload() const; |
|
234 |
|
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 |