[pypy-commit] pypy gc-del-3: More reverts, and adapt the docs

arigo pypy.commits at gmail.com
Wed May 4 11:19:42 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del-3
Changeset: r84188:4a45bfe534bc
Date: 2016-05-04 17:19 +0200
http://bitbucket.org/pypy/pypy/changeset/4a45bfe534bc/

Log:	More reverts, and adapt the docs

diff --git a/pypy/doc/discussion/finalizer-order.rst b/pypy/doc/discussion/finalizer-order.rst
--- a/pypy/doc/discussion/finalizer-order.rst
+++ b/pypy/doc/discussion/finalizer-order.rst
@@ -12,10 +12,15 @@
 
 * RPython objects can have ``__del__()``.  These are called
   immediately by the GC when the last reference to the object goes
-  away, like in CPython.  However (like "lightweight finalizers" used
-  to be), all ``__del__()`` methods must only contain simple enough
-  code, and this is checked.  We call this "destructors".  They can't
-  use operations that would resurrect the object, for example.
+  away, like in CPython.  However, the long-term goal is that all
+  ``__del__()`` methods should only contain simple enough code.  If
+  they do, we call them "destructors".  They can't use operations that
+  would resurrect the object, for example.  Use the decorator
+  ``@rgc.must_be_light_finalizer`` to ensure they are destructors.
+
+* RPython-level ``__del__()`` that are not passing the destructor test
+  are supported for backward compatibility, but deprecated.  The rest
+  of this document assumes that ``__del__()`` are all destructors.
 
 * For any more advanced usage --- in particular for any app-level
   object with a __del__ --- we don't use the RPython-level
diff --git a/rpython/doc/rpython.rst b/rpython/doc/rpython.rst
--- a/rpython/doc/rpython.rst
+++ b/rpython/doc/rpython.rst
@@ -191,9 +191,9 @@
   ``__setitem__`` for slicing isn't supported. Additionally, using negative
   indices for slicing is still not support, even when using ``__getslice__``.
 
-  Note that from May 2016 the destructor ``__del__`` must only contain
-  `simple operations`__; for any kind of more complex destructor, see
-  ``rpython.rlib.rgc.register_finalizer()``.
+  Note that the destructor ``__del__`` should only contain `simple
+  operations`__; for any kind of more complex destructor, consider
+  using instead ``rpython.rlib.rgc.FinalizerQueue``.
 
 .. __: garbage_collection.html
 
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -147,15 +147,15 @@
         the four malloc_[fixed,var]size[_clear]() functions.
         """
         size = self.fixed_size(typeid)
-        needs_destructor = (bool(self.destructor_or_custom_trace(typeid))
-                            and not self.has_custom_trace(typeid))
-        finalizer_is_light = (needs_destructor and
+        needs_finalizer = (bool(self.destructor_or_custom_trace(typeid))
+                           and not self.has_custom_trace(typeid))
+        finalizer_is_light = (needs_finalizer and
                               not self.is_old_style_finalizer(typeid))
         contains_weakptr = self.weakpointer_offset(typeid) >= 0
-        assert not (needs_destructor and contains_weakptr)
+        assert not (needs_finalizer and contains_weakptr)
         if self.is_varsize(typeid):
             assert not contains_weakptr
-            assert not needs_destructor
+            assert not needs_finalizer
             itemsize = self.varsize_item_sizes(typeid)
             offset_to_length = self.varsize_offset_to_length(typeid)
             if self.malloc_zero_filled:
@@ -170,7 +170,7 @@
                 malloc_fixedsize = self.malloc_fixedsize_clear
             else:
                 malloc_fixedsize = self.malloc_fixedsize
-            ref = malloc_fixedsize(typeid, size, needs_destructor,
+            ref = malloc_fixedsize(typeid, size, needs_finalizer,
                                    finalizer_is_light,
                                    contains_weakptr)
         # lots of cast and reverse-cast around...
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -608,7 +608,7 @@
 
 
     def malloc_fixedsize(self, typeid, size,
-                               needs_destructor=False,
+                               needs_finalizer=False,
                                is_finalizer_light=False,
                                contains_weakptr=False):
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -617,7 +617,7 @@
         #
         # If the object needs a finalizer, ask for a rawmalloc.
         # The following check should be constant-folded.
-        if needs_destructor and not is_finalizer_light:
+        if needs_finalizer and not is_finalizer_light:
             # old-style finalizers only!
             from rpython.rtyper.lltypesystem import rffi
             ll_assert(not contains_weakptr,
@@ -657,7 +657,7 @@
         #
         # If it is a weakref or has a lightweight destructor, record it
         # (checks constant-folded).
-        if needs_destructor:
+        if needs_finalizer:
             self.young_objects_with_destructors.append(obj)
         if contains_weakptr:
             self.young_objects_with_weakrefs.append(obj)
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -307,6 +307,7 @@
                 [s_gc, s_typeid16,
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeBool(),
+                annmodel.SomeBool(),
                 annmodel.SomeBool()], s_gcref,
                 inline = False)
             self.malloc_varsize_ptr = getfn(
@@ -321,6 +322,7 @@
                 [s_gc, s_typeid16,
                  annmodel.SomeInteger(nonneg=True),
                  annmodel.SomeBool(),
+                 annmodel.SomeBool(),
                  annmodel.SomeBool()], s_gcref,
                 inline = False)
             self.malloc_varsize_ptr = getfn(
@@ -383,7 +385,7 @@
                 malloc_fast,
                 [s_gc, s_typeid16,
                  annmodel.SomeInteger(nonneg=True),
-                 s_False, s_False], s_gcref,
+                 s_False, s_False, s_False], s_gcref,
                 inline = True)
         else:
             self.malloc_fast_ptr = None
@@ -792,10 +794,11 @@
         info = self.layoutbuilder.get_info(type_id)
         c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
         fptrs = self.special_funcptr_for_type(TYPE)
-        has_destructor = "destructor" in fptrs
-        assert "finalizer" not in fptrs         # removed
-        assert "light_finalizer" not in fptrs   # removed
-        c_has_destructor = rmodel.inputconst(lltype.Bool, has_destructor)
+        has_finalizer = "destructor" in fptrs or "old_style_finalizer" in fptrs
+        has_light_finalizer = "destructor" in fptrs
+        c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
+        c_has_light_finalizer = rmodel.inputconst(lltype.Bool,
+                                                  has_light_finalizer)
 
         if flags.get('nonmovable'):
             assert op.opname == 'malloc'
@@ -805,16 +808,16 @@
         elif not op.opname.endswith('_varsize') and not flags.get('varsize'):
             zero = flags.get('zero', False)
             if (self.malloc_fast_ptr is not None and
-                not c_has_destructor.value and
+                not c_has_finalizer.value and
                 (self.malloc_fast_is_clearing or not zero)):
                 malloc_ptr = self.malloc_fast_ptr
             else:
                 malloc_ptr = self.malloc_fixedsize_ptr
             args = [self.c_const_gc, c_type_id, c_size,
-                    c_has_destructor,
+                    c_has_finalizer, c_has_light_finalizer,
                     rmodel.inputconst(lltype.Bool, False)]
         else:
-            assert not c_has_destructor.value
+            assert not c_has_finalizer.value
             info_varsize = self.layoutbuilder.get_info_varsize(type_id)
             v_length = op.args[-1]
             c_ofstolength = rmodel.inputconst(lltype.Signed,
@@ -950,12 +953,13 @@
     def gct_do_malloc_fixedsize(self, hop):
         # used by the JIT (see rpython.jit.backend.llsupport.gc)
         op = hop.spaceop
-        [v_typeid, v_size, v_has_destructor, v_contains_weakptr] = op.args
+        [v_typeid, v_size,
+         v_has_finalizer, v_has_light_finalizer, v_contains_weakptr] = op.args
         livevars = self.push_roots(hop)
         hop.genop("direct_call",
                   [self.malloc_fixedsize_ptr, self.c_const_gc,
                    v_typeid, v_size,
-                   v_has_destructor,
+                   v_has_finalizer, v_has_light_finalizer,
                    v_contains_weakptr],
                   resultvar=op.result)
         self.pop_roots(hop, livevars)
@@ -1063,7 +1067,7 @@
         c_false = rmodel.inputconst(lltype.Bool, False)
         c_has_weakptr = rmodel.inputconst(lltype.Bool, True)
         args = [self.c_const_gc, c_type_id, c_size,
-                c_false, c_has_weakptr]
+                c_false, c_false, c_has_weakptr]
 
         # push and pop the current live variables *including* the argument
         # to the weakref_create operation, which must be kept alive and
@@ -1595,7 +1599,7 @@
 
     def make_destructor_funcptr_for_type(self, TYPE):
         if not self.has_destructor(TYPE):
-            return None
+            return None, False
         rtti = get_rtti(TYPE)
         destrptr = rtti._obj.destructor_funcptr
         DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
diff --git a/rpython/memory/test/test_transformed_gc.py b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -323,6 +323,35 @@
         res = run([5, 42]) #XXX pure lazyness here too
         assert res == 6
 
+    def define_old_style_finalizer(cls):
+        class B(object):
+            pass
+        b = B()
+        b.nextid = 0
+        b.num_deleted = 0
+        class A(object):
+            def __init__(self):
+                self.id = b.nextid
+                b.nextid += 1
+            def __del__(self):
+                llop.gc__collect(lltype.Void)
+                b.num_deleted += 1
+        def f(x, y):
+            a = A()
+            i = 0
+            while i < x:
+                i += 1
+                a = A()
+            llop.gc__collect(lltype.Void)
+            llop.gc__collect(lltype.Void)
+            return b.num_deleted
+        return f
+
+    def test_old_style_finalizer(self):
+        run = self.runner("old_style_finalizer")
+        res = run([5, 42]) #XXX pure lazyness here too
+        assert res == 6
+
     def define_finalizer(cls):
         class B(object):
             pass
@@ -846,7 +875,8 @@
                 if op.opname == 'do_malloc_fixedsize':
                     op.args = [Constant(type_id, llgroup.HALFWORD),
                                Constant(llmemory.sizeof(P), lltype.Signed),
-                               Constant(False, lltype.Bool), # has_destructor
+                               Constant(False, lltype.Bool), # has_finalizer
+                               Constant(False, lltype.Bool), # has_finalizer_light
                                Constant(False, lltype.Bool)] # contains_weakptr
                     break
             else:
@@ -882,7 +912,8 @@
                 if op.opname == 'do_malloc_fixedsize':
                     op.args = [Constant(type_id, llgroup.HALFWORD),
                                Constant(llmemory.sizeof(P), lltype.Signed),
-                               Constant(False, lltype.Bool), # has_destructor
+                               Constant(False, lltype.Bool), # has_finalizer
+                               Constant(False, lltype.Bool), # has_finalizer_light
                                Constant(False, lltype.Bool)] # contains_weakptr
                     break
             else:


More information about the pypy-commit mailing list