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