[pypy-commit] pypy custom-trace: test_transformed_gc for custom tracers.

arigo noreply at buildbot.pypy.org
Fri Jul 22 13:24:02 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: custom-trace
Changeset: r45869:7467e121d4ac
Date: 2011-07-21 21:28 +0200
http://bitbucket.org/pypy/pypy/changeset/7467e121d4ac/

Log:	test_transformed_gc for custom tracers.

diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -534,8 +534,8 @@
     #    this method is attached to the instance and redirects to
     #    layoutbuilder.get_type_id().
 
-    def finalizer_funcptr_for_type(self, TYPE):
-        return self.layoutbuilder.finalizer_funcptr_for_type(TYPE)
+    def special_funcptr_for_type(self, TYPE):
+        return self.layoutbuilder.special_funcptr_for_type(TYPE)
 
     def gc_header_for(self, obj, needs_hash=False):
         hdr = self.gcdata.gc.gcheaderbuilder.header_of_object(obj)
@@ -678,7 +678,9 @@
         c_type_id = rmodel.inputconst(TYPE_ID, type_id)
         info = self.layoutbuilder.get_info(type_id)
         c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
-        has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE))
+        kind_and_fptr = self.special_funcptr_for_type(TYPE)
+        has_finalizer = (kind_and_fptr is not None and
+                         kind_and_fptr[0] == "finalizer")
         c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
 
         if not op.opname.endswith('_varsize') and not flags.get('varsize'):
@@ -1233,19 +1235,21 @@
 
     def has_finalizer(self, TYPE):
         rtti = get_rtti(TYPE)
-        return rtti is not None and hasattr(rtti._obj, 'destructor_funcptr')
+        return rtti is not None and getattr(rtti._obj, 'destructor_funcptr',
+                                            None)
+
+    def has_custom_trace(self, TYPE):
+        rtti = get_rtti(TYPE)
+        return rtti is not None and getattr(rtti._obj, 'custom_trace_funcptr',
+                                            None)
 
     def make_finalizer_funcptr_for_type(self, TYPE):
-        if self.has_finalizer(TYPE):
+        if not self.has_finalizer(TYPE):
+            return None
             rtti = get_rtti(TYPE)
             destrptr = rtti._obj.destructor_funcptr
             DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
-        else:
-            destrptr = None
-            DESTR_ARG = None
-
         assert not type_contains_pyobjs(TYPE), "not implemented"
-        if destrptr:
             typename = TYPE.__name__
             def ll_finalizer(addr, ignored):
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
@@ -1254,8 +1258,17 @@
             fptr = self.transformer.annotate_finalizer(ll_finalizer,
                     [llmemory.Address, llmemory.Address], llmemory.Address)
             return fptr
-        else:
+
+    def make_custom_trace_funcptr_for_type(self, TYPE):
+        if not self.has_custom_trace(TYPE):
             return None
+        rtti = get_rtti(TYPE)
+        fptr = rtti._obj.custom_trace_funcptr
+        if not hasattr(fptr._obj, 'graph'):
+            ll_func = fptr._obj._callable
+            fptr = self.transformer.annotate_finalizer(ll_func,
+                    [llmemory.Address, llmemory.Address], llmemory.Address)
+        return fptr
 
 
 def gen_zero_gc_pointers(TYPE, v, llops, previous_steps=None):
diff --git a/pypy/rpython/memory/gctypelayout.py b/pypy/rpython/memory/gctypelayout.py
--- a/pypy/rpython/memory/gctypelayout.py
+++ b/pypy/rpython/memory/gctypelayout.py
@@ -188,7 +188,7 @@
     infobits = index
     info.ofstoptrs = builder.offsets2table(offsets, TYPE)
     #
-    kind_and_fptr = builder.finalizer_funcptr_for_type(TYPE)
+    kind_and_fptr = builder.special_funcptr_for_type(TYPE)
     if kind_and_fptr is not None:
         kind, fptr = kind_and_fptr
         info.finalizer_or_customtrace = fptr
@@ -263,7 +263,7 @@
         # for debugging, the following list collects all the prebuilt
         # GcStructs and GcArrays
         self.all_prebuilt_gc = []
-        self._finalizer_funcptrs = {}
+        self._special_funcptrs = {}
         self.offsettable_cache = {}
 
     def make_type_info_group(self):
@@ -364,9 +364,9 @@
         self.offsettable_cache = None
         return self.type_info_group
 
-    def finalizer_funcptr_for_type(self, TYPE):
-        if TYPE in self._finalizer_funcptrs:
-            return self._finalizer_funcptrs[TYPE]
+    def special_funcptr_for_type(self, TYPE):
+        if TYPE in self._special_funcptrs:
+            return self._special_funcptrs[TYPE]
         fptr1 = self.make_finalizer_funcptr_for_type(TYPE)
         fptr2 = self.make_custom_trace_funcptr_for_type(TYPE)
         assert not (fptr1 and fptr2), (
@@ -377,7 +377,7 @@
             kind_and_fptr = "custom_trace", fptr2
         else:
             kind_and_fptr = None
-        self._finalizer_funcptrs[TYPE] = kind_and_fptr
+        self._special_funcptrs[TYPE] = kind_and_fptr
         return kind_and_fptr
 
     def make_finalizer_funcptr_for_type(self, TYPE):
diff --git a/pypy/rpython/memory/test/test_transformed_gc.py b/pypy/rpython/memory/test/test_transformed_gc.py
--- a/pypy/rpython/memory/test/test_transformed_gc.py
+++ b/pypy/rpython/memory/test/test_transformed_gc.py
@@ -410,6 +410,40 @@
         res = run([5, 42]) #XXX pure lazyness here too
         assert 160 <= res <= 165
 
+    def define_custom_trace(cls):
+        from pypy.rpython.annlowlevel import llhelper
+        from pypy.rpython.lltypesystem import llmemory
+        #
+        S = lltype.GcStruct('S', ('x', llmemory.Address), rtti=True)
+        T = lltype.GcStruct('T', ('z', lltype.Signed))
+        offset_of_x = llmemory.offsetof(S, 'x')
+        def customtrace(obj, prev):
+            if not prev:
+                return obj + offset_of_x
+            else:
+                return llmemory.NULL
+        CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
+                                          llmemory.Address)
+        customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace)
+        lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr)
+        #
+        def setup():
+            s1 = lltype.malloc(S)
+            tx = lltype.malloc(T)
+            tx.z = 4243
+            s1.x = llmemory.cast_ptr_to_adr(tx)
+            return s1
+        def f():
+            s1 = setup()
+            llop.gc__collect(lltype.Void)
+            return llmemory.cast_adr_to_ptr(s1.x, lltype.Ptr(T)).z
+        return f
+
+    def test_custom_trace(self):
+        run = self.runner("custom_trace")
+        res = run([])
+        assert res == 4243
+
     def define_weakref(cls):
         import weakref, gc
         class A(object):
diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py
--- a/pypy/translator/c/gc.py
+++ b/pypy/translator/c/gc.py
@@ -320,8 +320,10 @@
             # still important to see it so that it can be followed as soon as
             # the mixlevelannotator resolves it.
             gctransf = self.db.gctransformer
-            fptr = gctransf.finalizer_funcptr_for_type(structdefnode.STRUCT)
-            self.db.get(fptr)
+            TYPE = structdefnode.STRUCT
+            kind_and_fptr = gctransf.special_funcptr_for_type(TYPE)
+            if kind_and_fptr:
+                self.db.get(kind_and_fptr[1])
 
     def array_setup(self, arraydefnode):
         pass


More information about the pypy-commit mailing list