mirror of https://github.com/python/cpython
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:
parent
7c74de4d00
commit
6cf185dc06
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue