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.
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.
28 #include <stddef.h> // for size_t
30 #include <wtf/Assertions.h>
31 #include <wtf/Forward.h>
32 #include <wtf/HashMap.h>
33 #include <wtf/HashTraits.h>
34 #include <wtf/MathExtras.h>
35 #include <wtf/MediaTime.h>
36 #include <wtf/StdLibExtras.h>
37 #include <wtf/TriState.h>
41 class AssemblyHelpers
;
52 class PutPropertySlot
;
57 class OSRExitCompiler
;
72 template <class T
> class WriteBarrierBase
;
74 enum PreferredPrimitiveType
{ NoPreference
, PreferNumber
, PreferString
};
75 enum ECMAMode
{ StrictMode
, NotStrictMode
};
77 typedef int64_t EncodedJSValue
;
79 union EncodedValueDescriptor
{
100 #define TagOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))
101 #define PayloadOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))
104 #define CellPayloadOffset 0
106 #define CellPayloadOffset PayloadOffset
109 enum WhichValueWord
{
114 // This implements ToInt32, defined in ECMA-262 9.5.
115 JS_EXPORT_PRIVATE
int32_t toInt32(double);
117 // This implements ToUInt32, defined in ECMA-262 9.6.
118 inline uint32_t toUInt32(double number
)
120 // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
121 // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
122 return toInt32(number
);
125 int64_t tryConvertToInt52(double);
126 bool isInt52(double);
128 enum class SourceCodeRepresentation
{
135 friend struct EncodedJSValueHashTraits
;
136 friend struct EncodedJSValueWithRepresentationHashTraits
;
137 friend class AssemblyHelpers
;
139 friend class JITSlowPathCall
;
140 friend class JITStubs
;
141 friend class JITStubCall
;
142 friend class JSInterfaceJIT
;
143 friend class JSValueSource
;
144 friend class SpecializedThunkJIT
;
146 friend class DFG::JITCompiler
;
147 friend class DFG::OSRExitCompiler
;
148 friend class DFG::SpeculativeJIT
;
151 friend class LLInt::CLoop
;
155 #if USE(JSVALUE32_64)
156 enum { Int32Tag
= 0xffffffff };
157 enum { BooleanTag
= 0xfffffffe };
158 enum { NullTag
= 0xfffffffd };
159 enum { UndefinedTag
= 0xfffffffc };
160 enum { CellTag
= 0xfffffffb };
161 enum { EmptyValueTag
= 0xfffffffa };
162 enum { DeletedValueTag
= 0xfffffff9 };
164 enum { LowestTag
= DeletedValueTag
};
167 static EncodedJSValue
encode(JSValue
);
168 static JSValue
decode(EncodedJSValue
);
170 enum JSNullTag
{ JSNull
};
171 enum JSUndefinedTag
{ JSUndefined
};
172 enum JSTrueTag
{ JSTrue
};
173 enum JSFalseTag
{ JSFalse
};
174 enum EncodeAsDoubleTag
{ EncodeAsDouble
};
178 JSValue(JSUndefinedTag
);
181 JSValue(JSCell
* ptr
);
182 JSValue(const JSCell
* ptr
);
185 JSValue(EncodeAsDoubleTag
, double);
186 explicit JSValue(double);
187 explicit JSValue(char);
188 explicit JSValue(unsigned char);
189 explicit JSValue(short);
190 explicit JSValue(unsigned short);
191 explicit JSValue(int);
192 explicit JSValue(unsigned);
193 explicit JSValue(long);
194 explicit JSValue(unsigned long);
195 explicit JSValue(long long);
196 explicit JSValue(unsigned long long);
198 explicit operator bool() const;
199 bool operator==(const JSValue
& other
) const;
200 bool operator!=(const JSValue
& other
) const;
202 bool isInt32() const;
203 bool isUInt32() const;
204 bool isDouble() const;
206 bool isFalse() const;
208 int32_t asInt32() const;
209 uint32_t asUInt32() const;
210 int64_t asMachineInt() const;
211 double asDouble() const;
212 bool asBoolean() const;
213 double asNumber() const;
215 int32_t asInt32ForArithmetic() const; // Boolean becomes an int, but otherwise like asInt32().
217 // Querying the type.
218 bool isEmpty() const;
219 bool isFunction() const;
220 bool isUndefined() const;
222 bool isUndefinedOrNull() const;
223 bool isBoolean() const;
224 bool isMachineInt() const;
225 bool isNumber() const;
226 bool isString() const;
227 bool isSymbol() const;
228 bool isPrimitive() const;
229 bool isGetterSetter() const;
230 bool isCustomGetterSetter() const;
231 bool isObject() const;
232 bool inherits(const ClassInfo
*) const;
234 // Extracting the value.
235 bool getString(ExecState
*, WTF::String
&) const;
236 WTF::String
getString(ExecState
*) const; // null string if not a string
237 JSObject
* getObject() const; // 0 if not an object
239 // Extracting integer values.
240 bool getUInt32(uint32_t&) const;
242 // Basic conversions.
243 JSValue
toPrimitive(ExecState
*, PreferredPrimitiveType
= NoPreference
) const;
244 bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
&);
246 bool toBoolean(ExecState
*) const;
247 TriState
pureToBoolean() const;
249 // toNumber conversion is expected to be side effect free if an exception has
250 // been set in the ExecState already.
251 double toNumber(ExecState
*) const;
252 JSString
* toString(ExecState
*) const;
253 Identifier
toPropertyKey(ExecState
*) const;
254 WTF::String
toWTFString(ExecState
*) const;
255 JSObject
* toObject(ExecState
*) const;
256 JSObject
* toObject(ExecState
*, JSGlobalObject
*) const;
258 // Integer conversions.
259 JS_EXPORT_PRIVATE
double toInteger(ExecState
*) const;
260 JS_EXPORT_PRIVATE
double toIntegerPreserveNaN(ExecState
*) const;
261 int32_t toInt32(ExecState
*) const;
262 uint32_t toUInt32(ExecState
*) const;
264 // Floating point conversions (this is a convenience function for WebCore;
265 // single precision float is not a representation used in JS or JSC).
266 float toFloat(ExecState
* exec
) const { return static_cast<float>(toNumber(exec
)); }
268 // Object operations, with the toObject operation included.
269 JSValue
get(ExecState
*, PropertyName
) const;
270 JSValue
get(ExecState
*, PropertyName
, PropertySlot
&) const;
271 JSValue
get(ExecState
*, unsigned propertyName
) const;
272 JSValue
get(ExecState
*, unsigned propertyName
, PropertySlot
&) const;
274 bool getPropertySlot(ExecState
*, PropertyName
, PropertySlot
&) const;
276 void put(ExecState
*, PropertyName
, JSValue
, PutPropertySlot
&);
277 JS_EXPORT_PRIVATE
void putToPrimitive(ExecState
*, PropertyName
, JSValue
, PutPropertySlot
&);
278 JS_EXPORT_PRIVATE
void putToPrimitiveByIndex(ExecState
*, unsigned propertyName
, JSValue
, bool shouldThrow
);
279 void putByIndex(ExecState
*, unsigned propertyName
, JSValue
, bool shouldThrow
);
281 JSValue
toThis(ExecState
*, ECMAMode
) const;
283 static bool equal(ExecState
*, JSValue v1
, JSValue v2
);
284 static bool equalSlowCase(ExecState
*, JSValue v1
, JSValue v2
);
285 static bool equalSlowCaseInline(ExecState
*, JSValue v1
, JSValue v2
);
286 static bool strictEqual(ExecState
*, JSValue v1
, JSValue v2
);
287 static bool strictEqualSlowCase(ExecState
*, JSValue v1
, JSValue v2
);
288 static bool strictEqualSlowCaseInline(ExecState
*, JSValue v1
, JSValue v2
);
289 static TriState
pureStrictEqual(JSValue v1
, JSValue v2
);
292 JSCell
* asCell() const;
293 JS_EXPORT_PRIVATE
bool isValidCallee();
295 JSValue
structureOrUndefined() const;
297 JS_EXPORT_PRIVATE
void dump(PrintStream
&) const;
298 void dumpInContext(PrintStream
&, DumpContext
*) const;
299 void dumpInContextAssumingStructure(PrintStream
&, DumpContext
*, Structure
*) const;
300 void dumpForBacktrace(PrintStream
&) const;
302 JS_EXPORT_PRIVATE JSObject
* synthesizePrototype(ExecState
*) const;
303 bool requireObjectCoercible(ExecState
*) const;
305 // Constants used for Int52. Int52 isn't part of JSValue right now, but JSValues may be
306 // converted to Int52s and back again.
307 static const unsigned numberOfInt52Bits
= 52;
308 static const int64_t notInt52
= static_cast<int64_t>(1) << numberOfInt52Bits
;
309 static const unsigned int52ShiftAmount
= 12;
311 static ptrdiff_t offsetOfPayload() { return OBJECT_OFFSETOF(JSValue
, u
.asBits
.payload
); }
312 static ptrdiff_t offsetOfTag() { return OBJECT_OFFSETOF(JSValue
, u
.asBits
.tag
); }
314 #if USE(JSVALUE32_64)
316 * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
317 * form for immediates.
319 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
320 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
321 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
322 * have a payload of zero. We assume that non-zero payloads are available to encode
323 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
324 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
325 * ranges to encode other values (however there are also other ranges of NaN space that
326 * could have been selected).
328 * For JSValues that do not contain a double value, the high 32 bits contain the tag
329 * values listed in the enums below, which all correspond to NaN-space. In the case of
330 * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
331 * integer or boolean value; in the case of all other tags the payload is 0.
333 uint32_t tag() const;
334 int32_t payload() const;
337 // This should only be used by the LLInt C Loop interpreter who needs
338 // synthesize JSValue from its "register"s holding tag and payload
340 explicit JSValue(int32_t tag
, int32_t payload
);
345 * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
346 * form for immediates.
348 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
349 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
350 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
351 * have a payload of zero. We assume that non-zero payloads are available to encode
352 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
353 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
354 * ranges to encode other values (however there are also other ranges of NaN space that
355 * could have been selected).
357 * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
358 * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
359 * numbers will fall in these ranges.
361 * The top 16-bits denote the type of the encoded JSValue:
363 * Pointer { 0000:PPPP:PPPP:PPPP
364 * / 0001:****:****:****
366 * \ FFFE:****:****:****
367 * Integer { FFFF:0000:IIII:IIII
369 * The scheme we have implemented encodes double precision values by performing a
370 * 64-bit integer addition of the value 2^48 to the number. After this manipulation
371 * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
372 * Values must be decoded by reversing this operation before subsequent floating point
373 * operations may be peformed.
375 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
377 * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
378 * null and undefined values are represented by specific, invalid pointer values:
385 * These values have the following properties:
386 * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
387 * quickly distinguished from all immediate values, including these invalid pointers.
388 * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
389 * same value, allowing null & undefined to be quickly detected.
391 * No valid JSValue will have the bit pattern 0x0, this is used to represent array
392 * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
395 // These values are #defines since using static const integers here is a ~1% regression!
397 // This value is 2^48, used to encode doubles such that the encoded value will begin
398 // with a 16-bit pattern within the range 0x0001..0xFFFE.
399 #define DoubleEncodeOffset 0x1000000000000ll
400 // If all bits in the mask are set, this indicates an integer number,
401 // if any but not all are set this value is a double precision number.
402 #define TagTypeNumber 0xffff000000000000ll
404 // All non-numeric (bool, null, undefined) immediates have bit 2 set.
405 #define TagBitTypeOther 0x2ll
406 #define TagBitBool 0x4ll
407 #define TagBitUndefined 0x8ll
408 // Combined integer value for non-numeric immediates.
409 #define ValueFalse (TagBitTypeOther | TagBitBool | false)
410 #define ValueTrue (TagBitTypeOther | TagBitBool | true)
411 #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
412 #define ValueNull (TagBitTypeOther)
414 // TagMask is used to check for all types of immediate values (either number or 'other').
415 #define TagMask (TagTypeNumber | TagBitTypeOther)
417 // These special values are never visible to JavaScript code; Empty is used to represent
418 // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
419 // These values would map to cell types in the JSValue encoding, but not valid GC cell
420 // pointer should have either of these values (Empty is null, deleted is at an invalid
421 // alignment for a GC cell, and in the zero page).
422 #define ValueEmpty 0x0ll
423 #define ValueDeleted 0x4ll
427 template <class T
> JSValue(WriteBarrierBase
<T
>);
429 enum HashTableDeletedValueTag
{ HashTableDeletedValue
};
430 JSValue(HashTableDeletedValueTag
);
432 inline const JSValue
asValue() const { return *this; }
433 JS_EXPORT_PRIVATE
double toNumberSlowCase(ExecState
*) const;
434 JS_EXPORT_PRIVATE JSString
* toStringSlowCase(ExecState
*) const;
435 JS_EXPORT_PRIVATE
WTF::String
toWTFStringSlowCase(ExecState
*) const;
436 JS_EXPORT_PRIVATE JSObject
* toObjectSlowCase(ExecState
*, JSGlobalObject
*) const;
437 JS_EXPORT_PRIVATE JSValue
toThisSlowCase(ExecState
*, ECMAMode
) const;
439 EncodedValueDescriptor u
;
442 typedef IntHash
<EncodedJSValue
> EncodedJSValueHash
;
444 #if USE(JSVALUE32_64)
445 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
446 static const bool emptyValueIsZero
= false;
447 static EncodedJSValue
emptyValue() { return JSValue::encode(JSValue()); }
448 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
449 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
452 struct EncodedJSValueHashTraits
: HashTraits
<EncodedJSValue
> {
453 static void constructDeletedValue(EncodedJSValue
& slot
) { slot
= JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
454 static bool isDeletedValue(EncodedJSValue value
) { return value
== JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)); }
458 typedef std::pair
<EncodedJSValue
, SourceCodeRepresentation
> EncodedJSValueWithRepresentation
;
460 struct EncodedJSValueWithRepresentationHashTraits
: HashTraits
<EncodedJSValueWithRepresentation
> {
461 static const bool emptyValueIsZero
= false;
462 static EncodedJSValueWithRepresentation
emptyValue() { return std::make_pair(JSValue::encode(JSValue()), SourceCodeRepresentation::Other
); }
463 static void constructDeletedValue(EncodedJSValueWithRepresentation
& slot
) { slot
= std::make_pair(JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)), SourceCodeRepresentation::Other
); }
464 static bool isDeletedValue(EncodedJSValueWithRepresentation value
) { return value
== std::make_pair(JSValue::encode(JSValue(JSValue::HashTableDeletedValue
)), SourceCodeRepresentation::Other
); }
467 struct EncodedJSValueWithRepresentationHash
{
468 static unsigned hash(const EncodedJSValueWithRepresentation
& value
)
470 return WTF::pairIntHash(EncodedJSValueHash::hash(value
.first
), IntHash
<SourceCodeRepresentation
>::hash(value
.second
));
472 static bool equal(const EncodedJSValueWithRepresentation
& a
, const EncodedJSValueWithRepresentation
& b
)
476 static const bool safeToCompareToEmptyOrDeleted
= true;
479 // Stand-alone helper functions.
480 inline JSValue
jsNull()
482 return JSValue(JSValue::JSNull
);
485 inline JSValue
jsUndefined()
487 return JSValue(JSValue::JSUndefined
);
490 inline JSValue
jsBoolean(bool b
)
492 return b
? JSValue(JSValue::JSTrue
) : JSValue(JSValue::JSFalse
);
495 ALWAYS_INLINE JSValue
jsDoubleNumber(double d
)
497 ASSERT(JSValue(JSValue::EncodeAsDouble
, d
).isNumber());
498 return JSValue(JSValue::EncodeAsDouble
, d
);
501 ALWAYS_INLINE JSValue
jsNumber(double d
)
503 ASSERT(JSValue(d
).isNumber());
507 ALWAYS_INLINE JSValue
jsNumber(MediaTime t
)
509 return jsNumber(t
.toDouble());
512 ALWAYS_INLINE JSValue
jsNumber(char i
)
517 ALWAYS_INLINE JSValue
jsNumber(unsigned char i
)
522 ALWAYS_INLINE JSValue
jsNumber(short i
)
527 ALWAYS_INLINE JSValue
jsNumber(unsigned short i
)
532 ALWAYS_INLINE JSValue
jsNumber(int i
)
537 ALWAYS_INLINE JSValue
jsNumber(unsigned i
)
542 ALWAYS_INLINE JSValue
jsNumber(long i
)
547 ALWAYS_INLINE JSValue
jsNumber(unsigned long i
)
552 ALWAYS_INLINE JSValue
jsNumber(long long i
)
557 ALWAYS_INLINE JSValue
jsNumber(unsigned long long i
)
562 inline bool operator==(const JSValue a
, const JSCell
* b
) { return a
== JSValue(b
); }
563 inline bool operator==(const JSCell
* a
, const JSValue b
) { return JSValue(a
) == b
; }
565 inline bool operator!=(const JSValue a
, const JSCell
* b
) { return a
!= JSValue(b
); }
566 inline bool operator!=(const JSCell
* a
, const JSValue b
) { return JSValue(a
) != b
; }
570 #endif // JSCJSValue_h