bpo-42208: Pass tstate to _PyGC_CollectNoFail() (GH-23038)

Move private _PyGC_CollectNoFail() to the internal C API.

Remove the private _PyGC_CollectIfEnabled() which was just an alias
to the public PyGC_Collect() function since Python 3.8.

Rename functions:

* collect() => gc_collect_main()
* collect_with_callback() => gc_collect_with_callback()
* collect_generations() => gc_collect_generations()
This commit is contained in:
Victor Stinner 2020-10-30 17:00:00 +01:00 committed by GitHub
parent 99608c733c
commit 8b3414818f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 34 deletions

View File

@ -79,10 +79,6 @@ PyAPI_FUNC(void) PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator);
PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator); PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator);
PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void);
PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void);
/* Test if an object implements the garbage collector protocol */ /* Test if an object implements the garbage collector protocol */
PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj); PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj);

View File

@ -161,7 +161,9 @@ struct _gc_runtime_state {
Py_ssize_t long_lived_pending; Py_ssize_t long_lived_pending;
}; };
PyAPI_FUNC(void) _PyGC_InitState(struct _gc_runtime_state *); extern void _PyGC_InitState(struct _gc_runtime_state *);
extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate);
// Functions to clear types free lists // Functions to clear types free lists

View File

@ -1176,8 +1176,9 @@ handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable,
/* This is the main function. Read this to understand how the /* This is the main function. Read this to understand how the
* collection process works. */ * collection process works. */
static Py_ssize_t static Py_ssize_t
collect(PyThreadState *tstate, int generation, gc_collect_main(PyThreadState *tstate, int generation,
Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, int nofail) Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
int nofail)
{ {
int i; int i;
Py_ssize_t m = 0; /* # objects collected */ Py_ssize_t m = 0; /* # objects collected */
@ -1395,19 +1396,19 @@ invoke_gc_callback(PyThreadState *tstate, const char *phase,
* progress callbacks. * progress callbacks.
*/ */
static Py_ssize_t static Py_ssize_t
collect_with_callback(PyThreadState *tstate, int generation) gc_collect_with_callback(PyThreadState *tstate, int generation)
{ {
assert(!_PyErr_Occurred(tstate)); assert(!_PyErr_Occurred(tstate));
Py_ssize_t result, collected, uncollectable; Py_ssize_t result, collected, uncollectable;
invoke_gc_callback(tstate, "start", generation, 0, 0); invoke_gc_callback(tstate, "start", generation, 0, 0);
result = collect(tstate, generation, &collected, &uncollectable, 0); result = gc_collect_main(tstate, generation, &collected, &uncollectable, 0);
invoke_gc_callback(tstate, "stop", generation, collected, uncollectable); invoke_gc_callback(tstate, "stop", generation, collected, uncollectable);
assert(!_PyErr_Occurred(tstate)); assert(!_PyErr_Occurred(tstate));
return result; return result;
} }
static Py_ssize_t static Py_ssize_t
collect_generations(PyThreadState *tstate) gc_collect_generations(PyThreadState *tstate)
{ {
GCState *gcstate = &tstate->interp->gc; GCState *gcstate = &tstate->interp->gc;
/* Find the oldest generation (highest numbered) where the count /* Find the oldest generation (highest numbered) where the count
@ -1455,7 +1456,7 @@ collect_generations(PyThreadState *tstate)
if (i == NUM_GENERATIONS - 1 if (i == NUM_GENERATIONS - 1
&& gcstate->long_lived_pending < gcstate->long_lived_total / 4) && gcstate->long_lived_pending < gcstate->long_lived_total / 4)
continue; continue;
n = collect_with_callback(tstate, i); n = gc_collect_with_callback(tstate, i);
break; break;
} }
} }
@ -1541,7 +1542,7 @@ gc_collect_impl(PyObject *module, int generation)
} }
else { else {
gcstate->collecting = 1; gcstate->collecting = 1;
n = collect_with_callback(tstate, generation); n = gc_collect_with_callback(tstate, generation);
gcstate->collecting = 0; gcstate->collecting = 0;
} }
return n; return n;
@ -2041,7 +2042,7 @@ PyInit_gc(void)
return m; return m;
} }
/* API to invoke gc.collect() from C */ /* Public API to invoke gc.collect() from C */
Py_ssize_t Py_ssize_t
PyGC_Collect(void) PyGC_Collect(void)
{ {
@ -2061,7 +2062,7 @@ PyGC_Collect(void)
PyObject *exc, *value, *tb; PyObject *exc, *value, *tb;
gcstate->collecting = 1; gcstate->collecting = 1;
_PyErr_Fetch(tstate, &exc, &value, &tb); _PyErr_Fetch(tstate, &exc, &value, &tb);
n = collect_with_callback(tstate, NUM_GENERATIONS - 1); n = gc_collect_with_callback(tstate, NUM_GENERATIONS - 1);
_PyErr_Restore(tstate, exc, value, tb); _PyErr_Restore(tstate, exc, value, tb);
gcstate->collecting = 0; gcstate->collecting = 0;
} }
@ -2070,19 +2071,11 @@ PyGC_Collect(void)
} }
Py_ssize_t Py_ssize_t
_PyGC_CollectIfEnabled(void) _PyGC_CollectNoFail(PyThreadState *tstate)
{ {
return PyGC_Collect();
}
Py_ssize_t
_PyGC_CollectNoFail(void)
{
PyThreadState *tstate = _PyThreadState_GET();
assert(!_PyErr_Occurred(tstate)); assert(!_PyErr_Occurred(tstate));
GCState *gcstate = &tstate->interp->gc; GCState *gcstate = &tstate->interp->gc;
Py_ssize_t n;
/* Ideally, this function is only called on interpreter shutdown, /* Ideally, this function is only called on interpreter shutdown,
and therefore not recursively. Unfortunately, when there are daemon and therefore not recursively. Unfortunately, when there are daemon
@ -2091,13 +2084,13 @@ _PyGC_CollectNoFail(void)
See http://bugs.python.org/issue8713#msg195178 for an example. See http://bugs.python.org/issue8713#msg195178 for an example.
*/ */
if (gcstate->collecting) { if (gcstate->collecting) {
n = 0; return 0;
} }
else {
Py_ssize_t n;
gcstate->collecting = 1; gcstate->collecting = 1;
n = collect(tstate, NUM_GENERATIONS - 1, NULL, NULL, 1); n = gc_collect_main(tstate, NUM_GENERATIONS - 1, NULL, NULL, 1);
gcstate->collecting = 0; gcstate->collecting = 0;
}
return n; return n;
} }
@ -2240,7 +2233,7 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize)
!_PyErr_Occurred(tstate)) !_PyErr_Occurred(tstate))
{ {
gcstate->collecting = 1; gcstate->collecting = 1;
collect_generations(tstate); gc_collect_generations(tstate);
gcstate->collecting = 0; gcstate->collecting = 0;
} }
PyObject *op = FROM_GC(g); PyObject *op = FROM_GC(g);

View File

@ -566,7 +566,7 @@ _PyImport_Cleanup(PyThreadState *tstate)
} }
Py_XDECREF(dict); Py_XDECREF(dict);
/* Collect references */ /* Collect references */
_PyGC_CollectNoFail(); _PyGC_CollectNoFail(tstate);
/* Dump GC stats before it's too late, since it uses the warnings /* Dump GC stats before it's too late, since it uses the warnings
machinery. */ machinery. */
_PyGC_DumpShutdownStats(tstate); _PyGC_DumpShutdownStats(tstate);
@ -626,7 +626,7 @@ _PyImport_Cleanup(PyThreadState *tstate)
Py_DECREF(modules); Py_DECREF(modules);
/* Once more */ /* Once more */
_PyGC_CollectNoFail(); _PyGC_CollectNoFail(tstate);
#undef CLEAR_MODULE #undef CLEAR_MODULE
#undef STORE_MODULE_WEAKREF #undef STORE_MODULE_WEAKREF

View File

@ -1293,7 +1293,7 @@ finalize_interp_clear(PyThreadState *tstate)
PyInterpreterState_Clear(tstate->interp); PyInterpreterState_Clear(tstate->interp);
/* Last explicit GC collection */ /* Last explicit GC collection */
_PyGC_CollectNoFail(); _PyGC_CollectNoFail(tstate);
/* Clear all loghooks */ /* Clear all loghooks */
/* Both _PySys_Audit function and users still need PyObject, such as tuple. /* Both _PySys_Audit function and users still need PyObject, such as tuple.
@ -1414,7 +1414,7 @@ Py_FinalizeEx(void)
* XXX but I'm unclear on exactly how that one happens. In any case, * XXX but I'm unclear on exactly how that one happens. In any case,
* XXX I haven't seen a real-life report of either of these. * XXX I haven't seen a real-life report of either of these.
*/ */
_PyGC_CollectIfEnabled(); PyGC_Collect();
/* Destroy all modules */ /* Destroy all modules */
_PyImport_Cleanup(tstate); _PyImport_Cleanup(tstate);