Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / js / src / jsval.h
blobf6298625c9eec920c77835166afa61dbdcb8322a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99 ft=cpp:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * June 30, 2010
20 * The Initial Developer of the Original Code is
21 * the Mozilla Corporation.
23 * Contributor(s):
24 * Luke Wagner <lw@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef jsvalimpl_h__
41 #define jsvalimpl_h__
43 * JS value implementation details for operations on jsval and jsid.
44 * Embeddings should not rely on any of the definitions in this file. For a
45 * description of the value representation and the engine-internal C++ value
46 * interface, js::Value, see jsvalue.h.
48 #include "jsutil.h"
50 JS_BEGIN_EXTERN_C
53 * Try to get jsvals 64-bit aligned. We could almost assert that all values are
54 * aligned, but MSVC and GCC occasionally break alignment.
56 #ifdef __GNUC__
57 # define JSVAL_ALIGNMENT __attribute__((aligned (8)))
58 #elif defined(_MSC_VER)
60 * Structs can be aligned with MSVC, but not if they are used as parameters,
61 * so we just don't try to align.
63 # define JSVAL_ALIGNMENT
64 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
65 # define JSVAL_ALIGNMENT
66 #endif
68 #if JS_BITS_PER_WORD == 64
69 # define JSVAL_TAG_SHIFT 47
70 #endif
73 * We try to use enums so that printing a jsval_layout in the debugger shows
74 * nice symbolic type tags, however we can only do this when we can force the
75 * underlying type of the enum to be the desired size.
77 #if defined(__cplusplus) && !defined(__SUNPRO_CC)
79 #if defined(_MSC_VER)
80 # define JS_ENUM_HEADER(id, type) enum id : type
81 # define JS_ENUM_MEMBER(id, type, value) id = (type)value,
82 # define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
83 # define JS_ENUM_FOOTER(id)
84 #else
85 # define JS_ENUM_HEADER(id, type) enum id
86 # define JS_ENUM_MEMBER(id, type, value) id = (type)value,
87 # define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
88 # define JS_ENUM_FOOTER(id) __attribute__((packed))
89 #endif
91 /* Remember to propagate changes to the C defines below. */
92 JS_ENUM_HEADER(JSValueType, uint8)
94 JSVAL_TYPE_DOUBLE = 0x00,
95 JSVAL_TYPE_INT32 = 0x01,
96 JSVAL_TYPE_UNDEFINED = 0x02,
97 JSVAL_TYPE_BOOLEAN = 0x03,
98 JSVAL_TYPE_MAGIC = 0x04,
99 JSVAL_TYPE_STRING = 0x05,
100 JSVAL_TYPE_NULL = 0x06,
101 JSVAL_TYPE_OBJECT = 0x07,
103 /* The below types never appear in a jsval; they are only used in tracing. */
105 JSVAL_TYPE_NONFUNOBJ = 0x57,
106 JSVAL_TYPE_FUNOBJ = 0x67,
108 JSVAL_TYPE_STRORNULL = 0x97,
109 JSVAL_TYPE_OBJORNULL = 0x98,
111 JSVAL_TYPE_BOXED = 0x99
112 } JS_ENUM_FOOTER(JSValueType);
114 JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
116 #if JS_BITS_PER_WORD == 32
118 /* Remember to propagate changes to the C defines below. */
119 JS_ENUM_HEADER(JSValueTag, uint32)
121 JSVAL_TAG_CLEAR = 0xFFFF0000,
122 JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32,
123 JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED,
124 JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING,
125 JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
126 JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
127 JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
128 JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
129 } JS_ENUM_FOOTER(JSValueTag);
131 JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
133 #elif JS_BITS_PER_WORD == 64
135 /* Remember to propagate changes to the C defines below. */
136 JS_ENUM_HEADER(JSValueTag, uint32)
138 JSVAL_TAG_MAX_DOUBLE = 0x1FFF0,
139 JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32,
140 JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED,
141 JSVAL_TAG_STRING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING,
142 JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
143 JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
144 JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
145 JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
146 } JS_ENUM_FOOTER(JSValueTag);
148 JS_STATIC_ASSERT(sizeof(JSValueTag) == sizeof(uint32));
150 JS_ENUM_HEADER(JSValueShiftedTag, uint64)
152 JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
153 JSVAL_SHIFTED_TAG_INT32 = (((uint64)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
154 JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
155 JSVAL_SHIFTED_TAG_STRING = (((uint64)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
156 JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
157 JSVAL_SHIFTED_TAG_MAGIC = (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
158 JSVAL_SHIFTED_TAG_NULL = (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
159 JSVAL_SHIFTED_TAG_OBJECT = (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
160 } JS_ENUM_FOOTER(JSValueShiftedTag);
162 JS_STATIC_ASSERT(sizeof(JSValueShiftedTag) == sizeof(uint64));
164 #endif
166 #else /* defined(__cplusplus) */
168 typedef uint8 JSValueType;
169 #define JSVAL_TYPE_DOUBLE ((uint8)0x00)
170 #define JSVAL_TYPE_INT32 ((uint8)0x01)
171 #define JSVAL_TYPE_UNDEFINED ((uint8)0x02)
172 #define JSVAL_TYPE_BOOLEAN ((uint8)0x03)
173 #define JSVAL_TYPE_MAGIC ((uint8)0x04)
174 #define JSVAL_TYPE_STRING ((uint8)0x05)
175 #define JSVAL_TYPE_NULL ((uint8)0x06)
176 #define JSVAL_TYPE_OBJECT ((uint8)0x07)
177 #define JSVAL_TYPE_NONFUNOBJ ((uint8)0x57)
178 #define JSVAL_TYPE_FUNOBJ ((uint8)0x67)
179 #define JSVAL_TYPE_STRORNULL ((uint8)0x97)
180 #define JSVAL_TYPE_OBJORNULL ((uint8)0x98)
181 #define JSVAL_TYPE_BOXED ((uint8)0x99)
182 #define JSVAL_TYPE_UNINITIALIZED ((uint8)0xcd)
184 #if JS_BITS_PER_WORD == 32
186 typedef uint32 JSValueTag;
187 #define JSVAL_TAG_CLEAR ((uint32)(0xFFFF0000))
188 #define JSVAL_TAG_INT32 ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
189 #define JSVAL_TAG_UNDEFINED ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
190 #define JSVAL_TAG_STRING ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
191 #define JSVAL_TAG_BOOLEAN ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
192 #define JSVAL_TAG_MAGIC ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
193 #define JSVAL_TAG_NULL ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
194 #define JSVAL_TAG_OBJECT ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
196 #elif JS_BITS_PER_WORD == 64
198 typedef uint32 JSValueTag;
199 #define JSVAL_TAG_MAX_DOUBLE ((uint32)(0x1FFF0))
200 #define JSVAL_TAG_INT32 (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
201 #define JSVAL_TAG_UNDEFINED (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
202 #define JSVAL_TAG_STRING (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
203 #define JSVAL_TAG_BOOLEAN (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
204 #define JSVAL_TAG_MAGIC (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
205 #define JSVAL_TAG_NULL (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
206 #define JSVAL_TAG_OBJECT (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
208 typedef uint64 JSValueShiftedTag;
209 #define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
210 #define JSVAL_SHIFTED_TAG_INT32 (((uint64)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
211 #define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
212 #define JSVAL_SHIFTED_TAG_STRING (((uint64)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
213 #define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
214 #define JSVAL_SHIFTED_TAG_MAGIC (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
215 #define JSVAL_SHIFTED_TAG_NULL (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
216 #define JSVAL_SHIFTED_TAG_OBJECT (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
218 #endif /* JS_BITS_PER_WORD */
219 #endif /* defined(__cplusplus) && !defined(__SUNPRO_CC) */
221 #define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET JSVAL_TYPE_NULL
222 #define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET JSVAL_TYPE_OBJECT
223 #define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
224 #define JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET JSVAL_TYPE_MAGIC
225 #define JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET JSVAL_TYPE_OBJECT
226 #define JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET JSVAL_TYPE_FUNOBJ
228 #if JS_BITS_PER_WORD == 32
230 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
232 #define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
233 #define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
234 #define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
235 #define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
237 #elif JS_BITS_PER_WORD == 64
239 #define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
240 #define JSVAL_TAG_MASK 0xFFFF800000000000LL
241 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
242 #define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
244 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
245 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
246 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
247 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET JSVAL_SHIFTED_TAG_MAGIC
248 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
250 #endif /* JS_BITS_PER_WORD */
252 typedef enum JSWhyMagic
254 JS_ARRAY_HOLE, /* a hole in a dense array */
255 JS_ARGS_HOLE, /* a hole in the args object's array */
256 JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
257 * to js_Enumerate, which really means the object can be
258 * enumerated like a native object. */
259 JS_NO_ITER_VALUE, /* there is not a pending iterator value */
260 JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */
261 JS_NO_CONSTANT, /* compiler sentinel value */
262 JS_THIS_POISON, /* used in debug builds to catch tracing errors */
263 JS_ARG_POISON, /* used in debug builds to catch tracing errors */
264 JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
265 JS_GENERIC_MAGIC /* for local use */
266 } JSWhyMagic;
268 typedef struct JSString JSString;
269 typedef struct JSFlatString JSFlatString;
270 typedef struct JSObject JSObject;
272 #if defined(IS_LITTLE_ENDIAN)
273 # if JS_BITS_PER_WORD == 32
274 typedef union jsval_layout
276 uint64 asBits;
277 struct {
278 union {
279 int32 i32;
280 uint32 u32;
281 JSBool boo;
282 JSString *str;
283 JSObject *obj;
284 void *ptr;
285 JSWhyMagic why;
286 jsuword word;
287 } payload;
288 JSValueTag tag;
289 } s;
290 double asDouble;
291 void *asPtr;
292 } jsval_layout;
293 # elif JS_BITS_PER_WORD == 64
294 typedef union jsval_layout
296 uint64 asBits;
297 #if (!defined(_WIN64) && defined(__cplusplus))
298 /* MSVC does not pack these correctly :-( */
299 struct {
300 uint64 payload47 : 47;
301 JSValueTag tag : 17;
302 } debugView;
303 #endif
304 struct {
305 union {
306 int32 i32;
307 uint32 u32;
308 JSWhyMagic why;
309 jsuword word;
310 } payload;
311 } s;
312 double asDouble;
313 void *asPtr;
314 } jsval_layout;
315 # endif /* JS_BITS_PER_WORD */
316 #else /* defined(IS_LITTLE_ENDIAN) */
317 # if JS_BITS_PER_WORD == 32
318 typedef union jsval_layout
320 uint64 asBits;
321 struct {
322 JSValueTag tag;
323 union {
324 int32 i32;
325 uint32 u32;
326 JSBool boo;
327 JSString *str;
328 JSObject *obj;
329 void *ptr;
330 JSWhyMagic why;
331 jsuword word;
332 } payload;
333 } s;
334 double asDouble;
335 void *asPtr;
336 } jsval_layout;
337 # elif JS_BITS_PER_WORD == 64
338 typedef union jsval_layout
340 uint64 asBits;
341 struct {
342 JSValueTag tag : 17;
343 uint64 payload47 : 47;
344 } debugView;
345 struct {
346 union {
347 int32 i32;
348 uint32 u32;
349 JSWhyMagic why;
350 } payload;
351 } s;
352 double asDouble;
353 void *asPtr;
354 } jsval_layout;
355 # endif /* JS_BITS_PER_WORD */
356 #endif /* defined(IS_LITTLE_ENDIAN) */
358 #if JS_BITS_PER_WORD == 32
361 * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
362 * JSValueTag even though its underlying type has been forced to be uint32.
363 * Thus, all comparisons should explicitly cast operands to uint32.
366 #define BUILD_JSVAL(tag, payload) \
367 ((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
369 static JS_ALWAYS_INLINE JSBool
370 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
372 return (uint32)l.s.tag <= (uint32)JSVAL_TAG_CLEAR;
375 static JS_ALWAYS_INLINE jsval_layout
376 DOUBLE_TO_JSVAL_IMPL(double d)
378 jsval_layout l;
379 l.asDouble = d;
380 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
381 return l;
384 static JS_ALWAYS_INLINE JSBool
385 JSVAL_IS_INT32_IMPL(jsval_layout l)
387 return l.s.tag == JSVAL_TAG_INT32;
390 static JS_ALWAYS_INLINE int32
391 JSVAL_TO_INT32_IMPL(jsval_layout l)
393 return l.s.payload.i32;
396 static JS_ALWAYS_INLINE jsval_layout
397 INT32_TO_JSVAL_IMPL(int32 i)
399 jsval_layout l;
400 l.s.tag = JSVAL_TAG_INT32;
401 l.s.payload.i32 = i;
402 return l;
405 static JS_ALWAYS_INLINE JSBool
406 JSVAL_IS_NUMBER_IMPL(jsval_layout l)
408 JSValueTag tag = l.s.tag;
409 JS_ASSERT(tag != JSVAL_TAG_CLEAR);
410 return (uint32)tag <= (uint32)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
413 static JS_ALWAYS_INLINE JSBool
414 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
416 return l.s.tag == JSVAL_TAG_UNDEFINED;
419 static JS_ALWAYS_INLINE JSBool
420 JSVAL_IS_STRING_IMPL(jsval_layout l)
422 return l.s.tag == JSVAL_TAG_STRING;
425 static JS_ALWAYS_INLINE jsval_layout
426 STRING_TO_JSVAL_IMPL(JSString *str)
428 jsval_layout l;
429 JS_ASSERT(str);
430 l.s.tag = JSVAL_TAG_STRING;
431 l.s.payload.str = str;
432 return l;
435 static JS_ALWAYS_INLINE JSString *
436 JSVAL_TO_STRING_IMPL(jsval_layout l)
438 return l.s.payload.str;
441 static JS_ALWAYS_INLINE JSBool
442 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
444 return l.s.tag == JSVAL_TAG_BOOLEAN;
447 static JS_ALWAYS_INLINE JSBool
448 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
450 return l.s.payload.boo;
453 static JS_ALWAYS_INLINE jsval_layout
454 BOOLEAN_TO_JSVAL_IMPL(JSBool b)
456 jsval_layout l;
457 l.s.tag = JSVAL_TAG_BOOLEAN;
458 l.s.payload.boo = b;
459 return l;
462 static JS_ALWAYS_INLINE JSBool
463 JSVAL_IS_MAGIC_IMPL(jsval_layout l)
465 return l.s.tag == JSVAL_TAG_MAGIC;
468 static JS_ALWAYS_INLINE JSObject *
469 MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
471 JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
472 return l.s.payload.obj;
475 static JS_ALWAYS_INLINE JSBool
476 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
478 return l.s.tag == JSVAL_TAG_OBJECT;
481 static JS_ALWAYS_INLINE JSBool
482 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
484 return (uint32)l.s.tag < (uint32)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
487 static JS_ALWAYS_INLINE JSBool
488 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
490 JS_ASSERT((uint32)l.s.tag <= (uint32)JSVAL_TAG_OBJECT);
491 return (uint32)l.s.tag >= (uint32)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
494 static JS_ALWAYS_INLINE JSObject *
495 JSVAL_TO_OBJECT_IMPL(jsval_layout l)
497 return l.s.payload.obj;
500 static JS_ALWAYS_INLINE jsval_layout
501 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
503 jsval_layout l;
504 JS_ASSERT(obj);
505 l.s.tag = JSVAL_TAG_OBJECT;
506 l.s.payload.obj = obj;
507 return l;
510 static JS_ALWAYS_INLINE JSBool
511 JSVAL_IS_NULL_IMPL(jsval_layout l)
513 return l.s.tag == JSVAL_TAG_NULL;
516 static JS_ALWAYS_INLINE jsval_layout
517 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
519 jsval_layout l;
520 JS_ASSERT(((uint32)ptr & 1) == 0);
521 l.s.tag = (JSValueTag)0;
522 l.s.payload.ptr = ptr;
523 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
524 return l;
527 static JS_ALWAYS_INLINE void *
528 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
530 return l.s.payload.ptr;
533 static JS_ALWAYS_INLINE JSBool
534 JSVAL_IS_GCTHING_IMPL(jsval_layout l)
536 /* gcc sometimes generates signed < without explicit casts. */
537 return (uint32)l.s.tag >= (uint32)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
540 static JS_ALWAYS_INLINE void *
541 JSVAL_TO_GCTHING_IMPL(jsval_layout l)
543 return l.s.payload.ptr;
546 static JS_ALWAYS_INLINE JSBool
547 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
549 return l.s.tag == JSVAL_TAG_STRING || l.s.tag == JSVAL_TAG_OBJECT;
552 static JS_ALWAYS_INLINE uint32
553 JSVAL_TRACE_KIND_IMPL(jsval_layout l)
555 return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
558 #elif JS_BITS_PER_WORD == 64
560 #define BUILD_JSVAL(tag, payload) \
561 ((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
563 static JS_ALWAYS_INLINE JSBool
564 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
566 return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
569 static JS_ALWAYS_INLINE jsval_layout
570 DOUBLE_TO_JSVAL_IMPL(double d)
572 jsval_layout l;
573 l.asDouble = d;
574 JS_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
575 return l;
578 static JS_ALWAYS_INLINE JSBool
579 JSVAL_IS_INT32_IMPL(jsval_layout l)
581 return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
584 static JS_ALWAYS_INLINE int32
585 JSVAL_TO_INT32_IMPL(jsval_layout l)
587 return (int32)l.asBits;
590 static JS_ALWAYS_INLINE jsval_layout
591 INT32_TO_JSVAL_IMPL(int32 i32)
593 jsval_layout l;
594 l.asBits = ((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32;
595 return l;
598 static JS_ALWAYS_INLINE JSBool
599 JSVAL_IS_NUMBER_IMPL(jsval_layout l)
601 return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
604 static JS_ALWAYS_INLINE JSBool
605 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
607 return l.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
610 static JS_ALWAYS_INLINE JSBool
611 JSVAL_IS_STRING_IMPL(jsval_layout l)
613 return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
616 static JS_ALWAYS_INLINE jsval_layout
617 STRING_TO_JSVAL_IMPL(JSString *str)
619 jsval_layout l;
620 uint64 strBits = (uint64)str;
621 JS_ASSERT(str);
622 JS_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
623 l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
624 return l;
627 static JS_ALWAYS_INLINE JSString *
628 JSVAL_TO_STRING_IMPL(jsval_layout l)
630 return (JSString *)(l.asBits & JSVAL_PAYLOAD_MASK);
633 static JS_ALWAYS_INLINE JSBool
634 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
636 return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
639 static JS_ALWAYS_INLINE JSBool
640 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
642 return (JSBool)l.asBits;
645 static JS_ALWAYS_INLINE jsval_layout
646 BOOLEAN_TO_JSVAL_IMPL(JSBool b)
648 jsval_layout l;
649 l.asBits = ((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
650 return l;
653 static JS_ALWAYS_INLINE JSBool
654 JSVAL_IS_MAGIC_IMPL(jsval_layout l)
656 return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
659 static JS_ALWAYS_INLINE JSObject *
660 MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
662 uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
663 JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
664 JS_ASSERT((ptrBits >> JSVAL_TAG_SHIFT) == 0);
665 return (JSObject *)ptrBits;
668 static JS_ALWAYS_INLINE JSBool
669 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
671 return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
674 static JS_ALWAYS_INLINE JSBool
675 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
677 JS_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_SHIFTED_TAG_OBJECT);
678 return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
681 static JS_ALWAYS_INLINE JSBool
682 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
684 JS_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
685 return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
688 static JS_ALWAYS_INLINE JSObject *
689 JSVAL_TO_OBJECT_IMPL(jsval_layout l)
691 uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
692 JS_ASSERT((ptrBits & 0x7) == 0);
693 return (JSObject *)ptrBits;
696 static JS_ALWAYS_INLINE jsval_layout
697 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
699 jsval_layout l;
700 uint64 objBits = (uint64)obj;
701 JS_ASSERT(obj);
702 JS_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
703 l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
704 return l;
707 static JS_ALWAYS_INLINE JSBool
708 JSVAL_IS_NULL_IMPL(jsval_layout l)
710 return l.asBits == JSVAL_SHIFTED_TAG_NULL;
713 static JS_ALWAYS_INLINE JSBool
714 JSVAL_IS_GCTHING_IMPL(jsval_layout l)
716 return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
719 static JS_ALWAYS_INLINE void *
720 JSVAL_TO_GCTHING_IMPL(jsval_layout l)
722 uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
723 JS_ASSERT((ptrBits & 0x7) == 0);
724 return (void *)ptrBits;
727 static JS_ALWAYS_INLINE JSBool
728 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
730 return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
733 static JS_ALWAYS_INLINE uint32
734 JSVAL_TRACE_KIND_IMPL(jsval_layout l)
736 return (uint32)(JSBool)!(JSVAL_IS_OBJECT_IMPL(l));
739 static JS_ALWAYS_INLINE jsval_layout
740 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
742 jsval_layout l;
743 uint64 ptrBits = (uint64)ptr;
744 JS_ASSERT((ptrBits & 1) == 0);
745 l.asBits = ptrBits >> 1;
746 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
747 return l;
750 static JS_ALWAYS_INLINE void *
751 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
753 JS_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
754 return (void *)(l.asBits << 1);
757 #endif
759 static JS_ALWAYS_INLINE double
760 JS_CANONICALIZE_NAN(double d)
762 if (JS_UNLIKELY(d != d)) {
763 jsval_layout l;
764 l.asBits = 0x7FF8000000000000LL;
765 return l.asDouble;
767 return d;
770 /* See JS_USE_JSVAL_JSID_STRUCT_TYPES comment in jsapi.h. */
771 #if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
772 # define JS_USE_JSVAL_JSID_STRUCT_TYPES
773 #endif
775 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
777 typedef JSVAL_ALIGNMENT jsval_layout jsval;
778 typedef struct jsid { size_t asBits; } jsid;
780 #if defined(__cplusplus)
781 extern "C++"
783 static JS_ALWAYS_INLINE bool
784 operator==(jsid lhs, jsid rhs)
786 return lhs.asBits == rhs.asBits;
789 static JS_ALWAYS_INLINE bool
790 operator!=(jsid lhs, jsid rhs)
792 return lhs.asBits != rhs.asBits;
795 static JS_ALWAYS_INLINE bool
796 operator==(jsval lhs, jsval rhs)
798 return lhs.asBits == rhs.asBits;
801 static JS_ALWAYS_INLINE bool
802 operator!=(jsval lhs, jsval rhs)
804 return lhs.asBits != rhs.asBits;
807 # endif /* defined(__cplusplus) */
809 /* Internal helper macros */
810 #define JSVAL_BITS(v) ((v).asBits)
811 #define JSVAL_FROM_LAYOUT(l) (l)
812 #define IMPL_TO_JSVAL(v) (v)
813 #define JSID_BITS(id) ((id).asBits)
815 #else /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
817 /* Use different primitive types so overloading works. */
818 typedef JSVAL_ALIGNMENT uint64 jsval;
819 typedef ptrdiff_t jsid;
821 /* Internal helper macros */
822 #define JSVAL_BITS(v) (v)
823 #define JSVAL_FROM_LAYOUT(l) ((l).asBits)
824 #define IMPL_TO_JSVAL(v) ((v).asBits)
825 #define JSID_BITS(id) (id)
827 #endif /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
829 JS_END_EXTERN_C
831 #endif /* jsvalimpl_h__ */