source: webkit/trunk/JavaScriptCore/runtime/JSValue.h@ 48788

Last change on this file since 48788 was 48068, checked in by Darin Adler, 16 years ago

DateInstance object collected on ARM JIT (JSValue: WTF_USE_JSVALUE32)
https://bugs.webkit.org/show_bug.cgi?id=28909

Patch by Darin Adler <Darin Adler> on 2009-09-04
Reviewed by Geoff Garen.

Part two.

Make some improvements to garbage collection code:

1) Create a runtime assertion that catches any classes that

override markChildren but have the HasDefaultMark bit set.

2) Remove checks of the mark bit outside the MarkStack::append

function; they are redundant.

3) Improve the efficiency of the asObject and asArray functions

when called on JSCell* to avoid a round trip to JSValue.

4) Make more callers use the checked asCell and asObject

casting functions rather than unchecked casts.

5) Removed the JSCell::marked function and other GC-related

functions because these operations are no longer things that
code other than the core GC code needs to do directly. Fixed
callers that were calling them.

  • runtime/Collector.cpp:

(JSC::Heap::markConservatively): Removed unneeded call to MarkStack::drain.
(JSC::Heap::markProtectedObjects): Removed unneeded check of the mark
bit and call to MarkStack::drain.
(JSC::Heap::collect): Removed unneeded checks of the mark bit and also
changed call to SmallStrings::mark to call markChildren instead to match
the rest of the objects.
(JSC::typeName): Removed unneeded cast to JSObject*.

  • runtime/JSArray.h:

(JSC::asArray): Added an overload for JSCell* and changed the JSValue
version to call it. Removed some unneeded casts.
(JSC::JSArray::markChildrenDirect): Marked this function inline. It's in
a header, and if not marked inline this could lead to linking problems.
(JSC::MarkStack::markChildren): Added. This helper function is used by
the drain function to avoid repating code. Also added the code here to
check fro default mark violations in debug code. If a markChildren
function adds something to the mark stack, but the type info claimed
hasDefaultMark was true, then we will get an assertion now. Also fixed
the assertion about the mark bit to use the Heap function directly
because we don't have a JSCell::marked function any more.
(JSC::MarkStack::drain): Changed a local variable from "v" to "value",
and from "currentCell" to "cell". Changed to call markChildren in two
places instead of repeating a chain of if statements twice. Changed
code that reads and writes the mark bit to use Heap::isCellMarked and
Heap::markCell so we can eliminate the JSCell::marked and
JSCell::markCellDirect functions.

  • runtime/JSCell.h: Removed JSCell's markCellDirect and marked member

functions. Added a comment explaining that asCell should be deprecated
in favor of the JSValue asCell member function.
(JSC::MarkStack::append): Added the assertion that catches callers
that have set the HasDefaultMark bit incorrectly. Changed
code that reads and writes the mark bit to use Heap::isCellMarked and
Heap::markCell so we can eliminate the JSCell::marked and
JSCell::markCellDirect functions. Moved the overload of
MarkStack::append for JSValue here so it can call through to the cell
version. The old version had a copy of all the code instead, but that
repeated the conversion from JSValue to JSCell* and the check for
whether a value is a cell multiple times.
(JSC::Structure::markAggregate): Moved this function here to avoid
dependencies for Structure.h, since this calls MarkStack::append.

  • runtime/JSObject.cpp:

(JSC::JSObject::markChildren): Added code to clear
m_isCheckingForDefaultMarkViolation so the marking done by JSObject
doesn't trigger the assertion.

  • runtime/JSValue.h: Moved some stray includes that were outside the

header guard inside it. Not sure how that happened! Removed the
GC-related member functions markChildren, hasChildren, marked, and
markDirect.

  • runtime/JSWrapperObject.h: Made markChildren private.

(JSC::JSWrapperObject::createStructure): Added. Fixes a bug where the
HasDefaultMark bit was set.

  • runtime/MarkStack.h: Added m_isCheckingForDefaultMarkViolation and

initialized it to false. Moved the append function body from here to
JSCell.h. Added a declaration of a private markChildren function used
inside the drain function.

  • runtime/SmallStrings.cpp:

(JSC::SmallStrings::markChildren): Changed the name and style of this
function to match other functions. This allows us to share the normal
mark stack code path.

  • runtime/SmallStrings.h: Changed the name and interface of mark to

the more-normal markChildren style.

  • runtime/Structure.h: Moved the body of markAggregate into the

JSCell.h to avoid a circular dependency with JSCell.h.

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