Skip to content

Commit 4891c36

Browse files
committed
pythongh-112529: Use GC mimalloc heaps for GC objects
1 parent a5504a0 commit 4891c36

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef Py_INTERNAL_OBJECT_ALLOC_H
2+
#define Py_INTERNAL_OBJECT_ALLOC_H
3+
4+
#include "pycore_object.h" // _PyType_HasFeature()
5+
#include "pycore_pystate.h" // _PyThreadState_GET()
6+
#include "pycore_tstate.h" // _PyThreadStateImpl
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
#ifndef Py_BUILD_CORE
13+
# error "this header requires Py_BUILD_CORE define"
14+
#endif
15+
16+
// Sets the heap used for PyObject_Malloc(), PyObject_Realloc(), etc. calls in
17+
// Py_GIL_DISABLED builds. We use different heaps depending on if the object
18+
// supports GC and if it has a pre-header. We smuggle the choice of heap
19+
// through the _mimalloc_thread_state.
20+
// This is a no-op outside of Py_GIL_DISABLED builds.
21+
static inline void *
22+
_PyObject_MallocWithType(PyTypeObject *tp, size_t size)
23+
{
24+
#ifdef Py_GIL_DISABLED
25+
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
26+
struct _mimalloc_thread_state *m = &tstate->mimalloc;
27+
if (_PyType_HasFeature(tp, Py_TPFLAGS_PREHEADER)) {
28+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_GC_PRE];
29+
}
30+
else if (_PyType_IS_GC(tp)) {
31+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_GC];
32+
}
33+
#endif
34+
void *mem = PyObject_Malloc(size);
35+
#ifdef Py_GIL_DISABLED
36+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_OBJECT];
37+
#endif
38+
return mem;
39+
}
40+
41+
static inline void *
42+
_PyObject_ReallocWithType(PyTypeObject *tp, void *ptr, size_t size)
43+
{
44+
#ifdef Py_GIL_DISABLED
45+
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
46+
struct _mimalloc_thread_state *m = &tstate->mimalloc;
47+
if (_PyType_HasFeature(tp, Py_TPFLAGS_PREHEADER)) {
48+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_GC_PRE];
49+
}
50+
else if (_PyType_IS_GC(tp)) {
51+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_GC];
52+
}
53+
#endif
54+
void *mem = PyObject_Realloc(ptr, size);
55+
#ifdef Py_GIL_DISABLED
56+
m->current_object_heap = &m->heaps[_Py_MIMALLOC_HEAP_OBJECT];
57+
#endif
58+
return mem;
59+
}
60+
61+
#ifdef __cplusplus
62+
}
63+
#endif
64+
#endif // !Py_INTERNAL_OBJECT_ALLOC_H

‎Objects/typeobject.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
1212
#include "pycore_moduleobject.h" // _PyModule_GetDef()
1313
#include "pycore_object.h" // _PyType_HasFeature()
14+
#include "pycore_object_alloc.h" // _PyObject_MallocWithType()
1415
#include "pycore_pyerrors.h" // _PyErr_Occurred()
1516
#include "pycore_pystate.h" // _PyThreadState_GET()
1617
#include "pycore_symtable.h" // _Py_Mangle()
@@ -1729,7 +1730,7 @@ _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems)
17291730
const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
17301731

17311732
const size_t presize = _PyType_PreHeaderSize(type);
1732-
char *alloc = PyObject_Malloc(size + presize);
1733+
char *alloc = _PyObject_MallocWithType(type, size + presize);
17331734
if (alloc == NULL) {
17341735
return PyErr_NoMemory();
17351736
}

0 commit comments

Comments
 (0)