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.
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;
49 class AssemblyHelpers;
51 class JITCodeGenerator;
53 class OSRExitCompiler;
57 #if ENABLE(LLINT_C_LOOP)
67 template <class T> class WriteBarrierBase;
69 enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
72 typedef int64_t EncodedJSValue;
74 union EncodedValueDescriptor {
95 // This implements ToInt32, defined in ECMA-262 9.5.
96 JS_EXPORT_PRIVATE int32_t toInt32(double);
98 // This implements ToUInt32, defined in ECMA-262 9.6.
99 inline uint32_t toUInt32(double number)
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);
107 friend struct EncodedJSValueHashTraits;
109 friend class JITStubs;
110 friend class JITStubCall;
111 friend class JSInterfaceJIT;
112 friend class SpecializedThunkJIT;
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;
121 #if ENABLE(LLINT_C_LOOP)
122 friend class LLInt::CLoop;
126 #if USE(JSVALUE32_64)
127 enum { Int32Tag = 0xffffffff };
128 enum { BooleanTag = 0xfffffffe };
129 enum { NullTag = 0xfffffffd };
130 enum { UndefinedTag = 0xfffffffc };
131 enum { CellTag = 0xfffffffb };
132 enum { EmptyValueTag = 0xfffffffa };
133 enum { DeletedValueTag = 0xfffffff9 };
135 enum { LowestTag = DeletedValueTag };
138 static EncodedJSValue encode(JSValue);
139 static JSValue decode(EncodedJSValue);
141 enum JSNullTag { JSNull };
142 enum JSUndefinedTag { JSUndefined };
143 enum JSTrueTag { JSTrue };
144 enum JSFalseTag { JSFalse };
145 enum EncodeAsDoubleTag { EncodeAsDouble };
149 JSValue(JSUndefinedTag);
152 JSValue(JSCell* ptr);
153 JSValue(const JSCell* ptr);
156 JSValue(EncodeAsDoubleTag, double);
157 explicit JSValue(double);
158 explicit JSValue(char);
159 explicit JSValue(unsigned char);
160 explicit JSValue(short);
161 explicit JSValue(unsigned short);
162 explicit JSValue(int);
163 explicit JSValue(unsigned);
164 explicit JSValue(long);
165 explicit JSValue(unsigned long);
166 explicit JSValue(long long);
167 explicit JSValue(unsigned long long);
169 operator bool() const;
170 bool operator==(const JSValue& other) const;
171 bool operator!=(const JSValue& other) const;
173 bool isInt32() const;
174 bool isUInt32() const;
175 bool isDouble() const;
177 bool isFalse() const;
179 int32_t asInt32() const;
180 uint32_t asUInt32() const;
181 double asDouble() const;
182 bool asBoolean() const;
183 double asNumber() const;
185 // Querying the type.
186 bool isEmpty() const;
187 bool isFunction() const;
188 bool isUndefined() const;
190 bool isUndefinedOrNull() const;
191 bool isBoolean() const;
192 bool isNumber() const;
193 bool isString() const;
194 bool isPrimitive() const;
195 bool isGetterSetter() const;
196 bool isObject() const;
197 bool inherits(const ClassInfo*) const;
199 // Extracting the value.
200 bool getString(ExecState*, WTF::String&) const;
201 WTF::String getString(ExecState*) const; // null string if not a string
202 JSObject* getObject() const; // 0 if not an object
204 // Extracting integer values.
205 bool getUInt32(uint32_t&) const;
207 // Basic conversions.
208 JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
209 bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
211 bool toBoolean(ExecState*) const;
213 // toNumber conversion is expected to be side effect free if an exception has
214 // been set in the ExecState already.
215 double toNumber(ExecState*) const;
216 JSString* toString(ExecState*) const;
217 WTF::String toWTFString(ExecState*) const;
218 WTF::String toWTFStringInline(ExecState*) const;
219 JSObject* toObject(ExecState*) const;
220 JSObject* toObject(ExecState*, JSGlobalObject*) const;
222 // Integer conversions.
223 JS_EXPORT_PRIVATE double toInteger(ExecState*) const;
224 double toIntegerPreserveNaN(ExecState*) const;
225 int32_t toInt32(ExecState*) const;
226 uint32_t toUInt32(ExecState*) const;
228 // Floating point conversions (this is a convenience method for webcore;
229 // signle precision float is not a representation used in JS or JSC).
230 float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
232 // Object operations, with the toObject operation included.
233 JSValue get(ExecState*, PropertyName) const;
234 JSValue get(ExecState*, PropertyName, PropertySlot&) const;
235 JSValue get(ExecState*, unsigned propertyName) const;
236 JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
237 void put(ExecState*, PropertyName, JSValue, PutPropertySlot&);
238 void putToPrimitive(ExecState*, PropertyName, JSValue, PutPropertySlot&);
239 void putToPrimitiveByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
240 void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
242 JSObject* toThisObject(ExecState*) const;
244 static bool equal(ExecState* exec, JSValue v1, JSValue v2);
245 static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
246 static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
247 static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
248 static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
249 static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
252 JSCell* asCell() const;
253 JS_EXPORT_PRIVATE bool isValidCallee();
255 JSValue structureOrUndefined() const;
257 JS_EXPORT_PRIVATE char* description() const;
259 JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
262 template <class T> JSValue(WriteBarrierBase<T>);
264 enum HashTableDeletedValueTag { HashTableDeletedValue };
265 JSValue(HashTableDeletedValueTag);
267 inline const JSValue asValue() const { return *this; }
268 JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
269 JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
270 JS_EXPORT_PRIVATE WTF::String toWTFStringSlowCase(ExecState*) const;
271 JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
272 JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
274 #if USE(JSVALUE32_64)
276 * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
277 * form for immediates.
279 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
280 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
281 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
282 * have a payload of zero. We assume that non-zero payloads are available to encode
283 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
284 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
285 * ranges to encode other values (however there are also other ranges of NaN space that
286 * could have been selected).
288 * For JSValues that do not contain a double value, the high 32 bits contain the tag
289 * values listed in the enums below, which all correspond to NaN-space. In the case of
290 * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
291 * integer or boolean value; in the case of all other tags the payload is 0.
293 uint32_t tag() const;
294 int32_t payload() const;
296 #if ENABLE(LLINT_C_LOOP)
297 // This should only be used by the LLInt C Loop interpreter who needs
298 // synthesize JSValue from its "register"s holding tag and payload
300 explicit JSValue(int32_t tag, int32_t payload);
305 * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
306 * form for immediates.
308 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
309 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
310 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
311 * have a payload of zero. We assume that non-zero payloads are available to encode
312 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
313 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
314 * ranges to encode other values (however there are also other ranges of NaN space that
315 * could have been selected).
317 * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
318 * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
319 * numbers will begin fall in these ranges.
321 * The top 16-bits denote the type of the encoded JSValue:
323 * Pointer { 0000:PPPP:PPPP:PPPP
324 * / 0001:****:****:****
326 * \ FFFE:****:****:****
327 * Integer { FFFF:0000:IIII:IIII
329 * The scheme we have implemented encodes double precision values by performing a
330 * 64-bit integer addition of the value 2^48 to the number. After this manipulation
331 * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
332 * Values must be decoded by reversing this operation before subsequent floating point
333 * operations my be peformed.
335 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
337 * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
338 * null and undefined values are represented by specific, invalid pointer values:
345 * These values have the following properties:
346 * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
347 * quickly distinguished from all immediate values, including these invalid pointers.
348 * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
349 * same value, allowing null & undefined to be quickly detected.
351 * No valid JSValue will have the bit pattern 0x0, this is used to represent array
352 * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
355 // These values are #defines since using static const integers here is a ~1% regression!
357 // This value is 2^48, used to encode doubles such that the encoded value will begin
358 // with a 16-bit pattern within the range 0x0001..0xFFFE.
359 #define DoubleEncodeOffset 0x1000000000000ll
360 // If all bits in the mask are set, this indicates an integer number,
361 // if any but not all are set this value is a double precision number.
362 #define TagTypeNumber 0xffff000000000000ll
364 // All non-numeric (bool, null, undefined) immediates have bit 2 set.
365 #define TagBitTypeOther 0x2ll
366 #define TagBitBool 0x4ll
367 #define TagBitUndefined 0x8ll
368 // Combined integer value for non-numeric immediates.
369 #define ValueFalse (TagBitTypeOther | TagBitBool | false)
370 #define ValueTrue (TagBitTypeOther | TagBitBool | true)
371 #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
372 #define ValueNull (TagBitTypeOther)
374 // TagMask is used to check for all types of immediate values (either number or 'other').
375 #define TagMask (TagTypeNumber | TagBitTypeOther)
377 // These special values are never visible to JavaScript code; Empty is used to represent
378 // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
379 // These values would map to cell types in the JSValue encoding, but not valid GC cell
380 // pointer should have either of these values (Empty is null, deleted is at an invalid
381 // alignment for a GC cell, and in the zero page).
382 #define ValueEmpty 0x0ll
383 #define ValueDeleted 0x4ll
386 EncodedValueDescriptor u;
389 typedef IntHash<EncodedJSValue> EncodedJSValueHash;
391 #if USE(JSVALUE32_64)
392 struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
393 static const bool emptyValueIsZero = false;
394 static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
395 static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
396 static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
399 struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
400 static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
401 static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
405 typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
407 // Stand-alone helper functions.
408 inline JSValue jsNull()
410 return JSValue(JSValue::JSNull);
413 inline JSValue jsUndefined()
415 return JSValue(JSValue::JSUndefined);
418 inline JSValue jsBoolean(bool b)
420 return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
423 ALWAYS_INLINE JSValue jsDoubleNumber(double d)
425 ASSERT(JSValue(JSValue::EncodeAsDouble, d).isNumber());
426 return JSValue(JSValue::EncodeAsDouble, d);
429 ALWAYS_INLINE JSValue jsNumber(double d)
431 ASSERT(JSValue(d).isNumber());
435 ALWAYS_INLINE JSValue jsNumber(char i)
440 ALWAYS_INLINE JSValue jsNumber(unsigned char i)
445 ALWAYS_INLINE JSValue jsNumber(short i)
450 ALWAYS_INLINE JSValue jsNumber(unsigned short i)
455 ALWAYS_INLINE JSValue jsNumber(int i)
460 ALWAYS_INLINE JSValue jsNumber(unsigned i)
465 ALWAYS_INLINE JSValue jsNumber(long i)
470 ALWAYS_INLINE JSValue jsNumber(unsigned long i)
475 ALWAYS_INLINE JSValue jsNumber(long long i)
480 ALWAYS_INLINE JSValue jsNumber(unsigned long long i)
485 inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
486 inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
488 inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
489 inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }