Bug 899309 - modify JS::Value and some helper functions to be constexpr-foldable; r=luke

This commit is contained in:
Nathan Froyd 2013-07-29 16:59:34 -04:00
Родитель 84ba23610c
Коммит b0ca59e796
1 изменённых файлов: 93 добавлений и 24 удалений

Просмотреть файл

@ -333,6 +333,49 @@ typedef union jsval_layout
JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
/*
* For codesize purposes on some platforms, it's important that the
* compiler know that JS::Values constructed from constant values can be
* folded to constant bit patterns at compile time, rather than
* constructed at runtime. Doing this requires a fair amount of C++11
* features, which are not supported on all of our compilers. Set up
* some defines and helper macros in an attempt to confine the ugliness
* here, rather than scattering it all about the file. The important
* features are:
*
* - constexpr;
* - defaulted functions;
* - C99-style designated initializers.
*/
#if defined(__clang__)
# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions)
# define JS_VALUE_IS_CONSTEXPR
# endif
#elif defined(__GNUC__)
/*
* We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6
* doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because
* versions prior to that have bugs in the C++ front-end that cause crashes.
*/
# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3)
# define JS_VALUE_IS_CONSTEXPR
# endif
#endif
#if defined(JS_VALUE_IS_CONSTEXPR)
# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
return (jsval_layout) { .asBits = (BITS) }
# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR
# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR
#else
# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
jsval_layout l; \
l.asBits = (BITS); \
return l;
# define JS_VALUE_CONSTEXPR
# define JS_VALUE_CONSTEXPR_VAR const
#endif
#if JS_BITS_PER_WORD == 32
/*
@ -341,12 +384,10 @@ JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
* Thus, all comparisons should explicitly cast operands to uint32_t.
*/
static inline jsval_layout
static inline JS_VALUE_CONSTEXPR jsval_layout
BUILD_JSVAL(JSValueTag tag, uint32_t payload)
{
jsval_layout l;
l.asBits = (((uint64_t)(uint32_t)tag) << 32) | payload;
return l;
JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << 32) | payload);
}
static inline bool
@ -376,13 +417,17 @@ JSVAL_TO_INT32_IMPL(jsval_layout l)
return l.s.payload.i32;
}
static inline jsval_layout
static inline JS_VALUE_CONSTEXPR jsval_layout
INT32_TO_JSVAL_IMPL(int32_t i)
{
#if defined(JS_VALUE_IS_CONSTEXPR)
return BUILD_JSVAL(JSVAL_TAG_INT32, i);
#else
jsval_layout l;
l.s.tag = JSVAL_TAG_INT32;
l.s.payload.i32 = i;
return l;
#endif
}
static inline bool
@ -569,12 +614,10 @@ JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
#elif JS_BITS_PER_WORD == 64
static inline jsval_layout
static inline JS_VALUE_CONSTEXPR jsval_layout
BUILD_JSVAL(JSValueTag tag, uint64_t payload)
{
jsval_layout l;
l.asBits = (((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload;
return l;
JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload);
}
static inline bool
@ -604,12 +647,10 @@ JSVAL_TO_INT32_IMPL(jsval_layout l)
return (int32_t)l.asBits;
}
static inline jsval_layout
static inline JS_VALUE_CONSTEXPR jsval_layout
INT32_TO_JSVAL_IMPL(int32_t i32)
{
jsval_layout l;
l.asBits = ((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32;
return l;
JS_RETURN_LAYOUT_FROM_BITS(((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
}
static inline bool
@ -812,10 +853,12 @@ JS_CANONICALIZE_NAN(double d)
}
static inline jsval_layout JSVAL_TO_IMPL(JS::Value v);
static inline JS::Value IMPL_TO_JSVAL(jsval_layout l);
static inline JS_VALUE_CONSTEXPR JS::Value IMPL_TO_JSVAL(jsval_layout l);
namespace JS {
static inline JS_VALUE_CONSTEXPR JS::Value UndefinedValue();
/*
* JS::Value is the interface for a single JavaScript Engine value. A few
* general notes on JS::Value:
@ -858,6 +901,10 @@ class Value
* N.B. the default constructor leaves Value unitialized. Adding a default
* constructor prevents Value from being stored in a union.
*/
#if defined(JS_VALUE_IS_CONSTEXPR)
Value() = default;
Value(const Value& v) = default;
#endif
/*** Mutators ***/
@ -1162,6 +1209,10 @@ class Value
jsval_layout data;
private:
#if defined(JS_VALUE_IS_CONSTEXPR)
JS_VALUE_CONSTEXPR Value(jsval_layout layout) : data(layout) {}
#endif
void staticAssertions() {
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
@ -1170,7 +1221,8 @@ class Value
}
friend jsval_layout (::JSVAL_TO_IMPL)(Value);
friend Value (::IMPL_TO_JSVAL)(jsval_layout l);
friend Value JS_VALUE_CONSTEXPR (::IMPL_TO_JSVAL)(jsval_layout l);
friend Value JS_VALUE_CONSTEXPR (JS::UndefinedValue)();
};
inline bool
@ -1193,12 +1245,16 @@ NullValue()
return v;
}
static inline Value
static inline JS_VALUE_CONSTEXPR Value
UndefinedValue()
{
Value v;
#if defined(JS_VALUE_IS_CONSTEXPR)
return Value(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
#else
JS::Value v;
v.setUndefined();
return v;
#endif
}
static inline Value
@ -1608,12 +1664,16 @@ JSVAL_TO_IMPL(JS::Value v)
return v.data;
}
inline JS::Value
inline JS_VALUE_CONSTEXPR JS::Value
IMPL_TO_JSVAL(jsval_layout l)
{
#if defined(JS_VALUE_IS_CONSTEXPR)
return JS::Value(l);
#else
JS::Value v;
v.data = l;
return v;
#endif
}
namespace JS {
@ -1691,7 +1751,7 @@ JSVAL_TO_INT(jsval v)
return JSVAL_TO_INT32_IMPL(JSVAL_TO_IMPL(v));
}
static inline jsval
static inline JS_VALUE_CONSTEXPR jsval
INT_TO_JSVAL(int32_t i)
{
return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i));
@ -1712,7 +1772,7 @@ JSVAL_TO_DOUBLE(jsval v)
return l.asDouble;
}
static inline jsval
static inline JS_VALUE_CONSTEXPR jsval
DOUBLE_TO_JSVAL(double d)
{
/*
@ -1721,20 +1781,26 @@ DOUBLE_TO_JSVAL(double d)
* return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
* because GCC from XCode 3.1.4 miscompiles the above code.
*/
#if defined(JS_VALUE_IS_CONSTEXPR)
return IMPL_TO_JSVAL(MOZ_UNLIKELY(d != d)
? (jsval_layout) { .asBits = 0x7FF8000000000000LL }
: (jsval_layout) { .asDouble = d });
#else
jsval_layout l;
if (MOZ_UNLIKELY(d != d))
l.asBits = 0x7FF8000000000000LL;
else
l.asDouble = d;
return IMPL_TO_JSVAL(l);
#endif
}
static inline jsval
static inline JS_VALUE_CONSTEXPR jsval
UINT_TO_JSVAL(uint32_t i)
{
if (i <= JSVAL_INT_MAX)
return INT_TO_JSVAL((int32_t)i);
return DOUBLE_TO_JSVAL((double)i);
return (i <= JSVAL_INT_MAX
? INT_TO_JSVAL((int32_t)i)
: DOUBLE_TO_JSVAL((double)i));
}
static inline bool
@ -1830,4 +1896,7 @@ JSVAL_TO_PRIVATE(jsval v)
return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
}
#undef JS_VALUE_IS_CONSTEXPR
#undef JS_RETURN_LAYOUT_FROM_BITS
#endif /* js_Value_h */