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

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Oct 16 14:50:34 CEST 2007


Author: cfbolz
Date: Tue Oct 16 14:50:33 2007
New Revision: 47497

Modified:
   pypy/dist/pypy/rpython/memory/gctransform/framework.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
   pypy/dist/pypy/rpython/memory/gctransform/transform.py
Log:
significantly reduce the number of pushing and popping
the framework GCs do: variables are only saved across a
call if the variable is needed afterwards.


Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py	Tue Oct 16 14:50:33 2007
@@ -416,9 +416,9 @@
 
     def gct_direct_call(self, hop):
         if self.collect_analyzer.analyze(hop.spaceop):
-            self.push_roots(hop)
+            livevars = self.push_roots(hop)
             self.default(hop)
-            self.pop_roots(hop)
+            self.pop_roots(hop, livevars)
         else:
             self.default(hop)
 
@@ -462,20 +462,20 @@
             args = [self.c_const_gc, c_type_id, v_length, c_size,
                     c_varitemsize, c_ofstolength, c_can_collect,
                     c_has_finalizer]
-        self.push_roots(hop)
+        livevars = self.push_roots(hop)
         v_result = hop.genop("direct_call", [malloc_ptr] + args,
                              resulttype=llmemory.GCREF)
-        self.pop_roots(hop)
+        self.pop_roots(hop, livevars)
         return v_result
 
     gct_fv_gc_malloc_varsize = gct_fv_gc_malloc
 
     def gct_gc__collect(self, hop):
         op = hop.spaceop
-        self.push_roots(hop)
+        livevars = self.push_roots(hop)
         hop.genop("direct_call", [self.collect_ptr, self.c_const_gc],
                   resultvar=op.result)
-        self.pop_roots(hop)
+        self.pop_roots(hop, livevars)
 
     def gct_gc_x_swap_pool(self, hop):
         op = hop.spaceop
@@ -502,11 +502,11 @@
     def gct_gc_x_become(self, hop):
         op = hop.spaceop
         [v_target, v_source] = op.args
-        self.push_roots(hop)
+        livevars = self.push_roots(hop)
         hop.genop("direct_call",
                   [self.x_become_ptr, self.c_const_gc, v_target, v_source],
                   resultvar=op.result)
-        self.pop_roots(hop)
+        self.pop_roots(hop, livevars)
 
     def gct_zero_gc_pointers_inside(self, hop):
         v_ob = hop.spaceop.args[0]
@@ -530,12 +530,12 @@
         v_instance, = op.args
         v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
                            resulttype=llmemory.Address)
-        self.push_roots(hop)
+        livevars = self.push_roots(hop)
         v_result = hop.genop("direct_call", [malloc_ptr] + args,
                              resulttype=llmemory.GCREF)
         v_result = hop.genop("cast_opaque_ptr", [v_result],
                             resulttype=WEAKREFPTR)
-        self.pop_roots(hop)
+        self.pop_roots(hop, livevars)
         hop.genop("bare_setfield",
                   [v_result, rmodel.inputconst(lltype.Void, "weakptr"), v_addr])
         v_weakref = hop.genop("cast_ptr_to_weakrefptr", [v_result],
@@ -551,13 +551,13 @@
 
     def gct_gc_id(self, hop):
         if self.id_ptr is not None:
-            self.push_roots(hop)
+            livevars = self.push_roots(hop)
             [v_ptr] = hop.spaceop.args
             v_ptr = hop.genop("cast_opaque_ptr", [v_ptr],
                               resulttype=llmemory.GCREF)
             hop.genop("direct_call", [self.id_ptr, self.c_const_gc, v_ptr],
                       resultvar=hop.spaceop.result)
-            self.pop_roots(hop)
+            self.pop_roots(hop, livevars)
         else:
             hop.rename('cast_ptr_to_int')     # works nicely for non-moving GCs
 
@@ -570,10 +570,17 @@
     def push_roots(self, hop):
         if self.incr_stack_ptr is None:
             return
-        livevars = [var for var in self.livevars if not var_ispyobj(var)]
+        if self.gcdata.gc.moving_gc:
+            # moving GCs don't borrow, so the caller does not need to keep
+            # the arguments alive
+            livevars = [var for var in self.livevars_after_op
+                            if not var_ispyobj(var)]
+        else:
+            livevars = self.livevars_after_op + self.current_op_keeps_alive
+            livevars = [var for var in livevars if not var_ispyobj(var)]
         self.num_pushs += len(livevars)
         if not livevars:
-            return
+            return []
         c_len = rmodel.inputconst(lltype.Signed, len(livevars) )
         base_addr = hop.genop("direct_call", [self.incr_stack_ptr, c_len ],
                               resulttype=llmemory.Address)
@@ -588,11 +595,11 @@
                                       resulttype=WEAKREFPTR)
             v_adr = gen_cast(hop.llops, llmemory.Address, var)
             hop.genop("raw_store", [base_addr, c_type, c_k, v_adr])
+        return livevars
 
-    def pop_roots(self, hop):
+    def pop_roots(self, hop, livevars):
         if self.decr_stack_ptr is None:
             return
-        livevars = [var for var in self.livevars if not var_ispyobj(var)]
         if not livevars:
             return
         c_len = rmodel.inputconst(lltype.Signed, len(livevars) )

Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py	Tue Oct 16 14:50:33 2007
@@ -79,7 +79,7 @@
         [varoftype(PTR_TYPE), Constant('x', lltype.Void)],
         varoftype(lltype.Void))
     transformer = WriteBarrierTransformer(t)
-    hop = GcHighLevelOp(transformer, spaceop, llops)
+    hop = GcHighLevelOp(transformer, spaceop, 0, llops)
     hop.dispatch()
     found = False
     for op in llops:

Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/transform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/transform.py	Tue Oct 16 14:50:33 2007
@@ -33,10 +33,17 @@
 PyObjPtr = lltype.Ptr(lltype.PyObject)
 
 class GcHighLevelOp(object):
-    def __init__(self, gctransformer, op, llops):
-        self.gctransformer = gctransformer
+    def __init__(self, gct, op, index, llops):
+        self.gctransformer = gct
         self.spaceop = op
+        self.index = index
         self.llops = llops
+        gct.livevars_after_op = [
+            var for var in gct.livevars
+                if gct.var_last_needed_in[var] > self.index]
+        gct.current_op_keeps_alive = [
+            var for var in self.spaceop.args
+                if gct.var_last_needed_in.get(var) == self.index]
 
     def dispatch(self):
         gct = self.gctransformer
@@ -56,6 +63,8 @@
                     gct.push_alive(v_result)
             elif opname not in ('direct_call', 'indirect_call'):
                 gct.push_alive(v_result)
+        
+
 
     def rename(self, newopname):
         self.llops.append(
@@ -152,8 +161,21 @@
         #self.curr_block = block
         self.livevars = [var for var in block.inputargs
                     if var_needsgc(var) and not is_borrowed(var)]
-        for op in block.operations:
-            hop = GcHighLevelOp(self, op, self.llops)
+        allvars = [var for var in block.getvariables() if var_needsgc(var)]
+        self.var_last_needed_in = dict.fromkeys(allvars, 0)
+        for i, op in enumerate(block.operations):
+            for var in op.args:
+                if not var_needsgc(var):
+                    continue
+                self.var_last_needed_in[var] = i
+        for link in block.exits:
+            for var in link.args:
+                if not var_needsgc(var):
+                    continue
+                self.var_last_needed_in[var] = len(block.operations) + 1
+        
+        for i, op in enumerate(block.operations):
+            hop = GcHighLevelOp(self, op, i, self.llops)
             hop.dispatch()
 
         if len(block.exits) != 0: # i.e not the return block
@@ -182,6 +204,7 @@
             block.operations[:] = self.llops
         self.llops = None
         self.livevars = None
+        self.var_last_needed_in = None
 
     def transform_graph(self, graph):
         if graph in self.minimal_transform:



More information about the Pypy-commit mailing list