From a63cc212348e276c8ede32773313c60ff7fda651 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 13 Apr 2015 20:10:06 +0200 Subject: Issue #23726: Don't enable GC for user subclasses of non-GC types that don't add any new fields. Patch by Eugene Toder. --- Lib/test/test_descr.py | 2 -- Lib/test/test_gc.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/typeobject.c | 7 ++++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index cdaae0a..9f3d34d 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3020,8 +3020,6 @@ order (MRO) for bases """ cant(object(), list) cant(list(), object) class Int(int): __slots__ = [] - cant(2, Int) - cant(Int(), int) cant(True, int) cant(2, bool) o = object() diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 2ac1d4b..254f64b 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -546,11 +546,31 @@ class GCTests(unittest.TestCase): class UserClass: pass + + class UserInt(int): + pass + + # Base class is object; no extra fields. + class UserClassSlots: + __slots__ = () + + # Base class is fixed size larger than object; no extra fields. + class UserFloatSlots(float): + __slots__ = () + + # Base class is variable size; no extra fields. + class UserIntSlots(int): + __slots__ = () + self.assertTrue(gc.is_tracked(gc)) self.assertTrue(gc.is_tracked(UserClass)) self.assertTrue(gc.is_tracked(UserClass())) + self.assertTrue(gc.is_tracked(UserInt())) self.assertTrue(gc.is_tracked([])) self.assertTrue(gc.is_tracked(set())) + self.assertFalse(gc.is_tracked(UserClassSlots())) + self.assertFalse(gc.is_tracked(UserFloatSlots())) + self.assertFalse(gc.is_tracked(UserIntSlots())) def test_bug1055820b(self): # Corresponds to temp2b.py in the bug report. diff --git a/Misc/NEWS b/Misc/NEWS index 3254a70..242cfcd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: XXX Core and Builtins ----------------- +- Issue #23726: Don't enable GC for user subclasses of non-GC types that + don't add any new fields. Patch by Eugene Toder. + - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted while it is holding a lock to a buffered I/O object, and the main thread tries to use the same I/O object (typically stdout or stderr). A fatal diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 030dc1f..0e54fe6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2645,9 +2645,10 @@ 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)) + /* Enable GC unless this class is not adding new instance variables and + the base class did not use GC. */ + if ((base->tp_flags & Py_TPFLAGS_HAVE_GC) || + type->tp_basicsize > base->tp_basicsize) type->tp_flags |= Py_TPFLAGS_HAVE_GC; /* Always override allocation strategy to use regular heap */ -- cgit v0.12