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