1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * the Mozilla Corporation.
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 ***** */
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.
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.
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
69 * We try to use enums so that printing a jsval_layout in the debugger shows
70 * nice symbolic type tags, however we can only do this when we can force the
71 * underlying type of the enum to be the desired size.
76 # define JS_ENUM_HEADER(id, type) enum id : type
77 # define JS_ENUM_MEMBER(id, type, value) id = (type)value,
78 # define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
79 # define JS_ENUM_FOOTER(id)
81 # define JS_ENUM_HEADER(id, type) enum id
82 # define JS_ENUM_MEMBER(id, type, value) id = (type)value,
83 # define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
84 # define JS_ENUM_FOOTER(id) __attribute__((packed))
87 /* Remember to propagate changes to the C defines below. */
88 JS_ENUM_HEADER(JSValueType
, uint8
)
90 JSVAL_TYPE_DOUBLE
= 0x00,
91 JSVAL_TYPE_INT32
= 0x01,
92 JSVAL_TYPE_UNDEFINED
= 0x02,
93 JSVAL_TYPE_BOOLEAN
= 0x03,
94 JSVAL_TYPE_MAGIC
= 0x04,
95 JSVAL_TYPE_STRING
= 0x05,
96 JSVAL_TYPE_NULL
= 0x06,
97 JSVAL_TYPE_OBJECT
= 0x07,
99 /* The below types never appear in a jsval; they are only used in tracing. */
101 JSVAL_TYPE_NONFUNOBJ
= 0x57,
102 JSVAL_TYPE_FUNOBJ
= 0x67,
104 JSVAL_TYPE_STRORNULL
= 0x97,
105 JSVAL_TYPE_OBJORNULL
= 0x98,
107 JSVAL_TYPE_BOXED
= 0x99,
108 JSVAL_TYPE_UNINITIALIZED
= 0xcd
109 } JS_ENUM_FOOTER(JSValueType
);
111 JS_STATIC_ASSERT(sizeof(JSValueType
) == 1);
113 #if JS_BITS_PER_WORD == 32
115 /* Remember to propagate changes to the C defines below. */
116 JS_ENUM_HEADER(JSValueTag
, uint32
)
118 JSVAL_TAG_CLEAR
= 0xFFFF0000,
119 JSVAL_TAG_INT32
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_INT32
,
120 JSVAL_TAG_UNDEFINED
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_UNDEFINED
,
121 JSVAL_TAG_STRING
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_STRING
,
122 JSVAL_TAG_BOOLEAN
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_BOOLEAN
,
123 JSVAL_TAG_MAGIC
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_MAGIC
,
124 JSVAL_TAG_NULL
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_NULL
,
125 JSVAL_TAG_OBJECT
= JSVAL_TAG_CLEAR
| JSVAL_TYPE_OBJECT
126 } JS_ENUM_FOOTER(JSValueType
);
128 JS_STATIC_ASSERT(sizeof(JSValueTag
) == 4);
130 #elif JS_BITS_PER_WORD == 64
132 /* Remember to propagate changes to the C defines below. */
133 JS_ENUM_HEADER(JSValueTag
, uint32
)
135 JSVAL_TAG_MAX_DOUBLE
= 0x1FFF0,
136 JSVAL_TAG_INT32
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_INT32
,
137 JSVAL_TAG_UNDEFINED
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_UNDEFINED
,
138 JSVAL_TAG_STRING
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_STRING
,
139 JSVAL_TAG_BOOLEAN
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_BOOLEAN
,
140 JSVAL_TAG_MAGIC
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_MAGIC
,
141 JSVAL_TAG_NULL
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_NULL
,
142 JSVAL_TAG_OBJECT
= JSVAL_TAG_MAX_DOUBLE
| JSVAL_TYPE_OBJECT
143 } JS_ENUM_FOOTER(JSValueType
);
145 JS_STATIC_ASSERT(sizeof(JSValueTag
) == 4);
149 #else /* defined(__cplusplus) */
151 typedef uint8 JSValueType
;
152 #define JSVAL_TYPE_DOUBLE ((uint8)0x00)
153 #define JSVAL_TYPE_INT32 ((uint8)0x01)
154 #define JSVAL_TYPE_UNDEFINED ((uint8)0x02)
155 #define JSVAL_TYPE_BOOLEAN ((uint8)0x03)
156 #define JSVAL_TYPE_MAGIC ((uint8)0x04)
157 #define JSVAL_TYPE_STRING ((uint8)0x05)
158 #define JSVAL_TYPE_NULL ((uint8)0x06)
159 #define JSVAL_TYPE_OBJECT ((uint8)0x07)
160 #define JSVAL_TYPE_NONFUNOBJ ((uint8)0x57)
161 #define JSVAL_TYPE_FUNOBJ ((uint8)0x67)
162 #define JSVAL_TYPE_STRORNULL ((uint8)0x97)
163 #define JSVAL_TYPE_OBJORNULL ((uint8)0x98)
164 #define JSVAL_TYPE_STRORNULL ((uint8)0x97)
165 #define JSVAL_TYPE_OBJORNULL ((uint8)0x98)
166 #define JSVAL_TYPE_BOXED ((uint8)0x99)
167 #define JSVAL_TYPE_UNINITIALIZED ((uint8)0xcd)
169 #if JS_BITS_PER_WORD == 32
171 typedef uint32 JSValueTag
;
172 #define JSVAL_TAG_CLEAR ((uint32)(0xFFFF0000))
173 #define JSVAL_TAG_INT32 ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
174 #define JSVAL_TAG_UNDEFINED ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
175 #define JSVAL_TAG_STRING ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
176 #define JSVAL_TAG_BOOLEAN ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
177 #define JSVAL_TAG_MAGIC ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
178 #define JSVAL_TAG_NULL ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
179 #define JSVAL_TAG_OBJECT ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
181 #elif JS_BITS_PER_WORD == 64
183 typedef uint32 JSValueTag
;
184 #define JSVAL_TAG_MAX_DOUBLE ((uint32)(0x1FFF0))
185 #define JSVAL_TAG_INT32 (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
186 #define JSVAL_TAG_UNDEFINED (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
187 #define JSVAL_TAG_STRING (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
188 #define JSVAL_TAG_BOOLEAN (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
189 #define JSVAL_TAG_MAGIC (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
190 #define JSVAL_TAG_NULL (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
191 #define JSVAL_TAG_OBJECT (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
193 #endif /* JS_BITS_PER_WORD */
194 #endif /* defined(__cplusplus) */
196 #define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET JSVAL_TYPE_NULL
197 #define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET JSVAL_TYPE_OBJECT
198 #define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
199 #define JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET JSVAL_TYPE_STRING
200 #define JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET JSVAL_TYPE_OBJECT
201 #define JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET JSVAL_TYPE_FUNOBJ
203 #if JS_BITS_PER_WORD == 32
205 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
207 #define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
208 #define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
209 #define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
210 #define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
212 #elif JS_BITS_PER_WORD == 64
214 #define JSVAL_TAG_SHIFT 47
215 #define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
216 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
217 #define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
219 #define JSVAL_SHIFTED_TAG_MAX_DOUBLE (((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT)
220 #define JSVAL_SHIFTED_TAG_INT32 (((uint64)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
221 #define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
222 #define JSVAL_SHIFTED_TAG_STRING (((uint64)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
223 #define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
224 #define JSVAL_SHIFTED_TAG_MAGIC (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
225 #define JSVAL_SHIFTED_TAG_NULL (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
226 #define JSVAL_SHIFTED_TAG_OBJECT (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
228 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
229 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
230 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
231 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
233 #endif /* JS_BITS_PER_WORD */
235 typedef enum JSWhyMagic
237 JS_ARRAY_HOLE
, /* a hole in a dense array */
238 JS_ARGS_HOLE
, /* a hole in the args object's array */
239 JS_NATIVE_ENUMERATE
, /* indicates that a custom enumerate hook forwarded
240 * to js_Enumerate, which really means the object can be
241 * enumerated like a native object. */
242 JS_NO_ITER_VALUE
, /* there is not a pending iterator value */
243 JS_GENERATOR_CLOSING
, /* exception value thrown when closing a generator */
244 JS_NO_CONSTANT
, /* compiler sentinel value */
245 JS_THIS_POISON
, /* used in debug builds to catch tracing errors */
246 JS_GENERIC_MAGIC
/* for local use */
249 typedef struct JSString JSString
;
250 typedef struct JSObject JSObject
;
252 #if defined(IS_LITTLE_ENDIAN)
253 # if JS_BITS_PER_WORD == 32
254 typedef union jsval_layout
271 # elif JS_BITS_PER_WORD == 64
272 typedef union jsval_layout
276 uint64 payload47
: 47;
288 # endif /* JS_BITS_PER_WORD */
289 #else /* defined(IS_LITTLE_ENDIAN) */
290 # if JS_BITS_PER_WORD == 32
291 typedef union jsval_layout
308 # endif /* JS_BITS_PER_WORD */
309 #endif /* defined(IS_LITTLE_ENDIAN) */
311 #if JS_BITS_PER_WORD == 32
314 * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
315 * JSValueTag even though its underlying type has been forced to be uint32.
316 * Thus, all comparisons should explicitly cast operands to uint32.
319 #define BUILD_JSVAL(tag, payload) \
320 ((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
322 static JS_ALWAYS_INLINE JSBool
323 JSVAL_IS_DOUBLE_IMPL(jsval_layout l
)
325 return (uint32
)l
.s
.tag
< (uint32
)JSVAL_TAG_CLEAR
;
328 static JS_ALWAYS_INLINE jsval_layout
329 DOUBLE_TO_JSVAL_IMPL(double d
)
333 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l
));
337 static JS_ALWAYS_INLINE JSBool
338 JSVAL_IS_INT32_IMPL(jsval_layout l
)
340 return l
.s
.tag
== JSVAL_TAG_INT32
;
343 static JS_ALWAYS_INLINE int32
344 JSVAL_TO_INT32_IMPL(jsval_layout l
)
346 return l
.s
.payload
.i32
;
349 static JS_ALWAYS_INLINE jsval_layout
350 INT32_TO_JSVAL_IMPL(int32 i
)
353 l
.s
.tag
= JSVAL_TAG_INT32
;
358 static JS_ALWAYS_INLINE JSBool
359 JSVAL_IS_NUMBER_IMPL(jsval_layout l
)
361 JSValueTag tag
= l
.s
.tag
;
362 JS_ASSERT(tag
!= JSVAL_TAG_CLEAR
);
363 return (uint32
)tag
<= (uint32
)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET
;
366 static JS_ALWAYS_INLINE JSBool
367 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l
)
369 return l
.s
.tag
== JSVAL_TAG_UNDEFINED
;
372 static JS_ALWAYS_INLINE JSBool
373 JSVAL_IS_STRING_IMPL(jsval_layout l
)
375 return l
.s
.tag
== JSVAL_TAG_STRING
;
378 static JS_ALWAYS_INLINE jsval_layout
379 STRING_TO_JSVAL_IMPL(JSString
*str
)
382 l
.s
.tag
= JSVAL_TAG_STRING
;
383 l
.s
.payload
.str
= str
;
387 static JS_ALWAYS_INLINE JSString
*
388 JSVAL_TO_STRING_IMPL(jsval_layout l
)
390 return l
.s
.payload
.str
;
393 static JS_ALWAYS_INLINE JSBool
394 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l
)
396 return l
.s
.tag
== JSVAL_TAG_BOOLEAN
;
399 static JS_ALWAYS_INLINE JSBool
400 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l
)
402 return l
.s
.payload
.boo
;
405 static JS_ALWAYS_INLINE jsval_layout
406 BOOLEAN_TO_JSVAL_IMPL(JSBool b
)
409 l
.s
.tag
= JSVAL_TAG_BOOLEAN
;
414 static JS_ALWAYS_INLINE JSBool
415 JSVAL_IS_OBJECT_IMPL(jsval_layout l
)
417 return l
.s
.tag
== JSVAL_TAG_OBJECT
;
420 static JS_ALWAYS_INLINE JSBool
421 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l
)
423 return (uint32
)l
.s
.tag
< (uint32
)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET
;
426 static JS_ALWAYS_INLINE JSBool
427 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l
)
429 JS_ASSERT((uint32
)l
.s
.tag
<= (uint32
)JSVAL_TAG_OBJECT
);
430 return (uint32
)l
.s
.tag
>= (uint32
)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET
;
433 static JS_ALWAYS_INLINE JSObject
*
434 JSVAL_TO_OBJECT_IMPL(jsval_layout l
)
436 return l
.s
.payload
.obj
;
439 static JS_ALWAYS_INLINE jsval_layout
440 OBJECT_TO_JSVAL_IMPL(JSObject
*obj
)
443 l
.s
.tag
= JSVAL_TAG_OBJECT
;
444 l
.s
.payload
.obj
= obj
;
448 static JS_ALWAYS_INLINE JSBool
449 JSVAL_IS_NULL_IMPL(jsval_layout l
)
451 return l
.s
.tag
== JSVAL_TAG_NULL
;
454 static JS_ALWAYS_INLINE jsval_layout
455 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr
)
458 JS_ASSERT(((uint32
)ptr
& 1) == 0);
459 l
.s
.tag
= (JSValueTag
)0;
460 l
.s
.payload
.ptr
= ptr
;
461 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l
));
465 static JS_ALWAYS_INLINE
void *
466 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l
)
468 return l
.s
.payload
.ptr
;
471 static JS_ALWAYS_INLINE JSBool
472 JSVAL_IS_GCTHING_IMPL(jsval_layout l
)
474 /* gcc sometimes generates signed < without explicit casts. */
475 return (uint32
)l
.s
.tag
>= (uint32
)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET
;
478 static JS_ALWAYS_INLINE
void *
479 JSVAL_TO_GCTHING_IMPL(jsval_layout l
)
481 return l
.s
.payload
.ptr
;
484 static JS_ALWAYS_INLINE JSBool
485 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l
)
487 return l
.s
.tag
== JSVAL_TAG_STRING
|| l
.s
.tag
== JSVAL_TAG_OBJECT
;
490 static JS_ALWAYS_INLINE uint32
491 JSVAL_TRACE_KIND_IMPL(jsval_layout l
)
493 return (uint32
)(JSBool
)JSVAL_IS_STRING_IMPL(l
);
496 #elif JS_BITS_PER_WORD == 64
498 #define BUILD_JSVAL(tag, payload) \
499 ((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
501 static JS_ALWAYS_INLINE JSBool
502 JSVAL_IS_DOUBLE_IMPL(jsval_layout l
)
504 return l
.asBits
<= JSVAL_SHIFTED_TAG_MAX_DOUBLE
;
507 static JS_ALWAYS_INLINE jsval_layout
508 DOUBLE_TO_JSVAL_IMPL(double d
)
512 JS_ASSERT(l
.asBits
<= JSVAL_SHIFTED_TAG_MAX_DOUBLE
);
516 static JS_ALWAYS_INLINE JSBool
517 JSVAL_IS_INT32_IMPL(jsval_layout l
)
519 return (uint32
)(l
.asBits
>> JSVAL_TAG_SHIFT
) == JSVAL_TAG_INT32
;
522 static JS_ALWAYS_INLINE int32
523 JSVAL_TO_INT32_IMPL(jsval_layout l
)
525 return (int32
)l
.asBits
;
528 static JS_ALWAYS_INLINE jsval_layout
529 INT32_TO_JSVAL_IMPL(int32 i32
)
532 l
.asBits
= ((uint64
)(uint32
)i32
) | JSVAL_SHIFTED_TAG_INT32
;
536 static JS_ALWAYS_INLINE JSBool
537 JSVAL_IS_NUMBER_IMPL(jsval_layout l
)
539 return l
.asBits
< JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET
;
542 static JS_ALWAYS_INLINE JSBool
543 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l
)
545 return l
.asBits
== JSVAL_SHIFTED_TAG_UNDEFINED
;
548 static JS_ALWAYS_INLINE JSBool
549 JSVAL_IS_STRING_IMPL(jsval_layout l
)
551 return (uint32
)(l
.asBits
>> JSVAL_TAG_SHIFT
) == JSVAL_TAG_STRING
;
554 static JS_ALWAYS_INLINE jsval_layout
555 STRING_TO_JSVAL_IMPL(JSString
*str
)
558 uint64 strBits
= (uint64
)str
;
559 JS_ASSERT((strBits
>> JSVAL_TAG_SHIFT
) == 0);
560 l
.asBits
= strBits
| JSVAL_SHIFTED_TAG_STRING
;
564 static JS_ALWAYS_INLINE JSString
*
565 JSVAL_TO_STRING_IMPL(jsval_layout l
)
567 return (JSString
*)(l
.asBits
& JSVAL_PAYLOAD_MASK
);
570 static JS_ALWAYS_INLINE JSBool
571 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l
)
573 return (uint32
)(l
.asBits
>> JSVAL_TAG_SHIFT
) == JSVAL_TAG_BOOLEAN
;
576 static JS_ALWAYS_INLINE JSBool
577 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l
)
579 return (JSBool
)l
.asBits
;
582 static JS_ALWAYS_INLINE jsval_layout
583 BOOLEAN_TO_JSVAL_IMPL(JSBool b
)
586 l
.asBits
= ((uint64
)(uint32
)b
) | JSVAL_SHIFTED_TAG_BOOLEAN
;
590 static JS_ALWAYS_INLINE JSBool
591 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l
)
593 return l
.asBits
< JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
;
596 static JS_ALWAYS_INLINE JSBool
597 JSVAL_IS_OBJECT_IMPL(jsval_layout l
)
599 JS_ASSERT((l
.asBits
>> JSVAL_TAG_SHIFT
) <= JSVAL_SHIFTED_TAG_OBJECT
);
600 return l
.asBits
>= JSVAL_SHIFTED_TAG_OBJECT
;
603 static JS_ALWAYS_INLINE JSBool
604 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l
)
606 JS_ASSERT((l
.asBits
>> JSVAL_TAG_SHIFT
) <= JSVAL_TAG_OBJECT
);
607 return l
.asBits
>= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
;
610 static JS_ALWAYS_INLINE JSObject
*
611 JSVAL_TO_OBJECT_IMPL(jsval_layout l
)
613 uint64 ptrBits
= l
.asBits
& JSVAL_PAYLOAD_MASK
;
614 JS_ASSERT((ptrBits
& 0x7) == 0);
615 return (JSObject
*)ptrBits
;
618 static JS_ALWAYS_INLINE jsval_layout
619 OBJECT_TO_JSVAL_IMPL(JSObject
*obj
)
622 uint64 objBits
= (uint64
)obj
;
623 JS_ASSERT((objBits
>> JSVAL_TAG_SHIFT
) == 0);
624 l
.asBits
= objBits
| JSVAL_SHIFTED_TAG_OBJECT
;
628 static JS_ALWAYS_INLINE JSBool
629 JSVAL_IS_NULL_IMPL(jsval_layout l
)
631 return l
.asBits
== JSVAL_SHIFTED_TAG_NULL
;
634 static JS_ALWAYS_INLINE JSBool
635 JSVAL_IS_GCTHING_IMPL(jsval_layout l
)
637 return l
.asBits
>= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET
;
640 static JS_ALWAYS_INLINE
void *
641 JSVAL_TO_GCTHING_IMPL(jsval_layout l
)
643 uint64 ptrBits
= l
.asBits
& JSVAL_PAYLOAD_MASK
;
644 JS_ASSERT((ptrBits
& 0x7) == 0);
645 return (void *)ptrBits
;
648 static JS_ALWAYS_INLINE JSBool
649 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l
)
651 return JSVAL_IS_GCTHING_IMPL(l
) && !JSVAL_IS_NULL_IMPL(l
);
654 static JS_ALWAYS_INLINE uint32
655 JSVAL_TRACE_KIND_IMPL(jsval_layout l
)
657 return (uint32
)(JSBool
)!(JSVAL_IS_OBJECT_IMPL(l
));
660 static JS_ALWAYS_INLINE jsval_layout
661 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr
)
664 uint64 ptrBits
= (uint64
)ptr
;
665 JS_ASSERT((ptrBits
& 1) == 0);
666 l
.asBits
= ptrBits
>> 1;
667 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l
));
671 static JS_ALWAYS_INLINE
void *
672 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l
)
674 JS_ASSERT((l
.asBits
& 0x8000000000000000LL
) == 0);
675 return (void *)(l
.asBits
<< 1);
680 static JS_ALWAYS_INLINE JSBool
681 JSVAL_IS_UNDERLYING_TYPE_OF_PRIVATE_IMPL(jsval_layout l
)
683 return JSVAL_IS_DOUBLE_IMPL(l
);
686 /* See JS_USE_JSVAL_JSID_STRUCT_TYPES comment in jsapi.h. */
687 #if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
688 # define JS_USE_JSVAL_JSID_STRUCT_TYPES
691 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
693 typedef JSVAL_ALIGNMENT jsval_layout jsval
;
694 typedef struct jsid
{ size_t asBits
; } jsid
;
696 #if defined(__cplusplus)
699 static JS_ALWAYS_INLINE
bool
700 operator==(jsid lhs
, jsid rhs
)
702 return lhs
.asBits
== rhs
.asBits
;
705 static JS_ALWAYS_INLINE
bool
706 operator!=(jsid lhs
, jsid rhs
)
708 return lhs
.asBits
!= rhs
.asBits
;
711 static JS_ALWAYS_INLINE
bool
712 operator==(jsval lhs
, jsval rhs
)
714 return lhs
.asBits
== rhs
.asBits
;
717 static JS_ALWAYS_INLINE
bool
718 operator!=(jsval lhs
, jsval rhs
)
720 return lhs
.asBits
!= rhs
.asBits
;
723 # endif /* defined(__cplusplus) */
725 /* Internal helper macros */
726 #define JSVAL_BITS(v) (v.asBits)
727 #define JSVAL_FROM_LAYOUT(l) (l)
728 #define IMPL_TO_JSVAL(v) (v)
729 #define JSID_BITS(id) (id.asBits)
731 #else /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
733 /* Use different primitive types so overloading works. */
734 typedef JSVAL_ALIGNMENT uint64 jsval
;
735 typedef ptrdiff_t jsid
;
737 /* Internal helper macros */
738 #define JSVAL_BITS(v) (v)
739 #define JSVAL_FROM_LAYOUT(l) ((l).asBits)
740 #define IMPL_TO_JSVAL(v) ((v).asBits)
741 #define JSID_BITS(id) (id)
743 #endif /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
747 #endif /* jsvalimpl_h__ */