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