mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-112529: Implement GC for free-threaded builds (#114262)
* gh-112529: Implement GC for free-threaded builds This implements a mark and sweep GC for the free-threaded builds of CPython. The implementation relies on mimalloc to find GC tracked objects (i.e., "containers").
This commit is contained in:
parent
4850410b60
commit
b52fc70d1a
18 changed files with 1952 additions and 22 deletions
84
Include/internal/pycore_object_stack.h
Normal file
84
Include/internal/pycore_object_stack.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#ifndef Py_INTERNAL_OBJECT_STACK_H
|
||||
#define Py_INTERNAL_OBJECT_STACK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
// _PyObjectStack is a stack of Python objects implemented as a linked list of
|
||||
// fixed size buffers.
|
||||
|
||||
// Chosen so that _PyObjectStackChunk is a power-of-two size.
|
||||
#define _Py_OBJECT_STACK_CHUNK_SIZE 254
|
||||
|
||||
typedef struct _PyObjectStackChunk {
|
||||
struct _PyObjectStackChunk *prev;
|
||||
Py_ssize_t n;
|
||||
PyObject *objs[_Py_OBJECT_STACK_CHUNK_SIZE];
|
||||
} _PyObjectStackChunk;
|
||||
|
||||
typedef struct _PyObjectStack {
|
||||
_PyObjectStackChunk *head;
|
||||
} _PyObjectStack;
|
||||
|
||||
|
||||
extern _PyObjectStackChunk *
|
||||
_PyObjectStackChunk_New(void);
|
||||
|
||||
extern void
|
||||
_PyObjectStackChunk_Free(_PyObjectStackChunk *);
|
||||
|
||||
extern void
|
||||
_PyObjectStackChunk_ClearFreeList(_PyFreeListState *state, int is_finalization);
|
||||
|
||||
// Push an item onto the stack. Return -1 on allocation failure, 0 on success.
|
||||
static inline int
|
||||
_PyObjectStack_Push(_PyObjectStack *stack, PyObject *obj)
|
||||
{
|
||||
_PyObjectStackChunk *buf = stack->head;
|
||||
if (buf == NULL || buf->n == _Py_OBJECT_STACK_CHUNK_SIZE) {
|
||||
buf = _PyObjectStackChunk_New();
|
||||
if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buf->prev = stack->head;
|
||||
buf->n = 0;
|
||||
stack->head = buf;
|
||||
}
|
||||
|
||||
assert(buf->n >= 0 && buf->n < _Py_OBJECT_STACK_CHUNK_SIZE);
|
||||
buf->objs[buf->n] = obj;
|
||||
buf->n++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pop the top item from the stack. Return NULL if the stack is empty.
|
||||
static inline PyObject *
|
||||
_PyObjectStack_Pop(_PyObjectStack *stack)
|
||||
{
|
||||
_PyObjectStackChunk *buf = stack->head;
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
assert(buf->n > 0 && buf->n <= _Py_OBJECT_STACK_CHUNK_SIZE);
|
||||
buf->n--;
|
||||
PyObject *obj = buf->objs[buf->n];
|
||||
if (buf->n == 0) {
|
||||
stack->head = buf->prev;
|
||||
_PyObjectStackChunk_Free(buf);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Remove all items from the stack
|
||||
extern void
|
||||
_PyObjectStack_Clear(_PyObjectStack *stack);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // !Py_INTERNAL_OBJECT_STACK_H
|
Loading…
Add table
Add a link
Reference in a new issue