]> granicus.if.org Git - python/commitdiff
Enable GC for new-style instances. This touches lots of files, since
authorGuido van Rossum <guido@python.org>
Fri, 5 Oct 2001 20:51:39 +0000 (20:51 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 5 Oct 2001 20:51:39 +0000 (20:51 +0000)
many types were subclassable but had a xxx_dealloc function that
called PyObject_DEL(self) directly instead of deferring to
self->ob_type->tp_free(self).  It is permissible to set tp_free in the
type object directly to _PyObject_Del, for non-GC types, or to
_PyObject_GC_Del, for GC types.  Still, PyObject_DEL was a tad faster,
so I'm fearing that our pystone rating is going down again.  I'm not
sure if doing something like

void xxx_dealloc(PyObject *self)
{
if (PyXxxCheckExact(self))
PyObject_DEL(self);
else
self->ob_type->tp_free(self);
}

is any faster than always calling the else branch, so I haven't
attempted that -- however those types whose own dealloc is fancier
(int, float, unicode) do use this pattern.

13 files changed:
Lib/test/test_gc.py
Objects/complexobject.c
Objects/dictobject.c
Objects/fileobject.c
Objects/floatobject.c
Objects/funcobject.c
Objects/listobject.c
Objects/longobject.c
Objects/moduleobject.c
Objects/stringobject.c
Objects/tupleobject.c
Objects/typeobject.c
Objects/unicodeobject.c

index 125521a6b0d435e9959154a0c8ae46fddc218ddf..4d12e533fbcbe60536501f2c1ca0479c39ab72fb 100644 (file)
@@ -73,6 +73,24 @@ def test_instance():
     del a
     expect_nonzero(gc.collect(), "instance")
 
+def test_newinstance():
+    class A(object):
+        pass
+    a = A()
+    a.a = a
+    gc.collect()
+    del a
+    expect_nonzero(gc.collect(), "newinstance")
+    class B(list):
+        pass
+    class C(B, A):
+        pass
+    a = C()
+    a.a = a
+    gc.collect()
+    del a
+    expect_nonzero(gc.collect(), "newinstance(2)")
+
 def test_method():
     # Tricky: self.__init__ is a bound method, it references the instance.
     class A:
@@ -170,6 +188,7 @@ def test_all():
     run_test("static classes", test_staticclass)
     run_test("dynamic classes", test_dynamicclass)
     run_test("instances", test_instance)
+    run_test("new instances", test_newinstance)
     run_test("methods", test_method)
     run_test("functions", test_function)
     run_test("frames", test_frame)
index ee0ede4fc5bd993315e57846bb719db4494aa83c..675d5b512aa43869fdcb299ba857d06ab63d383f 100644 (file)
@@ -265,7 +265,7 @@ PyComplex_AsCComplex(PyObject *op)
 static void
 complex_dealloc(PyObject *op)
 {
-       PyObject_DEL(op);
+       op->ob_type->tp_free(op);
 }
 
 
@@ -970,6 +970,7 @@ PyTypeObject PyComplex_Type = {
        0,                                      /* tp_init */
        0,                                      /* tp_alloc */
        complex_new,                            /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
 
 #endif
index f68a9648f42bd17840142e2f0eca276d08e9c145..829f76d383c1dabb761f79cca4a175c5b025faf5 100644 (file)
@@ -705,7 +705,7 @@ dict_dealloc(register dictobject *mp)
        }
        if (mp->ma_table != mp->ma_smalltable)
                PyMem_DEL(mp->ma_table);
-       PyObject_GC_Del(mp);
+       mp->ob_type->tp_free((PyObject *)mp);
        Py_TRASHCAN_SAFE_END(mp)
 }
 
@@ -1769,6 +1769,7 @@ PyTypeObject PyDict_Type = {
        (initproc)dict_init,                    /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        dict_new,                               /* tp_new */
+       _PyObject_GC_Del,                       /* tp_free */
 };
 
 /* For backward compatibility with old dictionary interface */
index d3309245021f3a395b82d5b313eea668557c028d..9a249aa61b74412224c458e67379ac8b98923fa5 100644 (file)
@@ -208,7 +208,7 @@ file_dealloc(PyFileObject *f)
        }
        Py_XDECREF(f->f_name);
        Py_XDECREF(f->f_mode);
-       PyObject_DEL(f);
+       f->ob_type->tp_free((PyObject *)f);
 }
 
 static PyObject *
@@ -1508,8 +1508,7 @@ PyTypeObject PyFile_Type = {
        PyObject_GenericGetAttr,                /* tp_getattro */
        0,                                      /* tp_setattro */
        0,                                      /* tp_as_buffer */
-       Py_TPFLAGS_DEFAULT |
-                       Py_TPFLAGS_BASETYPE,    /* tp_flags */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
        file_doc,                               /* tp_doc */
        0,                                      /* tp_traverse */
        0,                                      /* tp_clear */
@@ -1528,6 +1527,7 @@ PyTypeObject PyFile_Type = {
        (initproc)file_init,                    /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        file_new,                               /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
 
 /* Interface for the 'soft space' between print items. */
index 2de5535a707e3eb3d15a8796b9e47ad5807a2d86..12d49050ab7b90692ec832a47fc68c04d41ed7ec 100644 (file)
@@ -182,8 +182,12 @@ PyFloat_FromString(PyObject *v, char **pend)
 static void
 float_dealloc(PyFloatObject *op)
 {
-       op->ob_type = (struct _typeobject *)free_list;
-       free_list = op;
+       if (PyFloat_CheckExact(op)) {
+               op->ob_type = (struct _typeobject *)free_list;
+               free_list = op;
+       }
+       else
+               op->ob_type->tp_free((PyObject *)op);
 }
 
 double
index 4e77d524342734b1cdd07823cbc226e592a4a616..89dd7f9d917c2f02dbfa0a220dcb12d653a80c94 100644 (file)
@@ -461,7 +461,7 @@ static void
 cm_dealloc(classmethod *cm)
 {
        Py_XDECREF(cm->cm_callable);
-       PyObject_DEL(cm);
+       cm->ob_type->tp_free((PyObject *)cm);
 }
 
 static PyObject *
@@ -531,6 +531,7 @@ PyTypeObject PyClassMethod_Type = {
        cm_init,                                /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        PyType_GenericNew,                      /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
 
 PyObject *
@@ -571,7 +572,7 @@ static void
 sm_dealloc(staticmethod *sm)
 {
        Py_XDECREF(sm->sm_callable);
-       PyObject_DEL(sm);
+       sm->ob_type->tp_free((PyObject *)sm);
 }
 
 static PyObject *
@@ -641,6 +642,7 @@ PyTypeObject PyStaticMethod_Type = {
        sm_init,                                /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        PyType_GenericNew,                      /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
 
 PyObject *
index 2b6207fcbc475c960a2d0370f8cb661402f2ee0e..b05fe27d602999acdc3b51bbbb5c68ff991c4556 100644 (file)
@@ -208,7 +208,7 @@ list_dealloc(PyListObject *op)
                }
                PyMem_FREE(op->ob_item);
        }
-       PyObject_GC_Del(op);
+       op->ob_type->tp_free((PyObject *)op);
        Py_TRASHCAN_SAFE_END(op)
 }
 
@@ -1707,6 +1707,7 @@ PyTypeObject PyList_Type = {
        (initproc)list_init,                    /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        PyType_GenericNew,                      /* tp_new */
+       _PyObject_GC_Del,                       /* tp_free */
 };
 
 
index be4af3f2e61478115f9d3c008aac130285da26d4..5141d533c7edb0343d82a765ef4db48e32ab752a 100644 (file)
@@ -1227,7 +1227,7 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem)
 static void
 long_dealloc(PyObject *v)
 {
-       PyObject_DEL(v);
+       v->ob_type->tp_free(v);
 }
 
 static PyObject *
@@ -2341,4 +2341,5 @@ PyTypeObject PyLong_Type = {
        0,                                      /* tp_init */
        0,                                      /* tp_alloc */
        long_new,                               /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
index 586785c81e33b5448f597e2c63b85d7c75970e63..953d23cc2bb1d74a1c01dc8ed0cd8119cac588be 100644 (file)
@@ -151,7 +151,7 @@ module_dealloc(PyModuleObject *m)
                _PyModule_Clear((PyObject *)m);
                Py_DECREF(m->md_dict);
        }
-       PyObject_GC_Del(m);
+       m->ob_type->tp_free((PyObject *)m);
 }
 
 static PyObject *
@@ -225,4 +225,5 @@ PyTypeObject PyModule_Type = {
        (initproc)module_init,                  /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        PyType_GenericNew,                      /* tp_new */
+       _PyObject_GC_Del,                       /* tp_free */
 };
index a43f129e9543761908b388d345c09ef7299699da..8fab6a9e2515fbbb88ba808c3295175677e04332 100644 (file)
@@ -481,7 +481,7 @@ PyObject *PyString_AsEncodedString(PyObject *str,
 static void
 string_dealloc(PyObject *op)
 {
-       PyObject_DEL(op);
+       op->ob_type->tp_free(op);
 }
 
 static int
@@ -2746,6 +2746,7 @@ PyTypeObject PyString_Type = {
        0,                                      /* tp_init */
        0,                                      /* tp_alloc */
        string_new,                             /* tp_new */
+       _PyObject_Del,                          /* tp_free */
 };
 
 void
index f371e1ee3c8a50a108a0196674bfecd0aa4b9605..0b5507f1d9ebf4417917034393ef95ee299df3c2 100644 (file)
@@ -157,7 +157,7 @@ tupledealloc(register PyTupleObject *op)
                }
 #endif
        }
-       PyObject_GC_Del(op);
+       op->ob_type->tp_free((PyObject *)op);
 done:
        Py_TRASHCAN_SAFE_END(op)
 }
@@ -582,6 +582,7 @@ PyTypeObject PyTuple_Type = {
        0,                                      /* tp_init */
        0,                                      /* tp_alloc */
        tuple_new,                              /* tp_new */
+       _PyObject_GC_Del,                       /* tp_free */
 };
 
 /* The following function breaks the notion that tuples are immutable:
index e4f07e534e31839d82148a17927bfcf471d10cac..fed6c438faeac2d22adc0d1061d602fa2621f29e 100644 (file)
@@ -229,7 +229,36 @@ PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
        return type->tp_alloc(type, 0);
 }
 
-/* Helper for subtyping */
+/* Helpers for subtyping */
+
+static int
+subtype_traverse(PyObject *self, visitproc visit, void *arg)
+{
+       PyTypeObject *type, *base;
+       traverseproc f;
+       int err;
+
+       /* Find the nearest base with a different tp_traverse */
+       type = self->ob_type;
+       base = type->tp_base;
+       while ((f = base->tp_traverse) == subtype_traverse) {
+               base = base->tp_base;
+               assert(base);
+       }
+
+       if (type->tp_dictoffset != base->tp_dictoffset) {
+               PyObject **dictptr = _PyObject_GetDictPtr(self);
+               if (dictptr && *dictptr) {
+                       err = visit(*dictptr, arg);
+                       if (err)
+                               return err;
+               }
+       }
+
+       if (f)
+               return f(self, visit, arg);
+       return 0;
+}
 
 static void
 subtype_dealloc(PyObject *self)
@@ -968,11 +997,16 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        }
        type->tp_dealloc = subtype_dealloc;
 
+       /* Enable GC unless there are really no instance variables possible */
+       if (!(type->tp_basicsize == sizeof(PyObject) &&
+             type->tp_itemsize == 0))
+               type->tp_flags |= Py_TPFLAGS_HAVE_GC;
+
        /* Always override allocation strategy to use regular heap */
        type->tp_alloc = PyType_GenericAlloc;
        if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
                type->tp_free = _PyObject_GC_Del;
-               type->tp_traverse = base->tp_traverse;
+               type->tp_traverse = subtype_traverse;
                type->tp_clear = base->tp_clear;
        }
        else
@@ -1097,7 +1131,6 @@ type_dealloc(PyTypeObject *type)
        Py_XDECREF(type->tp_bases);
        Py_XDECREF(type->tp_mro);
        Py_XDECREF(type->tp_defined);
-       /* XXX more? */
        Py_XDECREF(et->name);
        Py_XDECREF(et->slots);
        type->ob_type->tp_free((PyObject *)type);
@@ -1291,12 +1324,6 @@ object_hash(PyObject *self)
        return _Py_HashPointer(self);
 }
 
-static void
-object_free(PyObject *self)
-{
-       PyObject_Del(self);
-}
-
 static PyObject *
 object_get_class(PyObject *self, void *closure)
 {
@@ -1446,7 +1473,7 @@ PyTypeObject PyBaseObject_Type = {
        object_init,                            /* tp_init */
        PyType_GenericAlloc,                    /* tp_alloc */
        PyType_GenericNew,                      /* tp_new */
-       object_free,                            /* tp_free */
+       _PyObject_Del,                          /* tp_free */
 };
 
 
index df8592d55e89b9ab43a0ee615ada345cfb2e4253..a252587e721eaf6567d4d72b155f245e8c95d86a 100644 (file)
@@ -224,8 +224,12 @@ PyUnicodeObject *_PyUnicode_New(int length)
 }
 
 static
-void _PyUnicode_Free(register PyUnicodeObject *unicode)
+void unicode_dealloc(register PyUnicodeObject *unicode)
 {
+    if (!PyUnicode_CheckExact(unicode)) {
+       unicode->ob_type->tp_free((PyObject *)unicode);
+       return;
+    }
     if (unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) {
         /* Keep-Alive optimization */
        if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
@@ -5693,7 +5697,7 @@ PyTypeObject PyUnicode_Type = {
     sizeof(PyUnicodeObject),           /* tp_size */
     0,                                         /* tp_itemsize */
     /* Slots */
-    (destructor)_PyUnicode_Free,       /* tp_dealloc */
+    (destructor)unicode_dealloc,       /* tp_dealloc */
     0,                                         /* tp_print */
     0,                                 /* tp_getattr */
     0,                                         /* tp_setattr */
@@ -5727,6 +5731,7 @@ PyTypeObject PyUnicode_Type = {
     0,                                 /* tp_init */
     0,                                 /* tp_alloc */
     unicode_new,                       /* tp_new */
+    _PyObject_Del,                     /* tp_free */
 };
 
 /* Initialize the Unicode implementation */