Merged revisions 77589 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r77589 | mark.dickinson | 2010-01-17 20:57:56 +0000 (Sun, 17 Jan 2010) | 7 lines

  Issue #7632: When Py_USING_MEMORY_DEBUGGER is defined, disable the
  private memory allocation scheme in dtoa.c, along with a piece of code
  that caches powers of 5 for future use.  This makes it easier to
  detect dtoa.c memory leaks with Valgrind or similar tools.

  Patch by Stefan Krah.
........
This commit is contained in:
Mark Dickinson 2010-01-17 21:02:55 +00:00
parent 2ff627a686
commit de5080038f
2 changed files with 102 additions and 0 deletions

View File

@ -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

View File

@ -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 digits */
static Bigint *
Balloc(int k)
{
int x;
Bigint *rv;
unsigned int len;
x = 1 << k;
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
rv = (Bigint*)MALLOC(len*sizeof(double));
if (rv == NULL)
return NULL;
rv->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. */