Remove spinlock in dtoa's Balloc, use xmalloc

The spinlock here performs poorly when there are multiple Ractors. The
improvement on single threaded performance doesn't seem that
significant, so I think we should just use malloc.
This commit is contained in:
John Hawthorn 2025-03-26 18:23:04 -07:00
parent 4646ab8917
commit b3b1d7b295
Notes: git 2025-04-07 23:57:00 +00:00

View File

@ -98,17 +98,6 @@
* 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 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,
* unless #defined to be a different length. This default length
* suffices to get rid of MALLOC calls except for unusual cases,
* such as decimal-to-binary conversion of a very long string of
* digits. The longest string dtoa can return is about 751 bytes
* long. For conversions by strtod of strings of 800 digits and
* all dtoa conversions in single-threaded executions with 8-byte
* pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
* pointers, PRIVATE_MEM >= 7112 appears adequate.
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for
* Infinity and NaN (case insensitively). On some systems (e.g.,
* some HP systems), it may be necessary to #define NAN_WORD0
@ -235,14 +224,6 @@ extern void FREE(void*);
#define NO_SANITIZE(x, y) y
#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
#undef Avoid_Underflow
#ifdef IEEE_BIG_ENDIAN
@ -527,60 +508,16 @@ struct Bigint {
typedef struct Bigint Bigint;
static Bigint *freelist[Kmax+1];
#define BLOCKING_BIGINT ((Bigint *)(-1))
static Bigint *
Balloc(int k)
{
int x;
Bigint *rv;
#ifndef Omit_Private_Memory
size_t len;
#endif
rv = 0;
ACQUIRE_DTOA_LOCK(0);
if (k <= Kmax) {
rv = freelist[k];
while (rv) {
Bigint *rvn = rv;
rv = ATOMIC_PTR_CAS(freelist[k], rv, BLOCKING_BIGINT);
if (LIKELY(rv != BLOCKING_BIGINT && rvn == rv)) {
rvn = ATOMIC_PTR_CAS(freelist[k], BLOCKING_BIGINT, rv->next);
assert(rvn == BLOCKING_BIGINT);
ASSUME(rv);
break;
}
}
}
if (!rv) {
x = 1 << k;
#ifdef Omit_Private_Memory
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
if (k <= Kmax) {
double *pnext = pmem_next;
while (pnext - private_mem + len <= PRIVATE_mem) {
double *p = pnext;
pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len);
if (LIKELY(p == pnext)) {
rv = (Bigint*)pnext;
ASSUME(rv);
break;
}
}
}
if (!rv)
rv = (Bigint*)MALLOC(len*sizeof(double));
#endif
rv->k = k;
rv->maxwds = x;
}
FREE_DTOA_LOCK(0);
x = 1 << k;
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
rv->k = k;
rv->maxwds = x;
rv->sign = rv->wds = 0;
return rv;
}
@ -588,21 +525,7 @@ Balloc(int k)
static void
Bfree(Bigint *v)
{
Bigint *vn;
if (v) {
if (v->k > Kmax) {
FREE(v);
return;
}
ACQUIRE_DTOA_LOCK(0);
do {
do {
vn = ATOMIC_PTR_CAS(freelist[v->k], 0, 0);
} while (UNLIKELY(vn == BLOCKING_BIGINT));
v->next = vn;
} while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn));
FREE_DTOA_LOCK(0);
}
FREE(v);
}
#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \