Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* JS::Value implementation. */
9 #ifndef js_Value_h
10 #define js_Value_h
12 #include "mozilla/Attributes.h"
13 #include "mozilla/FloatingPoint.h"
14 #include "mozilla/Likely.h"
16 #include <limits> /* for std::numeric_limits */
18 #include "jstypes.h"
20 #include "js/Anchor.h"
21 #include "js/RootingAPI.h"
22 #include "js/Utility.h"
24 namespace JS { class Value; }
26 /* JS::Value can store a full int32_t. */
27 #define JSVAL_INT_BITS 32
28 #define JSVAL_INT_MIN ((int32_t)0x80000000)
29 #define JSVAL_INT_MAX ((int32_t)0x7fffffff)
31 /*
32 * Try to get jsvals 64-bit aligned. We could almost assert that all values are
33 * aligned, but MSVC and GCC occasionally break alignment.
34 */
35 #if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
36 # define JSVAL_ALIGNMENT __attribute__((aligned (8)))
37 #elif defined(_MSC_VER)
38 /*
39 * Structs can be aligned with MSVC, but not if they are used as parameters,
40 * so we just don't try to align.
41 */
42 # define JSVAL_ALIGNMENT
43 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
44 # define JSVAL_ALIGNMENT
45 #elif defined(__HP_cc) || defined(__HP_aCC)
46 # define JSVAL_ALIGNMENT
47 #endif
49 #if JS_BITS_PER_WORD == 64
50 # define JSVAL_TAG_SHIFT 47
51 #endif
53 /*
54 * We try to use enums so that printing a jsval_layout in the debugger shows
55 * nice symbolic type tags, however we can only do this when we can force the
56 * underlying type of the enum to be the desired size.
57 */
58 #if !defined(__SUNPRO_CC) && !defined(__xlC__)
60 #if defined(_MSC_VER)
61 # define JS_ENUM_HEADER(id, type) enum id : type
62 # define JS_ENUM_FOOTER(id)
63 #else
64 # define JS_ENUM_HEADER(id, type) enum id
65 # define JS_ENUM_FOOTER(id) __attribute__((packed))
66 #endif
68 /* Remember to propagate changes to the C defines below. */
69 JS_ENUM_HEADER(JSValueType, uint8_t)
70 {
71 JSVAL_TYPE_DOUBLE = 0x00,
72 JSVAL_TYPE_INT32 = 0x01,
73 JSVAL_TYPE_UNDEFINED = 0x02,
74 JSVAL_TYPE_BOOLEAN = 0x03,
75 JSVAL_TYPE_MAGIC = 0x04,
76 JSVAL_TYPE_STRING = 0x05,
77 JSVAL_TYPE_NULL = 0x06,
78 JSVAL_TYPE_OBJECT = 0x07,
80 /* These never appear in a jsval; they are only provided as an out-of-band value. */
81 JSVAL_TYPE_UNKNOWN = 0x20,
82 JSVAL_TYPE_MISSING = 0x21
83 } JS_ENUM_FOOTER(JSValueType);
85 JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
87 #if JS_BITS_PER_WORD == 32
89 /* Remember to propagate changes to the C defines below. */
90 JS_ENUM_HEADER(JSValueTag, uint32_t)
91 {
92 JSVAL_TAG_CLEAR = 0xFFFFFF80,
93 JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32,
94 JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED,
95 JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING,
96 JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
97 JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
98 JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
99 JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
100 } JS_ENUM_FOOTER(JSValueTag);
102 JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
104 #elif JS_BITS_PER_WORD == 64
106 /* Remember to propagate changes to the C defines below. */
107 JS_ENUM_HEADER(JSValueTag, uint32_t)
108 {
109 JSVAL_TAG_MAX_DOUBLE = 0x1FFF0,
110 JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32,
111 JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED,
112 JSVAL_TAG_STRING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING,
113 JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
114 JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
115 JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
116 JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
117 } JS_ENUM_FOOTER(JSValueTag);
119 JS_STATIC_ASSERT(sizeof(JSValueTag) == sizeof(uint32_t));
121 JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
122 {
123 JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
124 JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
125 JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
126 JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
127 JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
128 JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
129 JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
130 JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
131 } JS_ENUM_FOOTER(JSValueShiftedTag);
133 JS_STATIC_ASSERT(sizeof(JSValueShiftedTag) == sizeof(uint64_t));
135 #endif
137 #else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
139 typedef uint8_t JSValueType;
140 #define JSVAL_TYPE_DOUBLE ((uint8_t)0x00)
141 #define JSVAL_TYPE_INT32 ((uint8_t)0x01)
142 #define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02)
143 #define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03)
144 #define JSVAL_TYPE_MAGIC ((uint8_t)0x04)
145 #define JSVAL_TYPE_STRING ((uint8_t)0x05)
146 #define JSVAL_TYPE_NULL ((uint8_t)0x06)
147 #define JSVAL_TYPE_OBJECT ((uint8_t)0x07)
148 #define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20)
150 #if JS_BITS_PER_WORD == 32
152 typedef uint32_t JSValueTag;
153 #define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80))
154 #define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
155 #define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
156 #define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
157 #define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
158 #define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
159 #define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
160 #define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
162 #elif JS_BITS_PER_WORD == 64
164 typedef uint32_t JSValueTag;
165 #define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0))
166 #define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
167 #define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
168 #define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
169 #define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
170 #define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
171 #define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
172 #define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
174 typedef uint64_t JSValueShiftedTag;
175 #define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
176 #define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
177 #define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
178 #define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
179 #define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
180 #define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
181 #define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
182 #define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
184 #endif /* JS_BITS_PER_WORD */
185 #endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
187 #define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET JSVAL_TYPE_NULL
188 #define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET JSVAL_TYPE_OBJECT
189 #define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
190 #define JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET JSVAL_TYPE_MAGIC
192 #if JS_BITS_PER_WORD == 32
194 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
196 #define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
197 #define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
198 #define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
199 #define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
201 #elif JS_BITS_PER_WORD == 64
203 #define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
204 #define JSVAL_TAG_MASK 0xFFFF800000000000LL
205 #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
206 #define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
208 #define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
209 #define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
210 #define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
211 #define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
213 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
214 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
215 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
216 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
218 #endif /* JS_BITS_PER_WORD */
220 typedef enum JSWhyMagic
221 {
222 JS_ELEMENTS_HOLE, /* a hole in a native object's elements */
223 JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
224 * to JS_EnumerateState, which really means the object can be
225 * enumerated like a native object. */
226 JS_NO_ITER_VALUE, /* there is not a pending iterator value */
227 JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */
228 JS_NO_CONSTANT, /* compiler sentinel value */
229 JS_THIS_POISON, /* used in debug builds to catch tracing errors */
230 JS_ARG_POISON, /* used in debug builds to catch tracing errors */
231 JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
232 JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
233 JS_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */
234 JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
235 JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
236 JS_BLOCK_NEEDS_CLONE, /* value of static block object slot */
237 JS_HASH_KEY_EMPTY, /* see class js::HashableValue */
238 JS_ION_ERROR, /* error while running Ion code */
239 JS_ION_BAILOUT, /* status code to signal EnterIon will OSR into Interpret */
240 JS_OPTIMIZED_OUT, /* optimized out slot */
241 JS_GENERIC_MAGIC /* for local use */
242 } JSWhyMagic;
244 #if defined(IS_LITTLE_ENDIAN)
245 # if JS_BITS_PER_WORD == 32
246 typedef union jsval_layout
247 {
248 uint64_t asBits;
249 struct {
250 union {
251 int32_t i32;
252 uint32_t u32;
253 uint32_t boo; // Don't use |bool| -- it must be four bytes.
254 JSString *str;
255 JSObject *obj;
256 void *ptr;
257 JSWhyMagic why;
258 size_t word;
259 uintptr_t uintptr;
260 } payload;
261 JSValueTag tag;
262 } s;
263 double asDouble;
264 void *asPtr;
265 } JSVAL_ALIGNMENT jsval_layout;
266 # elif JS_BITS_PER_WORD == 64
267 typedef union jsval_layout
268 {
269 uint64_t asBits;
270 #if !defined(_WIN64)
271 /* MSVC does not pack these correctly :-( */
272 struct {
273 uint64_t payload47 : 47;
274 JSValueTag tag : 17;
275 } debugView;
276 #endif
277 struct {
278 union {
279 int32_t i32;
280 uint32_t u32;
281 JSWhyMagic why;
282 } payload;
283 } s;
284 double asDouble;
285 void *asPtr;
286 size_t asWord;
287 uintptr_t asUIntPtr;
288 } JSVAL_ALIGNMENT jsval_layout;
289 # endif /* JS_BITS_PER_WORD */
290 #else /* defined(IS_LITTLE_ENDIAN) */
291 # if JS_BITS_PER_WORD == 32
292 typedef union jsval_layout
293 {
294 uint64_t asBits;
295 struct {
296 JSValueTag tag;
297 union {
298 int32_t i32;
299 uint32_t u32;
300 uint32_t boo; // Don't use |bool| -- it must be four bytes.
301 JSString *str;
302 JSObject *obj;
303 void *ptr;
304 JSWhyMagic why;
305 size_t word;
306 uintptr_t uintptr;
307 } payload;
308 } s;
309 double asDouble;
310 void *asPtr;
311 } JSVAL_ALIGNMENT jsval_layout;
312 # elif JS_BITS_PER_WORD == 64
313 typedef union jsval_layout
314 {
315 uint64_t asBits;
316 struct {
317 JSValueTag tag : 17;
318 uint64_t payload47 : 47;
319 } debugView;
320 struct {
321 uint32_t padding;
322 union {
323 int32_t i32;
324 uint32_t u32;
325 JSWhyMagic why;
326 } payload;
327 } s;
328 double asDouble;
329 void *asPtr;
330 size_t asWord;
331 uintptr_t asUIntPtr;
332 } JSVAL_ALIGNMENT jsval_layout;
333 # endif /* JS_BITS_PER_WORD */
334 #endif /* defined(IS_LITTLE_ENDIAN) */
336 JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
338 /*
339 * For codesize purposes on some platforms, it's important that the
340 * compiler know that JS::Values constructed from constant values can be
341 * folded to constant bit patterns at compile time, rather than
342 * constructed at runtime. Doing this requires a fair amount of C++11
343 * features, which are not supported on all of our compilers. Set up
344 * some defines and helper macros in an attempt to confine the ugliness
345 * here, rather than scattering it all about the file. The important
346 * features are:
347 *
348 * - constexpr;
349 * - defaulted functions;
350 * - C99-style designated initializers.
351 */
352 #if defined(__clang__)
353 # if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions)
354 # define JS_VALUE_IS_CONSTEXPR
355 # endif
356 #elif defined(__GNUC__)
357 /*
358 * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6
359 * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because
360 * versions prior to that have bugs in the C++ front-end that cause crashes.
361 */
362 # if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3)
363 # define JS_VALUE_IS_CONSTEXPR
364 # endif
365 #endif
367 #if defined(JS_VALUE_IS_CONSTEXPR)
368 # define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
369 return (jsval_layout) { .asBits = (BITS) }
370 # define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR
371 # define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR
372 #else
373 # define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
374 jsval_layout l; \
375 l.asBits = (BITS); \
376 return l;
377 # define JS_VALUE_CONSTEXPR
378 # define JS_VALUE_CONSTEXPR_VAR const
379 #endif
381 #if JS_BITS_PER_WORD == 32
383 /*
384 * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
385 * JSValueTag even though its underlying type has been forced to be uint32_t.
386 * Thus, all comparisons should explicitly cast operands to uint32_t.
387 */
389 static inline JS_VALUE_CONSTEXPR jsval_layout
390 BUILD_JSVAL(JSValueTag tag, uint32_t payload)
391 {
392 JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << 32) | payload);
393 }
395 static inline bool
396 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
397 {
398 return (uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_CLEAR;
399 }
401 static inline jsval_layout
402 DOUBLE_TO_JSVAL_IMPL(double d)
403 {
404 jsval_layout l;
405 l.asDouble = d;
406 MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
407 return l;
408 }
410 static inline bool
411 JSVAL_IS_INT32_IMPL(jsval_layout l)
412 {
413 return l.s.tag == JSVAL_TAG_INT32;
414 }
416 static inline int32_t
417 JSVAL_TO_INT32_IMPL(jsval_layout l)
418 {
419 return l.s.payload.i32;
420 }
422 static inline JS_VALUE_CONSTEXPR jsval_layout
423 INT32_TO_JSVAL_IMPL(int32_t i)
424 {
425 #if defined(JS_VALUE_IS_CONSTEXPR)
426 return BUILD_JSVAL(JSVAL_TAG_INT32, i);
427 #else
428 jsval_layout l;
429 l.s.tag = JSVAL_TAG_INT32;
430 l.s.payload.i32 = i;
431 return l;
432 #endif
433 }
435 static inline bool
436 JSVAL_IS_NUMBER_IMPL(jsval_layout l)
437 {
438 JSValueTag tag = l.s.tag;
439 MOZ_ASSERT(tag != JSVAL_TAG_CLEAR);
440 return (uint32_t)tag <= (uint32_t)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
441 }
443 static inline bool
444 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
445 {
446 return l.s.tag == JSVAL_TAG_UNDEFINED;
447 }
449 static inline bool
450 JSVAL_IS_STRING_IMPL(jsval_layout l)
451 {
452 return l.s.tag == JSVAL_TAG_STRING;
453 }
455 static inline jsval_layout
456 STRING_TO_JSVAL_IMPL(JSString *str)
457 {
458 jsval_layout l;
459 MOZ_ASSERT(uintptr_t(str) > 0x1000);
460 l.s.tag = JSVAL_TAG_STRING;
461 l.s.payload.str = str;
462 return l;
463 }
465 static inline JSString *
466 JSVAL_TO_STRING_IMPL(jsval_layout l)
467 {
468 return l.s.payload.str;
469 }
471 static inline bool
472 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
473 {
474 return l.s.tag == JSVAL_TAG_BOOLEAN;
475 }
477 static inline bool
478 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
479 {
480 return l.s.payload.boo;
481 }
483 static inline jsval_layout
484 BOOLEAN_TO_JSVAL_IMPL(bool b)
485 {
486 jsval_layout l;
487 l.s.tag = JSVAL_TAG_BOOLEAN;
488 l.s.payload.boo = b;
489 return l;
490 }
492 static inline bool
493 JSVAL_IS_MAGIC_IMPL(jsval_layout l)
494 {
495 return l.s.tag == JSVAL_TAG_MAGIC;
496 }
498 static inline bool
499 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
500 {
501 return l.s.tag == JSVAL_TAG_OBJECT;
502 }
504 static inline bool
505 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
506 {
507 return (uint32_t)l.s.tag < (uint32_t)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
508 }
510 static inline bool
511 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
512 {
513 MOZ_ASSERT((uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_OBJECT);
514 return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
515 }
517 static inline JSObject *
518 JSVAL_TO_OBJECT_IMPL(jsval_layout l)
519 {
520 return l.s.payload.obj;
521 }
523 static inline jsval_layout
524 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
525 {
526 jsval_layout l;
527 MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
528 l.s.tag = JSVAL_TAG_OBJECT;
529 l.s.payload.obj = obj;
530 return l;
531 }
533 static inline bool
534 JSVAL_IS_NULL_IMPL(jsval_layout l)
535 {
536 return l.s.tag == JSVAL_TAG_NULL;
537 }
539 static inline jsval_layout
540 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
541 {
542 jsval_layout l;
543 MOZ_ASSERT(((uint32_t)ptr & 1) == 0);
544 l.s.tag = (JSValueTag)0;
545 l.s.payload.ptr = ptr;
546 MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
547 return l;
548 }
550 static inline void *
551 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
552 {
553 return l.s.payload.ptr;
554 }
556 static inline bool
557 JSVAL_IS_GCTHING_IMPL(jsval_layout l)
558 {
559 /* gcc sometimes generates signed < without explicit casts. */
560 return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
561 }
563 static inline void *
564 JSVAL_TO_GCTHING_IMPL(jsval_layout l)
565 {
566 return l.s.payload.ptr;
567 }
569 static inline bool
570 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
571 {
572 return l.s.tag == JSVAL_TAG_STRING || l.s.tag == JSVAL_TAG_OBJECT;
573 }
575 static inline uint32_t
576 JSVAL_TRACE_KIND_IMPL(jsval_layout l)
577 {
578 return (uint32_t)(bool)JSVAL_IS_STRING_IMPL(l);
579 }
581 static inline bool
582 JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
583 {
584 return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
585 }
587 static inline bool
588 JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, bool b)
589 {
590 return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == uint32_t(b));
591 }
593 static inline jsval_layout
594 MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
595 {
596 jsval_layout l;
597 l.s.tag = JSVAL_TAG_MAGIC;
598 l.s.payload.why = why;
599 return l;
600 }
602 static inline jsval_layout
603 MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
604 {
605 jsval_layout l;
606 l.s.tag = JSVAL_TAG_MAGIC;
607 l.s.payload.u32 = payload;
608 return l;
609 }
611 static inline bool
612 JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
613 {
614 JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
615 return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
616 }
618 static inline JSValueType
619 JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
620 {
621 uint32_t type = l.s.tag & 0xF;
622 MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
623 return (JSValueType)type;
624 }
626 #elif JS_BITS_PER_WORD == 64
628 static inline JS_VALUE_CONSTEXPR jsval_layout
629 BUILD_JSVAL(JSValueTag tag, uint64_t payload)
630 {
631 JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload);
632 }
634 static inline bool
635 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
636 {
637 return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
638 }
640 static inline jsval_layout
641 DOUBLE_TO_JSVAL_IMPL(double d)
642 {
643 jsval_layout l;
644 l.asDouble = d;
645 MOZ_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
646 return l;
647 }
649 static inline bool
650 JSVAL_IS_INT32_IMPL(jsval_layout l)
651 {
652 return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
653 }
655 static inline int32_t
656 JSVAL_TO_INT32_IMPL(jsval_layout l)
657 {
658 return (int32_t)l.asBits;
659 }
661 static inline JS_VALUE_CONSTEXPR jsval_layout
662 INT32_TO_JSVAL_IMPL(int32_t i32)
663 {
664 JS_RETURN_LAYOUT_FROM_BITS(((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
665 }
667 static inline bool
668 JSVAL_IS_NUMBER_IMPL(jsval_layout l)
669 {
670 return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
671 }
673 static inline bool
674 JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
675 {
676 return l.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
677 }
679 static inline bool
680 JSVAL_IS_STRING_IMPL(jsval_layout l)
681 {
682 return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
683 }
685 static inline jsval_layout
686 STRING_TO_JSVAL_IMPL(JSString *str)
687 {
688 jsval_layout l;
689 uint64_t strBits = (uint64_t)str;
690 MOZ_ASSERT(uintptr_t(str) > 0x1000);
691 MOZ_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
692 l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
693 return l;
694 }
696 static inline JSString *
697 JSVAL_TO_STRING_IMPL(jsval_layout l)
698 {
699 return (JSString *)(l.asBits & JSVAL_PAYLOAD_MASK);
700 }
702 static inline bool
703 JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
704 {
705 return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
706 }
708 static inline bool
709 JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
710 {
711 return (bool)(l.asBits & JSVAL_PAYLOAD_MASK);
712 }
714 static inline jsval_layout
715 BOOLEAN_TO_JSVAL_IMPL(bool b)
716 {
717 jsval_layout l;
718 l.asBits = ((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
719 return l;
720 }
722 static inline bool
723 JSVAL_IS_MAGIC_IMPL(jsval_layout l)
724 {
725 return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
726 }
728 static inline bool
729 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
730 {
731 return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
732 }
734 static inline bool
735 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
736 {
737 MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
738 return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
739 }
741 static inline bool
742 JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
743 {
744 MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
745 return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
746 }
748 static inline JSObject *
749 JSVAL_TO_OBJECT_IMPL(jsval_layout l)
750 {
751 uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
752 MOZ_ASSERT((ptrBits & 0x7) == 0);
753 return (JSObject *)ptrBits;
754 }
756 static inline jsval_layout
757 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
758 {
759 jsval_layout l;
760 uint64_t objBits = (uint64_t)obj;
761 MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
762 MOZ_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
763 l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
764 return l;
765 }
767 static inline bool
768 JSVAL_IS_NULL_IMPL(jsval_layout l)
769 {
770 return l.asBits == JSVAL_SHIFTED_TAG_NULL;
771 }
773 static inline bool
774 JSVAL_IS_GCTHING_IMPL(jsval_layout l)
775 {
776 return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
777 }
779 static inline void *
780 JSVAL_TO_GCTHING_IMPL(jsval_layout l)
781 {
782 uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
783 MOZ_ASSERT((ptrBits & 0x7) == 0);
784 return (void *)ptrBits;
785 }
787 static inline bool
788 JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
789 {
790 return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
791 }
793 static inline uint32_t
794 JSVAL_TRACE_KIND_IMPL(jsval_layout l)
795 {
796 return (uint32_t)(bool)!(JSVAL_IS_OBJECT_IMPL(l));
797 }
799 static inline jsval_layout
800 PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
801 {
802 jsval_layout l;
803 uint64_t ptrBits = (uint64_t)ptr;
804 MOZ_ASSERT((ptrBits & 1) == 0);
805 l.asBits = ptrBits >> 1;
806 MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
807 return l;
808 }
810 static inline void *
811 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
812 {
813 MOZ_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
814 return (void *)(l.asBits << 1);
815 }
817 static inline bool
818 JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
819 {
820 return l.asBits == (((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
821 }
823 static inline bool
824 JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, bool b)
825 {
826 return l.asBits == (((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
827 }
829 static inline jsval_layout
830 MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
831 {
832 jsval_layout l;
833 l.asBits = ((uint64_t)(uint32_t)why) | JSVAL_SHIFTED_TAG_MAGIC;
834 return l;
835 }
837 static inline jsval_layout
838 MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
839 {
840 jsval_layout l;
841 l.asBits = ((uint64_t)payload) | JSVAL_SHIFTED_TAG_MAGIC;
842 return l;
843 }
845 static inline bool
846 JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
847 {
848 uint64_t lbits = lhs.asBits, rbits = rhs.asBits;
849 return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
850 (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
851 }
853 static inline JSValueType
854 JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
855 {
856 uint64_t type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
857 MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
858 return (JSValueType)type;
859 }
861 #endif /* JS_BITS_PER_WORD */
863 static inline jsval_layout JSVAL_TO_IMPL(JS::Value v);
864 static inline JS_VALUE_CONSTEXPR JS::Value IMPL_TO_JSVAL(jsval_layout l);
866 namespace JS {
868 static inline JS_VALUE_CONSTEXPR JS::Value UndefinedValue();
870 /**
871 * Returns a generic quiet NaN value, with all payload bits set to zero.
872 *
873 * Among other properties, this NaN's bit pattern conforms to JS::Value's
874 * bit pattern restrictions.
875 */
876 static MOZ_ALWAYS_INLINE double
877 GenericNaN()
878 {
879 return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
880 }
882 /* MSVC with PGO miscompiles this function. */
883 #if defined(_MSC_VER)
884 # pragma optimize("g", off)
885 #endif
886 static inline double
887 CanonicalizeNaN(double d)
888 {
889 if (MOZ_UNLIKELY(mozilla::IsNaN(d)))
890 return GenericNaN();
891 return d;
892 }
893 #if defined(_MSC_VER)
894 # pragma optimize("", on)
895 #endif
897 /*
898 * JS::Value is the interface for a single JavaScript Engine value. A few
899 * general notes on JS::Value:
900 *
901 * - JS::Value has setX() and isX() members for X in
902 *
903 * { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
904 *
905 * JS::Value also contains toX() for each of the non-singleton types.
906 *
907 * - Magic is a singleton type whose payload contains either a JSWhyMagic "reason" for
908 * the magic value or a uint32_t value. By providing JSWhyMagic values when
909 * creating and checking for magic values, it is possible to assert, at
910 * runtime, that only magic values with the expected reason flow through a
911 * particular value. For example, if cx->exception has a magic value, the
912 * reason must be JS_GENERATOR_CLOSING.
913 *
914 * - The JS::Value operations are preferred. The JSVAL_* operations remain for
915 * compatibility; they may be removed at some point. These operations mostly
916 * provide similar functionality. But there are a few key differences. One
917 * is that JS::Value gives null a separate type. Thus
918 *
919 * JSVAL_IS_OBJECT(v) === v.isObjectOrNull()
920 * !JSVAL_IS_PRIMITIVE(v) === v.isObject()
921 *
922 * Also, to help prevent mistakenly boxing a nullable JSObject* as an object,
923 * Value::setObject takes a JSObject&. (Conversely, Value::toObject returns a
924 * JSObject&.) A convenience member Value::setObjectOrNull is provided.
925 *
926 * - JSVAL_VOID is the same as the singleton value of the Undefined type.
927 *
928 * - Note that JS::Value is 8 bytes on 32 and 64-bit architectures. Thus, on
929 * 32-bit user code should avoid copying jsval/JS::Value as much as possible,
930 * preferring to pass by const Value &.
931 */
932 class Value
933 {
934 public:
935 /*
936 * N.B. the default constructor leaves Value unitialized. Adding a default
937 * constructor prevents Value from being stored in a union.
938 */
939 #if defined(JS_VALUE_IS_CONSTEXPR)
940 Value() = default;
941 Value(const Value& v) = default;
942 #endif
944 /*** Mutators ***/
946 void setNull() {
947 data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
948 }
950 void setUndefined() {
951 data.asBits = BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0).asBits;
952 }
954 void setInt32(int32_t i) {
955 data = INT32_TO_JSVAL_IMPL(i);
956 }
958 int32_t &getInt32Ref() {
959 MOZ_ASSERT(isInt32());
960 return data.s.payload.i32;
961 }
963 void setDouble(double d) {
964 data = DOUBLE_TO_JSVAL_IMPL(d);
965 }
967 void setNaN() {
968 setDouble(GenericNaN());
969 }
971 double &getDoubleRef() {
972 MOZ_ASSERT(isDouble());
973 return data.asDouble;
974 }
976 void setString(JSString *str) {
977 MOZ_ASSERT(!IsPoisonedPtr(str));
978 data = STRING_TO_JSVAL_IMPL(str);
979 }
981 void setObject(JSObject &obj) {
982 MOZ_ASSERT(!IsPoisonedPtr(&obj));
983 data = OBJECT_TO_JSVAL_IMPL(&obj);
984 }
986 void setBoolean(bool b) {
987 data = BOOLEAN_TO_JSVAL_IMPL(b);
988 }
990 void setMagic(JSWhyMagic why) {
991 data = MAGIC_TO_JSVAL_IMPL(why);
992 }
994 void setMagicUint32(uint32_t payload) {
995 data = MAGIC_UINT32_TO_JSVAL_IMPL(payload);
996 }
998 bool setNumber(uint32_t ui) {
999 if (ui > JSVAL_INT_MAX) {
1000 setDouble((double)ui);
1001 return false;
1002 } else {
1003 setInt32((int32_t)ui);
1004 return true;
1005 }
1006 }
1008 bool setNumber(double d) {
1009 int32_t i;
1010 if (mozilla::NumberIsInt32(d, &i)) {
1011 setInt32(i);
1012 return true;
1013 }
1015 setDouble(d);
1016 return false;
1017 }
1019 void setObjectOrNull(JSObject *arg) {
1020 if (arg)
1021 setObject(*arg);
1022 else
1023 setNull();
1024 }
1026 void swap(Value &rhs) {
1027 uint64_t tmp = rhs.data.asBits;
1028 rhs.data.asBits = data.asBits;
1029 data.asBits = tmp;
1030 }
1032 /*** Value type queries ***/
1034 bool isUndefined() const {
1035 return JSVAL_IS_UNDEFINED_IMPL(data);
1036 }
1038 bool isNull() const {
1039 return JSVAL_IS_NULL_IMPL(data);
1040 }
1042 bool isNullOrUndefined() const {
1043 return isNull() || isUndefined();
1044 }
1046 bool isInt32() const {
1047 return JSVAL_IS_INT32_IMPL(data);
1048 }
1050 bool isInt32(int32_t i32) const {
1051 return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
1052 }
1054 bool isDouble() const {
1055 return JSVAL_IS_DOUBLE_IMPL(data);
1056 }
1058 bool isNumber() const {
1059 return JSVAL_IS_NUMBER_IMPL(data);
1060 }
1062 bool isString() const {
1063 return JSVAL_IS_STRING_IMPL(data);
1064 }
1066 bool isObject() const {
1067 return JSVAL_IS_OBJECT_IMPL(data);
1068 }
1070 bool isPrimitive() const {
1071 return JSVAL_IS_PRIMITIVE_IMPL(data);
1072 }
1074 bool isObjectOrNull() const {
1075 return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
1076 }
1078 bool isGCThing() const {
1079 return JSVAL_IS_GCTHING_IMPL(data);
1080 }
1082 bool isBoolean() const {
1083 return JSVAL_IS_BOOLEAN_IMPL(data);
1084 }
1086 bool isTrue() const {
1087 return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
1088 }
1090 bool isFalse() const {
1091 return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
1092 }
1094 bool isMagic() const {
1095 return JSVAL_IS_MAGIC_IMPL(data);
1096 }
1098 bool isMagic(JSWhyMagic why) const {
1099 MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
1100 return JSVAL_IS_MAGIC_IMPL(data);
1101 }
1103 bool isMarkable() const {
1104 return JSVAL_IS_TRACEABLE_IMPL(data);
1105 }
1107 JSGCTraceKind gcKind() const {
1108 MOZ_ASSERT(isMarkable());
1109 return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
1110 }
1112 JSWhyMagic whyMagic() const {
1113 MOZ_ASSERT(isMagic());
1114 return data.s.payload.why;
1115 }
1117 uint32_t magicUint32() const {
1118 MOZ_ASSERT(isMagic());
1119 return data.s.payload.u32;
1120 }
1122 /*** Comparison ***/
1124 bool operator==(const Value &rhs) const {
1125 return data.asBits == rhs.data.asBits;
1126 }
1128 bool operator!=(const Value &rhs) const {
1129 return data.asBits != rhs.data.asBits;
1130 }
1132 friend inline bool SameType(const Value &lhs, const Value &rhs);
1134 /*** Extract the value's typed payload ***/
1136 int32_t toInt32() const {
1137 MOZ_ASSERT(isInt32());
1138 return JSVAL_TO_INT32_IMPL(data);
1139 }
1141 double toDouble() const {
1142 MOZ_ASSERT(isDouble());
1143 return data.asDouble;
1144 }
1146 double toNumber() const {
1147 MOZ_ASSERT(isNumber());
1148 return isDouble() ? toDouble() : double(toInt32());
1149 }
1151 JSString *toString() const {
1152 MOZ_ASSERT(isString());
1153 return JSVAL_TO_STRING_IMPL(data);
1154 }
1156 JSObject &toObject() const {
1157 MOZ_ASSERT(isObject());
1158 return *JSVAL_TO_OBJECT_IMPL(data);
1159 }
1161 JSObject *toObjectOrNull() const {
1162 MOZ_ASSERT(isObjectOrNull());
1163 return JSVAL_TO_OBJECT_IMPL(data);
1164 }
1166 void *toGCThing() const {
1167 MOZ_ASSERT(isGCThing());
1168 return JSVAL_TO_GCTHING_IMPL(data);
1169 }
1171 bool toBoolean() const {
1172 MOZ_ASSERT(isBoolean());
1173 return JSVAL_TO_BOOLEAN_IMPL(data);
1174 }
1176 uint32_t payloadAsRawUint32() const {
1177 MOZ_ASSERT(!isDouble());
1178 return data.s.payload.u32;
1179 }
1181 uint64_t asRawBits() const {
1182 return data.asBits;
1183 }
1185 JSValueType extractNonDoubleType() const {
1186 return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
1187 }
1189 /*
1190 * Private API
1191 *
1192 * Private setters/getters allow the caller to read/write arbitrary types
1193 * that fit in the 64-bit payload. It is the caller's responsibility, after
1194 * storing to a value with setPrivateX to read only using getPrivateX.
1195 * Privates values are given a type which ensures they are not marked.
1196 */
1198 void setPrivate(void *ptr) {
1199 data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
1200 }
1202 void *toPrivate() const {
1203 MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
1204 return JSVAL_TO_PRIVATE_PTR_IMPL(data);
1205 }
1207 void setPrivateUint32(uint32_t ui) {
1208 MOZ_ASSERT(uint32_t(int32_t(ui)) == ui);
1209 setInt32(int32_t(ui));
1210 }
1212 uint32_t toPrivateUint32() const {
1213 return uint32_t(toInt32());
1214 }
1216 /*
1217 * An unmarked value is just a void* cast as a Value. Thus, the Value is
1218 * not safe for GC and must not be marked. This API avoids raw casts
1219 * and the ensuing strict-aliasing warnings.
1220 */
1222 void setUnmarkedPtr(void *ptr) {
1223 data.asPtr = ptr;
1224 }
1226 void *toUnmarkedPtr() const {
1227 return data.asPtr;
1228 }
1230 const size_t *payloadWord() const {
1231 #if JS_BITS_PER_WORD == 32
1232 return &data.s.payload.word;
1233 #elif JS_BITS_PER_WORD == 64
1234 return &data.asWord;
1235 #endif
1236 }
1238 const uintptr_t *payloadUIntPtr() const {
1239 #if JS_BITS_PER_WORD == 32
1240 return &data.s.payload.uintptr;
1241 #elif JS_BITS_PER_WORD == 64
1242 return &data.asUIntPtr;
1243 #endif
1244 }
1246 #if !defined(_MSC_VER) && !defined(__sparc)
1247 // Value must be POD so that MSVC will pass it by value and not in memory
1248 // (bug 689101); the same is true for SPARC as well (bug 737344). More
1249 // precisely, we don't want Value return values compiled as out params.
1250 private:
1251 #endif
1253 jsval_layout data;
1255 private:
1256 #if defined(JS_VALUE_IS_CONSTEXPR)
1257 JS_VALUE_CONSTEXPR Value(jsval_layout layout) : data(layout) {}
1258 #endif
1260 void staticAssertions() {
1261 JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
1262 JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
1263 JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
1264 JS_STATIC_ASSERT(sizeof(Value) == 8);
1265 }
1267 friend jsval_layout (::JSVAL_TO_IMPL)(Value);
1268 friend Value JS_VALUE_CONSTEXPR (::IMPL_TO_JSVAL)(jsval_layout l);
1269 friend Value JS_VALUE_CONSTEXPR (JS::UndefinedValue)();
1270 };
1272 inline bool
1273 IsPoisonedValue(const Value &v)
1274 {
1275 if (v.isString())
1276 return IsPoisonedPtr(v.toString());
1277 if (v.isObject())
1278 return IsPoisonedPtr(&v.toObject());
1279 return false;
1280 }
1282 inline bool
1283 IsOptimizedPlaceholderMagicValue(const Value &v)
1284 {
1285 if (v.isMagic()) {
1286 MOZ_ASSERT(v.whyMagic() == JS_OPTIMIZED_ARGUMENTS || v.whyMagic() == JS_OPTIMIZED_OUT);
1287 return true;
1288 }
1289 return false;
1290 }
1292 /************************************************************************/
1294 static inline Value
1295 NullValue()
1296 {
1297 Value v;
1298 v.setNull();
1299 return v;
1300 }
1302 static inline JS_VALUE_CONSTEXPR Value
1303 UndefinedValue()
1304 {
1305 #if defined(JS_VALUE_IS_CONSTEXPR)
1306 return Value(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
1307 #else
1308 JS::Value v;
1309 v.setUndefined();
1310 return v;
1311 #endif
1312 }
1314 static inline Value
1315 Int32Value(int32_t i32)
1316 {
1317 Value v;
1318 v.setInt32(i32);
1319 return v;
1320 }
1322 static inline Value
1323 DoubleValue(double dbl)
1324 {
1325 Value v;
1326 v.setDouble(dbl);
1327 return v;
1328 }
1330 static inline Value
1331 DoubleNaNValue()
1332 {
1333 Value v;
1334 v.setNaN();
1335 return v;
1336 }
1338 static inline Value
1339 Float32Value(float f)
1340 {
1341 Value v;
1342 v.setDouble(f);
1343 return v;
1344 }
1346 static inline Value
1347 StringValue(JSString *str)
1348 {
1349 Value v;
1350 v.setString(str);
1351 return v;
1352 }
1354 static inline Value
1355 BooleanValue(bool boo)
1356 {
1357 Value v;
1358 v.setBoolean(boo);
1359 return v;
1360 }
1362 static inline Value
1363 TrueValue()
1364 {
1365 Value v;
1366 v.setBoolean(true);
1367 return v;
1368 }
1370 static inline Value
1371 FalseValue()
1372 {
1373 Value v;
1374 v.setBoolean(false);
1375 return v;
1376 }
1378 static inline Value
1379 ObjectValue(JSObject &obj)
1380 {
1381 Value v;
1382 v.setObject(obj);
1383 return v;
1384 }
1386 static inline Value
1387 ObjectValueCrashOnTouch()
1388 {
1389 Value v;
1390 v.setObject(*reinterpret_cast<JSObject *>(0x42));
1391 return v;
1392 }
1394 static inline Value
1395 MagicValue(JSWhyMagic why)
1396 {
1397 Value v;
1398 v.setMagic(why);
1399 return v;
1400 }
1402 static inline Value
1403 MagicValueUint32(uint32_t payload)
1404 {
1405 Value v;
1406 v.setMagicUint32(payload);
1407 return v;
1408 }
1410 static inline Value
1411 NumberValue(float f)
1412 {
1413 Value v;
1414 v.setNumber(f);
1415 return v;
1416 }
1418 static inline Value
1419 NumberValue(double dbl)
1420 {
1421 Value v;
1422 v.setNumber(dbl);
1423 return v;
1424 }
1426 static inline Value
1427 NumberValue(int8_t i)
1428 {
1429 return Int32Value(i);
1430 }
1432 static inline Value
1433 NumberValue(uint8_t i)
1434 {
1435 return Int32Value(i);
1436 }
1438 static inline Value
1439 NumberValue(int16_t i)
1440 {
1441 return Int32Value(i);
1442 }
1444 static inline Value
1445 NumberValue(uint16_t i)
1446 {
1447 return Int32Value(i);
1448 }
1450 static inline Value
1451 NumberValue(int32_t i)
1452 {
1453 return Int32Value(i);
1454 }
1456 static inline Value
1457 NumberValue(uint32_t i)
1458 {
1459 Value v;
1460 v.setNumber(i);
1461 return v;
1462 }
1464 namespace detail {
1466 template <bool Signed>
1467 class MakeNumberValue
1468 {
1469 public:
1470 template<typename T>
1471 static inline Value create(const T t)
1472 {
1473 Value v;
1474 if (JSVAL_INT_MIN <= t && t <= JSVAL_INT_MAX)
1475 v.setInt32(int32_t(t));
1476 else
1477 v.setDouble(double(t));
1478 return v;
1479 }
1480 };
1482 template <>
1483 class MakeNumberValue<false>
1484 {
1485 public:
1486 template<typename T>
1487 static inline Value create(const T t)
1488 {
1489 Value v;
1490 if (t <= JSVAL_INT_MAX)
1491 v.setInt32(int32_t(t));
1492 else
1493 v.setDouble(double(t));
1494 return v;
1495 }
1496 };
1498 } // namespace detail
1500 template <typename T>
1501 static inline Value
1502 NumberValue(const T t)
1503 {
1504 MOZ_ASSERT(T(double(t)) == t, "value creation would be lossy");
1505 return detail::MakeNumberValue<std::numeric_limits<T>::is_signed>::create(t);
1506 }
1508 static inline Value
1509 ObjectOrNullValue(JSObject *obj)
1510 {
1511 Value v;
1512 v.setObjectOrNull(obj);
1513 return v;
1514 }
1516 static inline Value
1517 PrivateValue(void *ptr)
1518 {
1519 Value v;
1520 v.setPrivate(ptr);
1521 return v;
1522 }
1524 static inline Value
1525 PrivateUint32Value(uint32_t ui)
1526 {
1527 Value v;
1528 v.setPrivateUint32(ui);
1529 return v;
1530 }
1532 inline bool
1533 SameType(const Value &lhs, const Value &rhs)
1534 {
1535 return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
1536 }
1538 } // namespace JS
1540 /************************************************************************/
1542 #ifdef JSGC_GENERATIONAL
1543 namespace JS {
1544 JS_PUBLIC_API(void) HeapValuePostBarrier(Value *valuep);
1545 JS_PUBLIC_API(void) HeapValueRelocate(Value *valuep);
1546 }
1547 #endif
1549 namespace js {
1551 template <> struct GCMethods<const JS::Value>
1552 {
1553 static JS::Value initial() { return JS::UndefinedValue(); }
1554 static ThingRootKind kind() { return THING_ROOT_VALUE; }
1555 static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
1556 };
1558 template <> struct GCMethods<JS::Value>
1559 {
1560 static JS::Value initial() { return JS::UndefinedValue(); }
1561 static ThingRootKind kind() { return THING_ROOT_VALUE; }
1562 static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
1563 static bool needsPostBarrier(const JS::Value &v) { return v.isMarkable(); }
1564 #ifdef JSGC_GENERATIONAL
1565 static void postBarrier(JS::Value *v) { JS::HeapValuePostBarrier(v); }
1566 static void relocate(JS::Value *v) { JS::HeapValueRelocate(v); }
1567 #endif
1568 };
1570 template <class Outer> class MutableValueOperations;
1572 /*
1573 * A class designed for CRTP use in implementing the non-mutating parts of the
1574 * Value interface in Value-like classes. Outer must be a class inheriting
1575 * ValueOperations<Outer> with a visible extract() method returning the
1576 * const Value* abstracted by Outer.
1577 */
1578 template <class Outer>
1579 class ValueOperations
1580 {
1581 friend class MutableValueOperations<Outer>;
1583 const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
1585 public:
1586 bool isUndefined() const { return value()->isUndefined(); }
1587 bool isNull() const { return value()->isNull(); }
1588 bool isBoolean() const { return value()->isBoolean(); }
1589 bool isTrue() const { return value()->isTrue(); }
1590 bool isFalse() const { return value()->isFalse(); }
1591 bool isNumber() const { return value()->isNumber(); }
1592 bool isInt32() const { return value()->isInt32(); }
1593 bool isDouble() const { return value()->isDouble(); }
1594 bool isString() const { return value()->isString(); }
1595 bool isObject() const { return value()->isObject(); }
1596 bool isMagic() const { return value()->isMagic(); }
1597 bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
1598 bool isMarkable() const { return value()->isMarkable(); }
1599 bool isPrimitive() const { return value()->isPrimitive(); }
1600 bool isGCThing() const { return value()->isGCThing(); }
1602 bool isNullOrUndefined() const { return value()->isNullOrUndefined(); }
1603 bool isObjectOrNull() const { return value()->isObjectOrNull(); }
1605 bool toBoolean() const { return value()->toBoolean(); }
1606 double toNumber() const { return value()->toNumber(); }
1607 int32_t toInt32() const { return value()->toInt32(); }
1608 double toDouble() const { return value()->toDouble(); }
1609 JSString *toString() const { return value()->toString(); }
1610 JSObject &toObject() const { return value()->toObject(); }
1611 JSObject *toObjectOrNull() const { return value()->toObjectOrNull(); }
1612 void *toGCThing() const { return value()->toGCThing(); }
1614 JSValueType extractNonDoubleType() const { return value()->extractNonDoubleType(); }
1615 uint32_t toPrivateUint32() const { return value()->toPrivateUint32(); }
1617 JSWhyMagic whyMagic() const { return value()->whyMagic(); }
1618 uint32_t magicUint32() const { return value()->magicUint32(); }
1619 };
1621 /*
1622 * A class designed for CRTP use in implementing all the mutating parts of the
1623 * Value interface in Value-like classes. Outer must be a class inheriting
1624 * MutableValueOperations<Outer> with visible extractMutable() and extract()
1625 * methods returning the const Value* and Value* abstracted by Outer.
1626 */
1627 template <class Outer>
1628 class MutableValueOperations : public ValueOperations<Outer>
1629 {
1630 JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
1632 public:
1633 void setNull() { value()->setNull(); }
1634 void setUndefined() { value()->setUndefined(); }
1635 void setInt32(int32_t i) { value()->setInt32(i); }
1636 void setDouble(double d) { value()->setDouble(d); }
1637 void setNaN() { setDouble(JS::GenericNaN()); }
1638 void setBoolean(bool b) { value()->setBoolean(b); }
1639 void setMagic(JSWhyMagic why) { value()->setMagic(why); }
1640 bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
1641 bool setNumber(double d) { return value()->setNumber(d); }
1642 void setString(JSString *str) { this->value()->setString(str); }
1643 void setObject(JSObject &obj) { this->value()->setObject(obj); }
1644 void setObjectOrNull(JSObject *arg) { this->value()->setObjectOrNull(arg); }
1645 };
1647 /*
1648 * Augment the generic Heap<T> interface when T = Value with
1649 * type-querying, value-extracting, and mutating operations.
1650 */
1651 template <>
1652 class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
1653 {
1654 typedef JS::Heap<JS::Value> Outer;
1656 friend class ValueOperations<Outer>;
1658 const JS::Value * extract() const { return static_cast<const Outer*>(this)->address(); }
1660 void setBarriered(const JS::Value &v) {
1661 static_cast<JS::Heap<JS::Value> *>(this)->set(v);
1662 }
1664 public:
1665 void setNull() { setBarriered(JS::NullValue()); }
1666 void setUndefined() { setBarriered(JS::UndefinedValue()); }
1667 void setInt32(int32_t i) { setBarriered(JS::Int32Value(i)); }
1668 void setDouble(double d) { setBarriered(JS::DoubleValue(d)); }
1669 void setNaN() { setDouble(JS::GenericNaN()); }
1670 void setBoolean(bool b) { setBarriered(JS::BooleanValue(b)); }
1671 void setMagic(JSWhyMagic why) { setBarriered(JS::MagicValue(why)); }
1672 void setString(JSString *str) { setBarriered(JS::StringValue(str)); }
1673 void setObject(JSObject &obj) { setBarriered(JS::ObjectValue(obj)); }
1675 bool setNumber(uint32_t ui) {
1676 if (ui > JSVAL_INT_MAX) {
1677 setDouble((double)ui);
1678 return false;
1679 } else {
1680 setInt32((int32_t)ui);
1681 return true;
1682 }
1683 }
1685 bool setNumber(double d) {
1686 int32_t i;
1687 if (mozilla::NumberIsInt32(d, &i)) {
1688 setInt32(i);
1689 return true;
1690 }
1692 setDouble(d);
1693 return false;
1694 }
1696 void setObjectOrNull(JSObject *arg) {
1697 if (arg)
1698 setObject(*arg);
1699 else
1700 setNull();
1701 }
1702 };
1704 /*
1705 * Augment the generic Handle<T> interface when T = Value with type-querying
1706 * and value-extracting operations.
1707 */
1708 template <>
1709 class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> >
1710 {
1711 friend class ValueOperations<JS::Handle<JS::Value> >;
1712 const JS::Value * extract() const {
1713 return static_cast<const JS::Handle<JS::Value>*>(this)->address();
1714 }
1715 };
1717 /*
1718 * Augment the generic MutableHandle<T> interface when T = Value with
1719 * type-querying, value-extracting, and mutating operations.
1720 */
1721 template <>
1722 class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> >
1723 {
1724 friend class ValueOperations<JS::MutableHandle<JS::Value> >;
1725 const JS::Value * extract() const {
1726 return static_cast<const JS::MutableHandle<JS::Value>*>(this)->address();
1727 }
1729 friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
1730 JS::Value * extractMutable() {
1731 return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
1732 }
1733 };
1735 /*
1736 * Augment the generic Rooted<T> interface when T = Value with type-querying,
1737 * value-extracting, and mutating operations.
1738 */
1739 template <>
1740 class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> >
1741 {
1742 friend class ValueOperations<JS::Rooted<JS::Value> >;
1743 const JS::Value * extract() const {
1744 return static_cast<const JS::Rooted<JS::Value>*>(this)->address();
1745 }
1747 friend class MutableValueOperations<JS::Rooted<JS::Value> >;
1748 JS::Value * extractMutable() {
1749 return static_cast<JS::Rooted<JS::Value>*>(this)->address();
1750 }
1751 };
1753 } // namespace js
1755 inline jsval_layout
1756 JSVAL_TO_IMPL(JS::Value v)
1757 {
1758 return v.data;
1759 }
1761 inline JS_VALUE_CONSTEXPR JS::Value
1762 IMPL_TO_JSVAL(jsval_layout l)
1763 {
1764 #if defined(JS_VALUE_IS_CONSTEXPR)
1765 return JS::Value(l);
1766 #else
1767 JS::Value v;
1768 v.data = l;
1769 return v;
1770 #endif
1771 }
1773 namespace JS {
1775 #ifndef __GNUC__
1776 /*
1777 * The default assignment operator for |struct C| has the signature:
1778 *
1779 * C& C::operator=(const C&)
1780 *
1781 * And in particular requires implicit conversion of |this| to type |C| for the
1782 * return value. But |volatile C| cannot thus be converted to |C|, so just
1783 * doing |sink = hold| as in the non-specialized version would fail to compile.
1784 * Do the assignment on asBits instead, since I don't think we want to give
1785 * jsval_layout an assignment operator returning |volatile jsval_layout|.
1786 */
1787 template<>
1788 inline Anchor<Value>::~Anchor()
1789 {
1790 volatile uint64_t bits;
1791 bits = JSVAL_TO_IMPL(hold).asBits;
1792 }
1793 #endif
1795 #ifdef JS_DEBUG
1796 namespace detail {
1798 struct ValueAlignmentTester { char c; JS::Value v; };
1799 static_assert(sizeof(ValueAlignmentTester) == 16,
1800 "JS::Value must be 16-byte-aligned");
1802 struct LayoutAlignmentTester { char c; jsval_layout l; };
1803 static_assert(sizeof(LayoutAlignmentTester) == 16,
1804 "jsval_layout must be 16-byte-aligned");
1806 } // namespace detail
1807 #endif /* JS_DEBUG */
1809 } // namespace JS
1811 /*
1812 * JS::Value and jsval are the same type; jsval is the old name, kept around
1813 * for backwards compatibility along with all the JSVAL_* operations below.
1814 * jsval_layout is an implementation detail and should not be used externally.
1815 */
1816 typedef JS::Value jsval;
1818 static_assert(sizeof(jsval_layout) == sizeof(JS::Value),
1819 "jsval_layout and JS::Value must have identical layouts");
1821 /************************************************************************/
1823 static inline bool
1824 JSVAL_IS_NULL(jsval v)
1825 {
1826 return JSVAL_IS_NULL_IMPL(JSVAL_TO_IMPL(v));
1827 }
1829 static inline bool
1830 JSVAL_IS_VOID(jsval v)
1831 {
1832 return JSVAL_IS_UNDEFINED_IMPL(JSVAL_TO_IMPL(v));
1833 }
1835 static inline bool
1836 JSVAL_IS_INT(jsval v)
1837 {
1838 return JSVAL_IS_INT32_IMPL(JSVAL_TO_IMPL(v));
1839 }
1841 static inline int32_t
1842 JSVAL_TO_INT(jsval v)
1843 {
1844 MOZ_ASSERT(JSVAL_IS_INT(v));
1845 return JSVAL_TO_INT32_IMPL(JSVAL_TO_IMPL(v));
1846 }
1848 static inline JS_VALUE_CONSTEXPR jsval
1849 INT_TO_JSVAL(int32_t i)
1850 {
1851 return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i));
1852 }
1854 static inline bool
1855 JSVAL_IS_DOUBLE(jsval v)
1856 {
1857 return JSVAL_IS_DOUBLE_IMPL(JSVAL_TO_IMPL(v));
1858 }
1860 static inline double
1861 JSVAL_TO_DOUBLE(jsval v)
1862 {
1863 jsval_layout l;
1864 MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
1865 l = JSVAL_TO_IMPL(v);
1866 return l.asDouble;
1867 }
1869 static inline JS_VALUE_CONSTEXPR jsval
1870 DOUBLE_TO_JSVAL(double d)
1871 {
1872 /*
1873 * This is a manually inlined version of:
1874 * d = JS_CANONICALIZE_NAN(d);
1875 * return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
1876 * because GCC from XCode 3.1.4 miscompiles the above code.
1877 */
1878 #if defined(JS_VALUE_IS_CONSTEXPR)
1879 return IMPL_TO_JSVAL(MOZ_UNLIKELY(d != d)
1880 ? (jsval_layout) { .asBits = 0x7FF8000000000000LL }
1881 : (jsval_layout) { .asDouble = d });
1882 #else
1883 jsval_layout l;
1884 if (MOZ_UNLIKELY(d != d))
1885 l.asBits = 0x7FF8000000000000LL;
1886 else
1887 l.asDouble = d;
1888 return IMPL_TO_JSVAL(l);
1889 #endif
1890 }
1892 static inline JS_VALUE_CONSTEXPR jsval
1893 UINT_TO_JSVAL(uint32_t i)
1894 {
1895 return (i <= JSVAL_INT_MAX
1896 ? INT_TO_JSVAL((int32_t)i)
1897 : DOUBLE_TO_JSVAL((double)i));
1898 }
1900 static inline bool
1901 JSVAL_IS_NUMBER(jsval v)
1902 {
1903 return JSVAL_IS_NUMBER_IMPL(JSVAL_TO_IMPL(v));
1904 }
1906 static inline bool
1907 JSVAL_IS_STRING(jsval v)
1908 {
1909 return JSVAL_IS_STRING_IMPL(JSVAL_TO_IMPL(v));
1910 }
1912 static inline JSString *
1913 JSVAL_TO_STRING(jsval v)
1914 {
1915 MOZ_ASSERT(JSVAL_IS_STRING(v));
1916 return JSVAL_TO_STRING_IMPL(JSVAL_TO_IMPL(v));
1917 }
1919 static inline jsval
1920 STRING_TO_JSVAL(JSString *str)
1921 {
1922 return IMPL_TO_JSVAL(STRING_TO_JSVAL_IMPL(str));
1923 }
1925 static inline JSObject *
1926 JSVAL_TO_OBJECT(jsval v)
1927 {
1928 MOZ_ASSERT(JSVAL_IS_OBJECT_OR_NULL_IMPL(JSVAL_TO_IMPL(v)));
1929 return JSVAL_TO_OBJECT_IMPL(JSVAL_TO_IMPL(v));
1930 }
1932 static inline jsval
1933 OBJECT_TO_JSVAL(JSObject *obj)
1934 {
1935 if (obj)
1936 return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(obj));
1937 return IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
1938 }
1940 static inline bool
1941 JSVAL_IS_BOOLEAN(jsval v)
1942 {
1943 return JSVAL_IS_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
1944 }
1946 static inline bool
1947 JSVAL_TO_BOOLEAN(jsval v)
1948 {
1949 MOZ_ASSERT(JSVAL_IS_BOOLEAN(v));
1950 return JSVAL_TO_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
1951 }
1953 static inline jsval
1954 BOOLEAN_TO_JSVAL(bool b)
1955 {
1956 return IMPL_TO_JSVAL(BOOLEAN_TO_JSVAL_IMPL(b));
1957 }
1959 static inline bool
1960 JSVAL_IS_PRIMITIVE(jsval v)
1961 {
1962 return JSVAL_IS_PRIMITIVE_IMPL(JSVAL_TO_IMPL(v));
1963 }
1965 static inline bool
1966 JSVAL_IS_GCTHING(jsval v)
1967 {
1968 return JSVAL_IS_GCTHING_IMPL(JSVAL_TO_IMPL(v));
1969 }
1971 static inline void *
1972 JSVAL_TO_GCTHING(jsval v)
1973 {
1974 MOZ_ASSERT(JSVAL_IS_GCTHING(v));
1975 return JSVAL_TO_GCTHING_IMPL(JSVAL_TO_IMPL(v));
1976 }
1978 /* To be GC-safe, privates are tagged as doubles. */
1980 static inline jsval
1981 PRIVATE_TO_JSVAL(void *ptr)
1982 {
1983 return IMPL_TO_JSVAL(PRIVATE_PTR_TO_JSVAL_IMPL(ptr));
1984 }
1986 static inline void *
1987 JSVAL_TO_PRIVATE(jsval v)
1988 {
1989 MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
1990 return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
1991 }
1993 // JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and
1994 // constructing values from scratch (e.g. Int32Value(0)). These constants are
1995 // stored in memory and initialized at startup, so testing against them and
1996 // using them requires memory loads and will be correspondingly slow.
1997 extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
1998 extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
1999 extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
2000 extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
2001 extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
2002 extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
2004 namespace JS {
2006 extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue;
2007 extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
2009 }
2011 #undef JS_VALUE_IS_CONSTEXPR
2012 #undef JS_RETURN_LAYOUT_FROM_BITS
2014 #endif /* js_Value_h */