mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
[3.13] GH-124567: Revert the Incremental GC in 3.13 (#124770)
Revert the incremental GC in 3.13, since it's not clear that without further turning, the benefits outweigh the costs. Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
parent
bc1fae89af
commit
e0eb44ad49
11 changed files with 5525 additions and 5908 deletions
|
@ -142,26 +142,11 @@ static inline void _PyObject_GC_SET_SHARED_INLINE(PyObject *op) {
|
|||
|
||||
/* Bit flags for _gc_prev */
|
||||
/* Bit 0 is set when tp_finalize is called */
|
||||
#define _PyGC_PREV_MASK_FINALIZED 1
|
||||
#define _PyGC_PREV_MASK_FINALIZED (1)
|
||||
/* Bit 1 is set when the object is in generation which is GCed currently. */
|
||||
#define _PyGC_PREV_MASK_COLLECTING 2
|
||||
|
||||
/* Bit 0 in _gc_next is the old space bit.
|
||||
* It is set as follows:
|
||||
* Young: gcstate->visited_space
|
||||
* old[0]: 0
|
||||
* old[1]: 1
|
||||
* permanent: 0
|
||||
*
|
||||
* During a collection all objects handled should have the bit set to
|
||||
* gcstate->visited_space, as objects are moved from the young gen
|
||||
* and the increment into old[gcstate->visited_space].
|
||||
* When object are moved from the pending space, old[gcstate->visited_space^1]
|
||||
* into the increment, the old space bit is flipped.
|
||||
*/
|
||||
#define _PyGC_NEXT_MASK_OLD_SPACE_1 1
|
||||
|
||||
#define _PyGC_PREV_SHIFT 2
|
||||
#define _PyGC_PREV_MASK_COLLECTING (2)
|
||||
/* The (N-2) most significant bits contain the real address. */
|
||||
#define _PyGC_PREV_SHIFT (2)
|
||||
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
|
||||
|
||||
/* set for debugging information */
|
||||
|
@ -187,13 +172,11 @@ typedef enum {
|
|||
// Lowest bit of _gc_next is used for flags only in GC.
|
||||
// But it is always 0 for normal code.
|
||||
static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) {
|
||||
uintptr_t next = gc->_gc_next & _PyGC_PREV_MASK;
|
||||
uintptr_t next = gc->_gc_next;
|
||||
return (PyGC_Head*)next;
|
||||
}
|
||||
static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) {
|
||||
uintptr_t unext = (uintptr_t)next;
|
||||
assert((unext & ~_PyGC_PREV_MASK) == 0);
|
||||
gc->_gc_next = (gc->_gc_next & ~_PyGC_PREV_MASK) | unext;
|
||||
gc->_gc_next = (uintptr_t)next;
|
||||
}
|
||||
|
||||
// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
|
||||
|
@ -201,7 +184,6 @@ static inline PyGC_Head* _PyGCHead_PREV(PyGC_Head *gc) {
|
|||
uintptr_t prev = (gc->_gc_prev & _PyGC_PREV_MASK);
|
||||
return (PyGC_Head*)prev;
|
||||
}
|
||||
|
||||
static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) {
|
||||
uintptr_t uprev = (uintptr_t)prev;
|
||||
assert((uprev & ~_PyGC_PREV_MASK) == 0);
|
||||
|
@ -287,13 +269,6 @@ struct gc_generation {
|
|||
generations */
|
||||
};
|
||||
|
||||
struct gc_collection_stats {
|
||||
/* number of collected objects */
|
||||
Py_ssize_t collected;
|
||||
/* total number of uncollectable objects (put into gc.garbage) */
|
||||
Py_ssize_t uncollectable;
|
||||
};
|
||||
|
||||
/* Running stats per generation */
|
||||
struct gc_generation_stats {
|
||||
/* total number of collections */
|
||||
|
@ -315,8 +290,8 @@ struct _gc_runtime_state {
|
|||
int enabled;
|
||||
int debug;
|
||||
/* linked lists of container objects */
|
||||
struct gc_generation young;
|
||||
struct gc_generation old[2];
|
||||
struct gc_generation generations[NUM_GENERATIONS];
|
||||
PyGC_Head *generation0;
|
||||
/* a permanent generation which won't be collected */
|
||||
struct gc_generation permanent_generation;
|
||||
struct gc_generation_stats generation_stats[NUM_GENERATIONS];
|
||||
|
@ -327,12 +302,6 @@ struct _gc_runtime_state {
|
|||
/* a list of callbacks to be invoked when collection is performed */
|
||||
PyObject *callbacks;
|
||||
|
||||
Py_ssize_t heap_size;
|
||||
Py_ssize_t work_to_do;
|
||||
/* Which of the old spaces is the visited space */
|
||||
int visited_space;
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
/* This is the number of objects that survived the last full
|
||||
collection. It approximates the number of long lived objects
|
||||
tracked by the GC.
|
||||
|
@ -345,6 +314,7 @@ struct _gc_runtime_state {
|
|||
the first time. */
|
||||
Py_ssize_t long_lived_pending;
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
/* gh-117783: Deferred reference counting is not fully implemented yet, so
|
||||
as a temporary measure we treat objects using deferred reference
|
||||
counting as immortal. The value may be zero, one, or a negative number:
|
||||
|
@ -365,7 +335,8 @@ struct _gc_thread_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_Collect(PyThreadState *tstate, int generation,
|
||||
_PyGC_Reason reason);
|
||||
extern void _PyGC_CollectNoFail(PyThreadState *tstate);
|
||||
|
||||
/* Freeze objects tracked by the GC and ignore them in future collections. */
|
||||
|
|
|
@ -353,12 +353,11 @@ static inline void _PyObject_GC_TRACK(
|
|||
filename, lineno, __func__);
|
||||
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
PyGC_Head *generation0 = &interp->gc.young.head;
|
||||
PyGC_Head *generation0 = interp->gc.generation0;
|
||||
PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
|
||||
_PyGCHead_SET_NEXT(last, gc);
|
||||
_PyGCHead_SET_PREV(gc, last);
|
||||
/* Young objects will be moved into the visited space during GC, so set the bit here */
|
||||
gc->_gc_next = ((uintptr_t)generation0) | interp->gc.visited_space;
|
||||
_PyGCHead_SET_NEXT(gc, generation0);
|
||||
generation0->_gc_prev = (uintptr_t)gc;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -228,12 +228,12 @@ extern PyTypeObject _PyExc_MemoryError;
|
|||
}, \
|
||||
.gc = { \
|
||||
.enabled = 1, \
|
||||
.young = { .threshold = 2000, }, \
|
||||
.old = { \
|
||||
.generations = { \
|
||||
/* .head is set in _PyGC_InitState(). */ \
|
||||
{ .threshold = 2000, }, \
|
||||
{ .threshold = 10, }, \
|
||||
{ .threshold = 10, }, \
|
||||
{ .threshold = 0, }, \
|
||||
}, \
|
||||
.work_to_do = -5000, \
|
||||
}, \
|
||||
.qsbr = { \
|
||||
.wr_seq = QSBR_INITIAL, \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue