Bug 175668: merged the fix for the pointer aliasing bug from the 2001

version of dtoa.c.  Removed the workaround of disabling compiler
optimizations on AIX.
Modified Files: Makefile.in prdtoa.c
This commit is contained in:
wtc%netscape.com 2002-10-22 21:28:03 +00:00
parent 7fe4fdbc33
commit 72e5b42617
2 changed files with 104 additions and 93 deletions

View File

@ -82,14 +82,6 @@ RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties
include $(topsrcdir)/config/rules.mk
# An AIX Optimization bug causes PR_dtoa() to produce wrong result.
# This suppresses optimization for this single compilation unit.
ifeq ($(OS_ARCH), AIX)
$(OBJDIR)/prdtoa.o: prdtoa.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c $(filter-out -O, $(CFLAGS)) $<
endif
#
# Generate prerr.h, prerr.c, and prerr.properties from prerr.et.
#

View File

@ -123,6 +123,11 @@
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
* directly -- and assumed always to succeed.
* #define YES_ALIAS to permit aliasing certain double values with
* arrays of unsigned Longs. This leads to slightly better code with
* some compilers and was always used prior to 19990916, but it
* is not strictly legal and can cause trouble with aggressively
* optimizing compilers (e.g., gcc 2.95.1 under -O2).
*/
#if defined(IS_LITTLE_ENDIAN)
#define IEEE_8087
@ -226,6 +231,10 @@ extern void *MALLOC(size_t);
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#endif
typedef union { double d; unsigned Long L[2]; } U;
#ifdef YES_ALIAS
#define dval(x) x
#ifdef IEEE_8087
#define word0(x) ((unsigned Long *)&x)[1]
#define word1(x) ((unsigned Long *)&x)[0]
@ -233,6 +242,16 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#define word0(x) ((unsigned Long *)&x)[0]
#define word1(x) ((unsigned Long *)&x)[1]
#endif
#else
#ifdef IEEE_8087
#define word0(x) ((U*)&x)->L[1]
#define word1(x) ((U*)&x)->L[0]
#else
#define word0(x) ((U*)&x)->L[0]
#define word1(x) ((U*)&x)->L[1]
#endif
#define dval(x) ((U*)&x)->d
#endif
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
@ -914,7 +933,7 @@ static double ulp(double x)
}
}
#endif
return a;
return dval(a);
}
static double
@ -984,7 +1003,7 @@ ret_d:
#undef d0
#undef d1
#endif
return d;
return dval(d);
}
static Bigint *
@ -1127,8 +1146,8 @@ ratio
double da, db;
PRInt32 k, ka, kb;
da = b2d(a, &ka);
db = b2d(b, &kb);
dval(da) = b2d(a, &ka);
dval(db) = b2d(b, &kb);
#ifdef Pack_32
k = ka - kb + 32*(a->wds - b->wds);
#else
@ -1138,13 +1157,13 @@ ratio
if (k > 0) {
word0(da) += (k >> 2)*Exp_msk1;
if (k &= 3)
da *= 1 << k;
dval(da) *= 1 << k;
}
else {
k = -k;
word0(db) += (k >> 2)*Exp_msk1;
if (k &= 3)
db *= 1 << k;
dval(db) *= 1 << k;
}
#else
if (k > 0)
@ -1154,7 +1173,7 @@ ratio
word0(db) += k*Exp_msk1;
}
#endif
return da / db;
return dval(da) / dval(db);
}
static CONST double
@ -1219,7 +1238,7 @@ PR_strtod(CONST char *s00, char **se)
if (!_pr_initialized) _PR_ImplicitInitialization();
sign = nz0 = nz = 0;
rv = 0.;
dval(rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
@ -1341,9 +1360,9 @@ dig_done:
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
rv = y;
dval(rv) = y;
if (k > 9)
rv = tens[k - 9] * rv + z;
dval(rv) = tens[k - 9] * dval(rv) + z;
bd0 = 0;
if (nd <= DBL_DIG
#ifndef RND_PRODQUOT
@ -1357,7 +1376,7 @@ dig_done:
#ifdef VAX
goto vax_ovfl_check;
#else
/* rv = */ rounded_product(rv, tens[e]);
/* rv = */ rounded_product(dval(rv), tens[e]);
goto ret;
#endif
}
@ -1367,27 +1386,27 @@ dig_done:
* this for larger i values.
*/
e -= i;
rv *= tens[i];
dval(rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
word0(rv) -= P*Exp_msk1;
/* rv = */ rounded_product(rv, tens[e]);
/* rv = */ rounded_product(dval(rv), tens[e]);
if ((word0(rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
word0(rv) += P*Exp_msk1;
#else
/* rv = */ rounded_product(rv, tens[e]);
/* rv = */ rounded_product(dval(rv), tens[e]);
#endif
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
/* rv = */ rounded_quotient(rv, tens[-e]);
/* rv = */ rounded_quotient(dval(rv), tens[-e]);
goto ret;
}
#endif
@ -1398,13 +1417,13 @@ dig_done:
if (e1 > 0) {
if ((i = e1 & 15) != 0)
rv *= tens[i];
dval(rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
PR_SetError(PR_RANGE_ERROR, 0);
#ifdef __STDC__
rv = HUGE_VAL;
dval(rv) = HUGE_VAL;
#else
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
@ -1422,10 +1441,10 @@ dig_done:
if (e1 >>= 4) {
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv *= bigtens[j];
dval(rv) *= bigtens[j];
/* The last multiplication could overflow. */
word0(rv) -= P*Exp_msk1;
rv *= bigtens[j];
dval(rv) *= bigtens[j];
if ((z = word0(rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
@ -1444,23 +1463,23 @@ dig_done:
else if (e1 < 0) {
e1 = -e1;
if ((i = e1 & 15) != 0)
rv /= tens[i];
dval(rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
if (e1 >= 1 << n_bigtens)
goto undfl;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
rv *= tinytens[j];
dval(rv) *= tinytens[j];
/* The last multiplication could underflow. */
rv0 = rv;
rv *= tinytens[j];
if (!rv) {
rv = 2.*rv0;
rv *= tinytens[j];
if (!rv) {
dval(rv0) = dval(rv);
dval(rv) *= tinytens[j];
if (!dval(rv)) {
dval(rv) = 2.*dval(rv0);
dval(rv) *= tinytens[j];
if (!dval(rv)) {
undfl:
rv = 0.;
dval(rv) = 0.;
PR_SetError(PR_RANGE_ERROR, 0);
if (bd0)
goto retfree;
@ -1484,7 +1503,7 @@ dig_done:
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
@ -1596,12 +1615,12 @@ dig_done:
break;
#endif
if (dsign)
rv += ulp(rv);
dval(rv) += ulp(dval(rv));
#ifndef ROUND_BIASED
else {
rv -= ulp(rv);
dval(rv) -= ulp(dval(rv));
#ifndef Sudden_Underflow
if (!rv)
if (!dval(rv))
goto undfl;
#endif
}
@ -1652,10 +1671,10 @@ dig_done:
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
rv0 = rv;
dval(rv0) = dval(rv);
word0(rv) -= P*Exp_msk1;
adj = aadj1 * ulp(rv);
rv += adj;
adj = aadj1 * ulp(dval(rv));
dval(rv) += adj;
if ((word0(rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
if (word0(rv0) == Big0 && word1(rv0) == Big1)
@ -1670,10 +1689,10 @@ dig_done:
else {
#ifdef Sudden_Underflow
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
rv0 = rv;
dval(rv0) = dval(rv);
word0(rv) += P*Exp_msk1;
adj = aadj1 * ulp(rv);
rv += adj;
adj = aadj1 * ulp(dval(rv));
dval(rv) += adj;
#ifdef IBM
if ((word0(rv) & Exp_mask) < P*Exp_msk1)
#else
@ -1691,8 +1710,8 @@ dig_done:
word0(rv) -= P*Exp_msk1;
}
else {
adj = aadj1 * ulp(rv);
rv += adj;
adj = aadj1 * ulp(dval(rv));
dval(rv) += adj;
}
#else
/* Compute adj so that the IEEE rounding rules will
@ -1707,8 +1726,8 @@ dig_done:
if (!dsign)
aadj1 = -aadj1;
}
adj = aadj1 * ulp(rv);
rv += adj;
adj = aadj1 * ulp(dval(rv));
dval(rv) += adj;
#endif
}
z = word0(rv) & Exp_mask;
@ -1739,7 +1758,7 @@ retfree:
ret:
if (se)
*se = (char *)s;
return sign ? -rv : rv;
return sign ? -dval(rv) : dval(rv);
}
static PRInt32
@ -1972,9 +1991,9 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
}
#endif
#ifdef IBM
d += 0; /* normalize */
dval(d) += 0; /* normalize */
#endif
if (!d) {
if (!dval(d)) {
*decpt = 1;
if (bufsize < 2) {
PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
@ -1988,18 +2007,18 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
return PR_SUCCESS;
}
b = d2b(d, &be, &bbits);
b = d2b(dval(d), &be, &bbits);
#ifdef Sudden_Underflow
i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
if ((i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
#endif
d2 = d;
dval(d2) = dval(d);
word0(d2) &= Frac_mask1;
word0(d2) |= Exp_11;
#ifdef IBM
if (j = 11 - hi0bits(word0(d2) & Frac_mask))
d2 /= 1 << j;
dval(d2) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
@ -2038,19 +2057,19 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
i = bbits + be + (Bias + (P-1) - 1);
x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
: word1(d) << (32 - i);
d2 = x;
dval(d2) = x;
word0(d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k = (PRInt32)ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
if (d < tens[k])
if (dval(d) < tens[k])
k--;
k_check = 0;
}
@ -2117,7 +2136,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
/* Try to get by with floating-point arithmetic. */
i = 0;
d2 = d;
dval(d2) = dval(d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@ -2127,7 +2146,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
d /= bigtens[n_bigtens-1];
dval(d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@ -2135,32 +2154,32 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
ieps++;
ds *= bigtens[i];
}
d /= ds;
dval(d) /= ds;
}
else if ((j1 = -k) != 0) {
d *= tens[j1 & 0xf];
dval(d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
d *= bigtens[i];
dval(d) *= bigtens[i];
}
}
if (k_check && d < 1. && ilim > 0) {
if (k_check && dval(d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
d *= 10.;
dval(d) *= 10.;
ieps++;
}
eps = ieps*d + 7.;
dval(eps) = ieps*dval(d) + 7.;
word0(eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
d -= 5.;
if (d > eps)
dval(d) -= 5.;
if (dval(d) > dval(eps))
goto one_digit;
if (d < -eps)
if (dval(d) < -dval(eps))
goto no_digits;
goto fast_failed;
}
@ -2169,33 +2188,33 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
/* Use Steele & White method of only
* generating digits needed.
*/
eps = 0.5/tens[ilim-1] - eps;
dval(eps) = 0.5/tens[ilim-1] - dval(eps);
for(i = 0;;) {
L = (Long) d;
d -= L;
L = (Long) (dval(d));
dval(d) -= L;
*s++ = '0' + (PRInt32)L;
if (d < eps)
if (dval(d) < dval(eps))
goto ret1;
if (1. - d < eps)
if (1. - dval(d) < dval(eps))
goto bump_up;
if (++i >= ilim)
break;
eps *= 10.;
d *= 10.;
dval(eps) *= 10.;
dval(d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
eps *= tens[ilim-1];
for(i = 1;; i++, d *= 10.) {
L = (Long) d;
d -= L;
dval(eps) *= tens[ilim-1];
for(i = 1;; i++, dval(d) *= 10.) {
L = (Long) (dval(d));
dval(d) -= L;
*s++ = '0' + (PRInt32)L;
if (i == ilim) {
if (d > 0.5 + eps)
if (dval(d) > 0.5 + dval(eps))
goto bump_up;
else if (d < 0.5 - eps) {
else if (dval(d) < 0.5 - dval(eps)) {
while(*--s == '0'){} /* just count -- nothing to execute */
s++;
goto ret1;
@ -2208,7 +2227,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
#endif
fast_failed:
s = s0;
d = d2;
dval(d) = dval(d2);
k = k0;
ilim = ilim0;
}
@ -2220,24 +2239,24 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
if (ilim < 0 || d <= 5*ds)
if (ilim < 0 || dval(d) <= 5*ds)
goto no_digits;
goto one_digit;
}
for(i = 1;; i++) {
L = (Long) (d / ds);
d -= L*ds;
L = (Long) (dval(d) / ds);
dval(d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (d < 0) {
if (dval(d) < 0) {
L--;
d += ds;
dval(d) += ds;
}
#endif
*s++ = '0' + (PRInt32)L;
if (i == ilim) {
d += d;
if ((d > ds) || (d == ds && L & 1)) {
dval(d) += dval(d);
if ((dval(d) > ds) || (dval(d) == ds && L & 1)) {
bump_up:
while(*--s == '9')
if (s == s0) {
@ -2249,7 +2268,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
}
break;
}
if (!(d *= 10.))
if (!(dval(d) *= 10.))
break;
}
goto ret1;
@ -2534,7 +2553,7 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,double fval)
return;
}
/* XXX Why use mode 1? */
if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz)
== PR_FAILURE) {
buf[0] = '\0';
goto done;