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