mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 509857 - Get rid of DTOA_LOCK. r=jwalden.
--HG-- extra : rebase_source : bec4d9441aa2af8488a04aa8604a65b7387cda6d
This commit is contained in:
parent
3e1a930003
commit
60d5805e46
348
js/src/dtoa.c
348
js/src/dtoa.c
@ -101,9 +101,10 @@
|
||||
* directly -- and assumed always to succeed. Similarly, if you
|
||||
* want something other than the system's free() to be called to
|
||||
* recycle memory acquired from MALLOC, #define FREE to be the
|
||||
* name of the alternate routine. (FREE or free is only called in
|
||||
* pathological cases, e.g., in a dtoa call after a dtoa return in
|
||||
* mode 3 with thousands of digits requested.)
|
||||
* name of the alternate routine. (Unless you #define
|
||||
* NO_GLOBAL_STATE and call destroydtoa, FREE or free is only
|
||||
* called in pathological cases, e.g., in a dtoa call after a dtoa
|
||||
* return in mode 3 with thousands of digits requested.)
|
||||
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
|
||||
* memory allocations from a private pool of memory when possible.
|
||||
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
|
||||
@ -164,6 +165,12 @@
|
||||
* inexact or when it is a numeric value rounded to +-infinity).
|
||||
* #define NO_ERRNO if strtod should not assign errno = ERANGE when
|
||||
* the result overflows to +-Infinity or underflows to 0.
|
||||
* #define NO_GLOBAL_STATE to avoid defining any non-const global or
|
||||
* static variables. Instead the necessary state is stored in an
|
||||
* opaque struct, DtoaState, a pointer to which must be passed to
|
||||
* every entry point. Two new functions are added to the API:
|
||||
* DtoaState *newdtoa(void);
|
||||
* void destroydtoa(DtoaState *);
|
||||
*/
|
||||
|
||||
#ifndef Long
|
||||
@ -195,12 +202,15 @@ extern void *MALLOC(size_t);
|
||||
#define MALLOC malloc
|
||||
#endif
|
||||
|
||||
#ifndef FREE
|
||||
#define FREE free
|
||||
#endif
|
||||
|
||||
#ifndef Omit_Private_Memory
|
||||
#ifndef PRIVATE_MEM
|
||||
#define PRIVATE_MEM 2304
|
||||
#endif
|
||||
#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
||||
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
|
||||
#endif
|
||||
|
||||
#undef IEEE_Arith
|
||||
@ -479,14 +489,87 @@ Bigint {
|
||||
|
||||
typedef struct Bigint Bigint;
|
||||
|
||||
static Bigint *freelist[Kmax+1];
|
||||
#ifdef NO_GLOBAL_STATE
|
||||
#ifdef MULTIPLE_THREADS
|
||||
#error "cannot have both NO_GLOBAL_STATE and MULTIPLE_THREADS"
|
||||
#endif
|
||||
struct
|
||||
DtoaState {
|
||||
#define DECLARE_GLOBAL_STATE /* nothing */
|
||||
#else
|
||||
#define DECLARE_GLOBAL_STATE static
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_STATE Bigint *freelist[Kmax+1];
|
||||
DECLARE_GLOBAL_STATE Bigint *p5s;
|
||||
#ifndef Omit_Private_Memory
|
||||
DECLARE_GLOBAL_STATE double private_mem[PRIVATE_mem];
|
||||
DECLARE_GLOBAL_STATE double *pmem_next
|
||||
#ifndef NO_GLOBAL_STATE
|
||||
= private_mem
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
#ifdef NO_GLOBAL_STATE
|
||||
};
|
||||
typedef struct DtoaState DtoaState;
|
||||
#ifdef KR_headers
|
||||
#define STATE_PARAM state,
|
||||
#define STATE_PARAM_DECL DtoaState *state;
|
||||
#else
|
||||
#define STATE_PARAM DtoaState *state,
|
||||
#endif
|
||||
#define PASS_STATE state,
|
||||
#define GET_STATE(field) (state->field)
|
||||
|
||||
static DtoaState *
|
||||
newdtoa(void)
|
||||
{
|
||||
DtoaState *state = (DtoaState *) MALLOC(sizeof(DtoaState));
|
||||
if (state) {
|
||||
memset(state, 0, sizeof(DtoaState));
|
||||
state->pmem_next = state->private_mem;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
static void
|
||||
destroydtoa
|
||||
#ifdef KR_headers
|
||||
(state) STATE_PARAM_DECL
|
||||
#else
|
||||
(DtoaState *state)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
Bigint *v, *next;
|
||||
|
||||
for (i = 0; i <= Kmax; i++) {
|
||||
for (v = GET_STATE(freelist)[i]; v; v = next) {
|
||||
next = v->next;
|
||||
#ifndef Omit_Private_Memory
|
||||
if ((double*)v < GET_STATE(private_mem) ||
|
||||
(double*)v >= GET_STATE(private_mem) + PRIVATE_mem)
|
||||
#endif
|
||||
FREE((void*)v);
|
||||
}
|
||||
}
|
||||
FREE((void *)state);
|
||||
}
|
||||
|
||||
#else
|
||||
#define STATE_PARAM /* nothing */
|
||||
#define STATE_PARAM_DECL /* nothing */
|
||||
#define PASS_STATE /* nothing */
|
||||
#define GET_STATE(name) name
|
||||
#endif
|
||||
|
||||
static Bigint *
|
||||
Balloc
|
||||
#ifdef KR_headers
|
||||
(k) int k;
|
||||
(STATE_PARAM k) STATE_PARAM_DECL int k;
|
||||
#else
|
||||
(int k)
|
||||
(STATE_PARAM int k)
|
||||
#endif
|
||||
{
|
||||
int x;
|
||||
@ -498,8 +581,8 @@ Balloc
|
||||
ACQUIRE_DTOA_LOCK(0);
|
||||
/* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
|
||||
/* but this case seems very unlikely. */
|
||||
if (k <= Kmax && (rv = freelist[k]))
|
||||
freelist[k] = rv->next;
|
||||
if (k <= Kmax && (rv = GET_STATE(freelist)[k]))
|
||||
GET_STATE(freelist)[k] = rv->next;
|
||||
else {
|
||||
x = 1 << k;
|
||||
#ifdef Omit_Private_Memory
|
||||
@ -507,9 +590,9 @@ Balloc
|
||||
#else
|
||||
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
|
||||
/sizeof(double);
|
||||
if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
|
||||
rv = (Bigint*)pmem_next;
|
||||
pmem_next += len;
|
||||
if (k <= Kmax && GET_STATE(pmem_next) - GET_STATE(private_mem) + len <= PRIVATE_mem) {
|
||||
rv = (Bigint*)GET_STATE(pmem_next);
|
||||
GET_STATE(pmem_next) += len;
|
||||
}
|
||||
else
|
||||
rv = (Bigint*)MALLOC(len*sizeof(double));
|
||||
@ -525,22 +608,18 @@ Balloc
|
||||
static void
|
||||
Bfree
|
||||
#ifdef KR_headers
|
||||
(v) Bigint *v;
|
||||
(STATE_PARAM v) STATE_PARAM_DECL Bigint *v;
|
||||
#else
|
||||
(Bigint *v)
|
||||
(STATE_PARAM Bigint *v)
|
||||
#endif
|
||||
{
|
||||
if (v) {
|
||||
if (v->k > Kmax)
|
||||
#ifdef FREE
|
||||
FREE((void*)v);
|
||||
#else
|
||||
free((void*)v);
|
||||
#endif
|
||||
else {
|
||||
ACQUIRE_DTOA_LOCK(0);
|
||||
v->next = freelist[v->k];
|
||||
freelist[v->k] = v;
|
||||
v->next = GET_STATE(freelist)[v->k];
|
||||
GET_STATE(freelist)[v->k] = v;
|
||||
FREE_DTOA_LOCK(0);
|
||||
}
|
||||
}
|
||||
@ -552,9 +631,9 @@ y->wds*sizeof(Long) + 2*sizeof(int))
|
||||
static Bigint *
|
||||
multadd
|
||||
#ifdef KR_headers
|
||||
(b, m, a) Bigint *b; int m, a;
|
||||
(STATE_PARAM b, m, a) STATE_PARAM_DECL Bigint *b; int m, a;
|
||||
#else
|
||||
(Bigint *b, int m, int a) /* multiply by m and add a */
|
||||
(STATE_PARAM Bigint *b, int m, int a) /* multiply by m and add a */
|
||||
#endif
|
||||
{
|
||||
int i, wds;
|
||||
@ -595,9 +674,9 @@ multadd
|
||||
while(++i < wds);
|
||||
if (carry) {
|
||||
if (wds >= b->maxwds) {
|
||||
b1 = Balloc(b->k+1);
|
||||
b1 = Balloc(PASS_STATE b->k+1);
|
||||
Bcopy(b1, b);
|
||||
Bfree(b);
|
||||
Bfree(PASS_STATE b);
|
||||
b = b1;
|
||||
}
|
||||
b->x[wds++] = (ULong) carry;
|
||||
@ -609,9 +688,9 @@ multadd
|
||||
static Bigint *
|
||||
s2b
|
||||
#ifdef KR_headers
|
||||
(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
|
||||
(STATE_PARAM s, nd0, nd, y9) STATE_PARAM_DECL CONST char *s; int nd0, nd; ULong y9;
|
||||
#else
|
||||
(CONST char *s, int nd0, int nd, ULong y9)
|
||||
(STATE_PARAM CONST char *s, int nd0, int nd, ULong y9)
|
||||
#endif
|
||||
{
|
||||
Bigint *b;
|
||||
@ -621,11 +700,11 @@ s2b
|
||||
x = (nd + 8) / 9;
|
||||
for(k = 0, y = 1; x > y; y <<= 1, k++) ;
|
||||
#ifdef Pack_32
|
||||
b = Balloc(k);
|
||||
b = Balloc(PASS_STATE k);
|
||||
b->x[0] = y9;
|
||||
b->wds = 1;
|
||||
#else
|
||||
b = Balloc(k+1);
|
||||
b = Balloc(PASS_STATE k+1);
|
||||
b->x[0] = y9 & 0xffff;
|
||||
b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
|
||||
#endif
|
||||
@ -633,14 +712,14 @@ s2b
|
||||
i = 9;
|
||||
if (9 < nd0) {
|
||||
s += 9;
|
||||
do b = multadd(b, 10, *s++ - '0');
|
||||
do b = multadd(PASS_STATE b, 10, *s++ - '0');
|
||||
while(++i < nd0);
|
||||
s++;
|
||||
}
|
||||
else
|
||||
s += 10;
|
||||
for(; i < nd; i++)
|
||||
b = multadd(b, 10, *s++ - '0');
|
||||
b = multadd(PASS_STATE b, 10, *s++ - '0');
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -729,14 +808,14 @@ lo0bits
|
||||
static Bigint *
|
||||
i2b
|
||||
#ifdef KR_headers
|
||||
(i) int i;
|
||||
(STATE_PARAM i) STATE_PARAM_DECL int i;
|
||||
#else
|
||||
(int i)
|
||||
(STATE_PARAM int i)
|
||||
#endif
|
||||
{
|
||||
Bigint *b;
|
||||
|
||||
b = Balloc(1);
|
||||
b = Balloc(PASS_STATE 1);
|
||||
b->x[0] = i;
|
||||
b->wds = 1;
|
||||
return b;
|
||||
@ -745,9 +824,9 @@ i2b
|
||||
static Bigint *
|
||||
mult
|
||||
#ifdef KR_headers
|
||||
(a, b) Bigint *a, *b;
|
||||
(STATE_PARAM a, b) STATE_PARAM_DECL Bigint *a, *b;
|
||||
#else
|
||||
(Bigint *a, Bigint *b)
|
||||
(STATE_PARAM Bigint *a, Bigint *b)
|
||||
#endif
|
||||
{
|
||||
Bigint *c;
|
||||
@ -774,7 +853,7 @@ mult
|
||||
wc = wa + wb;
|
||||
if (wc > a->maxwds)
|
||||
k++;
|
||||
c = Balloc(k);
|
||||
c = Balloc(PASS_STATE k);
|
||||
for(x = c->x, xa = x + wc; x < xa; x++)
|
||||
*x = 0;
|
||||
xa = a->x;
|
||||
@ -852,26 +931,24 @@ mult
|
||||
return c;
|
||||
}
|
||||
|
||||
static Bigint *p5s;
|
||||
|
||||
static Bigint *
|
||||
pow5mult
|
||||
#ifdef KR_headers
|
||||
(b, k) Bigint *b; int k;
|
||||
(STATE_PARAM b, k) STATE_PARAM_DECL Bigint *b; int k;
|
||||
#else
|
||||
(Bigint *b, int k)
|
||||
(STATE_PARAM Bigint *b, int k)
|
||||
#endif
|
||||
{
|
||||
Bigint *b1, *p5, *p51;
|
||||
int i;
|
||||
static int p05[3] = { 5, 25, 125 };
|
||||
static CONST int p05[3] = { 5, 25, 125 };
|
||||
|
||||
if ((i = k & 3))
|
||||
b = multadd(b, p05[i-1], 0);
|
||||
b = multadd(PASS_STATE b, p05[i-1], 0);
|
||||
|
||||
if (!(k >>= 2))
|
||||
return b;
|
||||
if (!(p5 = p5s)) {
|
||||
if (!(p5 = GET_STATE(p5s))) {
|
||||
/* first time */
|
||||
#ifdef MULTIPLE_THREADS
|
||||
ACQUIRE_DTOA_LOCK(1);
|
||||
@ -881,14 +958,14 @@ pow5mult
|
||||
}
|
||||
FREE_DTOA_LOCK(1);
|
||||
#else
|
||||
p5 = p5s = i2b(625);
|
||||
p5 = GET_STATE(p5s) = i2b(PASS_STATE 625);
|
||||
p5->next = 0;
|
||||
#endif
|
||||
}
|
||||
for(;;) {
|
||||
if (k & 1) {
|
||||
b1 = mult(b, p5);
|
||||
Bfree(b);
|
||||
b1 = mult(PASS_STATE b, p5);
|
||||
Bfree(PASS_STATE b);
|
||||
b = b1;
|
||||
}
|
||||
if (!(k >>= 1))
|
||||
@ -902,7 +979,7 @@ pow5mult
|
||||
}
|
||||
FREE_DTOA_LOCK(1);
|
||||
#else
|
||||
p51 = p5->next = mult(p5,p5);
|
||||
p51 = p5->next = mult(PASS_STATE p5,p5);
|
||||
p51->next = 0;
|
||||
#endif
|
||||
}
|
||||
@ -914,9 +991,9 @@ pow5mult
|
||||
static Bigint *
|
||||
lshift
|
||||
#ifdef KR_headers
|
||||
(b, k) Bigint *b; int k;
|
||||
(STATE_PARAM b, k) STATE_PARAM_DECL Bigint *b; int k;
|
||||
#else
|
||||
(Bigint *b, int k)
|
||||
(STATE_PARAM Bigint *b, int k)
|
||||
#endif
|
||||
{
|
||||
int i, k1, n, n1;
|
||||
@ -932,7 +1009,7 @@ lshift
|
||||
n1 = n + b->wds + 1;
|
||||
for(i = b->maxwds; n1 > i; i <<= 1)
|
||||
k1++;
|
||||
b1 = Balloc(k1);
|
||||
b1 = Balloc(PASS_STATE k1);
|
||||
x1 = b1->x;
|
||||
for(i = 0; i < n; i++)
|
||||
*x1++ = 0;
|
||||
@ -967,7 +1044,7 @@ lshift
|
||||
*x1++ = *x++;
|
||||
while(x < xe);
|
||||
b1->wds = n1 - 1;
|
||||
Bfree(b);
|
||||
Bfree(PASS_STATE b);
|
||||
return b1;
|
||||
}
|
||||
|
||||
@ -1008,9 +1085,9 @@ cmp
|
||||
static Bigint *
|
||||
diff
|
||||
#ifdef KR_headers
|
||||
(a, b) Bigint *a, *b;
|
||||
(STATE_PARAM a, b) STATE_PARAM_DECL Bigint *a, *b;
|
||||
#else
|
||||
(Bigint *a, Bigint *b)
|
||||
(STATE_PARAM Bigint *a, Bigint *b)
|
||||
#endif
|
||||
{
|
||||
Bigint *c;
|
||||
@ -1027,7 +1104,7 @@ diff
|
||||
|
||||
i = cmp(a,b);
|
||||
if (!i) {
|
||||
c = Balloc(0);
|
||||
c = Balloc(PASS_STATE 0);
|
||||
c->wds = 1;
|
||||
c->x[0] = 0;
|
||||
return c;
|
||||
@ -1040,7 +1117,7 @@ diff
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
c = Balloc(a->k);
|
||||
c = Balloc(PASS_STATE a->k);
|
||||
c->sign = i;
|
||||
wa = a->wds;
|
||||
xa = a->x;
|
||||
@ -1214,9 +1291,9 @@ b2d
|
||||
static Bigint *
|
||||
d2b
|
||||
#ifdef KR_headers
|
||||
(d, e, bits) U d; int *e, *bits;
|
||||
(STATE_PARAM d, e, bits) STATE_PARAM_DECL U d; int *e, *bits;
|
||||
#else
|
||||
(U d, int *e, int *bits)
|
||||
(STATE_PARAM U d, int *e, int *bits)
|
||||
#endif
|
||||
{
|
||||
Bigint *b;
|
||||
@ -1235,9 +1312,9 @@ d2b
|
||||
#endif
|
||||
|
||||
#ifdef Pack_32
|
||||
b = Balloc(1);
|
||||
b = Balloc(PASS_STATE 1);
|
||||
#else
|
||||
b = Balloc(2);
|
||||
b = Balloc(PASS_STATE 2);
|
||||
#endif
|
||||
x = b->x;
|
||||
|
||||
@ -1529,9 +1606,9 @@ hexnan
|
||||
static double
|
||||
_strtod
|
||||
#ifdef KR_headers
|
||||
(s00, se) CONST char *s00; char **se;
|
||||
(STATE_PARAM s00, se) STATE_PARAM_DECL CONST char *s00; char **se;
|
||||
#else
|
||||
(CONST char *s00, char **se)
|
||||
(STATE_PARAM CONST char *s00, char **se)
|
||||
#endif
|
||||
{
|
||||
#ifdef Avoid_Underflow
|
||||
@ -1953,13 +2030,13 @@ _strtod
|
||||
|
||||
/* Put digits into bd: true value = bd * 10^e */
|
||||
|
||||
bd0 = s2b(s0, nd0, nd, y);
|
||||
bd0 = s2b(PASS_STATE s0, nd0, nd, y);
|
||||
|
||||
for(;;) {
|
||||
bd = Balloc(bd0->k);
|
||||
bd = Balloc(PASS_STATE bd0->k);
|
||||
Bcopy(bd, bd0);
|
||||
bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
|
||||
bs = i2b(1);
|
||||
bb = d2b(PASS_STATE rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
|
||||
bs = i2b(PASS_STATE 1);
|
||||
|
||||
if (e >= 0) {
|
||||
bb2 = bb5 = 0;
|
||||
@ -2015,20 +2092,20 @@ _strtod
|
||||
bs2 -= i;
|
||||
}
|
||||
if (bb5 > 0) {
|
||||
bs = pow5mult(bs, bb5);
|
||||
bb1 = mult(bs, bb);
|
||||
Bfree(bb);
|
||||
bs = pow5mult(PASS_STATE bs, bb5);
|
||||
bb1 = mult(PASS_STATE bs, bb);
|
||||
Bfree(PASS_STATE bb);
|
||||
bb = bb1;
|
||||
}
|
||||
if (bb2 > 0)
|
||||
bb = lshift(bb, bb2);
|
||||
bb = lshift(PASS_STATE bb, bb2);
|
||||
if (bd5 > 0)
|
||||
bd = pow5mult(bd, bd5);
|
||||
bd = pow5mult(PASS_STATE bd, bd5);
|
||||
if (bd2 > 0)
|
||||
bd = lshift(bd, bd2);
|
||||
bd = lshift(PASS_STATE bd, bd2);
|
||||
if (bs2 > 0)
|
||||
bs = lshift(bs, bs2);
|
||||
delta = diff(bb, bd);
|
||||
bs = lshift(PASS_STATE bs, bs2);
|
||||
delta = diff(PASS_STATE bb, bd);
|
||||
dsign = delta->sign;
|
||||
delta->sign = 0;
|
||||
i = cmp(delta, bs);
|
||||
@ -2060,7 +2137,7 @@ _strtod
|
||||
if (y)
|
||||
#endif
|
||||
{
|
||||
delta = lshift(delta,Log2P);
|
||||
delta = lshift(PASS_STATE delta,Log2P);
|
||||
if (cmp(delta, bs) <= 0)
|
||||
adj = -0.5;
|
||||
}
|
||||
@ -2149,7 +2226,7 @@ _strtod
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
delta = lshift(delta,Log2P);
|
||||
delta = lshift(PASS_STATE delta,Log2P);
|
||||
if (cmp(delta, bs) > 0)
|
||||
goto drop_down;
|
||||
break;
|
||||
@ -2374,10 +2451,10 @@ _strtod
|
||||
}
|
||||
#endif
|
||||
cont:
|
||||
Bfree(bb);
|
||||
Bfree(bd);
|
||||
Bfree(bs);
|
||||
Bfree(delta);
|
||||
Bfree(PASS_STATE bb);
|
||||
Bfree(PASS_STATE bd);
|
||||
Bfree(PASS_STATE bs);
|
||||
Bfree(PASS_STATE delta);
|
||||
}
|
||||
#ifdef SET_INEXACT
|
||||
if (inexact) {
|
||||
@ -2410,11 +2487,11 @@ _strtod
|
||||
}
|
||||
#endif
|
||||
retfree:
|
||||
Bfree(bb);
|
||||
Bfree(bd);
|
||||
Bfree(bs);
|
||||
Bfree(bd0);
|
||||
Bfree(delta);
|
||||
Bfree(PASS_STATE bb);
|
||||
Bfree(PASS_STATE bd);
|
||||
Bfree(PASS_STATE bs);
|
||||
Bfree(PASS_STATE bd0);
|
||||
Bfree(PASS_STATE delta);
|
||||
ret:
|
||||
if (se)
|
||||
*se = (char *)s;
|
||||
@ -2539,15 +2616,16 @@ quorem
|
||||
return q;
|
||||
}
|
||||
|
||||
#ifndef MULTIPLE_THREADS
|
||||
#if !defined(MULTIPLE_THREADS) && !defined(NO_GLOBAL_STATE)
|
||||
#define USE_DTOA_RESULT 1
|
||||
static char *dtoa_result;
|
||||
#endif
|
||||
|
||||
static char *
|
||||
#ifdef KR_headers
|
||||
rv_alloc(i) int i;
|
||||
rv_alloc(STATE_PARAM i) STATE_PARAM_DECL int i;
|
||||
#else
|
||||
rv_alloc(int i)
|
||||
rv_alloc(STATE_PARAM int i)
|
||||
#endif
|
||||
{
|
||||
int j, k, *r;
|
||||
@ -2557,10 +2635,10 @@ rv_alloc(int i)
|
||||
sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned) i;
|
||||
j <<= 1)
|
||||
k++;
|
||||
r = (int*)Balloc(k);
|
||||
r = (int*)Balloc(PASS_STATE k);
|
||||
*r = k;
|
||||
return
|
||||
#ifndef MULTIPLE_THREADS
|
||||
#ifdef USE_DTOA_RESULT
|
||||
dtoa_result =
|
||||
#endif
|
||||
(char *)(r+1);
|
||||
@ -2568,14 +2646,14 @@ rv_alloc(int i)
|
||||
|
||||
static char *
|
||||
#ifdef KR_headers
|
||||
nrv_alloc(s, rve, n) char *s, **rve; int n;
|
||||
nrv_alloc(STATE_PARAM s, rve, n) STATE_PARAM_DECL char *s, **rve; int n;
|
||||
#else
|
||||
nrv_alloc(CONST char *s, char **rve, int n)
|
||||
nrv_alloc(STATE_PARAM CONST char *s, char **rve, int n)
|
||||
#endif
|
||||
{
|
||||
char *rv, *t;
|
||||
|
||||
t = rv = rv_alloc(n);
|
||||
t = rv = rv_alloc(PASS_STATE n);
|
||||
while((*t = *s++)) t++;
|
||||
if (rve)
|
||||
*rve = t;
|
||||
@ -2590,15 +2668,15 @@ nrv_alloc(CONST char *s, char **rve, int n)
|
||||
|
||||
static void
|
||||
#ifdef KR_headers
|
||||
freedtoa(s) char *s;
|
||||
freedtoa(STATE_PARAM s) STATE_PARAM_DECL char *s;
|
||||
#else
|
||||
freedtoa(char *s)
|
||||
freedtoa(STATE_PARAM char *s)
|
||||
#endif
|
||||
{
|
||||
Bigint *b = (Bigint *)((int *)s - 1);
|
||||
b->maxwds = 1 << (b->k = *(int*)b);
|
||||
Bfree(b);
|
||||
#ifndef MULTIPLE_THREADS
|
||||
Bfree(PASS_STATE b);
|
||||
#ifdef USE_DTOA_RESULT
|
||||
if (s == dtoa_result)
|
||||
dtoa_result = 0;
|
||||
#endif
|
||||
@ -2641,10 +2719,10 @@ freedtoa(char *s)
|
||||
static char *
|
||||
dtoa
|
||||
#ifdef KR_headers
|
||||
(d, mode, ndigits, decpt, sign, rve)
|
||||
U d; int mode, ndigits, *decpt, *sign; char **rve;
|
||||
(STATE_PARAM d, mode, ndigits, decpt, sign, rve)
|
||||
STATE_PARAM_DECL U d; int mode, ndigits, *decpt, *sign; char **rve;
|
||||
#else
|
||||
(U d, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
||||
(STATE_PARAM U d, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
||||
#endif
|
||||
{
|
||||
/* Arguments ndigits, decpt, sign are similar to those
|
||||
@ -2705,9 +2783,9 @@ dtoa
|
||||
mlo = NULL;
|
||||
#endif
|
||||
|
||||
#ifndef MULTIPLE_THREADS
|
||||
#ifdef USE_DTOA_RESULT
|
||||
if (dtoa_result) {
|
||||
freedtoa(dtoa_result);
|
||||
freedtoa(PASS_STATE dtoa_result);
|
||||
dtoa_result = 0;
|
||||
}
|
||||
#endif
|
||||
@ -2731,9 +2809,9 @@ dtoa
|
||||
*decpt = 9999;
|
||||
#ifdef IEEE_Arith
|
||||
if (!word1(d) && !(word0(d) & 0xfffff))
|
||||
return nrv_alloc("Infinity", rve, 8);
|
||||
return nrv_alloc(PASS_STATE "Infinity", rve, 8);
|
||||
#endif
|
||||
return nrv_alloc("NaN", rve, 3);
|
||||
return nrv_alloc(PASS_STATE "NaN", rve, 3);
|
||||
}
|
||||
#endif
|
||||
#ifdef IBM
|
||||
@ -2741,7 +2819,7 @@ dtoa
|
||||
#endif
|
||||
if (!dval(d)) {
|
||||
*decpt = 1;
|
||||
return nrv_alloc("0", rve, 1);
|
||||
return nrv_alloc(PASS_STATE "0", rve, 1);
|
||||
}
|
||||
|
||||
#ifdef SET_INEXACT
|
||||
@ -2758,7 +2836,7 @@ dtoa
|
||||
}
|
||||
#endif
|
||||
|
||||
b = d2b(d, &be, &bbits);
|
||||
b = d2b(PASS_STATE d, &be, &bbits);
|
||||
#ifdef Sudden_Underflow
|
||||
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
|
||||
#else
|
||||
@ -2884,7 +2962,7 @@ dtoa
|
||||
if (i <= 0)
|
||||
i = 1;
|
||||
}
|
||||
s = s0 = rv_alloc(i);
|
||||
s = s0 = rv_alloc(PASS_STATE i);
|
||||
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
if (mode > 1 && rounding != 1)
|
||||
@ -3061,7 +3139,7 @@ dtoa
|
||||
#endif
|
||||
b2 += i;
|
||||
s2 += i;
|
||||
mhi = i2b(1);
|
||||
mhi = i2b(PASS_STATE 1);
|
||||
}
|
||||
if (m2 > 0 && s2 > 0) {
|
||||
i = m2 < s2 ? m2 : s2;
|
||||
@ -3072,20 +3150,20 @@ dtoa
|
||||
if (b5 > 0) {
|
||||
if (leftright) {
|
||||
if (m5 > 0) {
|
||||
mhi = pow5mult(mhi, m5);
|
||||
b1 = mult(mhi, b);
|
||||
Bfree(b);
|
||||
mhi = pow5mult(PASS_STATE mhi, m5);
|
||||
b1 = mult(PASS_STATE mhi, b);
|
||||
Bfree(PASS_STATE b);
|
||||
b = b1;
|
||||
}
|
||||
if ((j = b5 - m5))
|
||||
b = pow5mult(b, j);
|
||||
b = pow5mult(PASS_STATE b, j);
|
||||
}
|
||||
else
|
||||
b = pow5mult(b, b5);
|
||||
b = pow5mult(PASS_STATE b, b5);
|
||||
}
|
||||
S = i2b(1);
|
||||
S = i2b(PASS_STATE 1);
|
||||
if (s5 > 0)
|
||||
S = pow5mult(S, s5);
|
||||
S = pow5mult(PASS_STATE S, s5);
|
||||
|
||||
/* Check for special case that d is a normalized power of 2. */
|
||||
|
||||
@ -3134,20 +3212,20 @@ dtoa
|
||||
s2 += i;
|
||||
}
|
||||
if (b2 > 0)
|
||||
b = lshift(b, b2);
|
||||
b = lshift(PASS_STATE b, b2);
|
||||
if (s2 > 0)
|
||||
S = lshift(S, s2);
|
||||
S = lshift(PASS_STATE S, s2);
|
||||
if (k_check) {
|
||||
if (cmp(b,S) < 0) {
|
||||
k--;
|
||||
b = multadd(b, 10, 0); /* we botched the k estimate */
|
||||
b = multadd(PASS_STATE b, 10, 0); /* we botched the k estimate */
|
||||
if (leftright)
|
||||
mhi = multadd(mhi, 10, 0);
|
||||
mhi = multadd(PASS_STATE mhi, 10, 0);
|
||||
ilim = ilim1;
|
||||
}
|
||||
}
|
||||
if (ilim <= 0 && (mode == 3 || mode == 5)) {
|
||||
if (ilim < 0 || cmp(b,S = multadd(S,5,0)) < 0) {
|
||||
if (ilim < 0 || cmp(b,S = multadd(PASS_STATE S,5,0)) < 0) {
|
||||
/* no digits, fcvt style */
|
||||
no_digits:
|
||||
/* MOZILLA CHANGE: Always return a non-empty string. */
|
||||
@ -3162,7 +3240,7 @@ dtoa
|
||||
}
|
||||
if (leftright) {
|
||||
if (m2 > 0)
|
||||
mhi = lshift(mhi, m2);
|
||||
mhi = lshift(PASS_STATE mhi, m2);
|
||||
|
||||
/* Compute mlo -- check for special case
|
||||
* that d is a normalized power of 2.
|
||||
@ -3170,9 +3248,9 @@ dtoa
|
||||
|
||||
mlo = mhi;
|
||||
if (spec_case) {
|
||||
mhi = Balloc(mhi->k);
|
||||
mhi = Balloc(PASS_STATE mhi->k);
|
||||
Bcopy(mhi, mlo);
|
||||
mhi = lshift(mhi, Log2P);
|
||||
mhi = lshift(PASS_STATE mhi, Log2P);
|
||||
}
|
||||
|
||||
for(i = 1;;i++) {
|
||||
@ -3181,9 +3259,9 @@ dtoa
|
||||
* that will round to d?
|
||||
*/
|
||||
j = cmp(b, mlo);
|
||||
delta = diff(S, mhi);
|
||||
delta = diff(PASS_STATE S, mhi);
|
||||
j1 = delta->sign ? 1 : cmp(b, delta);
|
||||
Bfree(delta);
|
||||
Bfree(PASS_STATE delta);
|
||||
#ifndef ROUND_BIASED
|
||||
if (j1 == 0 && mode != 1 && !(word1(d) & 1)
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
@ -3221,7 +3299,7 @@ dtoa
|
||||
}
|
||||
#endif /*Honor_FLT_ROUNDS*/
|
||||
if (j1 > 0) {
|
||||
b = lshift(b, 1);
|
||||
b = lshift(PASS_STATE b, 1);
|
||||
j1 = cmp(b, S);
|
||||
if ((j1 > 0 || (j1 == 0 && dig & 1))
|
||||
&& dig++ == '9')
|
||||
@ -3250,12 +3328,12 @@ dtoa
|
||||
*s++ = dig;
|
||||
if (i == ilim)
|
||||
break;
|
||||
b = multadd(b, 10, 0);
|
||||
b = multadd(PASS_STATE b, 10, 0);
|
||||
if (mlo == mhi)
|
||||
mlo = mhi = multadd(mhi, 10, 0);
|
||||
mlo = mhi = multadd(PASS_STATE mhi, 10, 0);
|
||||
else {
|
||||
mlo = multadd(mlo, 10, 0);
|
||||
mhi = multadd(mhi, 10, 0);
|
||||
mlo = multadd(PASS_STATE mlo, 10, 0);
|
||||
mhi = multadd(PASS_STATE mhi, 10, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3270,7 +3348,7 @@ dtoa
|
||||
}
|
||||
if (i >= ilim)
|
||||
break;
|
||||
b = multadd(b, 10, 0);
|
||||
b = multadd(PASS_STATE b, 10, 0);
|
||||
}
|
||||
|
||||
/* Round off last digit */
|
||||
@ -3281,7 +3359,7 @@ dtoa
|
||||
case 2: goto roundoff;
|
||||
}
|
||||
#endif
|
||||
b = lshift(b, 1);
|
||||
b = lshift(PASS_STATE b, 1);
|
||||
j = cmp(b, S);
|
||||
if (j >= 0) { /* ECMA compatible rounding needed by Spidermonkey */
|
||||
roundoff:
|
||||
@ -3301,11 +3379,11 @@ dtoa
|
||||
s++;
|
||||
}
|
||||
ret:
|
||||
Bfree(S);
|
||||
Bfree(PASS_STATE S);
|
||||
if (mhi) {
|
||||
if (mlo && mlo != mhi)
|
||||
Bfree(mlo);
|
||||
Bfree(mhi);
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
}
|
||||
ret1:
|
||||
#ifdef SET_INEXACT
|
||||
@ -3319,7 +3397,7 @@ dtoa
|
||||
else if (!oldinexact)
|
||||
clear_inexact();
|
||||
#endif
|
||||
Bfree(b);
|
||||
Bfree(PASS_STATE b);
|
||||
*s = 0;
|
||||
*decpt = k + 1;
|
||||
if (rve)
|
||||
|
@ -563,11 +563,8 @@ JSRuntime::JSRuntime()
|
||||
bool
|
||||
JSRuntime::init(uint32 maxbytes)
|
||||
{
|
||||
if (!js_InitDtoa() ||
|
||||
!js_InitGC(this, maxbytes) ||
|
||||
!js_InitAtomState(this)) {
|
||||
if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
|
||||
return false;
|
||||
}
|
||||
|
||||
deflatedStringCache = new js::DeflatedStringCache();
|
||||
if (!deflatedStringCache || !deflatedStringCache->init())
|
||||
@ -757,7 +754,6 @@ JS_ShutDown(void)
|
||||
reprmeter::js_DumpReprMeter();
|
||||
#endif
|
||||
|
||||
js_FinishDtoa();
|
||||
#ifdef JS_THREADSAFE
|
||||
js_CleanupLocks();
|
||||
#endif
|
||||
|
@ -100,7 +100,7 @@ CallStack::contains(JSStackFrame *fp)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
bool
|
||||
JSThreadData::init()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -111,6 +111,12 @@ JSThreadData::init()
|
||||
#ifdef JS_TRACER
|
||||
InitJIT(&traceMonitor);
|
||||
#endif
|
||||
dtoaState = js_NewDtoaState();
|
||||
if (!dtoaState) {
|
||||
finish();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -126,6 +132,9 @@ JSThreadData::finish()
|
||||
JS_ASSERT(!localRootStack);
|
||||
#endif
|
||||
|
||||
if (dtoaState)
|
||||
js_DestroyDtoaState(dtoaState);
|
||||
|
||||
js_FinishGSNCache(&gsnCache);
|
||||
js_FinishPropertyCache(&propertyCache);
|
||||
#if defined JS_TRACER
|
||||
@ -190,7 +199,10 @@ NewThread(jsword id)
|
||||
return NULL;
|
||||
JS_INIT_CLIST(&thread->contextList);
|
||||
thread->id = id;
|
||||
thread->data.init();
|
||||
if (!thread->data.init()) {
|
||||
js_free(thread);
|
||||
return NULL;
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "jslong.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsdhash.h"
|
||||
#include "jsdtoa.h"
|
||||
#include "jsgc.h"
|
||||
#include "jshashtable.h"
|
||||
#include "jsinterp.h"
|
||||
@ -555,6 +556,9 @@ struct JSThreadData {
|
||||
JSEvalCacheMeter evalCacheMeter;
|
||||
#endif
|
||||
|
||||
/* State used by dtoa.c. */
|
||||
DtoaState *dtoaState;
|
||||
|
||||
/*
|
||||
* Cache of reusable JSNativeEnumerators mapped by shape identifiers (as
|
||||
* stored in scope->shape). This cache is nulled by the GC and protected
|
||||
@ -569,7 +573,7 @@ struct JSThreadData {
|
||||
|
||||
jsuword nativeEnumCache[NATIVE_ENUM_CACHE_SIZE];
|
||||
|
||||
void init();
|
||||
bool init();
|
||||
void finish();
|
||||
void mark(JSTracer *trc);
|
||||
void purge(JSContext *cx);
|
||||
|
@ -2175,7 +2175,7 @@ date_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
|
||||
numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
|
||||
if (!numStr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
|
@ -49,10 +49,7 @@
|
||||
#include "jsnum.h"
|
||||
#include "jsbit.h"
|
||||
#include "jslibmath.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
#include "jslock.h"
|
||||
#endif
|
||||
#include "jscntxt.h"
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define IEEE_8087
|
||||
@ -78,46 +75,9 @@
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
static PRLock *dtoalock;
|
||||
static JSBool _dtoainited = JS_FALSE;
|
||||
|
||||
#define LOCK_DTOA() PR_Lock(dtoalock);
|
||||
#define UNLOCK_DTOA() PR_Unlock(dtoalock)
|
||||
#else
|
||||
#define LOCK_DTOA()
|
||||
#define UNLOCK_DTOA()
|
||||
#endif
|
||||
#define NO_GLOBAL_STATE
|
||||
#include "dtoa.c"
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_InitDtoa()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (!_dtoainited) {
|
||||
dtoalock = PR_NewLock();
|
||||
JS_ASSERT(dtoalock);
|
||||
_dtoainited = JS_TRUE;
|
||||
}
|
||||
|
||||
return (dtoalock != 0);
|
||||
#else
|
||||
return JS_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_FinishDtoa()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (_dtoainited) {
|
||||
PR_DestroyLock(dtoalock);
|
||||
dtoalock = NULL;
|
||||
_dtoainited = JS_FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Mapping of JSDToStrMode -> js_dtoa mode */
|
||||
static const uint8 dtoaModes[] = {
|
||||
0, /* DTOSTR_STANDARD */
|
||||
@ -126,20 +86,19 @@ static const uint8 dtoaModes[] = {
|
||||
2, /* DTOSTR_EXPONENTIAL, */
|
||||
2}; /* DTOSTR_PRECISION */
|
||||
|
||||
JS_FRIEND_API(double)
|
||||
JS_strtod(const char *s00, char **se, int *err)
|
||||
double
|
||||
js_strtod_harder(DtoaState *state, const char *s00, char **se, int *err)
|
||||
{
|
||||
double retval;
|
||||
if (err)
|
||||
*err = 0;
|
||||
LOCK_DTOA();
|
||||
retval = _strtod(s00, se);
|
||||
UNLOCK_DTOA();
|
||||
retval = _strtod(state, s00, se);
|
||||
return retval;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(char *)
|
||||
JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dinput)
|
||||
char *
|
||||
js_dtostr(DtoaState *state, char *buffer, size_t bufferSize, JSDToStrMode mode, int precision,
|
||||
double dinput)
|
||||
{
|
||||
U d;
|
||||
int decPt; /* Offset of decimal point from first digit */
|
||||
@ -159,24 +118,20 @@ JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, dou
|
||||
if (mode == DTOSTR_FIXED && (dinput >= 1e21 || dinput <= -1e21))
|
||||
mode = DTOSTR_STANDARD;
|
||||
|
||||
LOCK_DTOA();
|
||||
dval(d) = dinput;
|
||||
numBegin = dtoa(d, dtoaModes[mode], precision, &decPt, &sign, &numEnd);
|
||||
numBegin = dtoa(PASS_STATE d, dtoaModes[mode], precision, &decPt, &sign, &numEnd);
|
||||
if (!numBegin) {
|
||||
UNLOCK_DTOA();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nDigits = numEnd - numBegin;
|
||||
JS_ASSERT((size_t) nDigits <= bufferSize - 2);
|
||||
if ((size_t) nDigits > bufferSize - 2) {
|
||||
UNLOCK_DTOA();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buffer + 2, numBegin, nDigits);
|
||||
freedtoa(numBegin);
|
||||
UNLOCK_DTOA();
|
||||
freedtoa(PASS_STATE numBegin);
|
||||
numBegin = buffer + 2; /* +2 leaves space for sign and/or decimal point */
|
||||
numEnd = numBegin + nDigits;
|
||||
*numEnd = '\0';
|
||||
@ -353,8 +308,8 @@ static uint32 quorem2(Bigint *b, int32 k)
|
||||
#define DTOBASESTR_BUFFER_SIZE 1078
|
||||
#define BASEDIGIT(digit) ((char)(((digit) >= 10) ? 'a' - 10 + (digit) : '0' + (digit)))
|
||||
|
||||
JS_FRIEND_API(char *)
|
||||
JS_dtobasestr(int base, double dinput)
|
||||
char *
|
||||
js_dtobasestr(DtoaState *state, int base, double dinput)
|
||||
{
|
||||
U d;
|
||||
char *buffer; /* The output string */
|
||||
@ -386,7 +341,6 @@ JS_dtobasestr(int base, double dinput)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
LOCK_DTOA();
|
||||
/* Output the integer part of d with the digits in reverse order. */
|
||||
pInt = p;
|
||||
dval(di) = floor(dval(d));
|
||||
@ -404,14 +358,13 @@ JS_dtobasestr(int base, double dinput)
|
||||
} else {
|
||||
int e;
|
||||
int bits; /* Number of significant bits in di; not used. */
|
||||
Bigint *b = d2b(di, &e, &bits);
|
||||
Bigint *b = d2b(PASS_STATE di, &e, &bits);
|
||||
if (!b)
|
||||
goto nomem1;
|
||||
b = lshift(b, e);
|
||||
b = lshift(PASS_STATE b, e);
|
||||
if (!b) {
|
||||
nomem1:
|
||||
Bfree(b);
|
||||
UNLOCK_DTOA();
|
||||
Bfree(PASS_STATE b);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
@ -420,7 +373,7 @@ JS_dtobasestr(int base, double dinput)
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (b->wds);
|
||||
Bfree(b);
|
||||
Bfree(PASS_STATE b);
|
||||
}
|
||||
/* Reverse the digits of the integer part of d. */
|
||||
q = p-1;
|
||||
@ -440,15 +393,14 @@ JS_dtobasestr(int base, double dinput)
|
||||
b = s = mlo = mhi = NULL;
|
||||
|
||||
*p++ = '.';
|
||||
b = d2b(df, &e, &bbits);
|
||||
b = d2b(PASS_STATE df, &e, &bbits);
|
||||
if (!b) {
|
||||
nomem2:
|
||||
Bfree(b);
|
||||
Bfree(s);
|
||||
Bfree(PASS_STATE b);
|
||||
Bfree(PASS_STATE s);
|
||||
if (mlo != mhi)
|
||||
Bfree(mlo);
|
||||
Bfree(mhi);
|
||||
UNLOCK_DTOA();
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
js_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
@ -463,7 +415,7 @@ JS_dtobasestr(int base, double dinput)
|
||||
s2 += Bias + P;
|
||||
/* 1/2^s2 = (nextDouble(d) - d)/2 */
|
||||
JS_ASSERT(-s2 < e);
|
||||
mlo = i2b(1);
|
||||
mlo = i2b(PASS_STATE 1);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = mlo;
|
||||
@ -475,17 +427,17 @@ JS_dtobasestr(int base, double dinput)
|
||||
/* The special case. Here we want to be within a quarter of the last input
|
||||
significant digit instead of one half of it when the output string's value is less than d. */
|
||||
s2 += Log2P;
|
||||
mhi = i2b(1<<Log2P);
|
||||
mhi = i2b(PASS_STATE 1<<Log2P);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
b = lshift(b, e + s2);
|
||||
b = lshift(PASS_STATE b, e + s2);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
s = i2b(1);
|
||||
s = i2b(PASS_STATE 1);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
s = lshift(s, s2);
|
||||
s = lshift(PASS_STATE s, s2);
|
||||
if (!s)
|
||||
goto nomem2;
|
||||
/* At this point we have the following:
|
||||
@ -499,20 +451,20 @@ JS_dtobasestr(int base, double dinput)
|
||||
int32 j, j1;
|
||||
Bigint *delta;
|
||||
|
||||
b = multadd(b, base, 0);
|
||||
b = multadd(PASS_STATE b, base, 0);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
digit = quorem2(b, s2);
|
||||
if (mlo == mhi) {
|
||||
mlo = mhi = multadd(mlo, base, 0);
|
||||
mlo = mhi = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
else {
|
||||
mlo = multadd(mlo, base, 0);
|
||||
mlo = multadd(PASS_STATE mlo, base, 0);
|
||||
if (!mlo)
|
||||
goto nomem2;
|
||||
mhi = multadd(mhi, base, 0);
|
||||
mhi = multadd(PASS_STATE mhi, base, 0);
|
||||
if (!mhi)
|
||||
goto nomem2;
|
||||
}
|
||||
@ -520,11 +472,11 @@ JS_dtobasestr(int base, double dinput)
|
||||
/* Do we yet have the shortest string that will round to d? */
|
||||
j = cmp(b, mlo);
|
||||
/* j is b/2^s2 compared with mlo/2^s2. */
|
||||
delta = diff(s, mhi);
|
||||
delta = diff(PASS_STATE s, mhi);
|
||||
if (!delta)
|
||||
goto nomem2;
|
||||
j1 = delta->sign ? 1 : cmp(b, delta);
|
||||
Bfree(delta);
|
||||
Bfree(PASS_STATE delta);
|
||||
/* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
|
||||
|
||||
#ifndef ROUND_BIASED
|
||||
@ -542,7 +494,7 @@ JS_dtobasestr(int base, double dinput)
|
||||
if (j1 > 0) {
|
||||
/* Either dig or dig+1 would work here as the least significant digit.
|
||||
Use whichever would produce an output value closer to d. */
|
||||
b = lshift(b, 1);
|
||||
b = lshift(PASS_STATE b, 1);
|
||||
if (!b)
|
||||
goto nomem2;
|
||||
j1 = cmp(b, s);
|
||||
@ -558,15 +510,26 @@ JS_dtobasestr(int base, double dinput)
|
||||
JS_ASSERT(digit < (uint32)base);
|
||||
*p++ = BASEDIGIT(digit);
|
||||
} while (!done);
|
||||
Bfree(b);
|
||||
Bfree(s);
|
||||
Bfree(PASS_STATE b);
|
||||
Bfree(PASS_STATE s);
|
||||
if (mlo != mhi)
|
||||
Bfree(mlo);
|
||||
Bfree(mhi);
|
||||
Bfree(PASS_STATE mlo);
|
||||
Bfree(PASS_STATE mhi);
|
||||
}
|
||||
JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
|
||||
*p = '\0';
|
||||
UNLOCK_DTOA();
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
DtoaState *
|
||||
js_NewDtoaState()
|
||||
{
|
||||
return newdtoa();
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyDtoaState(DtoaState *state)
|
||||
{
|
||||
destroydtoa(state);
|
||||
}
|
||||
|
@ -48,23 +48,30 @@
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct DtoaState;
|
||||
|
||||
DtoaState *
|
||||
js_NewDtoaState();
|
||||
|
||||
void
|
||||
js_DestroyDtoaState(DtoaState *state);
|
||||
|
||||
/*
|
||||
* JS_strtod() returns as a double-precision floating-point number
|
||||
* the value represented by the character string pointed to by
|
||||
* s00. The string is scanned up to the first unrecognized
|
||||
* character.
|
||||
* If the value of se is not (char **)NULL, a pointer to
|
||||
* the character terminating the scan is returned in the location pointed
|
||||
* to by se. If no number can be formed, se is set to s00r, and
|
||||
* zero is returned.
|
||||
* js_strtod_harder() returns as a double-precision floating-point number the
|
||||
* value represented by the character string pointed to by s00. The string is
|
||||
* scanned up to the first unrecognized character.
|
||||
*
|
||||
* If se is not NULL, *se receives a pointer to the character terminating the
|
||||
* scan. If no number can be formed, *se receives a pointer to the first
|
||||
* unparseable character in s00, and zero is returned.
|
||||
*
|
||||
* *err is set to zero on success; it's set to JS_DTOA_ERANGE on range
|
||||
* errors and JS_DTOA_ENOMEM on memory failure.
|
||||
*/
|
||||
#define JS_DTOA_ERANGE 1
|
||||
#define JS_DTOA_ENOMEM 2
|
||||
JS_FRIEND_API(double)
|
||||
JS_strtod(const char *s00, char **se, int *err);
|
||||
double
|
||||
js_strtod_harder(DtoaState *state, const char *s00, char **se, int *err);
|
||||
|
||||
/*
|
||||
* Modes for converting floating-point numbers to strings.
|
||||
@ -102,8 +109,9 @@ typedef enum JSDToStrMode {
|
||||
*
|
||||
* Return NULL if out of memory.
|
||||
*/
|
||||
JS_FRIEND_API(char *)
|
||||
JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval);
|
||||
char *
|
||||
js_dtostr(DtoaState *state, char *buffer, size_t bufferSize, JSDToStrMode mode, int precision,
|
||||
double dval);
|
||||
|
||||
/*
|
||||
* Convert d to a string in the given base. The integral part of d will be printed exactly
|
||||
@ -116,15 +124,8 @@ JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, dou
|
||||
*
|
||||
* Return NULL if out of memory. If the result is not NULL, it must be released via free().
|
||||
*/
|
||||
JS_FRIEND_API(char *)
|
||||
JS_dtobasestr(int base, double d);
|
||||
|
||||
/*
|
||||
* Clean up any persistent RAM allocated during the execution of DtoA
|
||||
* routines, and remove any locks that might have been created.
|
||||
*/
|
||||
JS_FRIEND_API(JSBool) js_InitDtoa(void);
|
||||
JS_FRIEND_API(void) js_FinishDtoa(void);
|
||||
char *
|
||||
js_dtobasestr(DtoaState *state, int base, double d);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
|
@ -321,7 +321,8 @@ num_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, numBuf, sizeof numBuf,
|
||||
DTOSTR_STANDARD, 0, d);
|
||||
if (!numStr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
@ -575,7 +576,8 @@ num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
|
||||
return JS_FALSE;
|
||||
precision = js_DoubleToInteger(precision);
|
||||
if (precision < precisionMin || precision > precisionMax) {
|
||||
numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf,
|
||||
DTOSTR_STANDARD, 0, precision);
|
||||
if (!numStr)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
else
|
||||
@ -584,7 +586,8 @@ num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
|
||||
}
|
||||
}
|
||||
|
||||
numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf,
|
||||
oneArgMode, (jsint)precision + precisionOffset, d);
|
||||
if (!numStr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
@ -847,9 +850,10 @@ NumberToCString(JSContext *cx, jsdouble d, jsint base, char *buf, size_t bufSize
|
||||
numStr = IntToCString(i, base, buf, bufSize);
|
||||
} else {
|
||||
if (base == 10)
|
||||
numStr = JS_dtostr(buf, bufSize, DTOSTR_STANDARD, 0, d);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, bufSize,
|
||||
DTOSTR_STANDARD, 0, d);
|
||||
else
|
||||
numStr = JS_dtobasestr(base, d);
|
||||
numStr = js_dtobasestr(JS_THREAD_DATA(cx)->dtoaState, base, d);
|
||||
if (!numStr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
@ -915,7 +919,8 @@ js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
|
||||
cstr = IntToCString(JSVAL_TO_INT(v), 10, arr, arrSize);
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE(v));
|
||||
cstr = JS_dtostr(arr, arrSize, DTOSTR_STANDARD, 0, *JSVAL_TO_DOUBLE(v));
|
||||
cstr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, arr, arrSize,
|
||||
DTOSTR_STANDARD, 0, *JSVAL_TO_DOUBLE(v));
|
||||
}
|
||||
if (!cstr)
|
||||
return JS_FALSE;
|
||||
@ -1178,7 +1183,7 @@ js_strtod(JSContext *cx, const jschar *s, const jschar *send,
|
||||
estr = istr + 8;
|
||||
} else {
|
||||
int err;
|
||||
d = JS_strtod(cstr, &estr, &err);
|
||||
d = js_strtod_harder(JS_THREAD_DATA(cx)->dtoaState, cstr, &estr, &err);
|
||||
if (d == HUGE_VAL)
|
||||
d = js_PositiveInfinity;
|
||||
else if (d == -HUGE_VAL)
|
||||
@ -1296,7 +1301,7 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
|
||||
/*
|
||||
* If we're accumulating a decimal number and the number is >=
|
||||
* 2^53, then the result from the repeated multiply-add above may
|
||||
* be inaccurate. Call JS_strtod to get the correct answer.
|
||||
* be inaccurate. Call js_strtod_harder to get the correct answer.
|
||||
*/
|
||||
size_t i;
|
||||
size_t length = s1 - start;
|
||||
@ -1310,7 +1315,7 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
|
||||
cstr[i] = (char)start[i];
|
||||
cstr[length] = 0;
|
||||
|
||||
value = JS_strtod(cstr, &estr, &err);
|
||||
value = js_strtod_harder(JS_THREAD_DATA(cx)->dtoaState, cstr, &estr, &err);
|
||||
if (err == JS_DTOA_ENOMEM) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
cx->free(cstr);
|
||||
|
@ -482,7 +482,8 @@ Str(JSContext *cx, jsid id, JSObject *holder, StringifyContext *scx, jsval *vp,
|
||||
|
||||
char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
|
||||
jsdouble d = JSVAL_IS_INT(*vp) ? jsdouble(JSVAL_TO_INT(*vp)) : *JSVAL_TO_DOUBLE(*vp);
|
||||
numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, numBuf, sizeof numBuf,
|
||||
DTOSTR_STANDARD, 0, d);
|
||||
if (!numStr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
|
@ -1107,7 +1107,8 @@ SprintDoubleValue(Sprinter *sp, jsval v, JSOp *opp)
|
||||
: "1 / 0");
|
||||
*opp = JSOP_DIV;
|
||||
} else {
|
||||
s = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d);
|
||||
s = js_dtostr(JS_THREAD_DATA(sp->context)->dtoaState, buf, sizeof buf,
|
||||
DTOSTR_STANDARD, 0, d);
|
||||
if (!s) {
|
||||
JS_ReportOutOfMemory(sp->context);
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user