[pypy-svn] r23210 - in pypy/dist/pypy/rpython/memory: . test

mwh at codespeak.net mwh at codespeak.net
Fri Feb 10 17:03:17 CET 2006


Author: mwh
Date: Fri Feb 10 17:03:13 2006
New Revision: 23210

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
Log:
go to some effort to reuse static deallocator/decref graphs for types that do not
contain gc pointers.  this reduces the runtime of test_backendoptimized on my
machine from 424.91 seconds to 240.40 seconds (as compared with 200.56 seconds
on the trunk).

still should share dynamic deallocator graphs much more agressively but that
doesn't make so much difference to most tests.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Fri Feb 10 17:03:13 2006
@@ -191,9 +191,23 @@
         return [SpaceOperation("gc_pop_alive_pyobj", [var], result)]
 
     def free(self, var):
+        assert var.concretetype == llmemory.Address
         result = Variable()
         result.concretetype = lltype.Void
         return [SpaceOperation("gc_free", [var], result)]        
+
+    annotate_helper_count = 0
+    def annotate_helper(self, ll_helper, args):
+##         import sys
+##         self.annotate_helper_count += 1
+##         f = sys._getframe(1)
+##         TYPE = f.f_locals.get('TYPE')
+##         print "ahc", self.annotate_helper_count, f.f_code.co_name, 
+##         if TYPE:
+##             print len(find_gc_ptrs_in_type(TYPE))
+##         else:
+##             print 
+        return self.translator.rtyper.annotate_helper(ll_helper, args)
     
 
     # ----------------------------------------------------------------
@@ -220,17 +234,24 @@
     elif isinstance(TYPE, lltype.Ptr):
         yield '    '*depth + 'pop_alive(%s)'%v
 
-## def print_call_chain(ob):
-##     import sys
-##     f = sys._getframe(1)
-##     stack = []
-##     while f:
-##         if f.f_locals.get('self') is ob:
-##             stack.append((f.f_code.co_name, f.f_locals.get('TYPE')))
-##         f = f.f_back
-##     stack.reverse()
-##     for i, (a, b) in enumerate(stack):
-##         print ' '*i, a, repr(b)[:100-i-len(a)], id(b)
+counts = {}
+
+def print_call_chain(ob):
+    import sys
+    f = sys._getframe(1)
+    stack = []
+    flag = False
+    while f:
+        if f.f_locals.get('self') is ob:
+            stack.append((f.f_code.co_name, f.f_locals.get('TYPE')))
+            if not flag:
+                counts[f.f_code.co_name] = counts.get(f.f_code.co_name, 0) + 1
+                print counts
+                flag = True
+        f = f.f_back
+    stack.reverse()
+    for i, (a, b) in enumerate(stack):
+        print ' '*i, a, repr(b)[:100-i-len(a)], id(b)
 
 class RefcountingGCTransformer(GCTransformer):
 
@@ -243,12 +264,40 @@
             if adr:
                 gcheader = adr - RefcountingGCTransformer.gc_header_offset
                 gcheader.signed[0] = gcheader.signed[0] + 1
+        def compute_destroy_ll_ops(hop):
+            hop.llops.extend(self.free(hop.args_v[1]))
+            return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
+        def destroy(var):
+            pass
+        destroy.compute_ll_ops = compute_destroy_ll_ops
+        destroy.llresult = lltype.Void
+        def no_pointer_decref(adr):
+            if adr:
+                gcheader = adr - RefcountingGCTransformer.gc_header_offset
+                refcount = gcheader.signed[0] - 1
+                gcheader.signed[0] = refcount
+                if refcount == 0:
+                    destroy(adr)
+        def no_pointer_dealloc(adr):
+            destroy(adr)
         if self.translator is not None and self.translator.rtyper is not None:
-            self.increfgraph = self.translator.rtyper.annotate_helper(
+            self.increfgraph = self.annotate_helper(
                 incref, [annmodel.SomeAddress()])
             self.translator.rtyper.specialize_more_blocks()
             self.increfptr = const_funcptr_fromgraph(self.increfgraph)
             self.seen_graphs[self.increfgraph] = True
+            
+            self.no_pointer_decref_graph = self.annotate_helper(
+                no_pointer_decref, [annmodel.SomeAddress()])
+            self.translator.rtyper.specialize_more_blocks()
+            self.no_pointer_decref_ptr = const_funcptr_fromgraph(self.no_pointer_decref_graph)
+            self.seen_graphs[self.no_pointer_decref_graph] = True
+
+            self.no_pointer_dealloc_graph = self.annotate_helper(
+                no_pointer_dealloc, [annmodel.SomeAddress()])
+            self.translator.rtyper.specialize_more_blocks()
+            self.no_pointer_dealloc_ptr = const_funcptr_fromgraph(self.no_pointer_dealloc_graph)
+            self.seen_graphs[self.no_pointer_dealloc_graph] = True
         # cache graphs:
         self.decref_graphs = {}
         self.static_deallocator_graphs = {}
@@ -333,6 +382,12 @@
             destrptr = None
             DESTR_ARG = None
 
+        if destrptr is None and not PTRS:
+            #print repr(TYPE)[:80], 'is dealloc easy'
+            g = self.no_pointer_dealloc_graph
+            self.static_deallocator_graphs[TYPE] = g
+            return g
+
         if destrptr is not None:
             body = '\n'.join(_static_deallocator_body_for_type('v', TYPE, 2))
             src = """
@@ -350,13 +405,13 @@
     gcheader.signed[0] = refcount
     if refcount == 0:
 %s
-        destroy(v)
+        destroy(addr)
 """ % (body, )
         else:
             call_del = None
             body = '\n'.join(_static_deallocator_body_for_type('v', TYPE))
             src = ('def deallocator(addr):\n    v = cast_adr_to_ptr(addr, PTR_TYPE)\n' +
-                   body + '\n    destroy(v)\n')
+                   body + '\n    destroy(addr)\n')
         d = {'pop_alive': pop_alive,
              'destroy': destroy,
              'destrptr': destrptr,
@@ -368,7 +423,7 @@
              'os': py.std.os}
         exec src in d
         this = d['deallocator']
-        g = self.translator.rtyper.annotate_helper(this, [llmemory.Address])
+        g = self.annotate_helper(this, [llmemory.Address])
         # the produced deallocator graph does not need to be transformed
         self.seen_graphs[g] = True
         opcount = 0
@@ -387,6 +442,7 @@
     def dynamic_deallocation_graph_for_type(self, TYPE):
         if TYPE in self.dynamic_deallocator_graphs:
             return self.dynamic_deallocator_graphs[TYPE]
+        #print_call_chain(self)
 
         rtti = self.get_rtti(TYPE)
         assert rtti is not None
@@ -409,7 +465,7 @@
             rtti = queryptr(v)
             gcheader.signed[0] = 0
             call_destructor_for_rtti(addr, rtti)
-        g = self.translator.rtyper.annotate_helper(dealloc, [llmemory.Address])
+        g = self.annotate_helper(dealloc, [llmemory.Address])
         self.dynamic_deallocator_graphs[TYPE] = g
         self.seen_graphs[g] = True
         return g
@@ -417,12 +473,18 @@
     def decref_graph_for_type(self, TYPE):
         if TYPE in self.decref_graphs:
             return self.decref_graphs[TYPE]
+        #print_call_chain(self)
         need_dynamic_destructor = False
         rtti = self.get_rtti(TYPE)
         if rtti is None:
             need_dynamic_destructor = False
         else:
             need_dynamic_destructor = True
+        if rtti is None and not find_gc_ptrs_in_type(TYPE):
+            #print repr(TYPE)[:80], 'is decref easy'
+            g = self.no_pointer_decref_graph
+            self.decref_graphs[TYPE] = g
+            return g
         if not need_dynamic_destructor:
             graph = self.static_deallocation_graph_for_type(TYPE)
         else:
@@ -446,7 +508,7 @@
             gcheader.signed[0] = refcount
             if refcount == 0:
                 destructor(addr)
-        g = self.translator.rtyper.annotate_helper(decref, [llmemory.Address])
+        g = self.annotate_helper(decref, [llmemory.Address])
         # the produced deallocator graph does not need to be transformed
         self.seen_graphs[g] = True
         self.decref_graphs[TYPE] = g
@@ -544,7 +606,7 @@
                    "    v = cast_adr_to_ptr(addr, PTR_TYPE)\n"
                    "%s\n")%(static_body,)
             exec src in d
-            g = self.translator.rtyper.annotate_helper(d['finalizer'], [llmemory.Address])
+            g = self.annotate_helper(d['finalizer'], [llmemory.Address])
         elif destrptr:
             d = {'PTR_TYPE':DESTR_ARG,
                  'cast_adr_to_ptr':objectmodel.cast_adr_to_ptr,
@@ -553,8 +615,7 @@
                    "    v = cast_adr_to_ptr(addr, PTR_TYPE)\n"
                    "    destrptr(v)\n")
             exec src in d
-            g = self.translator.rtyper.annotate_helper(
-                d['finalizer'], [llmemory.Address])
+            g = self.annotate_helper(d['finalizer'], [llmemory.Address])
         else:
             g = None
 

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Fri Feb 10 17:03:13 2006
@@ -353,8 +353,8 @@
     ops = []
     for block in dgraph.iterblocks():
         ops.extend([op for op in block.operations if op.opname != 'same_as']) # XXX
-    assert len(ops) == 2
-    op = ops[1]
+    assert len(ops) == 1
+    op = ops[0]
     assert op.opname == 'gc_free'
 
 def test_deallocator_less_simple():



More information about the Pypy-commit mailing list