[JAEGER] Merge from tracemonkey.
[mozilla-central.git] / js / src / jsval.h
blob8fb61ee0dede6b3ed5dd88660c87a8335b61ba5b
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
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
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.
73 #ifdef __cplusplus
75 #if defined(_MSC_VER)
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)
80 #else
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))
85 #endif
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);
147 #endif
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 */
247 } JSWhyMagic;
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
256 uint64 asBits;
257 struct {
258 union {
259 int32 i32;
260 uint32 u32;
261 JSBool boo;
262 JSString *str;
263 JSObject *obj;
264 void *ptr;
265 JSWhyMagic why;
266 } payload;
267 JSValueTag tag;
268 } s;
269 double asDouble;
270 } jsval_layout;
271 # elif JS_BITS_PER_WORD == 64
272 typedef union jsval_layout
274 uint64 asBits;
275 struct {
276 uint64 payload47 : 47;
277 JSValueTag tag : 17;
278 } debugView;
279 struct {
280 union {
281 int32 i32;
282 uint32 u32;
283 JSWhyMagic why;
284 } payload;
285 } s;
286 double asDouble;
287 } jsval_layout;
288 # endif /* JS_BITS_PER_WORD */
289 #else /* defined(IS_LITTLE_ENDIAN) */
290 # if JS_BITS_PER_WORD == 32
291 typedef union jsval_layout
293 uint64 asBits;
294 struct {
295 JSValueTag tag;
296 union {
297 int32 i32;
298 uint32 u32;
299 JSBool boo;
300 JSString *str;
301 JSObject *obj;
302 void *ptr;
303 JSWhyMagic why;
304 } payload;
305 } s;
306 double asDouble;
307 } 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)
331 jsval_layout l;
332 l.asDouble = d;
333 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
334 return 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)
352 jsval_layout l;
353 l.s.tag = JSVAL_TAG_INT32;
354 l.s.payload.i32 = i;
355 return l;
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)
381 jsval_layout l;
382 l.s.tag = JSVAL_TAG_STRING;
383 l.s.payload.str = str;
384 return l;
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)
408 jsval_layout l;
409 l.s.tag = JSVAL_TAG_BOOLEAN;
410 l.s.payload.boo = b;
411 return l;
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)
442 jsval_layout l;
443 l.s.tag = JSVAL_TAG_OBJECT;
444 l.s.payload.obj = obj;
445 return l;
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)
457 jsval_layout l;
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));
462 return 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)
510 jsval_layout l;
511 l.asDouble = d;
512 JS_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
513 return l;
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)
531 jsval_layout l;
532 l.asBits = ((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32;
533 return l;
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)
557 jsval_layout l;
558 uint64 strBits = (uint64)str;
559 JS_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
560 l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
561 return l;
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)
585 jsval_layout l;
586 l.asBits = ((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
587 return l;
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)
621 jsval_layout l;
622 uint64 objBits = (uint64)obj;
623 JS_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
624 l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
625 return l;
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)
663 jsval_layout l;
664 uint64 ptrBits = (uint64)ptr;
665 JS_ASSERT((ptrBits & 1) == 0);
666 l.asBits = ptrBits >> 1;
667 JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
668 return 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);
678 #endif
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
689 #endif
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)
697 extern "C++"
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) */
745 JS_END_EXTERN_C
747 #endif /* jsvalimpl_h__ */