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