Author: Armin Rigo <[email protected]>
Branch: gc-del
Changeset: r62758:ff9d7eba9314
Date: 2013-03-25 21:37 +0100
http://bitbucket.org/pypy/pypy/changeset/ff9d7eba9314/

Log:    test_gc and test_transformed_gc pass now (with MiniMark only!)

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
@@ -331,13 +331,6 @@
     def debug_check_object(self, obj):
         pass
 
-    def register_finalizer(self, gcobj, llfn):
-        llobj = llmemory.cast_ptr_to_adr(gcobj)
-        self._register_finalizer(llobj, llfn)
-
-    def _register_finalizer(self, obj, llfn):
-        raise NotImplementedError   # must be overridden
-
     def execute_finalizers(self):
         if self.running_finalizers:
             return    # the outer invocation of execute_finalizers() will do it
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -973,7 +973,7 @@
                           "the card marker bits are not cleared")
                 i -= 1
 
-    def _register_finalizer(self, obj, llfn):
+    def register_finalizer(self, obj, llfn):
         if self.header(obj).tid & (
             GCFLAG_HAS_FINALIZER |      # obj has already a finalizer
             GCFLAG_NO_HEAP_PTRS):       # immortal object anyway, and we don't
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
@@ -431,6 +431,12 @@
                                             annmodel.SomeInteger(nonneg=True)],
                                            annmodel.s_None)
 
+        self.register_finalizer_ptr = getfn(GCClass.register_finalizer.im_func,
+                                            [s_gc, 
+                                             annmodel.SomeAddress(),
+                                             annmodel.SomeAddress()],
+                                            annmodel.s_None)
+
         self.write_barrier_ptr = None
         self.write_barrier_from_array_ptr = None
         if GCClass.needs_write_barrier:
@@ -1194,8 +1200,14 @@
     def pop_roots(self, hop, livevars):
         raise NotImplementedError
 
-    def gct_gc_register_finalizer(self, op):
-        xxx
+    def gct_gc_register_finalizer(self, hop):
+        v_obj, v_func = hop.spaceop.args
+        v_obj_addr = hop.genop("cast_ptr_to_adr", [v_obj],
+                               resulttype = llmemory.Address)
+        hop.genop("direct_call", [self.register_finalizer_ptr,
+                                  self.c_const_gc,
+                                  v_obj_addr, v_func],
+                  resultvar = hop.spaceop.result)
 
 
 class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder):
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -1,10 +1,10 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, llgroup
 from rpython.rtyper.lltypesystem import rclass
 from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rlib.debug import ll_assert, debug_print
+from rpython.rlib.debug import ll_assert, debug_print, llinterpcall
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib import rgc
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, running_on_llinterp
 from rpython.tool.identity_dict import identity_dict
 
 
@@ -140,14 +140,36 @@
         return infobits & T_ANY_SLOW_FLAG == 0
 
     def q_call_finalizer(self, finalizer, obj):
+        if not we_are_translated():
+            return GCData.p_call_finalizer(finalizer, obj)
+        if running_on_llinterp:
+            return llinterpcall(lltype.Bool, GCData.p_call_finalizer,
+                                finalizer, obj)
         finalizer = llmemory.cast_adr_to_ptr(finalizer, self.FINALIZER)
         try:
             finalizer(obj)
         except rgc.FinalizeLater:
             return False
         except Exception:
-            debug_print("exception from finalizer", finalizer, "of", obj)
-            llop.debug_fatalerror(lltype.Void, "exception from finalizer!")
+            debug_print("WARNING: unhandled exception from finalizer",
+                        finalizer, "of", obj)
+        return True
+
+    @staticmethod
+    def p_call_finalizer(finalizer, obj):
+        "NOT_RPYTHON"
+        from rpython.rtyper.llinterp import LLInterpreter, LLException
+        FUNC = lltype.typeOf(finalizer.ptr).TO
+        obj = llmemory.cast_adr_to_ptr(obj, FUNC.ARGS[0])
+        llinterp = LLInterpreter.current_interpreter
+        try:
+            llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
+                                recursive=True)
+        except LLException, e:
+            if ''.join(e.args[0].name) == 'FinalizeLater\x00':
+                return False
+            raise RuntimeError(
+                "a finalizer raised an exception, shouldn't happen")
         return True
 
 
@@ -404,11 +426,8 @@
         # must be overridden for proper custom tracer support
         return None
 
-    def initialize_gc_query_function(self, gc, call_finalizer=None):
-        gcdata = GCData(self.type_info_group)
-        if call_finalizer is not None:
-            gcdata.q_call_finalizer = call_finalizer   # for tests
-        gcdata.set_query_functions(gc)
+    def initialize_gc_query_function(self, gc):
+        GCData(self.type_info_group).set_query_functions(gc)
 
     def consider_constant(self, TYPE, value, gc):
         if value is not lltype.top_container(value):
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -29,8 +29,7 @@
                                                lltype2vtable,
                                                self.llinterp)
         self.get_type_id = layoutbuilder.get_type_id
-        layoutbuilder.initialize_gc_query_function(
-            self.gc, layoutbuilder._call_finalizer)
+        layoutbuilder.initialize_gc_query_function(self.gc)
 
         constants = collect_constants(flowgraphs)
         for obj in constants:
@@ -169,7 +168,8 @@
         return (hdr.tid & self.gc.gcflag_extra) != 0
 
     def register_finalizer(self, llptr, llfn):
-        self.gc.register_finalizer(llptr, llfn)
+        llobj = llmemory.cast_ptr_to_adr(llptr)
+        self.gc.register_finalizer(llobj, llfn)
 
 # ____________________________________________________________
 
@@ -239,19 +239,6 @@
         else:
             return None
 
-    def _call_finalizer(self, finalizer, obj):
-        FUNC = lltype.typeOf(finalizer.ptr).TO
-        obj = llmemory.cast_adr_to_ptr(obj, FUNC.ARGS[0])
-        try:
-            self.llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
-                                     recursive=True)
-        except llinterp.LLException, e:
-            if ''.join(e.args[0].name) == 'FinalizeLater\x00':
-                return False
-            raise RuntimeError(
-                "a finalizer raised an exception, shouldn't happen")
-        return True
-
 
 def collect_constants(graphs):
     constants = {}
diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py
--- a/rpython/memory/test/snippet.py
+++ b/rpython/memory/test/snippet.py
@@ -140,12 +140,13 @@
         class B:
             count = 0
         class A:
-            def __del__(self):
+            def finalizer(self):
                 self.b.count += 1
         def g():
             b = B()
             a = A()
             a.b = b
+            rgc.register_finalizer(a.finalizer)
             i = 0
             lst = [None]
             while i < MAX:
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
@@ -373,8 +373,6 @@
             count = 0
         a = A()
         class B(object):
-            def __init__(self, ref):
-                rgc.register_finalizer(self.finalizer)
             def finalizer(self):
                 # when the finalizer is called, the weakref to myself is
                 # still valid in RPython
@@ -383,7 +381,8 @@
             b = B()
             ref = weakref.ref(b)
             b.ref = ref
-            return b
+            rgc.register_finalizer(b.finalizer)
+            return ref
         def f():
             ref = g()
             llop.gc__collect(lltype.Void)
@@ -412,14 +411,12 @@
         res = self.interpret(f, [])
         assert res
 
-    def test_cycle_with_weakref_and_del(self):
+    def test_cycle_with_weakref_and_finalizer(self):
         import weakref
         class A(object):
             count = 0
         a = A()
         class B(object):
-            def __init__(self, ref):
-                rgc.register_finalizer(self.finalizer)
             def finalizer(self):
                 # when the finalizer is called, the weakref to c should be dead
                 if self.ref() is None:
@@ -433,6 +430,7 @@
             c.b = B()
             ref = weakref.ref(c)
             c.b.ref = ref
+            rgc.register_finalizer(c.b.finalizer)
             return ref
         def f():
             ref = g()
@@ -448,13 +446,12 @@
         class A(object):
             pass
         class B(object):
-            def __init__(self, ref):
-                rgc.register_finalizer(self.finalizer)
             def finalizer(self):
                 self.wref().x += 1
         def g(a):
             b = B()
             b.wref = weakref.ref(a)
+            rgc.register_finalizer(b.finalizer)
             # the only way to reach this weakref is via B, which is an
             # object with finalizer (but the weakref itself points to
             # a, which does not go away but will move during the next
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to