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