void _PyTuple_MaybeUntrack(PyObject *op) { PyTupleObject *t; Py_ssize_t i, n; if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) return; t = (PyTupleObject *) op; n = Py_SIZE(t); for (i = 0; i < n; i++) { PyObject *elt = PyTuple_GET_ITEM(t, i); /* Tuple with NULL elements aren't fully constructed, don't untrack them yet. */ if (!elt || _PyObject_GC_MAY_BE_TRACKED(elt)) return; } #ifdef SHOW_TRACK_COUNT count_tracked--; count_untracked++; #endif _PyObject_GC_UNTRACK(op); }
int _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) { PyTupleObject *v; PyTupleObject *sv; Py_ssize_t i; Py_ssize_t oldsize; v = (PyTupleObject *) *pv; if (v == NULL || Py_TYPE(v) != &PyTuple_Type || (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) { *pv = 0; Py_XDECREF(v); PyErr_BadInternalCall(); return -1; } oldsize = Py_SIZE(v); if (oldsize == newsize) return 0; if (oldsize == 0) { /* Empty tuples are often shared, so we should never resize them in-place even if we do own the only (current) reference */ Py_DECREF(v); *pv = PyTuple_New(newsize); return *pv == NULL ? -1 : 0; } /* XXX UNREF/NEWREF interface should be more symmetrical */ _Py_DEC_REFTOTAL; if (_PyObject_GC_IS_TRACKED(v)) _PyObject_GC_UNTRACK(v); _Py_ForgetReference((PyObject *) v); /* DECREF items deleted by shrinkage */ for (i = newsize; i < oldsize; i++) { Py_XDECREF(v->ob_item[i]); v->ob_item[i] = NULL; } sv = PyObject_GC_Resize(PyTupleObject, v, newsize); if (sv == NULL) { *pv = NULL; PyObject_GC_Del(v); return -1; } _Py_NewReference((PyObject *) sv); /* Zero out items added by growing */ if (newsize > oldsize) memset(&sv->ob_item[oldsize], 0, sizeof(*sv->ob_item) * (newsize - oldsize)); *pv = (PyObject *) sv; _PyObject_GC_TRACK(sv); return 0; }
static void _Py_HOT_FUNCTION frame_dealloc(PyFrameObject *f) { PyObject **p, **valuestack; PyCodeObject *co; if (_PyObject_GC_IS_TRACKED(f)) _PyObject_GC_UNTRACK(f); Py_TRASHCAN_SAFE_BEGIN(f) /* Kill all local variables */ valuestack = f->f_valuestack; for (p = f->f_localsplus; p < valuestack; p++) Py_CLEAR(*p); /* Free stack */ if (f->f_stacktop != NULL) { for (p = valuestack; p < f->f_stacktop; p++) Py_XDECREF(*p); } Py_XDECREF(f->f_back); Py_DECREF(f->f_builtins); Py_DECREF(f->f_globals); Py_CLEAR(f->f_locals); Py_CLEAR(f->f_trace); co = f->f_code; if (co->co_zombieframe == NULL) co->co_zombieframe = f; else if (numfree < PyFrame_MAXFREELIST) { ++numfree; f->f_back = free_list; free_list = f; } else PyObject_GC_Del(f); Py_DECREF(co); Py_TRASHCAN_SAFE_END(f) }