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