From d4c110a6b120deab9fed0b4533ae8ad39870226f Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 27 Aug 2009 13:59:19 -0700 Subject: [PATCH] Avoid bit twiddling on double values (513063, r=brendan). --- js/src/jsatom.cpp | 5 +-- js/src/jsnum.cpp | 10 ----- js/src/jsnum.h | 97 +++++++++++++++++++++++----------------------- js/src/jsops.cpp | 11 +----- js/src/jsotypes.h | 4 -- js/src/jsparse.cpp | 14 +------ 6 files changed, 52 insertions(+), 89 deletions(-) diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index ab6223d5d0f..dadc897c47e 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -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 diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 6b8e2d6f47d..74f8eb57dcc 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -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; diff --git a/js/src/jsnum.h b/js/src/jsnum.h index af4ee6068b4..945b6d1f9b1 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -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) \ diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index 37618689a94..3b5609f37c9 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -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, ®s.sp[-1])) goto error; } diff --git a/js/src/jsotypes.h b/js/src/jsotypes.h index ede1221b812..b977cec6812 100644 --- a/js/src/jsotypes.h +++ b/js/src/jsotypes.h @@ -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 -#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 */ diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 9d78cdf2b23..62d344a806d 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -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: