Issue #18874: _PyObject_Malloc/Realloc/Free() now falls back on

_PyMem_RawMalloc/Realloc/Free, instead of _PyMem_Malloc/Realloc/Free.  So it
becomes possible to use the fast pymalloc allocator for the PYMEM_DOMAIN_MEM
domain (PyMem_Malloc/Realloc/Free functions).
This commit is contained in:
Victor Stinner 2013-10-10 15:58:42 +02:00
parent 7c74de4d00
commit 6cf185dc06
2 changed files with 21 additions and 19 deletions

View File

@ -288,8 +288,8 @@ Customize PyObject Arena Allocator
Python has a *pymalloc* allocator for allocations smaller than 512 bytes. This Python has a *pymalloc* allocator for allocations smaller than 512 bytes. This
allocator is optimized for small objects with a short lifetime. It uses memory allocator is optimized for small objects with a short lifetime. It uses memory
mappings called "arenas" with a fixed size of 256 KB. It falls back to mappings called "arenas" with a fixed size of 256 KB. It falls back to
:c:func:`PyMem_Malloc` and :c:func:`PyMem_Realloc` for allocations larger than :c:func:`PyMem_RawMalloc` and :c:func:`PyMem_RawRealloc` for allocations larger
512 bytes. *pymalloc* is the default allocator used by than 512 bytes. *pymalloc* is the default allocator used by
:c:func:`PyObject_Malloc`. :c:func:`PyObject_Malloc`.
The default arena allocator uses the following functions: The default arena allocator uses the following functions:

View File

@ -125,10 +125,11 @@ _PyObject_ArenaFree(void *ctx, void *ptr, size_t size)
#define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawRealloc, _PyMem_RawFree #define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawRealloc, _PyMem_RawFree
#ifdef WITH_PYMALLOC #ifdef WITH_PYMALLOC
#define PYOBJECT_FUNCS _PyObject_Malloc, _PyObject_Realloc, _PyObject_Free # define PYOBJ_FUNCS _PyObject_Malloc, _PyObject_Realloc, _PyObject_Free
#else #else
#define PYOBJECT_FUNCS PYRAW_FUNCS # define PYOBJ_FUNCS PYRAW_FUNCS
#endif #endif
#define PYMEM_FUNCS PYRAW_FUNCS
#ifdef PYMALLOC_DEBUG #ifdef PYMALLOC_DEBUG
typedef struct { typedef struct {
@ -142,16 +143,16 @@ static struct {
debug_alloc_api_t obj; debug_alloc_api_t obj;
} _PyMem_Debug = { } _PyMem_Debug = {
{'r', {NULL, PYRAW_FUNCS}}, {'r', {NULL, PYRAW_FUNCS}},
{'m', {NULL, PYRAW_FUNCS}}, {'m', {NULL, PYMEM_FUNCS}},
{'o', {NULL, PYOBJECT_FUNCS}} {'o', {NULL, PYOBJ_FUNCS}}
}; };
#define PYDEBUG_FUNCS _PyMem_DebugMalloc, _PyMem_DebugRealloc, _PyMem_DebugFree #define PYDBG_FUNCS _PyMem_DebugMalloc, _PyMem_DebugRealloc, _PyMem_DebugFree
#endif #endif
static PyMemAllocator _PyMem_Raw = { static PyMemAllocator _PyMem_Raw = {
#ifdef PYMALLOC_DEBUG #ifdef PYMALLOC_DEBUG
&_PyMem_Debug.raw, PYDEBUG_FUNCS &_PyMem_Debug.raw, PYDBG_FUNCS
#else #else
NULL, PYRAW_FUNCS NULL, PYRAW_FUNCS
#endif #endif
@ -159,23 +160,24 @@ static PyMemAllocator _PyMem_Raw = {
static PyMemAllocator _PyMem = { static PyMemAllocator _PyMem = {
#ifdef PYMALLOC_DEBUG #ifdef PYMALLOC_DEBUG
&_PyMem_Debug.mem, PYDEBUG_FUNCS &_PyMem_Debug.mem, PYDBG_FUNCS
#else #else
NULL, PYRAW_FUNCS NULL, PYMEM_FUNCS
#endif #endif
}; };
static PyMemAllocator _PyObject = { static PyMemAllocator _PyObject = {
#ifdef PYMALLOC_DEBUG #ifdef PYMALLOC_DEBUG
&_PyMem_Debug.obj, PYDEBUG_FUNCS &_PyMem_Debug.obj, PYDBG_FUNCS
#else #else
NULL, PYOBJECT_FUNCS NULL, PYOBJ_FUNCS
#endif #endif
}; };
#undef PYRAW_FUNCS #undef PYRAW_FUNCS
#undef PYOBJECT_FUNCS #undef PYMEM_FUNCS
#undef PYDEBUG_FUNCS #undef PYOBJ_FUNCS
#undef PYDBG_FUNCS
static PyObjectArenaAllocator _PyObject_Arena = {NULL, static PyObjectArenaAllocator _PyObject_Arena = {NULL,
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
@ -924,7 +926,7 @@ new_arena(void)
return NULL; /* overflow */ return NULL; /* overflow */
#endif #endif
nbytes = numarenas * sizeof(*arenas); nbytes = numarenas * sizeof(*arenas);
arenaobj = (struct arena_object *)PyMem_Realloc(arenas, nbytes); arenaobj = (struct arena_object *)PyMem_RawRealloc(arenas, nbytes);
if (arenaobj == NULL) if (arenaobj == NULL)
return NULL; return NULL;
arenas = arenaobj; arenas = arenaobj;
@ -1309,7 +1311,7 @@ redirect:
* has been reached. * has been reached.
*/ */
{ {
void *result = PyMem_Malloc(nbytes); void *result = PyMem_RawMalloc(nbytes);
if (!result) if (!result)
_Py_AllocatedBlocks--; _Py_AllocatedBlocks--;
return result; return result;
@ -1539,7 +1541,7 @@ _PyObject_Free(void *ctx, void *p)
redirect: redirect:
#endif #endif
/* We didn't allocate this address. */ /* We didn't allocate this address. */
PyMem_Free(p); PyMem_RawFree(p);
} }
/* realloc. If p is NULL, this acts like malloc(nbytes). Else if nbytes==0, /* realloc. If p is NULL, this acts like malloc(nbytes). Else if nbytes==0,
@ -1608,14 +1610,14 @@ _PyObject_Realloc(void *ctx, void *p, size_t nbytes)
* at p. Instead we punt: let C continue to manage this block. * at p. Instead we punt: let C continue to manage this block.
*/ */
if (nbytes) if (nbytes)
return PyMem_Realloc(p, nbytes); return PyMem_RawRealloc(p, nbytes);
/* C doesn't define the result of realloc(p, 0) (it may or may not /* C doesn't define the result of realloc(p, 0) (it may or may not
* return NULL then), but Python's docs promise that nbytes==0 never * return NULL then), but Python's docs promise that nbytes==0 never
* returns NULL. We don't pass 0 to realloc(), to avoid that endcase * returns NULL. We don't pass 0 to realloc(), to avoid that endcase
* to begin with. Even then, we can't be sure that realloc() won't * to begin with. Even then, we can't be sure that realloc() won't
* return NULL. * return NULL.
*/ */
bp = PyMem_Realloc(p, 1); bp = PyMem_RawRealloc(p, 1);
return bp ? bp : p; return bp ? bp : p;
} }