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