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