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.
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.
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.
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.
27 #include <stddef.h> // for size_t
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>
46 class PutPropertySlot
;
50 class AssemblyHelpers
;
52 class JITCodeGenerator
;
54 class OSRExitCompiler
;
66 template <class T
> class WriteBarrierBase
;
68 enum PreferredPrimitiveType
{ NoPreference
, PreferNumber
, PreferString
};
72 typedef int64_t EncodedJSValue
;
74 typedef void* EncodedJSValue
;
77 union EncodedValueDescriptor
{
98 // This implements ToInt32, defined in ECMA-262 9.5.
99 JS_EXPORT_PRIVATE
int32_t toInt32(double);
101 // This implements ToUInt32, defined in ECMA-262 9.6.
102 inline uint32_t toUInt32(double number
)
104 // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
105 // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
106 return toInt32(number
);
110 friend struct EncodedJSValueHashTraits
;
112 friend class JITStubs
;
113 friend class JITStubCall
;
114 friend class JSInterfaceJIT
;
115 friend class SpecializedThunkJIT
;
117 friend class DFG::AssemblyHelpers
;
118 friend class DFG::JITCompiler
;
119 friend class DFG::JITCodeGenerator
;
120 friend class DFG::JSValueSource
;
121 friend class DFG::OSRExitCompiler
;
122 friend class DFG::SpeculativeJIT
;
124 friend class LLInt::Data
;
127 static EncodedJSValue
encode(JSValue
);
128 static JSValue
decode(EncodedJSValue
);
130 enum JSNullTag
{ JSNull
};
131 enum JSUndefinedTag
{ JSUndefined
};
132 enum JSTrueTag
{ JSTrue
};
133 enum JSFalseTag
{ JSFalse
};
134 enum EncodeAsDoubleTag
{ EncodeAsDouble
};
138 JSValue(JSUndefinedTag
);
141 JSValue(JSCell
* ptr
);
142 JSValue(const JSCell
* ptr
);
145 JSValue(EncodeAsDoubleTag
, double);
146 explicit JSValue(double);
147 explicit JSValue(char);
148 explicit JSValue(unsigned char);
149 explicit JSValue(short);
150 explicit JSValue(unsigned short);
151 explicit JSValue(int);
152 explicit JSValue(unsigned);
153 explicit JSValue(long);
154 explicit JSValue(unsigned long);
155 explicit JSValue(long long);
156 explicit JSValue(unsigned long long);
158 operator bool() const;
159 bool operator==(const JSValue
& other
) const;
160 bool operator!=(const JSValue
& other
) const;
162 bool isInt32() const;
163 bool isUInt32() const;
164 bool isDouble() const;
166 bool isFalse() const;
168 int32_t asInt32() const;
169 uint32_t asUInt32() const;
170 double asDouble() const;
171 bool asBoolean() const;
172 double asNumber() const;
174 // Querying the type.
175 bool isEmpty() const;
176 bool isFunction() const;
177 bool isUndefined() const;
179 bool isUndefinedOrNull() const;
180 bool isBoolean() const;
181 bool isNumber() const;
182 bool isString() const;
183 bool isPrimitive() const;
184 bool isGetterSetter() const;
185 bool isObject() const;
186 bool inherits(const ClassInfo
*) const;
188 // Extracting the value.
189 bool getString(ExecState
* exec
, UString
&) const;
190 UString
getString(ExecState
* exec
) const; // null string if not a string
191 JSObject
* getObject() const; // 0 if not an object
193 // Extracting integer values.
194 bool getUInt32(uint32_t&) const;
196 // Basic conversions.
197 JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
198 bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
&);
200 bool toBoolean(ExecState
*) const;
202 // toNumber conversion is expected to be side effect free if an exception has
203 // been set in the ExecState already.
204 double toNumber(ExecState
*) const;
205 JSString
* toString(ExecState
*) const;
206 UString
toUString(ExecState
*) const;
207 UString
toUStringInline(ExecState
*) const;
208 JSObject
* toObject(ExecState
*) const;
209 JSObject
* toObject(ExecState
*, JSGlobalObject
*) const;
211 // Integer conversions.
212 JS_EXPORT_PRIVATE
double toInteger(ExecState
*) const;
213 double toIntegerPreserveNaN(ExecState
*) const;
214 int32_t toInt32(ExecState
*) const;
215 uint32_t toUInt32(ExecState
*) const;
217 // Floating point conversions (this is a convenience method for webcore;
218 // signle precision float is not a representation used in JS or JSC).
219 float toFloat(ExecState
* exec
) const { return static_cast<float>(toNumber(exec
)); }
221 // Object operations, with the toObject operation included.
222 JSValue
get(ExecState
*, const Identifier
& propertyName
) const;
223 JSValue
get(ExecState
*, const Identifier
& propertyName
, PropertySlot
&) const;
224 JSValue
get(ExecState
*, unsigned propertyName
) const;
225 JSValue
get(ExecState
*, unsigned propertyName
, PropertySlot
&) const;
226 void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
227 void putToPrimitive(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
228 void putByIndex(ExecState
*, unsigned propertyName
, JSValue
, bool shouldThrow
);
230 JSObject
* toThisObject(ExecState
*) const;
232 static bool equal(ExecState
* exec
, JSValue v1
, JSValue v2
);
233 static bool equalSlowCase(ExecState
* exec
, JSValue v1
, JSValue v2
);
234 static bool equalSlowCaseInline(ExecState
* exec
, JSValue v1
, JSValue v2
);
235 static bool strictEqual(ExecState
* exec
, JSValue v1
, JSValue v2
);
236 static bool strictEqualSlowCase(ExecState
* exec
, JSValue v1
, JSValue v2
);
237 static bool strictEqualSlowCaseInline(ExecState
* exec
, JSValue v1
, JSValue v2
);
240 JSCell
* asCell() const;
241 JS_EXPORT_PRIVATE
bool isValidCallee();
245 JS_EXPORT_PRIVATE JSObject
* synthesizePrototype(ExecState
*) const;
248 template <class T
> JSValue(WriteBarrierBase
<T
>);
250 enum HashTableDeletedValueTag
{ HashTableDeletedValue
};
251 JSValue(HashTableDeletedValueTag
);
253 inline const JSValue
asValue() const { return *this; }
254 JS_EXPORT_PRIVATE
double toNumberSlowCase(ExecState
*) const;
255 JS_EXPORT_PRIVATE JSString
* toStringSlowCase(ExecState
*) const;
256 JS_EXPORT_PRIVATE UString
toUStringSlowCase(ExecState
*) const;
257 JS_EXPORT_PRIVATE JSObject
* toObjectSlowCase(ExecState
*, JSGlobalObject
*) const;
258 JS_EXPORT_PRIVATE JSObject
* toThisObjectSlowCase(ExecState
*) const;
260 #if USE(JSVALUE32_64)
262 * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
263 * form for immediates.
265 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
266 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
267 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
268 * have a payload of zero. We assume that non-zero payloads are available to encode
269 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
270 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
271 * ranges to encode other values (however there are also other ranges of NaN space that
272 * could have been selected).
274 * For JSValues that do not contain a double value, the high 32 bits contain the tag
275 * values listed in the enums below, which all correspond to NaN-space. In the case of
276 * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
277 * integer or boolean value; in the case of all other tags the payload is 0.
279 enum { Int32Tag
= 0xffffffff };
280 enum { BooleanTag
= 0xfffffffe };
281 enum { NullTag
= 0xfffffffd };
282 enum { UndefinedTag
= 0xfffffffc };
283 enum { CellTag
= 0xfffffffb };
284 enum { EmptyValueTag
= 0xfffffffa };
285 enum { DeletedValueTag
= 0xfffffff9 };
287 enum { LowestTag
= DeletedValueTag
};
289 uint32_t tag() const;
290 int32_t payload() const;
293 * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
294 * form for immediates.
296 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
297 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
298 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
299 * have a payload of zero. We assume that non-zero payloads are available to encode
300 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
301 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
302 * ranges to encode other values (however there are also other ranges of NaN space that
303 * could have been selected).
305 * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
306 * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
307 * numbers will begin fall in these ranges.
309 * The top 16-bits denote the type of the encoded JSValue:
311 * Pointer { 0000:PPPP:PPPP:PPPP
312 * / 0001:****:****:****
314 * \ FFFE:****:****:****
315 * Integer { FFFF:0000:IIII:IIII
317 * The scheme we have implemented encodes double precision values by performing a
318 * 64-bit integer addition of the value 2^48 to the number. After this manipulation
319 * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
320 * Values must be decoded by reversing this operation before subsequent floating point
321 * operations my be peformed.
323 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
325 * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
326 * null and undefined values are represented by specific, invalid pointer values:
333 * These values have the following properties:
334 * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
335 * quickly distinguished from all immediate values, including these invalid pointers.
336 * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
337 * same value, allowing null & undefined to be quickly detected.
339 * No valid JSValue will have the bit pattern 0x0, this is used to represent array
340 * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
343 // These values are #defines since using static const integers here is a ~1% regression!
345 // This value is 2^48, used to encode doubles such that the encoded value will begin
346 // with a 16-bit pattern within the range 0x0001..0xFFFE.
347 #define DoubleEncodeOffset 0x1000000000000ll
348 // If all bits in the mask are set, this indicates an integer number,
349 // if any but not all are set this value is a double precision number.
350 #define TagTypeNumber 0xffff000000000000ll
352 // All non-numeric (bool, null, undefined) immediates have bit 2 set.
353 #define TagBitTypeOther 0x2ll
354 #define TagBitBool 0x4ll
355 #define TagBitUndefined 0x8ll
356 // Combined integer value for non-numeric immediates.
357 #define ValueFalse (TagBitTypeOther | TagBitBool | false)
358 #define ValueTrue (TagBitTypeOther | TagBitBool | true)
359 #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
360 #define ValueNull (TagBitTypeOther)
362 // TagMask is used to check for all types of immediate values (either number or 'other').
363 #define TagMask (TagTypeNumber | TagBitTypeOther)
365 // These special values are never visible to JavaScript code; Empty is used to represent
366 // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
367 // These values would map to cell types in the JSValue encoding, but not valid GC cell
368 // pointer should have either of these values (Empty is null, deleted is at an invalid
369 // alignment for a GC cell, and in the zero page).
370 #define ValueEmpty 0x0ll
371 #define ValueDeleted 0x4ll
374 EncodedValueDescriptor u
;
377 #if USE(JSVALUE32_64)
378 typedef IntHash
<EncodedJSValue
> EncodedJSValueHash
;
380 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
381 static const bool emptyValueIsZero
= false;
382 static EncodedJSValue
emptyValue() { return JSValue::encode(JSValue()); }
383 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
384 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
387 typedef PtrHash
<EncodedJSValue
> EncodedJSValueHash
;
389 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
390 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
391 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
395 typedef HashMap
<EncodedJSValue
, unsigned, EncodedJSValueHash
, EncodedJSValueHashTraits
> JSValueMap
;
397 // Stand-alone helper functions.
398 inline JSValue
jsNull()
400 return JSValue(JSValue::JSNull
);
403 inline JSValue
jsUndefined()
405 return JSValue(JSValue::JSUndefined
);
408 inline JSValue
jsBoolean(bool b
)
410 return b
? JSValue(JSValue::JSTrue
) : JSValue(JSValue::JSFalse
);
413 ALWAYS_INLINE JSValue
jsDoubleNumber(double d
)
415 ASSERT(JSValue(JSValue::EncodeAsDouble
, d
).isNumber());
416 return JSValue(JSValue::EncodeAsDouble
, d
);
419 ALWAYS_INLINE JSValue
jsNumber(double d
)
421 ASSERT(JSValue(d
).isNumber());
425 ALWAYS_INLINE JSValue
jsNumber(char i
)
430 ALWAYS_INLINE JSValue
jsNumber(unsigned char i
)
435 ALWAYS_INLINE JSValue
jsNumber(short i
)
440 ALWAYS_INLINE JSValue
jsNumber(unsigned short i
)
445 ALWAYS_INLINE JSValue
jsNumber(int i
)
450 ALWAYS_INLINE JSValue
jsNumber(unsigned i
)
455 ALWAYS_INLINE JSValue
jsNumber(long i
)
460 ALWAYS_INLINE JSValue
jsNumber(unsigned long i
)
465 ALWAYS_INLINE JSValue
jsNumber(long long i
)
470 ALWAYS_INLINE JSValue
jsNumber(unsigned long long i
)
475 inline bool operator==(const JSValue a
, const JSCell
* b
) { return a
== JSValue(b
); }
476 inline bool operator==(const JSCell
* a
, const JSValue b
) { return JSValue(a
) == b
; }
478 inline bool operator!=(const JSValue a
, const JSCell
* b
) { return a
!= JSValue(b
); }
479 inline bool operator!=(const JSCell
* a
, const JSValue b
) { return JSValue(a
) != b
; }