[pypy-commit] pypy gc-del: Support the new finalizer interface in Boehm too.

arigo noreply at buildbot.pypy.org
Wed Mar 27 15:52:34 CET 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r62833:9ef6bb8aa5c2
Date: 2013-03-27 15:50 +0100
http://bitbucket.org/pypy/pypy/changeset/9ef6bb8aa5c2/

Log:	Support the new finalizer interface in Boehm too.

diff --git a/rpython/memory/gctransform/boehm.py b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -9,12 +9,12 @@
 
 class BoehmGCTransformer(GCTransformer):
     malloc_zero_filled = True
-    FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
+    DESTRUCTOR_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
     HDR = lltype.Struct("header", ("hash", lltype.Signed))
 
     def __init__(self, translator, inline=False):
         super(BoehmGCTransformer, self).__init__(translator, inline=inline)
-        self.finalizer_funcptrs = {}
+        self.destructor_funcptrs = {}
 
         atomic_mh = mallocHelpers()
         atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.Address, size)
@@ -66,10 +66,15 @@
         v_raw = hop.genop("direct_call",
                           [funcptr, c_size],
                           resulttype=llmemory.Address)
-        finalizer_ptr = self.finalizer_funcptr_for_type(TYPE)
-        if finalizer_ptr:
-            c_finalizer_ptr = Constant(finalizer_ptr, self.FINALIZER_PTR)
-            hop.genop("boehm_register_finalizer", [v_raw, c_finalizer_ptr])
+        destructor_ptr = self.destructor_funcptr_for_type(TYPE)
+        if destructor_ptr:
+            from rpython.rtyper.annlowlevel import base_ptr_lltype
+            c_destructor_ptr = Constant(destructor_ptr, self.DESTRUCTOR_PTR)
+            v_llfn = hop.genop('cast_ptr_to_adr', [c_destructor_ptr],
+                               resulttype=llmemory.Address)
+            v_self = hop.genop('cast_adr_to_ptr', [v_raw],
+                               resulttype=base_ptr_lltype())
+            hop.genop("gc_register_finalizer", [v_self, v_llfn])
         return v_raw
 
     def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
@@ -87,9 +92,9 @@
                                resulttype=llmemory.Address)
         return v_raw
 
-    def finalizer_funcptr_for_type(self, TYPE):
-        if TYPE in self.finalizer_funcptrs:
-            return self.finalizer_funcptrs[TYPE]
+    def destructor_funcptr_for_type(self, TYPE):
+        if TYPE in self.destructor_funcptrs:
+            return self.destructor_funcptrs[TYPE]
 
         rtti = get_rtti(TYPE)
         if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
@@ -102,16 +107,17 @@
         if destrptr:
             EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
             typename = TYPE.__name__
-            def ll_finalizer(addr):
+            def ll_destructor(addr):
                 exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE)
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
                 ll_call_destructor(destrptr, v, typename)
                 llop.gc_restore_exception(lltype.Void, exc_instance)
-            fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void)
+            fptr = self.annotate_finalizer(ll_destructor, [llmemory.Address],
+                                           lltype.Void)
         else:
-            fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
+            fptr = lltype.nullptr(self.DESTRUCTOR_PTR.TO)
 
-        self.finalizer_funcptrs[TYPE] = fptr
+        self.destructor_funcptrs[TYPE] = fptr
         return fptr
 
     def gct_weakref_create(self, hop):
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -148,7 +148,7 @@
         finalizer = llmemory.cast_adr_to_ptr(finalizer, self.FINALIZER)
         try:
             finalizer(obj)
-        except rgc.FinalizeLater:
+        except rgc._FinalizeLater:
             return False
         except Exception:
             debug_print("WARNING: unhandled exception from finalizer",
@@ -166,7 +166,7 @@
             llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
                                 recursive=True)
         except LLException, e:
-            if ''.join(e.args[0].name) == 'FinalizeLater\x00':
+            if ''.join(e.args[0].name) == '_FinalizeLater\x00':
                 return False
             raise RuntimeError(
                 "a finalizer raised an exception, shouldn't happen")
diff --git a/rpython/memory/test/test_gc.py b/rpython/memory/test/test_gc.py
--- a/rpython/memory/test/test_gc.py
+++ b/rpython/memory/test/test_gc.py
@@ -264,7 +264,7 @@
                 b.num_finalized += 1
                 debug_print("call to finalizer() number", b.num_finalized)
                 if (b.num_finalized % 3) == 0:
-                    raise rgc.FinalizeLater
+                    raise rgc._FinalizeLater
         def f(x):
             a = A()
             rgc.register_finalizer(a.finalizer)
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -6,6 +6,7 @@
 
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import we_are_translated, enforceargs, specialize
+from rpython.rlib.objectmodel import CDefinedIntSymbolic
 from rpython.rlib.nonconst import NonConstant
 from rpython.rtyper.extregistry import ExtRegistryEntry
 from rpython.rtyper.lltypesystem import lltype, llmemory
@@ -270,7 +271,7 @@
 
 # ____________________________________________________________
 
-class FinalizeLater(Exception):
+class _FinalizeLater(Exception):
     pass
 
 _finalizer_queue = collections.deque()
@@ -286,6 +287,12 @@
         progress_through_finalizer_queue()
         delattr(g, '__disable_del')
 
+gc_supports_finalize_later = CDefinedIntSymbolic('GC_SUPPORTS_FINALIZE_LATER',
+                                                 default=1)
+def finalize_later():
+    if gc_supports_finalize_later:
+        raise _FinalizeLater
+
 def register_finalizer(method):
     "NOT_RPYTHON"
     # Cheat, cheat.  When method() is called, its 'self' will actually be
@@ -336,7 +343,7 @@
         obj, func = _finalizer_queue.popleft()
         try:
             func(obj)
-        except FinalizeLater:
+        except _FinalizeLater:
             _finalizer_queue.appendleft((obj, func))
             break
         except Exception, e:
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -258,7 +258,7 @@
         def finalize(self):
             if len(seen) < 3:
                 seen.append((self.x, self.y))
-                raise rgc.FinalizeLater
+                raise rgc._FinalizeLater
             seen.append(True)
     p = Point(40, 2)
     rgc.register_finalizer(p.finalize)
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -981,9 +981,6 @@
 
     op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
 
-    def op_boehm_register_finalizer(self, p, finalizer):
-        pass
-
     def op_boehm_disappearing_link(self, link, obj):
         pass
 
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -413,7 +413,6 @@
 
     'boehm_malloc':         LLOp(),
     'boehm_malloc_atomic':  LLOp(),
-    'boehm_register_finalizer': LLOp(),
     'boehm_disappearing_link': LLOp(),
     'raw_malloc':           LLOp(),
     'raw_malloc_usage':     LLOp(sideeffects=False),
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -600,10 +600,6 @@
         return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
                                                                self.expr(op.result))
 
-    def OP_BOEHM_REGISTER_FINALIZER(self, op):
-        return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
-               % (self.expr(op.args[0]), self.expr(op.args[1]))
-
     def OP_RAW_MALLOC(self, op):
         eresult = self.expr(op.result)
         esize = self.expr(op.args[0])
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -91,6 +91,10 @@
 
 #endif /* RPY_ASSERT */
 
+
+#define GC_SUPPORTS_FINALIZE_LATER   1
+
+
 /* for Boehm GC */
 
 #ifdef PYPY_USING_BOEHM_GC
@@ -123,6 +127,10 @@
 #define OP_GC__DISABLE_FINALIZERS(r)  boehm_gc_finalizer_lock++
 #define OP_GC__ENABLE_FINALIZERS(r)  (boehm_gc_finalizer_lock--,	\
 				      boehm_gc_finalizer_notifier())
+#define OP_GC_REGISTER_FINALIZER(x, y, r)                               \
+                   GC_REGISTER_FINALIZER(x, (GC_finalization_proc)y, NULL, NULL, NULL)
+#undef GC_SUPPORTS_FINALIZE_LATER
+#define GC_SUPPORTS_FINALIZE_LATER   0
 
 #endif /* PYPY_USING_BOEHM_GC */
 
@@ -133,6 +141,9 @@
 #define OP_BOEHM_DISAPPEARING_LINK(link, obj, r)  /* nothing */
 #define OP_GC__DISABLE_FINALIZERS(r)  /* nothing */
 #define OP_GC__ENABLE_FINALIZERS(r)  /* nothing */
+#define OP_GC_REGISTER_FINALIZER(x, y, r)  /* nothing */
+#undef GC_SUPPORTS_FINALIZE_LATER
+#define GC_SUPPORTS_FINALIZE_LATER   0
 #endif
 
 /************************************************************/
diff --git a/rpython/translator/c/test/test_boehm.py b/rpython/translator/c/test/test_boehm.py
--- a/rpython/translator/c/test/test_boehm.py
+++ b/rpython/translator/c/test/test_boehm.py
@@ -136,9 +136,9 @@
         assert 0 < res1 <= 10
         assert 0 < res2 <= 5
 
-    def test_del_raises(self):
+    def test_finalizer_raises(self):
         class A(object):
-            def __del__(self):
+            def finalizer(self):
                 s.dels += 1
                 raise Exception
         class State:
@@ -164,6 +164,35 @@
         # it might be the test's fault though.
         assert res > 0
 
+    def test_finalizer_raises(self):
+        class A(object):
+            def finalizer(self):
+                s.dels += 1
+        class State:
+            pass
+        s = State()
+        s.dels = 0
+        def g():
+            a = A()
+            rgc.register_finalizer(a.finalizer)
+            assert not rgc.gc_supports_finalize_later
+        def f():
+            s.dels = 0
+            for i in range(10):
+                g()
+            llop.gc__collect(lltype.Void)
+            return s.dels
+        fn = self.getcompiled(f)
+        # we can't demand that boehm has collected all of the objects,
+        # even with the gc__collect call.  calling the compiled
+        # function twice seems to help, though.
+        res = 0
+        res += fn()
+        res += fn()
+        # if res is still 0, then we haven't tested anything so fail.
+        # it might be the test's fault though.
+        assert res > 0
+
     def test_memory_error_varsize(self):
         N = int(2**31-1)
         A = lltype.GcArray(lltype.Char)
diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -413,8 +413,9 @@
             def finalizer(self):
                 b.num_deleted += 1
                 if b.num_deleted == 3:
-                    raise rgc.FinalizeLater
+                    rgc.finalize_later()
         def f():
+            assert rgc.gc_supports_finalize_later
             A()
             i = 0
             while i < 5:


More information about the pypy-commit mailing list