]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSValue.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / JSValue.h
CommitLineData
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
ba379fdc 26#include <math.h>
f9bf01c6
A
27#include <stddef.h> // for size_t
28#include <stdint.h>
ba379fdc
A
29#include <wtf/AlwaysInline.h>
30#include <wtf/Assertions.h>
31#include <wtf/HashTraits.h>
32#include <wtf/MathExtras.h>
14957cd0 33#include <wtf/StdLibExtras.h>
9dae56ea
A
34
35namespace JSC {
36
14957cd0
A
37 extern const double NaN;
38 extern const double Inf;
39
40 class ExecState;
9dae56ea
A
41 class Identifier;
42 class JSCell;
ba379fdc 43 class JSGlobalData;
14957cd0 44 class JSGlobalObject;
9dae56ea
A
45 class JSObject;
46 class JSString;
47 class PropertySlot;
48 class PutPropertySlot;
49 class UString;
50
51 struct ClassInfo;
52 struct Instruction;
53
14957cd0
A
54 template <class T> class WriteBarrierBase;
55
9dae56ea
A
56 enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
57
14957cd0 58
ba379fdc
A
59#if USE(JSVALUE32_64)
60 typedef int64_t EncodedJSValue;
61#else
62 typedef void* EncodedJSValue;
63#endif
14957cd0
A
64
65 union EncodedValueDescriptor {
66 int64_t asInt64;
67#if USE(JSVALUE32_64)
68 double asDouble;
69#elif USE(JSVALUE64)
70 JSCell* ptr;
71#endif
72
73#if CPU(BIG_ENDIAN)
74 struct {
75 int32_t tag;
76 int32_t payload;
77 } asBits;
78#else
79 struct {
80 int32_t payload;
81 int32_t tag;
82 } asBits;
83#endif
84 };
9dae56ea 85
ba379fdc 86 double nonInlineNaN();
14957cd0
A
87
88 // This implements ToInt32, defined in ECMA-262 9.5.
89 int32_t toInt32(double);
90
91 // This implements ToUInt32, defined in ECMA-262 9.6.
92 inline uint32_t toUInt32(double number)
93 {
94 // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
95 // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
96 return toInt32(number);
97 }
9dae56ea 98
ba379fdc 99 class JSValue {
ba379fdc
A
100 friend struct EncodedJSValueHashTraits;
101 friend class JIT;
102 friend class JITStubs;
103 friend class JITStubCall;
4e4e5a6f
A
104 friend class JSInterfaceJIT;
105 friend class SpecializedThunkJIT;
9dae56ea 106
9dae56ea 107 public:
14957cd0
A
108 static EncodedJSValue encode(JSValue);
109 static JSValue decode(EncodedJSValue);
110
ba379fdc
A
111 enum JSNullTag { JSNull };
112 enum JSUndefinedTag { JSUndefined };
113 enum JSTrueTag { JSTrue };
114 enum JSFalseTag { JSFalse };
f9bf01c6 115 enum EncodeAsDoubleTag { EncodeAsDouble };
ba379fdc
A
116
117 JSValue();
118 JSValue(JSNullTag);
119 JSValue(JSUndefinedTag);
120 JSValue(JSTrueTag);
121 JSValue(JSFalseTag);
122 JSValue(JSCell* ptr);
123 JSValue(const JSCell* ptr);
124
125 // Numbers
14957cd0
A
126 JSValue(EncodeAsDoubleTag, double);
127 explicit JSValue(double);
128 explicit JSValue(char);
129 explicit JSValue(unsigned char);
130 explicit JSValue(short);
131 explicit JSValue(unsigned short);
132 explicit JSValue(int);
133 explicit JSValue(unsigned);
134 explicit JSValue(long);
135 explicit JSValue(unsigned long);
136 explicit JSValue(long long);
137 explicit JSValue(unsigned long long);
ba379fdc
A
138
139 operator bool() const;
140 bool operator==(const JSValue& other) const;
141 bool operator!=(const JSValue& other) const;
142
143 bool isInt32() const;
144 bool isUInt32() const;
145 bool isDouble() const;
146 bool isTrue() const;
147 bool isFalse() const;
148
149 int32_t asInt32() const;
150 uint32_t asUInt32() const;
151 double asDouble() const;
9dae56ea
A
152
153 // Querying the type.
154 bool isUndefined() const;
155 bool isNull() const;
156 bool isUndefinedOrNull() const;
157 bool isBoolean() const;
158 bool isNumber() const;
159 bool isString() const;
160 bool isGetterSetter() const;
161 bool isObject() const;
f9bf01c6 162 bool inherits(const ClassInfo*) const;
9dae56ea
A
163
164 // Extracting the value.
165 bool getBoolean(bool&) const;
166 bool getBoolean() const; // false if not a boolean
167 bool getNumber(double&) const;
168 double uncheckedGetNumber() const;
f9bf01c6
A
169 bool getString(ExecState* exec, UString&) const;
170 UString getString(ExecState* exec) const; // null string if not a string
9dae56ea
A
171 JSObject* getObject() const; // 0 if not an object
172
9dae56ea
A
173 // Extracting integer values.
174 bool getUInt32(uint32_t&) const;
9dae56ea
A
175
176 // Basic conversions.
ba379fdc
A
177 JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
178 bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
9dae56ea
A
179
180 bool toBoolean(ExecState*) const;
181
182 // toNumber conversion is expected to be side effect free if an exception has
183 // been set in the ExecState already.
184 double toNumber(ExecState*) const;
ba379fdc 185 JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
9dae56ea 186 UString toString(ExecState*) const;
f9bf01c6 187 UString toPrimitiveString(ExecState*) const;
9dae56ea 188 JSObject* toObject(ExecState*) const;
14957cd0 189 JSObject* toObject(ExecState*, JSGlobalObject*) const;
9dae56ea
A
190
191 // Integer conversions.
9dae56ea
A
192 double toInteger(ExecState*) const;
193 double toIntegerPreserveNaN(ExecState*) const;
194 int32_t toInt32(ExecState*) const;
9dae56ea 195 uint32_t toUInt32(ExecState*) const;
9dae56ea 196
f9bf01c6
A
197#if ENABLE(JSC_ZOMBIES)
198 bool isZombie() const;
199#endif
200
9dae56ea
A
201 // Floating point conversions (this is a convenience method for webcore;
202 // signle precision float is not a representation used in JS or JSC).
203 float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
204
9dae56ea 205 // Object operations, with the toObject operation included.
ba379fdc
A
206 JSValue get(ExecState*, const Identifier& propertyName) const;
207 JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
208 JSValue get(ExecState*, unsigned propertyName) const;
209 JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
210 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
4e4e5a6f 211 void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
ba379fdc 212 void put(ExecState*, unsigned propertyName, JSValue);
9dae56ea
A
213
214 bool needsThisConversion() const;
215 JSObject* toThisObject(ExecState*) const;
14957cd0 216 JSValue toStrictThisObject(ExecState*) const;
9dae56ea 217 UString toThisString(ExecState*) const;
4e4e5a6f 218 JSString* toThisJSString(ExecState*) const;
9dae56ea 219
ba379fdc
A
220 static bool equal(ExecState* exec, JSValue v1, JSValue v2);
221 static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
222 static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
f9bf01c6
A
223 static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
224 static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
225 static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
9dae56ea 226
ba379fdc 227 JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
9dae56ea
A
228
229 bool isCell() const;
230 JSCell* asCell() const;
14957cd0 231 bool isValidCallee();
9dae56ea 232
ba379fdc
A
233#ifndef NDEBUG
234 char* description();
235#endif
236
9dae56ea 237 private:
14957cd0
A
238 template <class T> JSValue(WriteBarrierBase<T>);
239
ba379fdc
A
240 enum HashTableDeletedValueTag { HashTableDeletedValue };
241 JSValue(HashTableDeletedValueTag);
242
243 inline const JSValue asValue() const { return *this; }
14957cd0 244 JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
ba379fdc
A
245 JSObject* toThisObjectSlowCase(ExecState*) const;
246
4e4e5a6f
A
247 JSObject* synthesizePrototype(ExecState*) const;
248 JSObject* synthesizeObject(ExecState*) const;
249
250#if USE(JSVALUE32_64)
14957cd0
A
251 /*
252 * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
253 * form for immediates.
254 *
255 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
256 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
257 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
258 * have a payload of zero. We assume that non-zero payloads are available to encode
259 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
260 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
261 * ranges to encode other values (however there are also other ranges of NaN space that
262 * could have been selected).
263 *
264 * For JSValues that do not contain a double value, the high 32 bits contain the tag
265 * values listed in the enums below, which all correspond to NaN-space. In the case of
266 * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
267 * integer or boolean value; in the case of all other tags the payload is 0.
268 */
ba379fdc 269 enum { Int32Tag = 0xffffffff };
14957cd0
A
270 enum { BooleanTag = 0xfffffffe };
271 enum { NullTag = 0xfffffffd };
272 enum { UndefinedTag = 0xfffffffc };
273 enum { CellTag = 0xfffffffb };
274 enum { EmptyValueTag = 0xfffffffa };
275 enum { DeletedValueTag = 0xfffffff9 };
276
ba379fdc 277 enum { LowestTag = DeletedValueTag };
14957cd0 278
ba379fdc
A
279 uint32_t tag() const;
280 int32_t payload() const;
14957cd0
A
281#elif USE(JSVALUE64)
282 /*
283 * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
284 * form for immediates.
285 *
286 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
287 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
288 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
289 * have a payload of zero. We assume that non-zero payloads are available to encode
290 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
291 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
292 * ranges to encode other values (however there are also other ranges of NaN space that
293 * could have been selected).
294 *
295 * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
296 * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
297 * numbers will begin fall in these ranges.
298 *
299 * The top 16-bits denote the type of the encoded JSValue:
300 *
301 * Pointer { 0000:PPPP:PPPP:PPPP
302 * / 0001:****:****:****
303 * Double { ...
304 * \ FFFE:****:****:****
305 * Integer { FFFF:0000:IIII:IIII
306 *
307 * The scheme we have implemented encodes double precision values by performing a
308 * 64-bit integer addition of the value 2^48 to the number. After this manipulation
309 * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
310 * Values must be decoded by reversing this operation before subsequent floating point
311 * operations my be peformed.
312 *
313 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
314 *
315 * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
316 * null and undefined values are represented by specific, invalid pointer values:
317 *
318 * False: 0x06
319 * True: 0x07
320 * Undefined: 0x0a
321 * Null: 0x02
322 *
323 * These values have the following properties:
324 * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
325 * quickly distinguished from all immediate values, including these invalid pointers.
326 * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
327 * same value, allowing null & undefined to be quickly detected.
328 *
329 * No valid JSValue will have the bit pattern 0x0, this is used to represent array
330 * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
331 */
332
333 // These values are #defines since using static const integers here is a ~1% regression!
334
335 // This value is 2^48, used to encode doubles such that the encoded value will begin
336 // with a 16-bit pattern within the range 0x0001..0xFFFE.
337 #define DoubleEncodeOffset 0x1000000000000ll
338 // If all bits in the mask are set, this indicates an integer number,
339 // if any but not all are set this value is a double precision number.
340 #define TagTypeNumber 0xffff000000000000ll
341
342 // All non-numeric (bool, null, undefined) immediates have bit 2 set.
343 #define TagBitTypeOther 0x2ll
344 #define TagBitBool 0x4ll
345 #define TagBitUndefined 0x8ll
346 // Combined integer value for non-numeric immediates.
347 #define ValueFalse (TagBitTypeOther | TagBitBool | false)
348 #define ValueTrue (TagBitTypeOther | TagBitBool | true)
349 #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
350 #define ValueNull (TagBitTypeOther)
351
352 // TagMask is used to check for all types of immediate values (either number or 'other').
353 #define TagMask (TagTypeNumber | TagBitTypeOther)
354
355 // These special values are never visible to JavaScript code; Empty is used to represent
356 // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
357 // These values would map to cell types in the JSValue encoding, but not valid GC cell
358 // pointer should have either of these values (Empty is null, deleted is at an invalid
359 // alignment for a GC cell, and in the zero page).
360 #define ValueEmpty 0x0ll
361 #define ValueDeleted 0x4ll
ba379fdc 362#endif
14957cd0
A
363
364 EncodedValueDescriptor u;
ba379fdc 365 };
9dae56ea 366
ba379fdc
A
367#if USE(JSVALUE32_64)
368 typedef IntHash<EncodedJSValue> EncodedJSValueHash;
9dae56ea 369
ba379fdc
A
370 struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
371 static const bool emptyValueIsZero = false;
372 static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
373 static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
374 static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
9dae56ea 375 };
ba379fdc
A
376#else
377 typedef PtrHash<EncodedJSValue> EncodedJSValueHash;
378
379 struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
380 static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
381 static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
382 };
383#endif
384
385 // Stand-alone helper functions.
386 inline JSValue jsNull()
387 {
388 return JSValue(JSValue::JSNull);
389 }
390
391 inline JSValue jsUndefined()
392 {
393 return JSValue(JSValue::JSUndefined);
394 }
395
396 inline JSValue jsBoolean(bool b)
397 {
398 return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
399 }
400
14957cd0 401 ALWAYS_INLINE JSValue jsDoubleNumber(double d)
ba379fdc 402 {
1df5f87f 403 ASSERT(JSValue(JSValue::EncodeAsDouble, d).isNumber());
14957cd0 404 return JSValue(JSValue::EncodeAsDouble, d);
ba379fdc
A
405 }
406
14957cd0 407 ALWAYS_INLINE JSValue jsNumber(double d)
ba379fdc 408 {
1df5f87f 409 ASSERT(JSValue(d).isNumber());
14957cd0 410 return JSValue(d);
ba379fdc
A
411 }
412
14957cd0 413 ALWAYS_INLINE JSValue jsNumber(char i)
ba379fdc 414 {
14957cd0 415 return JSValue(i);
ba379fdc
A
416 }
417
14957cd0 418 ALWAYS_INLINE JSValue jsNumber(unsigned char i)
ba379fdc 419 {
14957cd0 420 return JSValue(i);
ba379fdc
A
421 }
422
14957cd0 423 ALWAYS_INLINE JSValue jsNumber(short i)
ba379fdc 424 {
14957cd0 425 return JSValue(i);
ba379fdc
A
426 }
427
14957cd0 428 ALWAYS_INLINE JSValue jsNumber(unsigned short i)
ba379fdc 429 {
14957cd0 430 return JSValue(i);
ba379fdc
A
431 }
432
14957cd0 433 ALWAYS_INLINE JSValue jsNumber(int i)
ba379fdc 434 {
14957cd0 435 return JSValue(i);
ba379fdc
A
436 }
437
14957cd0 438 ALWAYS_INLINE JSValue jsNumber(unsigned i)
ba379fdc 439 {
14957cd0 440 return JSValue(i);
ba379fdc
A
441 }
442
14957cd0 443 ALWAYS_INLINE JSValue jsNumber(long i)
ba379fdc 444 {
14957cd0 445 return JSValue(i);
ba379fdc
A
446 }
447
14957cd0 448 ALWAYS_INLINE JSValue jsNumber(unsigned long i)
ba379fdc 449 {
14957cd0 450 return JSValue(i);
ba379fdc
A
451 }
452
14957cd0 453 ALWAYS_INLINE JSValue jsNumber(long long i)
ba379fdc 454 {
14957cd0 455 return JSValue(i);
ba379fdc
A
456 }
457
14957cd0 458 ALWAYS_INLINE JSValue jsNumber(unsigned long long i)
ba379fdc 459 {
14957cd0 460 return JSValue(i);
ba379fdc
A
461 }
462
463 inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
464 inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
465
466 inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
467 inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
468
14957cd0 469 bool isZombie(const JSCell*);
ba379fdc 470
9dae56ea
A
471} // namespace JSC
472
473#endif // JSValue_h