diff --git a/Misc/NEWS b/Misc/NEWS index fba4060e902..8eecb72c2c2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -613,6 +613,10 @@ Extension Modules Build ----- +- Issue #7632: When Py_USING_MEMORY_DEBUGGER is defined, disable the + private memory allocation scheme in dtoa.c and use PyMem_Malloc and + PyMem_Free instead. Also disable caching of powers of 5. + - Issue #6491: Allow --with-dbmliborder to specify that no dbms will be built. - Issue #6943: Use pkg-config to find the libffi headers when the diff --git a/Python/dtoa.c b/Python/dtoa.c index 24ce9226079..de3ca9e4c74 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -308,6 +308,8 @@ Bigint { typedef struct Bigint Bigint; +#ifndef Py_USING_MEMORY_DEBUGGER + /* Memory management: memory is allocated from, and returned to, Kmax+1 pools of memory, where pool k (0 <= k <= Kmax) is for Bigints b with b->maxwds == 1 << k. These pools are maintained as linked lists, with freelist[k] @@ -375,6 +377,48 @@ Bfree(Bigint *v) } } +#else + +/* Alternative versions of Balloc and Bfree that use PyMem_Malloc and + PyMem_Free directly in place of the custom memory allocation scheme above. + These are provided for the benefit of memory debugging tools like + Valgrind. */ + +/* Allocate space for a Bigint with up to 1<k = k; + rv->maxwds = x; + rv->sign = rv->wds = 0; + return rv; +} + +/* Free a Bigint allocated with Balloc */ + +static void +Bfree(Bigint *v) +{ + if (v) { + FREE((void*)v); + } +} + +#endif /* Py_USING_MEMORY_DEBUGGER */ + #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ y->wds*sizeof(Long) + 2*sizeof(int)) @@ -652,6 +696,8 @@ mult(Bigint *a, Bigint *b) return c; } +#ifndef Py_USING_MEMORY_DEBUGGER + /* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */ static Bigint *p5s; @@ -711,6 +757,58 @@ pow5mult(Bigint *b, int k) return b; } +#else + +/* Version of pow5mult that doesn't cache powers of 5. Provided for + the benefit of memory debugging tools like Valgrind. */ + +static Bigint * +pow5mult(Bigint *b, int k) +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3)) { + b = multadd(b, p05[i-1], 0); + if (b == NULL) + return NULL; + } + + if (!(k >>= 2)) + return b; + p5 = i2b(625); + if (p5 == NULL) { + Bfree(b); + return NULL; + } + + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + if (b == NULL) { + Bfree(p5); + return NULL; + } + } + if (!(k >>= 1)) + break; + p51 = mult(p5, p5); + Bfree(p5); + p5 = p51; + if (p5 == NULL) { + Bfree(b); + return NULL; + } + } + Bfree(p5); + return b; +} + +#endif /* Py_USING_MEMORY_DEBUGGER */ + /* shift a Bigint b left by k bits. Return a pointer to the shifted result, or NULL on failure. If the returned pointer is distinct from b then the original b will have been Bfree'd. Ignores the sign of b. */