js/public/Value.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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;
  1008     bool setNumber(double d) {
  1009         int32_t i;
  1010         if (mozilla::NumberIsInt32(d, &i)) {
  1011             setInt32(i);
  1012             return true;
  1015         setDouble(d);
  1016         return false;
  1019     void setObjectOrNull(JSObject *arg) {
  1020         if (arg)
  1021             setObject(*arg);
  1022         else
  1023             setNull();
  1026     void swap(Value &rhs) {
  1027         uint64_t tmp = rhs.data.asBits;
  1028         rhs.data.asBits = data.asBits;
  1029         data.asBits = tmp;
  1032     /*** Value type queries ***/
  1034     bool isUndefined() const {
  1035         return JSVAL_IS_UNDEFINED_IMPL(data);
  1038     bool isNull() const {
  1039         return JSVAL_IS_NULL_IMPL(data);
  1042     bool isNullOrUndefined() const {
  1043         return isNull() || isUndefined();
  1046     bool isInt32() const {
  1047         return JSVAL_IS_INT32_IMPL(data);
  1050     bool isInt32(int32_t i32) const {
  1051         return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
  1054     bool isDouble() const {
  1055         return JSVAL_IS_DOUBLE_IMPL(data);
  1058     bool isNumber() const {
  1059         return JSVAL_IS_NUMBER_IMPL(data);
  1062     bool isString() const {
  1063         return JSVAL_IS_STRING_IMPL(data);
  1066     bool isObject() const {
  1067         return JSVAL_IS_OBJECT_IMPL(data);
  1070     bool isPrimitive() const {
  1071         return JSVAL_IS_PRIMITIVE_IMPL(data);
  1074     bool isObjectOrNull() const {
  1075         return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
  1078     bool isGCThing() const {
  1079         return JSVAL_IS_GCTHING_IMPL(data);
  1082     bool isBoolean() const {
  1083         return JSVAL_IS_BOOLEAN_IMPL(data);
  1086     bool isTrue() const {
  1087         return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
  1090     bool isFalse() const {
  1091         return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
  1094     bool isMagic() const {
  1095         return JSVAL_IS_MAGIC_IMPL(data);
  1098     bool isMagic(JSWhyMagic why) const {
  1099         MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
  1100         return JSVAL_IS_MAGIC_IMPL(data);
  1103     bool isMarkable() const {
  1104         return JSVAL_IS_TRACEABLE_IMPL(data);
  1107     JSGCTraceKind gcKind() const {
  1108         MOZ_ASSERT(isMarkable());
  1109         return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
  1112     JSWhyMagic whyMagic() const {
  1113         MOZ_ASSERT(isMagic());
  1114         return data.s.payload.why;
  1117     uint32_t magicUint32() const {
  1118         MOZ_ASSERT(isMagic());
  1119         return data.s.payload.u32;
  1122     /*** Comparison ***/
  1124     bool operator==(const Value &rhs) const {
  1125         return data.asBits == rhs.data.asBits;
  1128     bool operator!=(const Value &rhs) const {
  1129         return data.asBits != rhs.data.asBits;
  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);
  1141     double toDouble() const {
  1142         MOZ_ASSERT(isDouble());
  1143         return data.asDouble;
  1146     double toNumber() const {
  1147         MOZ_ASSERT(isNumber());
  1148         return isDouble() ? toDouble() : double(toInt32());
  1151     JSString *toString() const {
  1152         MOZ_ASSERT(isString());
  1153         return JSVAL_TO_STRING_IMPL(data);
  1156     JSObject &toObject() const {
  1157         MOZ_ASSERT(isObject());
  1158         return *JSVAL_TO_OBJECT_IMPL(data);
  1161     JSObject *toObjectOrNull() const {
  1162         MOZ_ASSERT(isObjectOrNull());
  1163         return JSVAL_TO_OBJECT_IMPL(data);
  1166     void *toGCThing() const {
  1167         MOZ_ASSERT(isGCThing());
  1168         return JSVAL_TO_GCTHING_IMPL(data);
  1171     bool toBoolean() const {
  1172         MOZ_ASSERT(isBoolean());
  1173         return JSVAL_TO_BOOLEAN_IMPL(data);
  1176     uint32_t payloadAsRawUint32() const {
  1177         MOZ_ASSERT(!isDouble());
  1178         return data.s.payload.u32;
  1181     uint64_t asRawBits() const {
  1182         return data.asBits;
  1185     JSValueType extractNonDoubleType() const {
  1186         return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
  1189     /*
  1190      * Private API
  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);
  1202     void *toPrivate() const {
  1203         MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
  1204         return JSVAL_TO_PRIVATE_PTR_IMPL(data);
  1207     void setPrivateUint32(uint32_t ui) {
  1208         MOZ_ASSERT(uint32_t(int32_t(ui)) == ui);
  1209         setInt32(int32_t(ui));
  1212     uint32_t toPrivateUint32() const {
  1213         return uint32_t(toInt32());
  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;
  1226     void *toUnmarkedPtr() const {
  1227         return data.asPtr;
  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
  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
  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);
  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)
  1275     if (v.isString())
  1276         return IsPoisonedPtr(v.toString());
  1277     if (v.isObject())
  1278         return IsPoisonedPtr(&v.toObject());
  1279     return false;
  1282 inline bool
  1283 IsOptimizedPlaceholderMagicValue(const Value &v)
  1285     if (v.isMagic()) {
  1286         MOZ_ASSERT(v.whyMagic() == JS_OPTIMIZED_ARGUMENTS || v.whyMagic() == JS_OPTIMIZED_OUT);
  1287         return true;
  1289     return false;
  1292 /************************************************************************/
  1294 static inline Value
  1295 NullValue()
  1297     Value v;
  1298     v.setNull();
  1299     return v;
  1302 static inline JS_VALUE_CONSTEXPR Value
  1303 UndefinedValue()
  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
  1314 static inline Value
  1315 Int32Value(int32_t i32)
  1317     Value v;
  1318     v.setInt32(i32);
  1319     return v;
  1322 static inline Value
  1323 DoubleValue(double dbl)
  1325     Value v;
  1326     v.setDouble(dbl);
  1327     return v;
  1330 static inline Value
  1331 DoubleNaNValue()
  1333     Value v;
  1334     v.setNaN();
  1335     return v;
  1338 static inline Value
  1339 Float32Value(float f)
  1341     Value v;
  1342     v.setDouble(f);
  1343     return v;
  1346 static inline Value
  1347 StringValue(JSString *str)
  1349     Value v;
  1350     v.setString(str);
  1351     return v;
  1354 static inline Value
  1355 BooleanValue(bool boo)
  1357     Value v;
  1358     v.setBoolean(boo);
  1359     return v;
  1362 static inline Value
  1363 TrueValue()
  1365     Value v;
  1366     v.setBoolean(true);
  1367     return v;
  1370 static inline Value
  1371 FalseValue()
  1373     Value v;
  1374     v.setBoolean(false);
  1375     return v;
  1378 static inline Value
  1379 ObjectValue(JSObject &obj)
  1381     Value v;
  1382     v.setObject(obj);
  1383     return v;
  1386 static inline Value
  1387 ObjectValueCrashOnTouch()
  1389     Value v;
  1390     v.setObject(*reinterpret_cast<JSObject *>(0x42));
  1391     return v;
  1394 static inline Value
  1395 MagicValue(JSWhyMagic why)
  1397     Value v;
  1398     v.setMagic(why);
  1399     return v;
  1402 static inline Value
  1403 MagicValueUint32(uint32_t payload)
  1405     Value v;
  1406     v.setMagicUint32(payload);
  1407     return v;
  1410 static inline Value
  1411 NumberValue(float f)
  1413     Value v;
  1414     v.setNumber(f);
  1415     return v;
  1418 static inline Value
  1419 NumberValue(double dbl)
  1421     Value v;
  1422     v.setNumber(dbl);
  1423     return v;
  1426 static inline Value
  1427 NumberValue(int8_t i)
  1429     return Int32Value(i);
  1432 static inline Value
  1433 NumberValue(uint8_t i)
  1435     return Int32Value(i);
  1438 static inline Value
  1439 NumberValue(int16_t i)
  1441     return Int32Value(i);
  1444 static inline Value
  1445 NumberValue(uint16_t i)
  1447     return Int32Value(i);
  1450 static inline Value
  1451 NumberValue(int32_t i)
  1453     return Int32Value(i);
  1456 static inline Value
  1457 NumberValue(uint32_t i)
  1459     Value v;
  1460     v.setNumber(i);
  1461     return v;
  1464 namespace detail {
  1466 template <bool Signed>
  1467 class MakeNumberValue
  1469   public:
  1470     template<typename T>
  1471     static inline Value create(const T t)
  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;
  1480 };
  1482 template <>
  1483 class MakeNumberValue<false>
  1485   public:
  1486     template<typename T>
  1487     static inline Value create(const T t)
  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;
  1496 };
  1498 } // namespace detail
  1500 template <typename T>
  1501 static inline Value
  1502 NumberValue(const T t)
  1504     MOZ_ASSERT(T(double(t)) == t, "value creation would be lossy");
  1505     return detail::MakeNumberValue<std::numeric_limits<T>::is_signed>::create(t);
  1508 static inline Value
  1509 ObjectOrNullValue(JSObject *obj)
  1511     Value v;
  1512     v.setObjectOrNull(obj);
  1513     return v;
  1516 static inline Value
  1517 PrivateValue(void *ptr)
  1519     Value v;
  1520     v.setPrivate(ptr);
  1521     return v;
  1524 static inline Value
  1525 PrivateUint32Value(uint32_t ui)
  1527     Value v;
  1528     v.setPrivateUint32(ui);
  1529     return v;
  1532 inline bool
  1533 SameType(const Value &lhs, const Value &rhs)
  1535     return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
  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);
  1547 #endif
  1549 namespace js {
  1551 template <> struct GCMethods<const JS::Value>
  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>
  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
  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>
  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> >
  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);
  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;
  1685     bool setNumber(double d) {
  1686         int32_t i;
  1687         if (mozilla::NumberIsInt32(d, &i)) {
  1688             setInt32(i);
  1689             return true;
  1692         setDouble(d);
  1693         return false;
  1696     void setObjectOrNull(JSObject *arg) {
  1697         if (arg)
  1698             setObject(*arg);
  1699         else
  1700             setNull();
  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> >
  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();
  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> >
  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();
  1729     friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
  1730     JS::Value * extractMutable() {
  1731         return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
  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> >
  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();
  1747     friend class MutableValueOperations<JS::Rooted<JS::Value> >;
  1748     JS::Value * extractMutable() {
  1749         return static_cast<JS::Rooted<JS::Value>*>(this)->address();
  1751 };
  1753 } // namespace js
  1755 inline jsval_layout
  1756 JSVAL_TO_IMPL(JS::Value v)
  1758     return v.data;
  1761 inline JS_VALUE_CONSTEXPR JS::Value
  1762 IMPL_TO_JSVAL(jsval_layout l)
  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
  1773 namespace JS {
  1775 #ifndef __GNUC__
  1776 /*
  1777  * The default assignment operator for |struct C| has the signature:
  1779  *   C& C::operator=(const C&)
  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()
  1790     volatile uint64_t bits;
  1791     bits = JSVAL_TO_IMPL(hold).asBits;
  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)
  1826     return JSVAL_IS_NULL_IMPL(JSVAL_TO_IMPL(v));
  1829 static inline bool
  1830 JSVAL_IS_VOID(jsval v)
  1832     return JSVAL_IS_UNDEFINED_IMPL(JSVAL_TO_IMPL(v));
  1835 static inline bool
  1836 JSVAL_IS_INT(jsval v)
  1838     return JSVAL_IS_INT32_IMPL(JSVAL_TO_IMPL(v));
  1841 static inline int32_t
  1842 JSVAL_TO_INT(jsval v)
  1844     MOZ_ASSERT(JSVAL_IS_INT(v));
  1845     return JSVAL_TO_INT32_IMPL(JSVAL_TO_IMPL(v));
  1848 static inline JS_VALUE_CONSTEXPR jsval
  1849 INT_TO_JSVAL(int32_t i)
  1851     return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i));
  1854 static inline bool
  1855 JSVAL_IS_DOUBLE(jsval v)
  1857     return JSVAL_IS_DOUBLE_IMPL(JSVAL_TO_IMPL(v));
  1860 static inline double
  1861 JSVAL_TO_DOUBLE(jsval v)
  1863     jsval_layout l;
  1864     MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
  1865     l = JSVAL_TO_IMPL(v);
  1866     return l.asDouble;
  1869 static inline JS_VALUE_CONSTEXPR jsval
  1870 DOUBLE_TO_JSVAL(double d)
  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
  1892 static inline JS_VALUE_CONSTEXPR jsval
  1893 UINT_TO_JSVAL(uint32_t i)
  1895     return (i <= JSVAL_INT_MAX
  1896             ? INT_TO_JSVAL((int32_t)i)
  1897             : DOUBLE_TO_JSVAL((double)i));
  1900 static inline bool
  1901 JSVAL_IS_NUMBER(jsval v)
  1903     return JSVAL_IS_NUMBER_IMPL(JSVAL_TO_IMPL(v));
  1906 static inline bool
  1907 JSVAL_IS_STRING(jsval v)
  1909     return JSVAL_IS_STRING_IMPL(JSVAL_TO_IMPL(v));
  1912 static inline JSString *
  1913 JSVAL_TO_STRING(jsval v)
  1915     MOZ_ASSERT(JSVAL_IS_STRING(v));
  1916     return JSVAL_TO_STRING_IMPL(JSVAL_TO_IMPL(v));
  1919 static inline jsval
  1920 STRING_TO_JSVAL(JSString *str)
  1922     return IMPL_TO_JSVAL(STRING_TO_JSVAL_IMPL(str));
  1925 static inline JSObject *
  1926 JSVAL_TO_OBJECT(jsval v)
  1928     MOZ_ASSERT(JSVAL_IS_OBJECT_OR_NULL_IMPL(JSVAL_TO_IMPL(v)));
  1929     return JSVAL_TO_OBJECT_IMPL(JSVAL_TO_IMPL(v));
  1932 static inline jsval
  1933 OBJECT_TO_JSVAL(JSObject *obj)
  1935     if (obj)
  1936         return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(obj));
  1937     return IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
  1940 static inline bool
  1941 JSVAL_IS_BOOLEAN(jsval v)
  1943     return JSVAL_IS_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
  1946 static inline bool
  1947 JSVAL_TO_BOOLEAN(jsval v)
  1949     MOZ_ASSERT(JSVAL_IS_BOOLEAN(v));
  1950     return JSVAL_TO_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
  1953 static inline jsval
  1954 BOOLEAN_TO_JSVAL(bool b)
  1956     return IMPL_TO_JSVAL(BOOLEAN_TO_JSVAL_IMPL(b));
  1959 static inline bool
  1960 JSVAL_IS_PRIMITIVE(jsval v)
  1962     return JSVAL_IS_PRIMITIVE_IMPL(JSVAL_TO_IMPL(v));
  1965 static inline bool
  1966 JSVAL_IS_GCTHING(jsval v)
  1968     return JSVAL_IS_GCTHING_IMPL(JSVAL_TO_IMPL(v));
  1971 static inline void *
  1972 JSVAL_TO_GCTHING(jsval v)
  1974     MOZ_ASSERT(JSVAL_IS_GCTHING(v));
  1975     return JSVAL_TO_GCTHING_IMPL(JSVAL_TO_IMPL(v));
  1978 /* To be GC-safe, privates are tagged as doubles. */
  1980 static inline jsval
  1981 PRIVATE_TO_JSVAL(void *ptr)
  1983     return IMPL_TO_JSVAL(PRIVATE_PTR_TO_JSVAL_IMPL(ptr));
  1986 static inline void *
  1987 JSVAL_TO_PRIVATE(jsval v)
  1989     MOZ_ASSERT(JSVAL_IS_DOUBLE(v));
  1990     return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
  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;
  2011 #undef JS_VALUE_IS_CONSTEXPR
  2012 #undef JS_RETURN_LAYOUT_FROM_BITS
  2014 #endif /* js_Value_h */

mercurial