js/public/Value.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/public/Value.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2014 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* JS::Value implementation. */
    1.11 +
    1.12 +#ifndef js_Value_h
    1.13 +#define js_Value_h
    1.14 +
    1.15 +#include "mozilla/Attributes.h"
    1.16 +#include "mozilla/FloatingPoint.h"
    1.17 +#include "mozilla/Likely.h"
    1.18 +
    1.19 +#include <limits> /* for std::numeric_limits */
    1.20 +
    1.21 +#include "jstypes.h"
    1.22 +
    1.23 +#include "js/Anchor.h"
    1.24 +#include "js/RootingAPI.h"
    1.25 +#include "js/Utility.h"
    1.26 +
    1.27 +namespace JS { class Value; }
    1.28 +
    1.29 +/* JS::Value can store a full int32_t. */
    1.30 +#define JSVAL_INT_BITS          32
    1.31 +#define JSVAL_INT_MIN           ((int32_t)0x80000000)
    1.32 +#define JSVAL_INT_MAX           ((int32_t)0x7fffffff)
    1.33 +
    1.34 +/*
    1.35 + * Try to get jsvals 64-bit aligned. We could almost assert that all values are
    1.36 + * aligned, but MSVC and GCC occasionally break alignment.
    1.37 + */
    1.38 +#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
    1.39 +# define JSVAL_ALIGNMENT        __attribute__((aligned (8)))
    1.40 +#elif defined(_MSC_VER)
    1.41 +  /*
    1.42 +   * Structs can be aligned with MSVC, but not if they are used as parameters,
    1.43 +   * so we just don't try to align.
    1.44 +   */
    1.45 +# define JSVAL_ALIGNMENT
    1.46 +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
    1.47 +# define JSVAL_ALIGNMENT
    1.48 +#elif defined(__HP_cc) || defined(__HP_aCC)
    1.49 +# define JSVAL_ALIGNMENT
    1.50 +#endif
    1.51 +
    1.52 +#if JS_BITS_PER_WORD == 64
    1.53 +# define JSVAL_TAG_SHIFT 47
    1.54 +#endif
    1.55 +
    1.56 +/*
    1.57 + * We try to use enums so that printing a jsval_layout in the debugger shows
    1.58 + * nice symbolic type tags, however we can only do this when we can force the
    1.59 + * underlying type of the enum to be the desired size.
    1.60 + */
    1.61 +#if !defined(__SUNPRO_CC) && !defined(__xlC__)
    1.62 +
    1.63 +#if defined(_MSC_VER)
    1.64 +# define JS_ENUM_HEADER(id, type)              enum id : type
    1.65 +# define JS_ENUM_FOOTER(id)
    1.66 +#else
    1.67 +# define JS_ENUM_HEADER(id, type)              enum id
    1.68 +# define JS_ENUM_FOOTER(id)                    __attribute__((packed))
    1.69 +#endif
    1.70 +
    1.71 +/* Remember to propagate changes to the C defines below. */
    1.72 +JS_ENUM_HEADER(JSValueType, uint8_t)
    1.73 +{
    1.74 +    JSVAL_TYPE_DOUBLE              = 0x00,
    1.75 +    JSVAL_TYPE_INT32               = 0x01,
    1.76 +    JSVAL_TYPE_UNDEFINED           = 0x02,
    1.77 +    JSVAL_TYPE_BOOLEAN             = 0x03,
    1.78 +    JSVAL_TYPE_MAGIC               = 0x04,
    1.79 +    JSVAL_TYPE_STRING              = 0x05,
    1.80 +    JSVAL_TYPE_NULL                = 0x06,
    1.81 +    JSVAL_TYPE_OBJECT              = 0x07,
    1.82 +
    1.83 +    /* These never appear in a jsval; they are only provided as an out-of-band value. */
    1.84 +    JSVAL_TYPE_UNKNOWN             = 0x20,
    1.85 +    JSVAL_TYPE_MISSING             = 0x21
    1.86 +} JS_ENUM_FOOTER(JSValueType);
    1.87 +
    1.88 +JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
    1.89 +
    1.90 +#if JS_BITS_PER_WORD == 32
    1.91 +
    1.92 +/* Remember to propagate changes to the C defines below. */
    1.93 +JS_ENUM_HEADER(JSValueTag, uint32_t)
    1.94 +{
    1.95 +    JSVAL_TAG_CLEAR                = 0xFFFFFF80,
    1.96 +    JSVAL_TAG_INT32                = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32,
    1.97 +    JSVAL_TAG_UNDEFINED            = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED,
    1.98 +    JSVAL_TAG_STRING               = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING,
    1.99 +    JSVAL_TAG_BOOLEAN              = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
   1.100 +    JSVAL_TAG_MAGIC                = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
   1.101 +    JSVAL_TAG_NULL                 = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
   1.102 +    JSVAL_TAG_OBJECT               = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
   1.103 +} JS_ENUM_FOOTER(JSValueTag);
   1.104 +
   1.105 +JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
   1.106 +
   1.107 +#elif JS_BITS_PER_WORD == 64
   1.108 +
   1.109 +/* Remember to propagate changes to the C defines below. */
   1.110 +JS_ENUM_HEADER(JSValueTag, uint32_t)
   1.111 +{
   1.112 +    JSVAL_TAG_MAX_DOUBLE           = 0x1FFF0,
   1.113 +    JSVAL_TAG_INT32                = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32,
   1.114 +    JSVAL_TAG_UNDEFINED            = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED,
   1.115 +    JSVAL_TAG_STRING               = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING,
   1.116 +    JSVAL_TAG_BOOLEAN              = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
   1.117 +    JSVAL_TAG_MAGIC                = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
   1.118 +    JSVAL_TAG_NULL                 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
   1.119 +    JSVAL_TAG_OBJECT               = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
   1.120 +} JS_ENUM_FOOTER(JSValueTag);
   1.121 +
   1.122 +JS_STATIC_ASSERT(sizeof(JSValueTag) == sizeof(uint32_t));
   1.123 +
   1.124 +JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
   1.125 +{
   1.126 +    JSVAL_SHIFTED_TAG_MAX_DOUBLE   = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
   1.127 +    JSVAL_SHIFTED_TAG_INT32        = (((uint64_t)JSVAL_TAG_INT32)      << JSVAL_TAG_SHIFT),
   1.128 +    JSVAL_SHIFTED_TAG_UNDEFINED    = (((uint64_t)JSVAL_TAG_UNDEFINED)  << JSVAL_TAG_SHIFT),
   1.129 +    JSVAL_SHIFTED_TAG_STRING       = (((uint64_t)JSVAL_TAG_STRING)     << JSVAL_TAG_SHIFT),
   1.130 +    JSVAL_SHIFTED_TAG_BOOLEAN      = (((uint64_t)JSVAL_TAG_BOOLEAN)    << JSVAL_TAG_SHIFT),
   1.131 +    JSVAL_SHIFTED_TAG_MAGIC        = (((uint64_t)JSVAL_TAG_MAGIC)      << JSVAL_TAG_SHIFT),
   1.132 +    JSVAL_SHIFTED_TAG_NULL         = (((uint64_t)JSVAL_TAG_NULL)       << JSVAL_TAG_SHIFT),
   1.133 +    JSVAL_SHIFTED_TAG_OBJECT       = (((uint64_t)JSVAL_TAG_OBJECT)     << JSVAL_TAG_SHIFT)
   1.134 +} JS_ENUM_FOOTER(JSValueShiftedTag);
   1.135 +
   1.136 +JS_STATIC_ASSERT(sizeof(JSValueShiftedTag) == sizeof(uint64_t));
   1.137 +
   1.138 +#endif
   1.139 +
   1.140 +#else  /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
   1.141 +
   1.142 +typedef uint8_t JSValueType;
   1.143 +#define JSVAL_TYPE_DOUBLE            ((uint8_t)0x00)
   1.144 +#define JSVAL_TYPE_INT32             ((uint8_t)0x01)
   1.145 +#define JSVAL_TYPE_UNDEFINED         ((uint8_t)0x02)
   1.146 +#define JSVAL_TYPE_BOOLEAN           ((uint8_t)0x03)
   1.147 +#define JSVAL_TYPE_MAGIC             ((uint8_t)0x04)
   1.148 +#define JSVAL_TYPE_STRING            ((uint8_t)0x05)
   1.149 +#define JSVAL_TYPE_NULL              ((uint8_t)0x06)
   1.150 +#define JSVAL_TYPE_OBJECT            ((uint8_t)0x07)
   1.151 +#define JSVAL_TYPE_UNKNOWN           ((uint8_t)0x20)
   1.152 +
   1.153 +#if JS_BITS_PER_WORD == 32
   1.154 +
   1.155 +typedef uint32_t JSValueTag;
   1.156 +#define JSVAL_TAG_CLEAR              ((uint32_t)(0xFFFFFF80))
   1.157 +#define JSVAL_TAG_INT32              ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
   1.158 +#define JSVAL_TAG_UNDEFINED          ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
   1.159 +#define JSVAL_TAG_STRING             ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
   1.160 +#define JSVAL_TAG_BOOLEAN            ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
   1.161 +#define JSVAL_TAG_MAGIC              ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
   1.162 +#define JSVAL_TAG_NULL               ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
   1.163 +#define JSVAL_TAG_OBJECT             ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
   1.164 +
   1.165 +#elif JS_BITS_PER_WORD == 64
   1.166 +
   1.167 +typedef uint32_t JSValueTag;
   1.168 +#define JSVAL_TAG_MAX_DOUBLE         ((uint32_t)(0x1FFF0))
   1.169 +#define JSVAL_TAG_INT32              (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
   1.170 +#define JSVAL_TAG_UNDEFINED          (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
   1.171 +#define JSVAL_TAG_STRING             (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
   1.172 +#define JSVAL_TAG_BOOLEAN            (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
   1.173 +#define JSVAL_TAG_MAGIC              (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
   1.174 +#define JSVAL_TAG_NULL               (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
   1.175 +#define JSVAL_TAG_OBJECT             (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
   1.176 +
   1.177 +typedef uint64_t JSValueShiftedTag;
   1.178 +#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
   1.179 +#define JSVAL_SHIFTED_TAG_INT32      (((uint64_t)JSVAL_TAG_INT32)      << JSVAL_TAG_SHIFT)
   1.180 +#define JSVAL_SHIFTED_TAG_UNDEFINED  (((uint64_t)JSVAL_TAG_UNDEFINED)  << JSVAL_TAG_SHIFT)
   1.181 +#define JSVAL_SHIFTED_TAG_STRING     (((uint64_t)JSVAL_TAG_STRING)     << JSVAL_TAG_SHIFT)
   1.182 +#define JSVAL_SHIFTED_TAG_BOOLEAN    (((uint64_t)JSVAL_TAG_BOOLEAN)    << JSVAL_TAG_SHIFT)
   1.183 +#define JSVAL_SHIFTED_TAG_MAGIC      (((uint64_t)JSVAL_TAG_MAGIC)      << JSVAL_TAG_SHIFT)
   1.184 +#define JSVAL_SHIFTED_TAG_NULL       (((uint64_t)JSVAL_TAG_NULL)       << JSVAL_TAG_SHIFT)
   1.185 +#define JSVAL_SHIFTED_TAG_OBJECT     (((uint64_t)JSVAL_TAG_OBJECT)     << JSVAL_TAG_SHIFT)
   1.186 +
   1.187 +#endif  /* JS_BITS_PER_WORD */
   1.188 +#endif  /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
   1.189 +
   1.190 +#define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET        JSVAL_TYPE_NULL
   1.191 +#define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET          JSVAL_TYPE_OBJECT
   1.192 +#define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET             JSVAL_TYPE_INT32
   1.193 +#define JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET        JSVAL_TYPE_MAGIC
   1.194 +
   1.195 +#if JS_BITS_PER_WORD == 32
   1.196 +
   1.197 +#define JSVAL_TYPE_TO_TAG(type)      ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
   1.198 +
   1.199 +#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET         JSVAL_TAG_NULL
   1.200 +#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET           JSVAL_TAG_OBJECT
   1.201 +#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET              JSVAL_TAG_INT32
   1.202 +#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET             JSVAL_TAG_STRING
   1.203 +
   1.204 +#elif JS_BITS_PER_WORD == 64
   1.205 +
   1.206 +#define JSVAL_PAYLOAD_MASK           0x00007FFFFFFFFFFFLL
   1.207 +#define JSVAL_TAG_MASK               0xFFFF800000000000LL
   1.208 +#define JSVAL_TYPE_TO_TAG(type)      ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
   1.209 +#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
   1.210 +
   1.211 +#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET         JSVAL_TAG_NULL
   1.212 +#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET           JSVAL_TAG_OBJECT
   1.213 +#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET              JSVAL_TAG_INT32
   1.214 +#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET             JSVAL_TAG_STRING
   1.215 +
   1.216 +#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET  JSVAL_SHIFTED_TAG_NULL
   1.217 +#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET    JSVAL_SHIFTED_TAG_OBJECT
   1.218 +#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET       JSVAL_SHIFTED_TAG_UNDEFINED
   1.219 +#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET      JSVAL_SHIFTED_TAG_STRING
   1.220 +
   1.221 +#endif /* JS_BITS_PER_WORD */
   1.222 +
   1.223 +typedef enum JSWhyMagic
   1.224 +{
   1.225 +    JS_ELEMENTS_HOLE,            /* a hole in a native object's elements */
   1.226 +    JS_NATIVE_ENUMERATE,         /* indicates that a custom enumerate hook forwarded
   1.227 +                                  * to JS_EnumerateState, which really means the object can be
   1.228 +                                  * enumerated like a native object. */
   1.229 +    JS_NO_ITER_VALUE,            /* there is not a pending iterator value */
   1.230 +    JS_GENERATOR_CLOSING,        /* exception value thrown when closing a generator */
   1.231 +    JS_NO_CONSTANT,              /* compiler sentinel value */
   1.232 +    JS_THIS_POISON,              /* used in debug builds to catch tracing errors */
   1.233 +    JS_ARG_POISON,               /* used in debug builds to catch tracing errors */
   1.234 +    JS_SERIALIZE_NO_NODE,        /* an empty subnode in the AST serializer */
   1.235 +    JS_LAZY_ARGUMENTS,           /* lazy arguments value on the stack */
   1.236 +    JS_OPTIMIZED_ARGUMENTS,      /* optimized-away 'arguments' value */
   1.237 +    JS_IS_CONSTRUCTING,          /* magic value passed to natives to indicate construction */
   1.238 +    JS_OVERWRITTEN_CALLEE,       /* arguments.callee has been overwritten */
   1.239 +    JS_BLOCK_NEEDS_CLONE,        /* value of static block object slot */
   1.240 +    JS_HASH_KEY_EMPTY,           /* see class js::HashableValue */
   1.241 +    JS_ION_ERROR,                /* error while running Ion code */
   1.242 +    JS_ION_BAILOUT,              /* status code to signal EnterIon will OSR into Interpret */
   1.243 +    JS_OPTIMIZED_OUT,            /* optimized out slot */
   1.244 +    JS_GENERIC_MAGIC             /* for local use */
   1.245 +} JSWhyMagic;
   1.246 +
   1.247 +#if defined(IS_LITTLE_ENDIAN)
   1.248 +# if JS_BITS_PER_WORD == 32
   1.249 +typedef union jsval_layout
   1.250 +{
   1.251 +    uint64_t asBits;
   1.252 +    struct {
   1.253 +        union {
   1.254 +            int32_t        i32;
   1.255 +            uint32_t       u32;
   1.256 +            uint32_t       boo;     // Don't use |bool| -- it must be four bytes.
   1.257 +            JSString       *str;
   1.258 +            JSObject       *obj;
   1.259 +            void           *ptr;
   1.260 +            JSWhyMagic     why;
   1.261 +            size_t         word;
   1.262 +            uintptr_t      uintptr;
   1.263 +        } payload;
   1.264 +        JSValueTag tag;
   1.265 +    } s;
   1.266 +    double asDouble;
   1.267 +    void *asPtr;
   1.268 +} JSVAL_ALIGNMENT jsval_layout;
   1.269 +# elif JS_BITS_PER_WORD == 64
   1.270 +typedef union jsval_layout
   1.271 +{
   1.272 +    uint64_t asBits;
   1.273 +#if !defined(_WIN64)
   1.274 +    /* MSVC does not pack these correctly :-( */
   1.275 +    struct {
   1.276 +        uint64_t           payload47 : 47;
   1.277 +        JSValueTag         tag : 17;
   1.278 +    } debugView;
   1.279 +#endif
   1.280 +    struct {
   1.281 +        union {
   1.282 +            int32_t        i32;
   1.283 +            uint32_t       u32;
   1.284 +            JSWhyMagic     why;
   1.285 +        } payload;
   1.286 +    } s;
   1.287 +    double asDouble;
   1.288 +    void *asPtr;
   1.289 +    size_t asWord;
   1.290 +    uintptr_t asUIntPtr;
   1.291 +} JSVAL_ALIGNMENT jsval_layout;
   1.292 +# endif  /* JS_BITS_PER_WORD */
   1.293 +#else   /* defined(IS_LITTLE_ENDIAN) */
   1.294 +# if JS_BITS_PER_WORD == 32
   1.295 +typedef union jsval_layout
   1.296 +{
   1.297 +    uint64_t asBits;
   1.298 +    struct {
   1.299 +        JSValueTag tag;
   1.300 +        union {
   1.301 +            int32_t        i32;
   1.302 +            uint32_t       u32;
   1.303 +            uint32_t       boo;     // Don't use |bool| -- it must be four bytes.
   1.304 +            JSString       *str;
   1.305 +            JSObject       *obj;
   1.306 +            void           *ptr;
   1.307 +            JSWhyMagic     why;
   1.308 +            size_t         word;
   1.309 +            uintptr_t      uintptr;
   1.310 +        } payload;
   1.311 +    } s;
   1.312 +    double asDouble;
   1.313 +    void *asPtr;
   1.314 +} JSVAL_ALIGNMENT jsval_layout;
   1.315 +# elif JS_BITS_PER_WORD == 64
   1.316 +typedef union jsval_layout
   1.317 +{
   1.318 +    uint64_t asBits;
   1.319 +    struct {
   1.320 +        JSValueTag         tag : 17;
   1.321 +        uint64_t           payload47 : 47;
   1.322 +    } debugView;
   1.323 +    struct {
   1.324 +        uint32_t           padding;
   1.325 +        union {
   1.326 +            int32_t        i32;
   1.327 +            uint32_t       u32;
   1.328 +            JSWhyMagic     why;
   1.329 +        } payload;
   1.330 +    } s;
   1.331 +    double asDouble;
   1.332 +    void *asPtr;
   1.333 +    size_t asWord;
   1.334 +    uintptr_t asUIntPtr;
   1.335 +} JSVAL_ALIGNMENT jsval_layout;
   1.336 +# endif /* JS_BITS_PER_WORD */
   1.337 +#endif  /* defined(IS_LITTLE_ENDIAN) */
   1.338 +
   1.339 +JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
   1.340 +
   1.341 +/*
   1.342 + * For codesize purposes on some platforms, it's important that the
   1.343 + * compiler know that JS::Values constructed from constant values can be
   1.344 + * folded to constant bit patterns at compile time, rather than
   1.345 + * constructed at runtime.  Doing this requires a fair amount of C++11
   1.346 + * features, which are not supported on all of our compilers.  Set up
   1.347 + * some defines and helper macros in an attempt to confine the ugliness
   1.348 + * here, rather than scattering it all about the file.  The important
   1.349 + * features are:
   1.350 + *
   1.351 + * - constexpr;
   1.352 + * - defaulted functions;
   1.353 + * - C99-style designated initializers.
   1.354 + */
   1.355 +#if defined(__clang__)
   1.356 +#  if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions)
   1.357 +#    define JS_VALUE_IS_CONSTEXPR
   1.358 +#  endif
   1.359 +#elif defined(__GNUC__)
   1.360 +/*
   1.361 + * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6
   1.362 + * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because
   1.363 + * versions prior to that have bugs in the C++ front-end that cause crashes.
   1.364 + */
   1.365 +#  if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3)
   1.366 +#    define JS_VALUE_IS_CONSTEXPR
   1.367 +#  endif
   1.368 +#endif
   1.369 +
   1.370 +#if defined(JS_VALUE_IS_CONSTEXPR)
   1.371 +#  define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
   1.372 +    return (jsval_layout) { .asBits = (BITS) }
   1.373 +#  define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR
   1.374 +#  define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR
   1.375 +#else
   1.376 +#  define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
   1.377 +    jsval_layout l;                        \
   1.378 +    l.asBits = (BITS);                     \
   1.379 +    return l;
   1.380 +#  define JS_VALUE_CONSTEXPR
   1.381 +#  define JS_VALUE_CONSTEXPR_VAR const
   1.382 +#endif
   1.383 +
   1.384 +#if JS_BITS_PER_WORD == 32
   1.385 +
   1.386 +/*
   1.387 + * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
   1.388 + * JSValueTag even though its underlying type has been forced to be uint32_t.
   1.389 + * Thus, all comparisons should explicitly cast operands to uint32_t.
   1.390 + */
   1.391 +
   1.392 +static inline JS_VALUE_CONSTEXPR jsval_layout
   1.393 +BUILD_JSVAL(JSValueTag tag, uint32_t payload)
   1.394 +{
   1.395 +    JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << 32) | payload);
   1.396 +}
   1.397 +
   1.398 +static inline bool
   1.399 +JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
   1.400 +{
   1.401 +    return (uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_CLEAR;
   1.402 +}
   1.403 +
   1.404 +static inline jsval_layout
   1.405 +DOUBLE_TO_JSVAL_IMPL(double d)
   1.406 +{
   1.407 +    jsval_layout l;
   1.408 +    l.asDouble = d;
   1.409 +    MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
   1.410 +    return l;
   1.411 +}
   1.412 +
   1.413 +static inline bool
   1.414 +JSVAL_IS_INT32_IMPL(jsval_layout l)
   1.415 +{
   1.416 +    return l.s.tag == JSVAL_TAG_INT32;
   1.417 +}
   1.418 +
   1.419 +static inline int32_t
   1.420 +JSVAL_TO_INT32_IMPL(jsval_layout l)
   1.421 +{
   1.422 +    return l.s.payload.i32;
   1.423 +}
   1.424 +
   1.425 +static inline JS_VALUE_CONSTEXPR jsval_layout
   1.426 +INT32_TO_JSVAL_IMPL(int32_t i)
   1.427 +{
   1.428 +#if defined(JS_VALUE_IS_CONSTEXPR)
   1.429 +    return BUILD_JSVAL(JSVAL_TAG_INT32, i);
   1.430 +#else
   1.431 +    jsval_layout l;
   1.432 +    l.s.tag = JSVAL_TAG_INT32;
   1.433 +    l.s.payload.i32 = i;
   1.434 +    return l;
   1.435 +#endif
   1.436 +}
   1.437 +
   1.438 +static inline bool
   1.439 +JSVAL_IS_NUMBER_IMPL(jsval_layout l)
   1.440 +{
   1.441 +    JSValueTag tag = l.s.tag;
   1.442 +    MOZ_ASSERT(tag != JSVAL_TAG_CLEAR);
   1.443 +    return (uint32_t)tag <= (uint32_t)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
   1.444 +}
   1.445 +
   1.446 +static inline bool
   1.447 +JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
   1.448 +{
   1.449 +    return l.s.tag == JSVAL_TAG_UNDEFINED;
   1.450 +}
   1.451 +
   1.452 +static inline bool
   1.453 +JSVAL_IS_STRING_IMPL(jsval_layout l)
   1.454 +{
   1.455 +    return l.s.tag == JSVAL_TAG_STRING;
   1.456 +}
   1.457 +
   1.458 +static inline jsval_layout
   1.459 +STRING_TO_JSVAL_IMPL(JSString *str)
   1.460 +{
   1.461 +    jsval_layout l;
   1.462 +    MOZ_ASSERT(uintptr_t(str) > 0x1000);
   1.463 +    l.s.tag = JSVAL_TAG_STRING;
   1.464 +    l.s.payload.str = str;
   1.465 +    return l;
   1.466 +}
   1.467 +
   1.468 +static inline JSString *
   1.469 +JSVAL_TO_STRING_IMPL(jsval_layout l)
   1.470 +{
   1.471 +    return l.s.payload.str;
   1.472 +}
   1.473 +
   1.474 +static inline bool
   1.475 +JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
   1.476 +{
   1.477 +    return l.s.tag == JSVAL_TAG_BOOLEAN;
   1.478 +}
   1.479 +
   1.480 +static inline bool
   1.481 +JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
   1.482 +{
   1.483 +    return l.s.payload.boo;
   1.484 +}
   1.485 +
   1.486 +static inline jsval_layout
   1.487 +BOOLEAN_TO_JSVAL_IMPL(bool b)
   1.488 +{
   1.489 +    jsval_layout l;
   1.490 +    l.s.tag = JSVAL_TAG_BOOLEAN;
   1.491 +    l.s.payload.boo = b;
   1.492 +    return l;
   1.493 +}
   1.494 +
   1.495 +static inline bool
   1.496 +JSVAL_IS_MAGIC_IMPL(jsval_layout l)
   1.497 +{
   1.498 +    return l.s.tag == JSVAL_TAG_MAGIC;
   1.499 +}
   1.500 +
   1.501 +static inline bool
   1.502 +JSVAL_IS_OBJECT_IMPL(jsval_layout l)
   1.503 +{
   1.504 +    return l.s.tag == JSVAL_TAG_OBJECT;
   1.505 +}
   1.506 +
   1.507 +static inline bool
   1.508 +JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
   1.509 +{
   1.510 +    return (uint32_t)l.s.tag < (uint32_t)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
   1.511 +}
   1.512 +
   1.513 +static inline bool
   1.514 +JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
   1.515 +{
   1.516 +    MOZ_ASSERT((uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_OBJECT);
   1.517 +    return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
   1.518 +}
   1.519 +
   1.520 +static inline JSObject *
   1.521 +JSVAL_TO_OBJECT_IMPL(jsval_layout l)
   1.522 +{
   1.523 +    return l.s.payload.obj;
   1.524 +}
   1.525 +
   1.526 +static inline jsval_layout
   1.527 +OBJECT_TO_JSVAL_IMPL(JSObject *obj)
   1.528 +{
   1.529 +    jsval_layout l;
   1.530 +    MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
   1.531 +    l.s.tag = JSVAL_TAG_OBJECT;
   1.532 +    l.s.payload.obj = obj;
   1.533 +    return l;
   1.534 +}
   1.535 +
   1.536 +static inline bool
   1.537 +JSVAL_IS_NULL_IMPL(jsval_layout l)
   1.538 +{
   1.539 +    return l.s.tag == JSVAL_TAG_NULL;
   1.540 +}
   1.541 +
   1.542 +static inline jsval_layout
   1.543 +PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
   1.544 +{
   1.545 +    jsval_layout l;
   1.546 +    MOZ_ASSERT(((uint32_t)ptr & 1) == 0);
   1.547 +    l.s.tag = (JSValueTag)0;
   1.548 +    l.s.payload.ptr = ptr;
   1.549 +    MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
   1.550 +    return l;
   1.551 +}
   1.552 +
   1.553 +static inline void *
   1.554 +JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
   1.555 +{
   1.556 +    return l.s.payload.ptr;
   1.557 +}
   1.558 +
   1.559 +static inline bool
   1.560 +JSVAL_IS_GCTHING_IMPL(jsval_layout l)
   1.561 +{
   1.562 +    /* gcc sometimes generates signed < without explicit casts. */
   1.563 +    return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
   1.564 +}
   1.565 +
   1.566 +static inline void *
   1.567 +JSVAL_TO_GCTHING_IMPL(jsval_layout l)
   1.568 +{
   1.569 +    return l.s.payload.ptr;
   1.570 +}
   1.571 +
   1.572 +static inline bool
   1.573 +JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
   1.574 +{
   1.575 +    return l.s.tag == JSVAL_TAG_STRING || l.s.tag == JSVAL_TAG_OBJECT;
   1.576 +}
   1.577 +
   1.578 +static inline uint32_t
   1.579 +JSVAL_TRACE_KIND_IMPL(jsval_layout l)
   1.580 +{
   1.581 +    return (uint32_t)(bool)JSVAL_IS_STRING_IMPL(l);
   1.582 +}
   1.583 +
   1.584 +static inline bool
   1.585 +JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
   1.586 +{
   1.587 +    return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
   1.588 +}
   1.589 +
   1.590 +static inline bool
   1.591 +JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, bool b)
   1.592 +{
   1.593 +    return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == uint32_t(b));
   1.594 +}
   1.595 +
   1.596 +static inline jsval_layout
   1.597 +MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
   1.598 +{
   1.599 +    jsval_layout l;
   1.600 +    l.s.tag = JSVAL_TAG_MAGIC;
   1.601 +    l.s.payload.why = why;
   1.602 +    return l;
   1.603 +}
   1.604 +
   1.605 +static inline jsval_layout
   1.606 +MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
   1.607 +{
   1.608 +    jsval_layout l;
   1.609 +    l.s.tag = JSVAL_TAG_MAGIC;
   1.610 +    l.s.payload.u32 = payload;
   1.611 +    return l;
   1.612 +}
   1.613 +
   1.614 +static inline bool
   1.615 +JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
   1.616 +{
   1.617 +    JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
   1.618 +    return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
   1.619 +}
   1.620 +
   1.621 +static inline JSValueType
   1.622 +JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
   1.623 +{
   1.624 +    uint32_t type = l.s.tag & 0xF;
   1.625 +    MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
   1.626 +    return (JSValueType)type;
   1.627 +}
   1.628 +
   1.629 +#elif JS_BITS_PER_WORD == 64
   1.630 +
   1.631 +static inline JS_VALUE_CONSTEXPR jsval_layout
   1.632 +BUILD_JSVAL(JSValueTag tag, uint64_t payload)
   1.633 +{
   1.634 +    JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload);
   1.635 +}
   1.636 +
   1.637 +static inline bool
   1.638 +JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
   1.639 +{
   1.640 +    return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
   1.641 +}
   1.642 +
   1.643 +static inline jsval_layout
   1.644 +DOUBLE_TO_JSVAL_IMPL(double d)
   1.645 +{
   1.646 +    jsval_layout l;
   1.647 +    l.asDouble = d;
   1.648 +    MOZ_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
   1.649 +    return l;
   1.650 +}
   1.651 +
   1.652 +static inline bool
   1.653 +JSVAL_IS_INT32_IMPL(jsval_layout l)
   1.654 +{
   1.655 +    return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
   1.656 +}
   1.657 +
   1.658 +static inline int32_t
   1.659 +JSVAL_TO_INT32_IMPL(jsval_layout l)
   1.660 +{
   1.661 +    return (int32_t)l.asBits;
   1.662 +}
   1.663 +
   1.664 +static inline JS_VALUE_CONSTEXPR jsval_layout
   1.665 +INT32_TO_JSVAL_IMPL(int32_t i32)
   1.666 +{
   1.667 +    JS_RETURN_LAYOUT_FROM_BITS(((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
   1.668 +}
   1.669 +
   1.670 +static inline bool
   1.671 +JSVAL_IS_NUMBER_IMPL(jsval_layout l)
   1.672 +{
   1.673 +    return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
   1.674 +}
   1.675 +
   1.676 +static inline bool
   1.677 +JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
   1.678 +{
   1.679 +    return l.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
   1.680 +}
   1.681 +
   1.682 +static inline bool
   1.683 +JSVAL_IS_STRING_IMPL(jsval_layout l)
   1.684 +{
   1.685 +    return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
   1.686 +}
   1.687 +
   1.688 +static inline jsval_layout
   1.689 +STRING_TO_JSVAL_IMPL(JSString *str)
   1.690 +{
   1.691 +    jsval_layout l;
   1.692 +    uint64_t strBits = (uint64_t)str;
   1.693 +    MOZ_ASSERT(uintptr_t(str) > 0x1000);
   1.694 +    MOZ_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
   1.695 +    l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
   1.696 +    return l;
   1.697 +}
   1.698 +
   1.699 +static inline JSString *
   1.700 +JSVAL_TO_STRING_IMPL(jsval_layout l)
   1.701 +{
   1.702 +    return (JSString *)(l.asBits & JSVAL_PAYLOAD_MASK);
   1.703 +}
   1.704 +
   1.705 +static inline bool
   1.706 +JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
   1.707 +{
   1.708 +    return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
   1.709 +}
   1.710 +
   1.711 +static inline bool
   1.712 +JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
   1.713 +{
   1.714 +    return (bool)(l.asBits & JSVAL_PAYLOAD_MASK);
   1.715 +}
   1.716 +
   1.717 +static inline jsval_layout
   1.718 +BOOLEAN_TO_JSVAL_IMPL(bool b)
   1.719 +{
   1.720 +    jsval_layout l;
   1.721 +    l.asBits = ((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
   1.722 +    return l;
   1.723 +}
   1.724 +
   1.725 +static inline bool
   1.726 +JSVAL_IS_MAGIC_IMPL(jsval_layout l)
   1.727 +{
   1.728 +    return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
   1.729 +}
   1.730 +
   1.731 +static inline bool
   1.732 +JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
   1.733 +{
   1.734 +    return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
   1.735 +}
   1.736 +
   1.737 +static inline bool
   1.738 +JSVAL_IS_OBJECT_IMPL(jsval_layout l)
   1.739 +{
   1.740 +    MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
   1.741 +    return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
   1.742 +}
   1.743 +
   1.744 +static inline bool
   1.745 +JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
   1.746 +{
   1.747 +    MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
   1.748 +    return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
   1.749 +}
   1.750 +
   1.751 +static inline JSObject *
   1.752 +JSVAL_TO_OBJECT_IMPL(jsval_layout l)
   1.753 +{
   1.754 +    uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
   1.755 +    MOZ_ASSERT((ptrBits & 0x7) == 0);
   1.756 +    return (JSObject *)ptrBits;
   1.757 +}
   1.758 +
   1.759 +static inline jsval_layout
   1.760 +OBJECT_TO_JSVAL_IMPL(JSObject *obj)
   1.761 +{
   1.762 +    jsval_layout l;
   1.763 +    uint64_t objBits = (uint64_t)obj;
   1.764 +    MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
   1.765 +    MOZ_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
   1.766 +    l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
   1.767 +    return l;
   1.768 +}
   1.769 +
   1.770 +static inline bool
   1.771 +JSVAL_IS_NULL_IMPL(jsval_layout l)
   1.772 +{
   1.773 +    return l.asBits == JSVAL_SHIFTED_TAG_NULL;
   1.774 +}
   1.775 +
   1.776 +static inline bool
   1.777 +JSVAL_IS_GCTHING_IMPL(jsval_layout l)
   1.778 +{
   1.779 +    return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
   1.780 +}
   1.781 +
   1.782 +static inline void *
   1.783 +JSVAL_TO_GCTHING_IMPL(jsval_layout l)
   1.784 +{
   1.785 +    uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
   1.786 +    MOZ_ASSERT((ptrBits & 0x7) == 0);
   1.787 +    return (void *)ptrBits;
   1.788 +}
   1.789 +
   1.790 +static inline bool
   1.791 +JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
   1.792 +{
   1.793 +    return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
   1.794 +}
   1.795 +
   1.796 +static inline uint32_t
   1.797 +JSVAL_TRACE_KIND_IMPL(jsval_layout l)
   1.798 +{
   1.799 +    return (uint32_t)(bool)!(JSVAL_IS_OBJECT_IMPL(l));
   1.800 +}
   1.801 +
   1.802 +static inline jsval_layout
   1.803 +PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
   1.804 +{
   1.805 +    jsval_layout l;
   1.806 +    uint64_t ptrBits = (uint64_t)ptr;
   1.807 +    MOZ_ASSERT((ptrBits & 1) == 0);
   1.808 +    l.asBits = ptrBits >> 1;
   1.809 +    MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
   1.810 +    return l;
   1.811 +}
   1.812 +
   1.813 +static inline void *
   1.814 +JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
   1.815 +{
   1.816 +    MOZ_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
   1.817 +    return (void *)(l.asBits << 1);
   1.818 +}
   1.819 +
   1.820 +static inline bool
   1.821 +JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
   1.822 +{
   1.823 +    return l.asBits == (((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
   1.824 +}
   1.825 +
   1.826 +static inline bool
   1.827 +JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, bool b)
   1.828 +{
   1.829 +    return l.asBits == (((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
   1.830 +}
   1.831 +
   1.832 +static inline jsval_layout
   1.833 +MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
   1.834 +{
   1.835 +    jsval_layout l;
   1.836 +    l.asBits = ((uint64_t)(uint32_t)why) | JSVAL_SHIFTED_TAG_MAGIC;
   1.837 +    return l;
   1.838 +}
   1.839 +
   1.840 +static inline jsval_layout
   1.841 +MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
   1.842 +{
   1.843 +    jsval_layout l;
   1.844 +    l.asBits = ((uint64_t)payload) | JSVAL_SHIFTED_TAG_MAGIC;
   1.845 +    return l;
   1.846 +}
   1.847 +
   1.848 +static inline bool
   1.849 +JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
   1.850 +{
   1.851 +    uint64_t lbits = lhs.asBits, rbits = rhs.asBits;
   1.852 +    return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
   1.853 +           (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
   1.854 +}
   1.855 +
   1.856 +static inline JSValueType
   1.857 +JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
   1.858 +{
   1.859 +   uint64_t type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
   1.860 +   MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
   1.861 +   return (JSValueType)type;
   1.862 +}
   1.863 +
   1.864 +#endif  /* JS_BITS_PER_WORD */
   1.865 +
   1.866 +static inline jsval_layout JSVAL_TO_IMPL(JS::Value v);
   1.867 +static inline JS_VALUE_CONSTEXPR JS::Value IMPL_TO_JSVAL(jsval_layout l);
   1.868 +
   1.869 +namespace JS {
   1.870 +
   1.871 +static inline JS_VALUE_CONSTEXPR JS::Value UndefinedValue();
   1.872 +
   1.873 +/**
   1.874 + * Returns a generic quiet NaN value, with all payload bits set to zero.
   1.875 + *
   1.876 + * Among other properties, this NaN's bit pattern conforms to JS::Value's
   1.877 + * bit pattern restrictions.
   1.878 + */
   1.879 +static MOZ_ALWAYS_INLINE double
   1.880 +GenericNaN()
   1.881 +{
   1.882 +  return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
   1.883 +}
   1.884 +
   1.885 +/* MSVC with PGO miscompiles this function. */
   1.886 +#if defined(_MSC_VER)
   1.887 +# pragma optimize("g", off)
   1.888 +#endif
   1.889 +static inline double
   1.890 +CanonicalizeNaN(double d)
   1.891 +{
   1.892 +    if (MOZ_UNLIKELY(mozilla::IsNaN(d)))
   1.893 +        return GenericNaN();
   1.894 +    return d;
   1.895 +}
   1.896 +#if defined(_MSC_VER)
   1.897 +# pragma optimize("", on)
   1.898 +#endif
   1.899 +
   1.900 +/*
   1.901 + * JS::Value is the interface for a single JavaScript Engine value.  A few
   1.902 + * general notes on JS::Value:
   1.903 + *
   1.904 + * - JS::Value has setX() and isX() members for X in
   1.905 + *
   1.906 + *     { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
   1.907 + *
   1.908 + *   JS::Value also contains toX() for each of the non-singleton types.
   1.909 + *
   1.910 + * - Magic is a singleton type whose payload contains either a JSWhyMagic "reason" for
   1.911 + *   the magic value or a uint32_t value. By providing JSWhyMagic values when
   1.912 + *   creating and checking for magic values, it is possible to assert, at
   1.913 + *   runtime, that only magic values with the expected reason flow through a
   1.914 + *   particular value. For example, if cx->exception has a magic value, the
   1.915 + *   reason must be JS_GENERATOR_CLOSING.
   1.916 + *
   1.917 + * - The JS::Value operations are preferred.  The JSVAL_* operations remain for
   1.918 + *   compatibility; they may be removed at some point.  These operations mostly
   1.919 + *   provide similar functionality.  But there are a few key differences.  One
   1.920 + *   is that JS::Value gives null a separate type. Thus
   1.921 + *
   1.922 + *           JSVAL_IS_OBJECT(v) === v.isObjectOrNull()
   1.923 + *       !JSVAL_IS_PRIMITIVE(v) === v.isObject()
   1.924 + *
   1.925 + *   Also, to help prevent mistakenly boxing a nullable JSObject* as an object,
   1.926 + *   Value::setObject takes a JSObject&. (Conversely, Value::toObject returns a
   1.927 + *   JSObject&.)  A convenience member Value::setObjectOrNull is provided.
   1.928 + *
   1.929 + * - JSVAL_VOID is the same as the singleton value of the Undefined type.
   1.930 + *
   1.931 + * - Note that JS::Value is 8 bytes on 32 and 64-bit architectures. Thus, on
   1.932 + *   32-bit user code should avoid copying jsval/JS::Value as much as possible,
   1.933 + *   preferring to pass by const Value &.
   1.934 + */
   1.935 +class Value
   1.936 +{
   1.937 +  public:
   1.938 +    /*
   1.939 +     * N.B. the default constructor leaves Value unitialized. Adding a default
   1.940 +     * constructor prevents Value from being stored in a union.
   1.941 +     */
   1.942 +#if defined(JS_VALUE_IS_CONSTEXPR)
   1.943 +    Value() = default;
   1.944 +    Value(const Value& v) = default;
   1.945 +#endif
   1.946 +
   1.947 +    /*** Mutators ***/
   1.948 +
   1.949 +    void setNull() {
   1.950 +        data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
   1.951 +    }
   1.952 +
   1.953 +    void setUndefined() {
   1.954 +        data.asBits = BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0).asBits;
   1.955 +    }
   1.956 +
   1.957 +    void setInt32(int32_t i) {
   1.958 +        data = INT32_TO_JSVAL_IMPL(i);
   1.959 +    }
   1.960 +
   1.961 +    int32_t &getInt32Ref() {
   1.962 +        MOZ_ASSERT(isInt32());
   1.963 +        return data.s.payload.i32;
   1.964 +    }
   1.965 +
   1.966 +    void setDouble(double d) {
   1.967 +        data = DOUBLE_TO_JSVAL_IMPL(d);
   1.968 +    }
   1.969 +
   1.970 +    void setNaN() {
   1.971 +        setDouble(GenericNaN());
   1.972 +    }
   1.973 +
   1.974 +    double &getDoubleRef() {
   1.975 +        MOZ_ASSERT(isDouble());
   1.976 +        return data.asDouble;
   1.977 +    }
   1.978 +
   1.979 +    void setString(JSString *str) {
   1.980 +        MOZ_ASSERT(!IsPoisonedPtr(str));
   1.981 +        data = STRING_TO_JSVAL_IMPL(str);
   1.982 +    }
   1.983 +
   1.984 +    void setObject(JSObject &obj) {
   1.985 +        MOZ_ASSERT(!IsPoisonedPtr(&obj));
   1.986 +        data = OBJECT_TO_JSVAL_IMPL(&obj);
   1.987 +    }
   1.988 +
   1.989 +    void setBoolean(bool b) {
   1.990 +        data = BOOLEAN_TO_JSVAL_IMPL(b);
   1.991 +    }
   1.992 +
   1.993 +    void setMagic(JSWhyMagic why) {
   1.994 +        data = MAGIC_TO_JSVAL_IMPL(why);
   1.995 +    }
   1.996 +
   1.997 +    void setMagicUint32(uint32_t payload) {
   1.998 +        data = MAGIC_UINT32_TO_JSVAL_IMPL(payload);
   1.999 +    }
  1.1000 +
  1.1001 +    bool setNumber(uint32_t ui) {
  1.1002 +        if (ui > JSVAL_INT_MAX) {
  1.1003 +            setDouble((double)ui);
  1.1004 +            return false;
  1.1005 +        } else {
  1.1006 +            setInt32((int32_t)ui);
  1.1007 +            return true;
  1.1008 +        }
  1.1009 +    }
  1.1010 +
  1.1011 +    bool setNumber(double d) {
  1.1012 +        int32_t i;
  1.1013 +        if (mozilla::NumberIsInt32(d, &i)) {
  1.1014 +            setInt32(i);
  1.1015 +            return true;
  1.1016 +        }
  1.1017 +
  1.1018 +        setDouble(d);
  1.1019 +        return false;
  1.1020 +    }
  1.1021 +
  1.1022 +    void setObjectOrNull(JSObject *arg) {
  1.1023 +        if (arg)
  1.1024 +            setObject(*arg);
  1.1025 +        else
  1.1026 +            setNull();
  1.1027 +    }
  1.1028 +
  1.1029 +    void swap(Value &rhs) {
  1.1030 +        uint64_t tmp = rhs.data.asBits;
  1.1031 +        rhs.data.asBits = data.asBits;
  1.1032 +        data.asBits = tmp;
  1.1033 +    }
  1.1034 +
  1.1035 +    /*** Value type queries ***/
  1.1036 +
  1.1037 +    bool isUndefined() const {
  1.1038 +        return JSVAL_IS_UNDEFINED_IMPL(data);
  1.1039 +    }
  1.1040 +
  1.1041 +    bool isNull() const {
  1.1042 +        return JSVAL_IS_NULL_IMPL(data);
  1.1043 +    }
  1.1044 +
  1.1045 +    bool isNullOrUndefined() const {
  1.1046 +        return isNull() || isUndefined();
  1.1047 +    }
  1.1048 +
  1.1049 +    bool isInt32() const {
  1.1050 +        return JSVAL_IS_INT32_IMPL(data);
  1.1051 +    }
  1.1052 +
  1.1053 +    bool isInt32(int32_t i32) const {
  1.1054 +        return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
  1.1055 +    }
  1.1056 +
  1.1057 +    bool isDouble() const {
  1.1058 +        return JSVAL_IS_DOUBLE_IMPL(data);
  1.1059 +    }
  1.1060 +
  1.1061 +    bool isNumber() const {
  1.1062 +        return JSVAL_IS_NUMBER_IMPL(data);
  1.1063 +    }
  1.1064 +
  1.1065 +    bool isString() const {
  1.1066 +        return JSVAL_IS_STRING_IMPL(data);
  1.1067 +    }
  1.1068 +
  1.1069 +    bool isObject() const {
  1.1070 +        return JSVAL_IS_OBJECT_IMPL(data);
  1.1071 +    }
  1.1072 +
  1.1073 +    bool isPrimitive() const {
  1.1074 +        return JSVAL_IS_PRIMITIVE_IMPL(data);
  1.1075 +    }
  1.1076 +
  1.1077 +    bool isObjectOrNull() const {
  1.1078 +        return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
  1.1079 +    }
  1.1080 +
  1.1081 +    bool isGCThing() const {
  1.1082 +        return JSVAL_IS_GCTHING_IMPL(data);
  1.1083 +    }
  1.1084 +
  1.1085 +    bool isBoolean() const {
  1.1086 +        return JSVAL_IS_BOOLEAN_IMPL(data);
  1.1087 +    }
  1.1088 +
  1.1089 +    bool isTrue() const {
  1.1090 +        return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
  1.1091 +    }
  1.1092 +
  1.1093 +    bool isFalse() const {
  1.1094 +        return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
  1.1095 +    }
  1.1096 +
  1.1097 +    bool isMagic() const {
  1.1098 +        return JSVAL_IS_MAGIC_IMPL(data);
  1.1099 +    }
  1.1100 +
  1.1101 +    bool isMagic(JSWhyMagic why) const {
  1.1102 +        MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
  1.1103 +        return JSVAL_IS_MAGIC_IMPL(data);
  1.1104 +    }
  1.1105 +
  1.1106 +    bool isMarkable() const {
  1.1107 +        return JSVAL_IS_TRACEABLE_IMPL(data);
  1.1108 +    }
  1.1109 +
  1.1110 +    JSGCTraceKind gcKind() const {
  1.1111 +        MOZ_ASSERT(isMarkable());
  1.1112 +        return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
  1.1113 +    }
  1.1114 +
  1.1115 +    JSWhyMagic whyMagic() const {
  1.1116 +        MOZ_ASSERT(isMagic());
  1.1117 +        return data.s.payload.why;
  1.1118 +    }
  1.1119 +
  1.1120 +    uint32_t magicUint32() const {
  1.1121 +        MOZ_ASSERT(isMagic());
  1.1122 +        return data.s.payload.u32;
  1.1123 +    }
  1.1124 +
  1.1125 +    /*** Comparison ***/
  1.1126 +
  1.1127 +    bool operator==(const Value &rhs) const {
  1.1128 +        return data.asBits == rhs.data.asBits;
  1.1129 +    }
  1.1130 +
  1.1131 +    bool operator!=(const Value &rhs) const {
  1.1132 +        return data.asBits != rhs.data.asBits;
  1.1133 +    }
  1.1134 +
  1.1135 +    friend inline bool SameType(const Value &lhs, const Value &rhs);
  1.1136 +
  1.1137 +    /*** Extract the value's typed payload ***/
  1.1138 +
  1.1139 +    int32_t toInt32() const {
  1.1140 +        MOZ_ASSERT(isInt32());
  1.1141 +        return JSVAL_TO_INT32_IMPL(data);
  1.1142 +    }
  1.1143 +
  1.1144 +    double toDouble() const {
  1.1145 +        MOZ_ASSERT(isDouble());
  1.1146 +        return data.asDouble;
  1.1147 +    }
  1.1148 +
  1.1149 +    double toNumber() const {
  1.1150 +        MOZ_ASSERT(isNumber());
  1.1151 +        return isDouble() ? toDouble() : double(toInt32());
  1.1152 +    }
  1.1153 +
  1.1154 +    JSString *toString() const {
  1.1155 +        MOZ_ASSERT(isString());
  1.1156 +        return JSVAL_TO_STRING_IMPL(data);
  1.1157 +    }
  1.1158 +
  1.1159 +    JSObject &toObject() const {
  1.1160 +        MOZ_ASSERT(isObject());
  1.1161 +        return *JSVAL_TO_OBJECT_IMPL(data);
  1.1162 +    }
  1.1163 +
  1.1164 +    JSObject *toObjectOrNull() const {
  1.1165 +        MOZ_ASSERT(isObjectOrNull());
  1.1166 +        return JSVAL_TO_OBJECT_IMPL(data);
  1.1167 +    }
  1.1168 +
  1.1169 +    void *toGCThing() const {
  1.1170 +        MOZ_ASSERT(isGCThing());
  1.1171 +        return JSVAL_TO_GCTHING_IMPL(data);
  1.1172 +    }
  1.1173 +
  1.1174 +    bool toBoolean() const {
  1.1175 +        MOZ_ASSERT(isBoolean());
  1.1176 +        return JSVAL_TO_BOOLEAN_IMPL(data);
  1.1177 +    }
  1.1178 +
  1.1179 +    uint32_t payloadAsRawUint32() const {
  1.1180 +        MOZ_ASSERT(!isDouble());
  1.1181 +        return data.s.payload.u32;
  1.1182 +    }
  1.1183 +
  1.1184 +    uint64_t asRawBits() const {
  1.1185 +        return data.asBits;
  1.1186 +    }
  1.1187 +
  1.1188 +    JSValueType extractNonDoubleType() const {
  1.1189 +        return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
  1.1190 +    }
  1.1191 +
  1.1192 +    /*
  1.1193 +     * Private API
  1.1194 +     *
  1.1195 +     * Private setters/getters allow the caller to read/write arbitrary types
  1.1196 +     * that fit in the 64-bit payload. It is the caller's responsibility, after
  1.1197 +     * storing to a value with setPrivateX to read only using getPrivateX.
  1.1198 +     * Privates values are given a type which ensures they are not marked.
  1.1199 +     */
  1.1200 +
  1.1201 +    void setPrivate(void *ptr) {
  1.1202 +        data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
  1.1203 +    }
  1.1204 +
  1.1205 +    void *toPrivate() const {
  1.1206 +        MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
  1.1207 +        return JSVAL_TO_PRIVATE_PTR_IMPL(data);
  1.1208 +    }
  1.1209 +
  1.1210 +    void setPrivateUint32(uint32_t ui) {
  1.1211 +        MOZ_ASSERT(uint32_t(int32_t(ui)) == ui);
  1.1212 +        setInt32(int32_t(ui));
  1.1213 +    }
  1.1214 +
  1.1215 +    uint32_t toPrivateUint32() const {
  1.1216 +        return uint32_t(toInt32());
  1.1217 +    }
  1.1218 +
  1.1219 +    /*
  1.1220 +     * An unmarked value is just a void* cast as a Value. Thus, the Value is
  1.1221 +     * not safe for GC and must not be marked. This API avoids raw casts
  1.1222 +     * and the ensuing strict-aliasing warnings.
  1.1223 +     */
  1.1224 +
  1.1225 +    void setUnmarkedPtr(void *ptr) {
  1.1226 +        data.asPtr = ptr;
  1.1227 +    }
  1.1228 +
  1.1229 +    void *toUnmarkedPtr() const {
  1.1230 +        return data.asPtr;
  1.1231 +    }
  1.1232 +
  1.1233 +    const size_t *payloadWord() const {
  1.1234 +#if JS_BITS_PER_WORD == 32
  1.1235 +        return &data.s.payload.word;
  1.1236 +#elif JS_BITS_PER_WORD == 64
  1.1237 +        return &data.asWord;
  1.1238 +#endif
  1.1239 +    }
  1.1240 +
  1.1241 +    const uintptr_t *payloadUIntPtr() const {
  1.1242 +#if JS_BITS_PER_WORD == 32
  1.1243 +        return &data.s.payload.uintptr;
  1.1244 +#elif JS_BITS_PER_WORD == 64
  1.1245 +        return &data.asUIntPtr;
  1.1246 +#endif
  1.1247 +    }
  1.1248 +
  1.1249 +#if !defined(_MSC_VER) && !defined(__sparc)
  1.1250 +  // Value must be POD so that MSVC will pass it by value and not in memory
  1.1251 +  // (bug 689101); the same is true for SPARC as well (bug 737344).  More
  1.1252 +  // precisely, we don't want Value return values compiled as out params.
  1.1253 +  private:
  1.1254 +#endif
  1.1255 +
  1.1256 +    jsval_layout data;
  1.1257 +
  1.1258 +  private:
  1.1259 +#if defined(JS_VALUE_IS_CONSTEXPR)
  1.1260 +    JS_VALUE_CONSTEXPR Value(jsval_layout layout) : data(layout) {}
  1.1261 +#endif
  1.1262 +
  1.1263 +    void staticAssertions() {
  1.1264 +        JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
  1.1265 +        JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
  1.1266 +        JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
  1.1267 +        JS_STATIC_ASSERT(sizeof(Value) == 8);
  1.1268 +    }
  1.1269 +
  1.1270 +    friend jsval_layout (::JSVAL_TO_IMPL)(Value);
  1.1271 +    friend Value JS_VALUE_CONSTEXPR (::IMPL_TO_JSVAL)(jsval_layout l);
  1.1272 +    friend Value JS_VALUE_CONSTEXPR (JS::UndefinedValue)();
  1.1273 +};
  1.1274 +
  1.1275 +inline bool
  1.1276 +IsPoisonedValue(const Value &v)
  1.1277 +{
  1.1278 +    if (v.isString())
  1.1279 +        return IsPoisonedPtr(v.toString());
  1.1280 +    if (v.isObject())
  1.1281 +        return IsPoisonedPtr(&v.toObject());
  1.1282 +    return false;
  1.1283 +}
  1.1284 +
  1.1285 +inline bool
  1.1286 +IsOptimizedPlaceholderMagicValue(const Value &v)
  1.1287 +{
  1.1288 +    if (v.isMagic()) {
  1.1289 +        MOZ_ASSERT(v.whyMagic() == JS_OPTIMIZED_ARGUMENTS || v.whyMagic() == JS_OPTIMIZED_OUT);
  1.1290 +        return true;
  1.1291 +    }
  1.1292 +    return false;
  1.1293 +}
  1.1294 +
  1.1295 +/************************************************************************/
  1.1296 +
  1.1297 +static inline Value
  1.1298 +NullValue()
  1.1299 +{
  1.1300 +    Value v;
  1.1301 +    v.setNull();
  1.1302 +    return v;
  1.1303 +}
  1.1304 +
  1.1305 +static inline JS_VALUE_CONSTEXPR Value
  1.1306 +UndefinedValue()
  1.1307 +{
  1.1308 +#if defined(JS_VALUE_IS_CONSTEXPR)
  1.1309 +    return Value(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
  1.1310 +#else
  1.1311 +    JS::Value v;
  1.1312 +    v.setUndefined();
  1.1313 +    return v;
  1.1314 +#endif
  1.1315 +}
  1.1316 +
  1.1317 +static inline Value
  1.1318 +Int32Value(int32_t i32)
  1.1319 +{
  1.1320 +    Value v;
  1.1321 +    v.setInt32(i32);
  1.1322 +    return v;
  1.1323 +}
  1.1324 +
  1.1325 +static inline Value
  1.1326 +DoubleValue(double dbl)
  1.1327 +{
  1.1328 +    Value v;
  1.1329 +    v.setDouble(dbl);
  1.1330 +    return v;
  1.1331 +}
  1.1332 +
  1.1333 +static inline Value
  1.1334 +DoubleNaNValue()
  1.1335 +{
  1.1336 +    Value v;
  1.1337 +    v.setNaN();
  1.1338 +    return v;
  1.1339 +}
  1.1340 +
  1.1341 +static inline Value
  1.1342 +Float32Value(float f)
  1.1343 +{
  1.1344 +    Value v;
  1.1345 +    v.setDouble(f);
  1.1346 +    return v;
  1.1347 +}
  1.1348 +
  1.1349 +static inline Value
  1.1350 +StringValue(JSString *str)
  1.1351 +{
  1.1352 +    Value v;
  1.1353 +    v.setString(str);
  1.1354 +    return v;
  1.1355 +}
  1.1356 +
  1.1357 +static inline Value
  1.1358 +BooleanValue(bool boo)
  1.1359 +{
  1.1360 +    Value v;
  1.1361 +    v.setBoolean(boo);
  1.1362 +    return v;
  1.1363 +}
  1.1364 +
  1.1365 +static inline Value
  1.1366 +TrueValue()
  1.1367 +{
  1.1368 +    Value v;
  1.1369 +    v.setBoolean(true);
  1.1370 +    return v;
  1.1371 +}
  1.1372 +
  1.1373 +static inline Value
  1.1374 +FalseValue()
  1.1375 +{
  1.1376 +    Value v;
  1.1377 +    v.setBoolean(false);
  1.1378 +    return v;
  1.1379 +}
  1.1380 +
  1.1381 +static inline Value
  1.1382 +ObjectValue(JSObject &obj)
  1.1383 +{
  1.1384 +    Value v;
  1.1385 +    v.setObject(obj);
  1.1386 +    return v;
  1.1387 +}
  1.1388 +
  1.1389 +static inline Value
  1.1390 +ObjectValueCrashOnTouch()
  1.1391 +{
  1.1392 +    Value v;
  1.1393 +    v.setObject(*reinterpret_cast<JSObject *>(0x42));
  1.1394 +    return v;
  1.1395 +}
  1.1396 +
  1.1397 +static inline Value
  1.1398 +MagicValue(JSWhyMagic why)
  1.1399 +{
  1.1400 +    Value v;
  1.1401 +    v.setMagic(why);
  1.1402 +    return v;
  1.1403 +}
  1.1404 +
  1.1405 +static inline Value
  1.1406 +MagicValueUint32(uint32_t payload)
  1.1407 +{
  1.1408 +    Value v;
  1.1409 +    v.setMagicUint32(payload);
  1.1410 +    return v;
  1.1411 +}
  1.1412 +
  1.1413 +static inline Value
  1.1414 +NumberValue(float f)
  1.1415 +{
  1.1416 +    Value v;
  1.1417 +    v.setNumber(f);
  1.1418 +    return v;
  1.1419 +}
  1.1420 +
  1.1421 +static inline Value
  1.1422 +NumberValue(double dbl)
  1.1423 +{
  1.1424 +    Value v;
  1.1425 +    v.setNumber(dbl);
  1.1426 +    return v;
  1.1427 +}
  1.1428 +
  1.1429 +static inline Value
  1.1430 +NumberValue(int8_t i)
  1.1431 +{
  1.1432 +    return Int32Value(i);
  1.1433 +}
  1.1434 +
  1.1435 +static inline Value
  1.1436 +NumberValue(uint8_t i)
  1.1437 +{
  1.1438 +    return Int32Value(i);
  1.1439 +}
  1.1440 +
  1.1441 +static inline Value
  1.1442 +NumberValue(int16_t i)
  1.1443 +{
  1.1444 +    return Int32Value(i);
  1.1445 +}
  1.1446 +
  1.1447 +static inline Value
  1.1448 +NumberValue(uint16_t i)
  1.1449 +{
  1.1450 +    return Int32Value(i);
  1.1451 +}
  1.1452 +
  1.1453 +static inline Value
  1.1454 +NumberValue(int32_t i)
  1.1455 +{
  1.1456 +    return Int32Value(i);
  1.1457 +}
  1.1458 +
  1.1459 +static inline Value
  1.1460 +NumberValue(uint32_t i)
  1.1461 +{
  1.1462 +    Value v;
  1.1463 +    v.setNumber(i);
  1.1464 +    return v;
  1.1465 +}
  1.1466 +
  1.1467 +namespace detail {
  1.1468 +
  1.1469 +template <bool Signed>
  1.1470 +class MakeNumberValue
  1.1471 +{
  1.1472 +  public:
  1.1473 +    template<typename T>
  1.1474 +    static inline Value create(const T t)
  1.1475 +    {
  1.1476 +        Value v;
  1.1477 +        if (JSVAL_INT_MIN <= t && t <= JSVAL_INT_MAX)
  1.1478 +            v.setInt32(int32_t(t));
  1.1479 +        else
  1.1480 +            v.setDouble(double(t));
  1.1481 +        return v;
  1.1482 +    }
  1.1483 +};
  1.1484 +
  1.1485 +template <>
  1.1486 +class MakeNumberValue<false>
  1.1487 +{
  1.1488 +  public:
  1.1489 +    template<typename T>
  1.1490 +    static inline Value create(const T t)
  1.1491 +    {
  1.1492 +        Value v;
  1.1493 +        if (t <= JSVAL_INT_MAX)
  1.1494 +            v.setInt32(int32_t(t));
  1.1495 +        else
  1.1496 +            v.setDouble(double(t));
  1.1497 +        return v;
  1.1498 +    }
  1.1499 +};
  1.1500 +
  1.1501 +} // namespace detail
  1.1502 +
  1.1503 +template <typename T>
  1.1504 +static inline Value
  1.1505 +NumberValue(const T t)
  1.1506 +{
  1.1507 +    MOZ_ASSERT(T(double(t)) == t, "value creation would be lossy");
  1.1508 +    return detail::MakeNumberValue<std::numeric_limits<T>::is_signed>::create(t);
  1.1509 +}
  1.1510 +
  1.1511 +static inline Value
  1.1512 +ObjectOrNullValue(JSObject *obj)
  1.1513 +{
  1.1514 +    Value v;
  1.1515 +    v.setObjectOrNull(obj);
  1.1516 +    return v;
  1.1517 +}
  1.1518 +
  1.1519 +static inline Value
  1.1520 +PrivateValue(void *ptr)
  1.1521 +{
  1.1522 +    Value v;
  1.1523 +    v.setPrivate(ptr);
  1.1524 +    return v;
  1.1525 +}
  1.1526 +
  1.1527 +static inline Value
  1.1528 +PrivateUint32Value(uint32_t ui)
  1.1529 +{
  1.1530 +    Value v;
  1.1531 +    v.setPrivateUint32(ui);
  1.1532 +    return v;
  1.1533 +}
  1.1534 +
  1.1535 +inline bool
  1.1536 +SameType(const Value &lhs, const Value &rhs)
  1.1537 +{
  1.1538 +    return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
  1.1539 +}
  1.1540 +
  1.1541 +} // namespace JS
  1.1542 +
  1.1543 +/************************************************************************/
  1.1544 +
  1.1545 +#ifdef JSGC_GENERATIONAL
  1.1546 +namespace JS {
  1.1547 +JS_PUBLIC_API(void) HeapValuePostBarrier(Value *valuep);
  1.1548 +JS_PUBLIC_API(void) HeapValueRelocate(Value *valuep);
  1.1549 +}
  1.1550 +#endif
  1.1551 +
  1.1552 +namespace js {
  1.1553 +
  1.1554 +template <> struct GCMethods<const JS::Value>
  1.1555 +{
  1.1556 +    static JS::Value initial() { return JS::UndefinedValue(); }
  1.1557 +    static ThingRootKind kind() { return THING_ROOT_VALUE; }
  1.1558 +    static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
  1.1559 +};
  1.1560 +
  1.1561 +template <> struct GCMethods<JS::Value>
  1.1562 +{
  1.1563 +    static JS::Value initial() { return JS::UndefinedValue(); }
  1.1564 +    static ThingRootKind kind() { return THING_ROOT_VALUE; }
  1.1565 +    static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
  1.1566 +    static bool needsPostBarrier(const JS::Value &v) { return v.isMarkable(); }
  1.1567 +#ifdef JSGC_GENERATIONAL
  1.1568 +    static void postBarrier(JS::Value *v) { JS::HeapValuePostBarrier(v); }
  1.1569 +    static void relocate(JS::Value *v) { JS::HeapValueRelocate(v); }
  1.1570 +#endif
  1.1571 +};
  1.1572 +
  1.1573 +template <class Outer> class MutableValueOperations;
  1.1574 +
  1.1575 +/*
  1.1576 + * A class designed for CRTP use in implementing the non-mutating parts of the
  1.1577 + * Value interface in Value-like classes.  Outer must be a class inheriting
  1.1578 + * ValueOperations<Outer> with a visible extract() method returning the
  1.1579 + * const Value* abstracted by Outer.
  1.1580 + */
  1.1581 +template <class Outer>
  1.1582 +class ValueOperations
  1.1583 +{
  1.1584 +    friend class MutableValueOperations<Outer>;
  1.1585 +
  1.1586 +    const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
  1.1587 +
  1.1588 +  public:
  1.1589 +    bool isUndefined() const { return value()->isUndefined(); }
  1.1590 +    bool isNull() const { return value()->isNull(); }
  1.1591 +    bool isBoolean() const { return value()->isBoolean(); }
  1.1592 +    bool isTrue() const { return value()->isTrue(); }
  1.1593 +    bool isFalse() const { return value()->isFalse(); }
  1.1594 +    bool isNumber() const { return value()->isNumber(); }
  1.1595 +    bool isInt32() const { return value()->isInt32(); }
  1.1596 +    bool isDouble() const { return value()->isDouble(); }
  1.1597 +    bool isString() const { return value()->isString(); }
  1.1598 +    bool isObject() const { return value()->isObject(); }
  1.1599 +    bool isMagic() const { return value()->isMagic(); }
  1.1600 +    bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
  1.1601 +    bool isMarkable() const { return value()->isMarkable(); }
  1.1602 +    bool isPrimitive() const { return value()->isPrimitive(); }
  1.1603 +    bool isGCThing() const { return value()->isGCThing(); }
  1.1604 +
  1.1605 +    bool isNullOrUndefined() const { return value()->isNullOrUndefined(); }
  1.1606 +    bool isObjectOrNull() const { return value()->isObjectOrNull(); }
  1.1607 +
  1.1608 +    bool toBoolean() const { return value()->toBoolean(); }
  1.1609 +    double toNumber() const { return value()->toNumber(); }
  1.1610 +    int32_t toInt32() const { return value()->toInt32(); }
  1.1611 +    double toDouble() const { return value()->toDouble(); }
  1.1612 +    JSString *toString() const { return value()->toString(); }
  1.1613 +    JSObject &toObject() const { return value()->toObject(); }
  1.1614 +    JSObject *toObjectOrNull() const { return value()->toObjectOrNull(); }
  1.1615 +    void *toGCThing() const { return value()->toGCThing(); }
  1.1616 +
  1.1617 +    JSValueType extractNonDoubleType() const { return value()->extractNonDoubleType(); }
  1.1618 +    uint32_t toPrivateUint32() const { return value()->toPrivateUint32(); }
  1.1619 +
  1.1620 +    JSWhyMagic whyMagic() const { return value()->whyMagic(); }
  1.1621 +    uint32_t magicUint32() const { return value()->magicUint32(); }
  1.1622 +};
  1.1623 +
  1.1624 +/*
  1.1625 + * A class designed for CRTP use in implementing all the mutating parts of the
  1.1626 + * Value interface in Value-like classes.  Outer must be a class inheriting
  1.1627 + * MutableValueOperations<Outer> with visible extractMutable() and extract()
  1.1628 + * methods returning the const Value* and Value* abstracted by Outer.
  1.1629 + */
  1.1630 +template <class Outer>
  1.1631 +class MutableValueOperations : public ValueOperations<Outer>
  1.1632 +{
  1.1633 +    JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
  1.1634 +
  1.1635 +  public:
  1.1636 +    void setNull() { value()->setNull(); }
  1.1637 +    void setUndefined() { value()->setUndefined(); }
  1.1638 +    void setInt32(int32_t i) { value()->setInt32(i); }
  1.1639 +    void setDouble(double d) { value()->setDouble(d); }
  1.1640 +    void setNaN() { setDouble(JS::GenericNaN()); }
  1.1641 +    void setBoolean(bool b) { value()->setBoolean(b); }
  1.1642 +    void setMagic(JSWhyMagic why) { value()->setMagic(why); }
  1.1643 +    bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
  1.1644 +    bool setNumber(double d) { return value()->setNumber(d); }
  1.1645 +    void setString(JSString *str) { this->value()->setString(str); }
  1.1646 +    void setObject(JSObject &obj) { this->value()->setObject(obj); }
  1.1647 +    void setObjectOrNull(JSObject *arg) { this->value()->setObjectOrNull(arg); }
  1.1648 +};
  1.1649 +
  1.1650 +/*
  1.1651 + * Augment the generic Heap<T> interface when T = Value with
  1.1652 + * type-querying, value-extracting, and mutating operations.
  1.1653 + */
  1.1654 +template <>
  1.1655 +class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
  1.1656 +{
  1.1657 +    typedef JS::Heap<JS::Value> Outer;
  1.1658 +
  1.1659 +    friend class ValueOperations<Outer>;
  1.1660 +
  1.1661 +    const JS::Value * extract() const { return static_cast<const Outer*>(this)->address(); }
  1.1662 +
  1.1663 +    void setBarriered(const JS::Value &v) {
  1.1664 +        static_cast<JS::Heap<JS::Value> *>(this)->set(v);
  1.1665 +    }
  1.1666 +
  1.1667 +  public:
  1.1668 +    void setNull() { setBarriered(JS::NullValue()); }
  1.1669 +    void setUndefined() { setBarriered(JS::UndefinedValue()); }
  1.1670 +    void setInt32(int32_t i) { setBarriered(JS::Int32Value(i)); }
  1.1671 +    void setDouble(double d) { setBarriered(JS::DoubleValue(d)); }
  1.1672 +    void setNaN() { setDouble(JS::GenericNaN()); }
  1.1673 +    void setBoolean(bool b) { setBarriered(JS::BooleanValue(b)); }
  1.1674 +    void setMagic(JSWhyMagic why) { setBarriered(JS::MagicValue(why)); }
  1.1675 +    void setString(JSString *str) { setBarriered(JS::StringValue(str)); }
  1.1676 +    void setObject(JSObject &obj) { setBarriered(JS::ObjectValue(obj)); }
  1.1677 +
  1.1678 +    bool setNumber(uint32_t ui) {
  1.1679 +        if (ui > JSVAL_INT_MAX) {
  1.1680 +            setDouble((double)ui);
  1.1681 +            return false;
  1.1682 +        } else {
  1.1683 +            setInt32((int32_t)ui);
  1.1684 +            return true;
  1.1685 +        }
  1.1686 +    }
  1.1687 +
  1.1688 +    bool setNumber(double d) {
  1.1689 +        int32_t i;
  1.1690 +        if (mozilla::NumberIsInt32(d, &i)) {
  1.1691 +            setInt32(i);
  1.1692 +            return true;
  1.1693 +        }
  1.1694 +
  1.1695 +        setDouble(d);
  1.1696 +        return false;
  1.1697 +    }
  1.1698 +
  1.1699 +    void setObjectOrNull(JSObject *arg) {
  1.1700 +        if (arg)
  1.1701 +            setObject(*arg);
  1.1702 +        else
  1.1703 +            setNull();
  1.1704 +    }
  1.1705 +};
  1.1706 +
  1.1707 +/*
  1.1708 + * Augment the generic Handle<T> interface when T = Value with type-querying
  1.1709 + * and value-extracting operations.
  1.1710 + */
  1.1711 +template <>
  1.1712 +class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> >
  1.1713 +{
  1.1714 +    friend class ValueOperations<JS::Handle<JS::Value> >;
  1.1715 +    const JS::Value * extract() const {
  1.1716 +        return static_cast<const JS::Handle<JS::Value>*>(this)->address();
  1.1717 +    }
  1.1718 +};
  1.1719 +
  1.1720 +/*
  1.1721 + * Augment the generic MutableHandle<T> interface when T = Value with
  1.1722 + * type-querying, value-extracting, and mutating operations.
  1.1723 + */
  1.1724 +template <>
  1.1725 +class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> >
  1.1726 +{
  1.1727 +    friend class ValueOperations<JS::MutableHandle<JS::Value> >;
  1.1728 +    const JS::Value * extract() const {
  1.1729 +        return static_cast<const JS::MutableHandle<JS::Value>*>(this)->address();
  1.1730 +    }
  1.1731 +
  1.1732 +    friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
  1.1733 +    JS::Value * extractMutable() {
  1.1734 +        return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
  1.1735 +    }
  1.1736 +};
  1.1737 +
  1.1738 +/*
  1.1739 + * Augment the generic Rooted<T> interface when T = Value with type-querying,
  1.1740 + * value-extracting, and mutating operations.
  1.1741 + */
  1.1742 +template <>
  1.1743 +class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> >
  1.1744 +{
  1.1745 +    friend class ValueOperations<JS::Rooted<JS::Value> >;
  1.1746 +    const JS::Value * extract() const {
  1.1747 +        return static_cast<const JS::Rooted<JS::Value>*>(this)->address();
  1.1748 +    }
  1.1749 +
  1.1750 +    friend class MutableValueOperations<JS::Rooted<JS::Value> >;
  1.1751 +    JS::Value * extractMutable() {
  1.1752 +        return static_cast<JS::Rooted<JS::Value>*>(this)->address();
  1.1753 +    }
  1.1754 +};
  1.1755 +
  1.1756 +} // namespace js
  1.1757 +
  1.1758 +inline jsval_layout
  1.1759 +JSVAL_TO_IMPL(JS::Value v)
  1.1760 +{
  1.1761 +    return v.data;
  1.1762 +}
  1.1763 +
  1.1764 +inline JS_VALUE_CONSTEXPR JS::Value
  1.1765 +IMPL_TO_JSVAL(jsval_layout l)
  1.1766 +{
  1.1767 +#if defined(JS_VALUE_IS_CONSTEXPR)
  1.1768 +    return JS::Value(l);
  1.1769 +#else
  1.1770 +    JS::Value v;
  1.1771 +    v.data = l;
  1.1772 +    return v;
  1.1773 +#endif
  1.1774 +}
  1.1775 +
  1.1776 +namespace JS {
  1.1777 +
  1.1778 +#ifndef __GNUC__
  1.1779 +/*
  1.1780 + * The default assignment operator for |struct C| has the signature:
  1.1781 + *
  1.1782 + *   C& C::operator=(const C&)
  1.1783 + *
  1.1784 + * And in particular requires implicit conversion of |this| to type |C| for the
  1.1785 + * return value. But |volatile C| cannot thus be converted to |C|, so just
  1.1786 + * doing |sink = hold| as in the non-specialized version would fail to compile.
  1.1787 + * Do the assignment on asBits instead, since I don't think we want to give
  1.1788 + * jsval_layout an assignment operator returning |volatile jsval_layout|.
  1.1789 + */
  1.1790 +template<>
  1.1791 +inline Anchor<Value>::~Anchor()
  1.1792 +{
  1.1793 +    volatile uint64_t bits;
  1.1794 +    bits = JSVAL_TO_IMPL(hold).asBits;
  1.1795 +}
  1.1796 +#endif
  1.1797 +
  1.1798 +#ifdef JS_DEBUG
  1.1799 +namespace detail {
  1.1800 +
  1.1801 +struct ValueAlignmentTester { char c; JS::Value v; };
  1.1802 +static_assert(sizeof(ValueAlignmentTester) == 16,
  1.1803 +              "JS::Value must be 16-byte-aligned");
  1.1804 +
  1.1805 +struct LayoutAlignmentTester { char c; jsval_layout l; };
  1.1806 +static_assert(sizeof(LayoutAlignmentTester) == 16,
  1.1807 +              "jsval_layout must be 16-byte-aligned");
  1.1808 +
  1.1809 +} // namespace detail
  1.1810 +#endif /* JS_DEBUG */
  1.1811 +
  1.1812 +} // namespace JS
  1.1813 +
  1.1814 +/*
  1.1815 + * JS::Value and jsval are the same type; jsval is the old name, kept around
  1.1816 + * for backwards compatibility along with all the JSVAL_* operations below.
  1.1817 + * jsval_layout is an implementation detail and should not be used externally.
  1.1818 + */
  1.1819 +typedef JS::Value jsval;
  1.1820 +
  1.1821 +static_assert(sizeof(jsval_layout) == sizeof(JS::Value),
  1.1822 +              "jsval_layout and JS::Value must have identical layouts");
  1.1823 +
  1.1824 +/************************************************************************/
  1.1825 +
  1.1826 +static inline bool
  1.1827 +JSVAL_IS_NULL(jsval v)
  1.1828 +{
  1.1829 +    return JSVAL_IS_NULL_IMPL(JSVAL_TO_IMPL(v));
  1.1830 +}
  1.1831 +
  1.1832 +static inline bool
  1.1833 +JSVAL_IS_VOID(jsval v)
  1.1834 +{
  1.1835 +    return JSVAL_IS_UNDEFINED_IMPL(JSVAL_TO_IMPL(v));
  1.1836 +}
  1.1837 +
  1.1838 +static inline bool
  1.1839 +JSVAL_IS_INT(jsval v)
  1.1840 +{
  1.1841 +    return JSVAL_IS_INT32_IMPL(JSVAL_TO_IMPL(v));
  1.1842 +}
  1.1843 +
  1.1844 +static inline int32_t
  1.1845 +JSVAL_TO_INT(jsval v)
  1.1846 +{
  1.1847 +    MOZ_ASSERT(JSVAL_IS_INT(v));
  1.1848 +    return JSVAL_TO_INT32_IMPL(JSVAL_TO_IMPL(v));
  1.1849 +}
  1.1850 +
  1.1851 +static inline JS_VALUE_CONSTEXPR jsval
  1.1852 +INT_TO_JSVAL(int32_t i)
  1.1853 +{
  1.1854 +    return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i));
  1.1855 +}
  1.1856 +
  1.1857 +static inline bool
  1.1858 +JSVAL_IS_DOUBLE(jsval v)
  1.1859 +{
  1.1860 +    return JSVAL_IS_DOUBLE_IMPL(JSVAL_TO_IMPL(v));
  1.1861 +}
  1.1862 +
  1.1863 +static inline double
  1.1864 +JSVAL_TO_DOUBLE(jsval v)
  1.1865 +{
  1.1866 +    jsval_layout l;
  1.1867 +    MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
  1.1868 +    l = JSVAL_TO_IMPL(v);
  1.1869 +    return l.asDouble;
  1.1870 +}
  1.1871 +
  1.1872 +static inline JS_VALUE_CONSTEXPR jsval
  1.1873 +DOUBLE_TO_JSVAL(double d)
  1.1874 +{
  1.1875 +    /*
  1.1876 +     * This is a manually inlined version of:
  1.1877 +     *    d = JS_CANONICALIZE_NAN(d);
  1.1878 +     *    return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
  1.1879 +     * because GCC from XCode 3.1.4 miscompiles the above code.
  1.1880 +     */
  1.1881 +#if defined(JS_VALUE_IS_CONSTEXPR)
  1.1882 +    return IMPL_TO_JSVAL(MOZ_UNLIKELY(d != d)
  1.1883 +                         ? (jsval_layout) { .asBits = 0x7FF8000000000000LL }
  1.1884 +                         : (jsval_layout) { .asDouble = d });
  1.1885 +#else
  1.1886 +    jsval_layout l;
  1.1887 +    if (MOZ_UNLIKELY(d != d))
  1.1888 +        l.asBits = 0x7FF8000000000000LL;
  1.1889 +    else
  1.1890 +        l.asDouble = d;
  1.1891 +    return IMPL_TO_JSVAL(l);
  1.1892 +#endif
  1.1893 +}
  1.1894 +
  1.1895 +static inline JS_VALUE_CONSTEXPR jsval
  1.1896 +UINT_TO_JSVAL(uint32_t i)
  1.1897 +{
  1.1898 +    return (i <= JSVAL_INT_MAX
  1.1899 +            ? INT_TO_JSVAL((int32_t)i)
  1.1900 +            : DOUBLE_TO_JSVAL((double)i));
  1.1901 +}
  1.1902 +
  1.1903 +static inline bool
  1.1904 +JSVAL_IS_NUMBER(jsval v)
  1.1905 +{
  1.1906 +    return JSVAL_IS_NUMBER_IMPL(JSVAL_TO_IMPL(v));
  1.1907 +}
  1.1908 +
  1.1909 +static inline bool
  1.1910 +JSVAL_IS_STRING(jsval v)
  1.1911 +{
  1.1912 +    return JSVAL_IS_STRING_IMPL(JSVAL_TO_IMPL(v));
  1.1913 +}
  1.1914 +
  1.1915 +static inline JSString *
  1.1916 +JSVAL_TO_STRING(jsval v)
  1.1917 +{
  1.1918 +    MOZ_ASSERT(JSVAL_IS_STRING(v));
  1.1919 +    return JSVAL_TO_STRING_IMPL(JSVAL_TO_IMPL(v));
  1.1920 +}
  1.1921 +
  1.1922 +static inline jsval
  1.1923 +STRING_TO_JSVAL(JSString *str)
  1.1924 +{
  1.1925 +    return IMPL_TO_JSVAL(STRING_TO_JSVAL_IMPL(str));
  1.1926 +}
  1.1927 +
  1.1928 +static inline JSObject *
  1.1929 +JSVAL_TO_OBJECT(jsval v)
  1.1930 +{
  1.1931 +    MOZ_ASSERT(JSVAL_IS_OBJECT_OR_NULL_IMPL(JSVAL_TO_IMPL(v)));
  1.1932 +    return JSVAL_TO_OBJECT_IMPL(JSVAL_TO_IMPL(v));
  1.1933 +}
  1.1934 +
  1.1935 +static inline jsval
  1.1936 +OBJECT_TO_JSVAL(JSObject *obj)
  1.1937 +{
  1.1938 +    if (obj)
  1.1939 +        return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(obj));
  1.1940 +    return IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
  1.1941 +}
  1.1942 +
  1.1943 +static inline bool
  1.1944 +JSVAL_IS_BOOLEAN(jsval v)
  1.1945 +{
  1.1946 +    return JSVAL_IS_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
  1.1947 +}
  1.1948 +
  1.1949 +static inline bool
  1.1950 +JSVAL_TO_BOOLEAN(jsval v)
  1.1951 +{
  1.1952 +    MOZ_ASSERT(JSVAL_IS_BOOLEAN(v));
  1.1953 +    return JSVAL_TO_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
  1.1954 +}
  1.1955 +
  1.1956 +static inline jsval
  1.1957 +BOOLEAN_TO_JSVAL(bool b)
  1.1958 +{
  1.1959 +    return IMPL_TO_JSVAL(BOOLEAN_TO_JSVAL_IMPL(b));
  1.1960 +}
  1.1961 +
  1.1962 +static inline bool
  1.1963 +JSVAL_IS_PRIMITIVE(jsval v)
  1.1964 +{
  1.1965 +    return JSVAL_IS_PRIMITIVE_IMPL(JSVAL_TO_IMPL(v));
  1.1966 +}
  1.1967 +
  1.1968 +static inline bool
  1.1969 +JSVAL_IS_GCTHING(jsval v)
  1.1970 +{
  1.1971 +    return JSVAL_IS_GCTHING_IMPL(JSVAL_TO_IMPL(v));
  1.1972 +}
  1.1973 +
  1.1974 +static inline void *
  1.1975 +JSVAL_TO_GCTHING(jsval v)
  1.1976 +{
  1.1977 +    MOZ_ASSERT(JSVAL_IS_GCTHING(v));
  1.1978 +    return JSVAL_TO_GCTHING_IMPL(JSVAL_TO_IMPL(v));
  1.1979 +}
  1.1980 +
  1.1981 +/* To be GC-safe, privates are tagged as doubles. */
  1.1982 +
  1.1983 +static inline jsval
  1.1984 +PRIVATE_TO_JSVAL(void *ptr)
  1.1985 +{
  1.1986 +    return IMPL_TO_JSVAL(PRIVATE_PTR_TO_JSVAL_IMPL(ptr));
  1.1987 +}
  1.1988 +
  1.1989 +static inline void *
  1.1990 +JSVAL_TO_PRIVATE(jsval v)
  1.1991 +{
  1.1992 +    MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
  1.1993 +    return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
  1.1994 +}
  1.1995 +
  1.1996 +// JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and
  1.1997 +// constructing values from scratch (e.g. Int32Value(0)).  These constants are
  1.1998 +// stored in memory and initialized at startup, so testing against them and
  1.1999 +// using them requires memory loads and will be correspondingly slow.
  1.2000 +extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
  1.2001 +extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
  1.2002 +extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
  1.2003 +extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
  1.2004 +extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
  1.2005 +extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
  1.2006 +
  1.2007 +namespace JS {
  1.2008 +
  1.2009 +extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue;
  1.2010 +extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
  1.2011 +
  1.2012 +}
  1.2013 +
  1.2014 +#undef JS_VALUE_IS_CONSTEXPR
  1.2015 +#undef JS_RETURN_LAYOUT_FROM_BITS
  1.2016 +
  1.2017 +#endif /* js_Value_h */

mercurial