add gc support to slice (closes #26659)

This commit is contained in:
Benjamin Peterson 2016-04-16 14:47:12 -07:00
parent a07ab29a79
commit 2b601d3905
3 changed files with 31 additions and 7 deletions

View File

@ -1,11 +1,13 @@
# tests for slice objects; in particular the indices method.
import unittest
from pickle import loads, dumps
import itertools
import operator
import sys
import unittest
import weakref
from pickle import loads, dumps
from test import support
def evaluate_slice_index(arg):
@ -240,5 +242,14 @@ class SliceTest(unittest.TestCase):
self.assertEqual(s.indices(15), t.indices(15))
self.assertNotEqual(id(s), id(t))
def test_cycle(self):
class myobj(): pass
o = myobj()
o.s = slice(o)
w = weakref.ref(o)
o = None
test_support.gc_collect()
self.assertIsNone(w())
if __name__ == "__main__":
unittest.main()

View File

@ -10,6 +10,8 @@ Release date: tba
Core and Builtins
-----------------
- Issue #26659: Make the builtin slice type support cycle collection.
- Issue #26718: super.__init__ no longer leaks memory if called multiple times.
NOTE: A direct call of super.__init__ is not endorsed!

View File

@ -119,7 +119,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
slice_cache = NULL;
_Py_NewReference((PyObject *)obj);
} else {
obj = PyObject_New(PySliceObject, &PySlice_Type);
obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
if (obj == NULL)
return NULL;
}
@ -135,6 +135,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
obj->start = start;
obj->stop = stop;
_PyObject_GC_TRACK(obj);
return (PyObject *) obj;
}
@ -288,13 +289,14 @@ Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
static void
slice_dealloc(PySliceObject *r)
{
_PyObject_GC_UNTRACK(r);
Py_DECREF(r->step);
Py_DECREF(r->start);
Py_DECREF(r->stop);
if (slice_cache == NULL)
slice_cache = r;
else
PyObject_Del(r);
PyObject_GC_Del(r);
}
static PyObject *
@ -586,6 +588,15 @@ slice_richcompare(PyObject *v, PyObject *w, int op)
return res;
}
static int
slice_traverse(PySliceObject *v, visitproc visit, void *arg)
{
Py_VISIT(v->start);
Py_VISIT(v->stop);
Py_VISIT(v->step);
return 0;
}
PyTypeObject PySlice_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"slice", /* Name of this type */
@ -606,9 +617,9 @@ PyTypeObject PySlice_Type = {
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
slice_doc, /* tp_doc */
0, /* tp_traverse */
(traverseproc)slice_traverse, /* tp_traverse */
0, /* tp_clear */
slice_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */