Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Include/internal/pycore_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ static inline void _PyObject_GC_TRACK(

PyInterpreterState *interp = _PyInterpreterState_GET();
PyGC_Head *generation0 = &interp->gc.young.head;
interp->gc.young.count++; /* number of tracked GC objects */
PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
_PyGCHead_SET_NEXT(last, gc);
_PyGCHead_SET_PREV(gc, last);
Expand Down Expand Up @@ -280,6 +281,10 @@ static inline void _PyObject_GC_UNTRACK(
_PyGCHead_SET_PREV(next, prev);
gc->_gc_next = 0;
gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->gc.young.count > 0) {
interp->gc.young.count--;
}
#endif
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Do not track immutable tuples in GC. Count only tracked objects in GC young
objects counter. Patch by Sergey Miryanov and Mikhail Efimov
54 changes: 42 additions & 12 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ _PyTuple_MaybeUntrack(PyObject *op)
_PyObject_GC_UNTRACK(op);
}

static bool
tuple_need_tracking(PyTupleObject *t)
{
Py_ssize_t i = 0, n = Py_SIZE(t);
for (; i < n; i++) {
PyObject *elt = PyTuple_GET_ITEM(t, i);
/* Tuple with NULL elements aren't
fully constructed, we should track them. */
if (!elt ||
_PyObject_GC_MAY_BE_TRACKED(elt)) {
return true;
}
}
return false;
}

PyObject *
PyTuple_Pack(Py_ssize_t n, ...)
{
Expand All @@ -169,19 +185,21 @@ PyTuple_Pack(Py_ssize_t n, ...)
}

va_start(vargs, n);
PyTupleObject *result = tuple_alloc(n);
if (result == NULL) {
PyTupleObject *tuple = tuple_alloc(n);
if (tuple == NULL) {
va_end(vargs);
return NULL;
}
items = result->ob_item;
items = tuple->ob_item;
for (i = 0; i < n; i++) {
o = va_arg(vargs, PyObject *);
items[i] = Py_NewRef(o);
}
va_end(vargs);
_PyObject_GC_TRACK(result);
return (PyObject *)result;
if (tuple_need_tracking(tuple)) {
_PyObject_GC_TRACK(tuple);
}
return (PyObject *)tuple;
}


Expand Down Expand Up @@ -381,7 +399,9 @@ PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
PyObject *item = src[i];
dst[i] = Py_NewRef(item);
}
_PyObject_GC_TRACK(tuple);
if (tuple_need_tracking(tuple)) {
_PyObject_GC_TRACK(tuple);
}
return (PyObject *)tuple;
}

Expand All @@ -399,7 +419,9 @@ _PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
for (Py_ssize_t i = 0; i < n; i++) {
dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
}
_PyObject_GC_TRACK(tuple);
if (tuple_need_tracking(tuple)) {
_PyObject_GC_TRACK(tuple);
}
return (PyObject *)tuple;
}

Expand All @@ -421,7 +443,9 @@ _PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n)
PyObject *item = src[i];
dst[i] = item;
}
_PyObject_GC_TRACK(tuple);
if (tuple_need_tracking(tuple)) {
_PyObject_GC_TRACK(tuple);
}
return (PyObject *)tuple;
}

Expand Down Expand Up @@ -494,7 +518,9 @@ tuple_concat(PyObject *aa, PyObject *bb)
dest[i] = Py_NewRef(v);
}

_PyObject_GC_TRACK(np);
if (_PyObject_GC_IS_TRACKED(a) || _PyObject_GC_IS_TRACKED(b)) {
_PyObject_GC_TRACK(np);
}
return (PyObject *)np;
}

Expand Down Expand Up @@ -543,8 +569,10 @@ tuple_repeat(PyObject *self, Py_ssize_t n)
_Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size,
sizeof(PyObject *)*input_size);
}
_PyObject_GC_TRACK(np);
return (PyObject *) np;
if (_PyObject_GC_IS_TRACKED(a)) {
_PyObject_GC_TRACK(np);
}
return (PyObject *)np;
}

/*[clinic input]
Expand Down Expand Up @@ -821,7 +849,9 @@ tuple_subscript(PyObject *op, PyObject* item)
dest[i] = it;
}

_PyObject_GC_TRACK(result);
if (_PyObject_GC_IS_TRACKED(self)) {
_PyObject_GC_TRACK(result);
}
return (PyObject *)result;
}
}
Expand Down
4 changes: 0 additions & 4 deletions Python/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2296,7 +2296,6 @@ _PyObject_GC_Link(PyObject *op)
GCState *gcstate = &tstate->interp->gc;
gc->_gc_next = 0;
gc->_gc_prev = 0;
gcstate->young.count++; /* number of allocated GC objects */
gcstate->heap_size++;
if (gcstate->young.count > gcstate->young.threshold &&
gcstate->enabled &&
Expand Down Expand Up @@ -2428,9 +2427,6 @@ PyObject_GC_Del(void *op)
#endif
}
GCState *gcstate = get_gc_state();
if (gcstate->young.count > 0) {
gcstate->young.count--;
}
gcstate->heap_size--;
PyObject_Free(((char *)op)-presize);
}
Expand Down
Loading