mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
GH-108362: Revert "GH-108362: Incremental GC implementation (GH-108038)" (#115132)
Revert "GH-108362: Incremental GC implementation (GH-108038)"
This reverts commit 36518e69d7.
This commit is contained in:
parent
d0322fdf2c
commit
8a3c499ffe
13 changed files with 446 additions and 701 deletions
|
|
@ -88,15 +88,11 @@ static inline void _PyObject_GC_SET_SHARED(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 is set if the object belongs to old space 1 */
|
||||
#define _PyGC_NEXT_MASK_OLD_SPACE_1 1
|
||||
|
||||
#define _PyGC_PREV_MASK_COLLECTING (2)
|
||||
/* The (N-2) most significant bits contain the real address. */
|
||||
#define _PyGC_PREV_SHIFT 2
|
||||
#define _PyGC_PREV_SHIFT (2)
|
||||
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
|
||||
|
||||
/* set for debugging information */
|
||||
|
|
@ -122,13 +118,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.
|
||||
|
|
@ -136,7 +130,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);
|
||||
|
|
@ -222,13 +215,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 */
|
||||
|
|
@ -250,8 +236,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];
|
||||
|
|
@ -264,20 +250,22 @@ struct _gc_runtime_state {
|
|||
/* This is the number of objects that survived the last full
|
||||
collection. It approximates the number of long lived objects
|
||||
tracked by the GC.
|
||||
|
||||
(by "full collection", we mean a collection of the oldest
|
||||
generation). */
|
||||
Py_ssize_t long_lived_total;
|
||||
|
||||
Py_ssize_t work_to_do;
|
||||
/* Which of the old spaces is the visited space */
|
||||
int visited_space;
|
||||
/* This is the number of objects that survived all "non-full"
|
||||
collections, and are awaiting to undergo a full collection for
|
||||
the first time. */
|
||||
Py_ssize_t long_lived_pending;
|
||||
};
|
||||
|
||||
|
||||
extern void _PyGC_InitState(struct _gc_runtime_state *);
|
||||
|
||||
extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason);
|
||||
extern void _PyGC_CollectNoFail(PyThreadState *tstate);
|
||||
extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation,
|
||||
_PyGC_Reason reason);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -125,7 +125,19 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
|
|||
}
|
||||
#define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n)
|
||||
|
||||
extern void _Py_SetImmortal(PyObject *op);
|
||||
static inline void _Py_SetImmortal(PyObject *op)
|
||||
{
|
||||
if (op) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
op->ob_tid = _Py_UNOWNED_TID;
|
||||
op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
|
||||
op->ob_ref_shared = 0;
|
||||
#else
|
||||
op->ob_refcnt = _Py_IMMORTAL_REFCNT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#define _Py_SetImmortal(op) _Py_SetImmortal(_PyObject_CAST(op))
|
||||
|
||||
// Makes an immortal object mortal again with the specified refcnt. Should only
|
||||
// be used during runtime finalization.
|
||||
|
|
@ -313,12 +325,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);
|
||||
_PyGCHead_SET_NEXT(gc, generation0);
|
||||
assert((gc->_gc_next & _PyGC_NEXT_MASK_OLD_SPACE_1) == 0);
|
||||
generation0->_gc_prev = (uintptr_t)gc;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,12 +162,12 @@ extern PyTypeObject _PyExc_MemoryError;
|
|||
}, \
|
||||
.gc = { \
|
||||
.enabled = 1, \
|
||||
.young = { .threshold = 2000, }, \
|
||||
.old = { \
|
||||
.generations = { \
|
||||
/* .head is set in _PyGC_InitState(). */ \
|
||||
{ .threshold = 700, }, \
|
||||
{ .threshold = 10, }, \
|
||||
{ .threshold = 10, }, \
|
||||
{ .threshold = 0, }, \
|
||||
}, \
|
||||
.work_to_do = -5000, \
|
||||
}, \
|
||||
.object_state = _py_object_state_INIT(INTERP), \
|
||||
.dtoa = _dtoa_state_INIT(&(INTERP)), \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue