[pypy-svn] r23353 - in pypy: branch/genc-gc-refactoring dist/pypy/objspace/flow dist/pypy/rpython/memory

pedronis at codespeak.net pedronis at codespeak.net
Wed Feb 15 04:08:50 CET 2006


Author: pedronis
Date: Wed Feb 15 04:08:46 2006
New Revision: 23353

Modified:
   pypy/branch/genc-gc-refactoring/funcgen.py
   pypy/dist/pypy/objspace/flow/model.py
   pypy/dist/pypy/rpython/memory/gctransform.py
Log:
don't let genc accept (in)direct_calls without an explict .cleanup set to None (cannot raise)
or some op sequence. Too much risk of not catching exceptions by mistake.

tweak the tranforms to respect this condition.



Modified: pypy/branch/genc-gc-refactoring/funcgen.py
==============================================================================
--- pypy/branch/genc-gc-refactoring/funcgen.py	(original)
+++ pypy/branch/genc-gc-refactoring/funcgen.py	Wed Feb 15 04:08:46 2006
@@ -301,7 +301,7 @@
 
             errorcases = {}
             for i, op in list(enumerate(block.operations))[::-1]:
-                if not hasattr(op, 'cleanup'):
+                if getattr(op, 'cleanup', None) is None:
                     continue
                 errorcases.setdefault(op.cleanup, []).append(i)
 
@@ -413,7 +413,11 @@
             # skip assignment of 'void' return value
             r = self.expr(op.result)
             line = '%s = %s' % (r, line)
-        if getattr(op, 'cleanup', None) is not None:
+        try:
+            cleanup = op.cleanup
+        except AttributeError:
+            raise AttributeError("(in)direct_call %r without explicit .cleanup" % op)
+        if cleanup is not None:
             line = '%s\n%s' % (line, self.check_directcall_result(op, err))
         return line
 

Modified: pypy/dist/pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py	(original)
+++ pypy/dist/pypy/objspace/flow/model.py	Wed Feb 15 04:08:46 2006
@@ -323,14 +323,18 @@
     __reduce__ = __reduce_ex__
 
 
+NOCLEANUP = object()
+
 class SpaceOperation(object):
     __slots__ = "opname args result offset cleanup".split()
 
-    def __init__(self, opname, args, result, offset=-1):
+    def __init__(self, opname, args, result, offset=-1, cleanup=NOCLEANUP):
         self.opname = intern(opname)      # operation name
         self.args   = list(args)  # mixed list of var/const
         self.result = result      # either Variable or Constant instance
         self.offset = offset      # offset in code string
+        if cleanup is not NOCLEANUP:
+            self.cleanup = cleanup
 
     def __eq__(self, other):
         return (self.__class__ is other.__class__ and 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed Feb 15 04:08:46 2006
@@ -209,6 +209,15 @@
         return r
     
 
+def exception_clean(graph):
+    c = 0
+    for block in graph.iterblocks():
+        for op in block.operations:
+            if op.opname in ('direct_call', 'indirect_call'):
+                op.cleanup = None
+                c += 1
+    return c
+
 class MinimalGCTransformer(GCTransformer):
     def push_alive_nopyobj(self, var):
         return []
@@ -292,6 +301,8 @@
             decref_graph = self.annotate_helper(
                 decref, [annmodel.SomeAddress(), lltype.Ptr(ADDRESS_VOID_FUNC)])
             self.translator.rtyper.specialize_more_blocks()
+            nsafecalls = exception_clean(decref_graph)
+            assert nsafecalls == 1
             self.decref_ptr = const_funcptr_fromgraph(decref_graph)
             self.seen_graphs[decref_graph] = True
 
@@ -314,7 +325,7 @@
         adr1 = varoftype(llmemory.Address)
         result = [SpaceOperation("cast_ptr_to_adr", [var], adr1)]
         result.append(SpaceOperation("direct_call", [self.increfptr, adr1],
-                                     varoftype(lltype.Void)))
+                                     varoftype(lltype.Void), cleanup=None))
         return result
 
     def pop_alive_nopyobj(self, var):
@@ -328,7 +339,7 @@
              
         result.append(SpaceOperation("direct_call",
                                      [self.decref_ptr, adr1, cdealloc_fptr],
-                                     varoftype(lltype.Void)))
+                                     varoftype(lltype.Void), cleanup=None))
         return result
 
     def replace_setfield(self, op):
@@ -485,6 +496,9 @@
             gcheader.signed[0] = 0
             objectmodel.llop.gc_call_rtti_destructor(lltype.Void, rtti, addr)
         g = self.annotate_helper(dealloc, [llmemory.Address])
+        self.specialize_more_blocks()
+        nsafecalls = exception_clean(g)
+        assert nsafecalls == 1        
         self.seen_graphs[g] = True
         
         fptr = lltype.functionptr(ADDRESS_VOID_FUNC, g.name, graph=g)
@@ -589,7 +603,7 @@
             d = {'PTR_TYPE':DESTR_ARG,
                  'cast_adr_to_ptr':objectmodel.cast_adr_to_ptr,
                  'destrptr':destrptr}
-            # XXX swallow __del__ exceptions, preserve preexisting ones in case, minimal transform!!
+            # XXX swallow __del__ exceptions, preserve preexisting ones in case!
             src = ("def finalizer(addr):\n"
                    "    v = cast_adr_to_ptr(addr, PTR_TYPE)\n"
                    "    destrptr(v)\n")
@@ -601,7 +615,7 @@
         if g:
             self.seen_graphs[g] = True
             self.specialize_more_blocks()
-            
+            MinimalGCTransformer(self.translator).transform_graph(g)
             fptr = lltype.functionptr(ADDRESS_VOID_FUNC, g.name, graph=g)
             self.finalizer_funcptrs[TYPE] = fptr
             return fptr



More information about the Pypy-commit mailing list