gh-113688: Split up gcmodule.c (gh-113715)

This splits part of Modules/gcmodule.c of into Python/gc.c, which
now contains the core garbage collection implementation. The Python
module remain in the Modules/gcmodule.c file.
This commit is contained in:
Sam Gross 2024-01-05 15:17:16 -05:00 committed by GitHub
parent 0b7476080b
commit 99854ce170
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2032 additions and 1961 deletions

View File

@ -64,6 +64,26 @@ static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) {
#define _PyGC_PREV_SHIFT (2) #define _PyGC_PREV_SHIFT (2)
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT) #define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
/* set for debugging information */
#define _PyGC_DEBUG_STATS (1<<0) /* print collection statistics */
#define _PyGC_DEBUG_COLLECTABLE (1<<1) /* print collectable objects */
#define _PyGC_DEBUG_UNCOLLECTABLE (1<<2) /* print uncollectable objects */
#define _PyGC_DEBUG_SAVEALL (1<<5) /* save all garbage in gc.garbage */
#define _PyGC_DEBUG_LEAK _PyGC_DEBUG_COLLECTABLE | \
_PyGC_DEBUG_UNCOLLECTABLE | \
_PyGC_DEBUG_SAVEALL
typedef enum {
// GC was triggered by heap allocation
_Py_GC_REASON_HEAP,
// GC was called during shutdown
_Py_GC_REASON_SHUTDOWN,
// GC was called by gc.collect() or PyGC_Collect()
_Py_GC_REASON_MANUAL
} _PyGC_Reason;
// Lowest bit of _gc_next is used for flags only in GC. // Lowest bit of _gc_next is used for flags only in GC.
// But it is always 0 for normal code. // But it is always 0 for normal code.
static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) { static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) {
@ -203,8 +223,19 @@ struct _gc_runtime_state {
extern void _PyGC_InitState(struct _gc_runtime_state *); extern void _PyGC_InitState(struct _gc_runtime_state *);
extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation,
_PyGC_Reason reason);
extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate); extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate);
/* Freeze objects tracked by the GC and ignore them in future collections. */
extern void _PyGC_Freeze(PyInterpreterState *interp);
/* Unfreezes objects placing them in the oldest generation */
extern void _PyGC_Unfreeze(PyInterpreterState *interp);
/* Number of frozen objects */
extern Py_ssize_t _PyGC_GetFreezeCount(PyInterpreterState *interp);
extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, Py_ssize_t generation);
extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs);
// Functions to clear types free lists // Functions to clear types free lists
extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); extern void _PyTuple_ClearFreeList(PyInterpreterState *interp);

View File

@ -1225,7 +1225,7 @@ class GCCallbackTests(unittest.TestCase):
p.stderr.close() p.stderr.close()
# Verify that stderr has a useful error message: # Verify that stderr has a useful error message:
self.assertRegex(stderr, self.assertRegex(stderr,
br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.') br'gc\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.')
self.assertRegex(stderr, self.assertRegex(stderr,
br'refcount is too small') br'refcount is too small')
# "address : 0x7fb5062efc18" # "address : 0x7fb5062efc18"

View File

@ -417,6 +417,7 @@ PYTHON_OBJS= \
Python/frame.o \ Python/frame.o \
Python/frozenmain.o \ Python/frozenmain.o \
Python/future.o \ Python/future.o \
Python/gc.o \
Python/getargs.o \ Python/getargs.o \
Python/getcompiler.o \ Python/getcompiler.o \
Python/getcopyright.o \ Python/getcopyright.o \

File diff suppressed because it is too large Load Diff

View File

@ -207,6 +207,7 @@
<ClCompile Include="..\Python\formatter_unicode.c" /> <ClCompile Include="..\Python\formatter_unicode.c" />
<ClCompile Include="..\Python\frame.c" /> <ClCompile Include="..\Python\frame.c" />
<ClCompile Include="..\Python\future.c" /> <ClCompile Include="..\Python\future.c" />
<ClCompile Include="..\Python\gc.c" />
<ClCompile Include="..\Python\getargs.c" /> <ClCompile Include="..\Python\getargs.c" />
<ClCompile Include="..\Python\getcompiler.c" /> <ClCompile Include="..\Python\getcompiler.c" />
<ClCompile Include="..\Python\getcopyright.c" /> <ClCompile Include="..\Python\getcopyright.c" />

View File

@ -166,6 +166,9 @@
<ClCompile Include="..\Python\future.c"> <ClCompile Include="..\Python\future.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\gc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\gcmodule.c"> <ClCompile Include="..\Modules\gcmodule.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@ -566,6 +566,7 @@
<AdditionalIncludeDirectories>$(GeneratedFrozenModulesDir)Python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(GeneratedFrozenModulesDir)Python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\future.c" /> <ClCompile Include="..\Python\future.c" />
<ClCompile Include="..\Python\gc.c" />
<ClCompile Include="..\Python\getargs.c" /> <ClCompile Include="..\Python\getargs.c" />
<ClCompile Include="..\Python\getcompiler.c" /> <ClCompile Include="..\Python\getcompiler.c" />
<ClCompile Include="..\Python\getcopyright.c" /> <ClCompile Include="..\Python\getcopyright.c" />

View File

@ -1280,6 +1280,9 @@
<ClCompile Include="..\Python\future.c"> <ClCompile Include="..\Python\future.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\gc.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\getargs.c"> <ClCompile Include="..\Python\getargs.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>

1958
Python/gc.c Normal file

File diff suppressed because it is too large Load Diff