Avoid bit twiddling on double values (513063, r=brendan).

This commit is contained in:
Andreas Gal 2009-08-27 13:59:19 -07:00
parent 99a4b18694
commit d4c110a6b1
6 changed files with 52 additions and 89 deletions

View File

@ -325,11 +325,8 @@ static const JSDHashTableOps StringHashOps = {
static JSDHashNumber
HashDouble(JSDHashTable *table, const void *key)
{
jsdouble d;
JS_ASSERT(IS_DOUBLE_TABLE(table));
d = *(jsdouble *)key;
return JSDOUBLE_HI32(d) ^ JSDOUBLE_LO32(d);
return JS_HASH_DOUBLE(*(jsdouble *)key);
}
static JSDHashNumber

View File

@ -1185,16 +1185,6 @@ js_strtod(JSContext *cx, const jschar *s, const jschar *send,
d = *cx->runtime->jsPositiveInfinity;
else if (d == -HUGE_VAL)
d = *cx->runtime->jsNegativeInfinity;
#ifdef HPUX
if (d == 0.0 && negative) {
/*
* "-0", "-1e-2000" come out as positive zero
* here on HPUX. Force a negative zero instead.
*/
JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
JSDOUBLE_LO32(d) = 0;
}
#endif
}
i = estr - cstr;

View File

@ -76,66 +76,65 @@ typedef union jsdpun {
jsdouble d;
} jsdpun;
#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
/*
* This version of the macros is safe for the alias optimizations that gcc
* does, but uses gcc-specific extensions.
*/
#define JSDOUBLE_HI32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.hi; }))
#define JSDOUBLE_LO32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.lo; }))
#define JSDOUBLE_SET_HI32(x, y) \
(__extension__ ({ jsdpun u; u.d = (x); u.s.hi = (y); (x) = u.d; }))
#define JSDOUBLE_SET_LO32(x, y) \
(__extension__ ({ jsdpun u; u.d = (x); u.s.lo = (y); (x) = u.d; }))
#else /* not or old GNUC */
/*
* We don't know of any non-gcc compilers that perform alias optimization,
* so this code should work.
*/
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
static inline int
JSDOUBLE_IS_NaN(jsdouble d)
{
#ifdef WIN32
return _isnan(d);
#else
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
return isnan(d);
#endif
}
#define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y))
#define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y))
static inline int
JSDOUBLE_IS_FINITE(jsdouble d)
{
#ifdef WIN32
return _finite(d);
#else
return finite(d);
#endif
}
#endif /* not or old GNUC */
static inline int
JSDOUBLE_IS_NEGZERO(jsdouble d)
{
#ifdef WIN32
return (d == 0 && (_fpclass(d) & _FPCLASS_NZ));
#else
return (d == 0 && signbit(d));
#endif
}
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
#define JSDOUBLE_IS_NaN(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
static inline int
JSDOUBLE_IS_INT(jsdouble d, jsint& i)
{
if (JSDOUBLE_IS_NEGZERO(d))
return false;
return d == (i = jsint(d));
}
#define JSDOUBLE_IS_INFINITE(x) \
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
!JSDOUBLE_LO32(x))
static inline int
JSDOUBLE_IS_NEG(jsdouble d)
{
#ifdef WIN32
return JSDOUBLE_IS_NEGZERO(d) || d < 0;
#else
return signbit(d);
#endif
}
#define JSDOUBLE_IS_FINITE(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
JSDOUBLE_LO32(d) == 0)
/*
* JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid
* raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is
* safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point
* comparisons under MSVC.
*/
#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \
&& !JSDOUBLE_IS_NEGZERO(d) \
&& ((d) == (i = (jsint)(d))))
static inline uint32
JS_HASH_DOUBLE(jsdouble d)
{
jsdpun u;
u.d = d;
return u.s.lo ^ u.s.hi;
}
#if defined(XP_WIN)
#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \

View File

@ -1080,7 +1080,7 @@
#endif
if (d == 0 || JSDOUBLE_IS_NaN(d))
rval = DOUBLE_TO_JSVAL(rt->jsNaN);
else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
else if (JSDOUBLE_IS_NEG(d) != JSDOUBLE_IS_NEG(d2))
rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
else
rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
@ -1138,16 +1138,7 @@
JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||
regs.sp[-1] == JSVAL_TRUE);
}
#ifdef HPUX
/*
* Negation of a zero doesn't produce a negative
* zero on HPUX. Perform the operation by bit
* twiddling.
*/
JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
#else
d = -d;
#endif
if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
goto error;
}

View File

@ -99,9 +99,6 @@ typedef JSIntn intn;
typedef JSInt64 int64;
/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
#ifdef HPUX
#include <model.h>
#else
#if !defined(_WIN32) && !defined(XP_OS2)
typedef JSInt32 int32;
#else
@ -109,7 +106,6 @@ typedef long int32;
#endif
typedef JSInt16 int16;
typedef JSInt8 int8;
#endif /* HPUX */
#endif /* AIX && HAVE_SYS_INTTYPES_H */
#endif /* XP_BEOS */

View File

@ -3521,8 +3521,7 @@ HashFindPropValKey(JSDHashTable *table, const void *key)
ASSERT_VALID_PROPERTY_KEY(pnkey);
return (pnkey->pn_type == TOK_NUMBER)
? (JSDHashNumber) (JSDOUBLE_HI32(pnkey->pn_dval) ^
JSDOUBLE_LO32(pnkey->pn_dval))
? (JSDHashNumber) JS_HASH_DOUBLE(pnkey->pn_dval)
: ATOM_HASH(pnkey->pn_atom);
}
@ -8402,7 +8401,7 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2,
#endif
if (d == 0 || JSDOUBLE_IS_NaN(d))
d = *cx->runtime->jsNaN;
else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
else if (JSDOUBLE_IS_NEG(d) != JSDOUBLE_IS_NEG(d2))
d = *cx->runtime->jsNegativeInfinity;
else
d = *cx->runtime->jsPositiveInfinity;
@ -9017,16 +9016,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond)
break;
case JSOP_NEG:
#ifdef HPUX
/*
* Negation of a zero doesn't produce a negative
* zero on HPUX. Perform the operation by bit
* twiddling.
*/
JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
#else
d = -d;
#endif
break;
case JSOP_POS: