[pypy-commit] pypy default: Provide a hint that can be specified as a decorator - @rgc.is_light_finalizer

fijal noreply at buildbot.pypy.org
Tue Oct 25 18:21:33 CEST 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: 
Changeset: r48445:9d13b202cb4b
Date: 2011-10-25 18:21 +0200
http://bitbucket.org/pypy/pypy/changeset/9d13b202cb4b/

Log:	Provide a hint that can be specified as a decorator -
	@rgc.is_light_finalizer

diff --git a/pypy/rlib/rgc.py b/pypy/rlib/rgc.py
--- a/pypy/rlib/rgc.py
+++ b/pypy/rlib/rgc.py
@@ -214,6 +214,10 @@
     func._gc_no_collect_ = True
     return func
 
+def is_light_finalizer(func):
+    func._is_light_finalizer_ = True
+    return func
+
 # ____________________________________________________________
 
 def get_rpy_roots():
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
@@ -1293,7 +1293,7 @@
         fptr = self.transformer.annotate_finalizer(ll_finalizer,
                 [llmemory.Address, llmemory.Address], llmemory.Address)
         g = destrptr._obj.graph
-        light = not FinalizerAnalyzer(self.translator).analyze_direct_call(g)
+        light = not FinalizerAnalyzer(self.translator).analyze_light_finalizer(g)
         return fptr, light
 
     def make_custom_trace_funcptr_for_type(self, TYPE):
diff --git a/pypy/rpython/memory/gcwrapper.py b/pypy/rpython/memory/gcwrapper.py
--- a/pypy/rpython/memory/gcwrapper.py
+++ b/pypy/rpython/memory/gcwrapper.py
@@ -201,7 +201,7 @@
 
         assert not type_contains_pyobjs(TYPE), "not implemented"
         t = self.llinterp.typer.annotator.translator
-        light = not FinalizerAnalyzer(t).analyze_direct_call(destrgraph)
+        light = not FinalizerAnalyzer(t).analyze_light_finalizer(destrgraph)
         def ll_finalizer(addr, dummy):
             assert dummy == llmemory.NULL
             try:
diff --git a/pypy/translator/backendopt/finalizer.py b/pypy/translator/backendopt/finalizer.py
--- a/pypy/translator/backendopt/finalizer.py
+++ b/pypy/translator/backendopt/finalizer.py
@@ -2,6 +2,11 @@
 from pypy.translator.backendopt import graphanalyze
 from pypy.rpython.lltypesystem import lltype
 
+class FinalizerError(Exception):
+    """ __del__ marked as lightweight finalizer, but the analyzer did
+    not agreed
+    """
+
 class FinalizerAnalyzer(graphanalyze.BoolGraphAnalyzer):
     """ Analyzer that determines whether a finalizer is lightweight enough
     so it can be called without all the complicated logic in the garbage
@@ -15,6 +20,13 @@
                      'direct_ptradd', 'force_cast', 'track_alloc_stop',
                      'raw_free']
     
+    def analyze_light_finalizer(self, graph):
+        result = self.analyze_direct_call(graph)
+        if (result is self.top_result() and
+            getattr(graph.func, '_is_light_finalizer_', False)):
+            raise FinalizerError(FinalizerError.__doc__, graph)
+        return result
+    
     def analyze_simple_operation(self, op, graphinfo):
         if op.opname in self.ok_operations:
             return self.bottom_result()
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -1,11 +1,13 @@
 
 import py
-from pypy.translator.backendopt.finalizer import FinalizerAnalyzer
+from pypy.translator.backendopt.finalizer import FinalizerAnalyzer,\
+     FinalizerError
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.unsimplify import varoftype
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.conftest import option
+from pypy.rlib import rgc
 
 
 class BaseFinalizerAnalyzerTests(object):
@@ -26,7 +28,7 @@
             t.view()
         a = FinalizerAnalyzer(t)
         fgraph = graphof(t, func_to_analyze)
-        result = a.analyze_direct_call(fgraph)
+        result = a.analyze_light_finalizer(fgraph)
         return result
 
     def test_nothing(self):
@@ -124,15 +126,17 @@
         r = self.analyze(f, [], A.__del__.im_func)
         assert r
 
-    def test_os_call(self):
-        py.test.skip("can allocate OSError, but also can raise, ignore for now")
-        import os
-        
-        def f(i):
-            os.close(i)
+    def test_is_light_finalizer_decorator(self):
+        S = lltype.GcStruct('S')
 
-        r = self.analyze(f, [int], backendopt=True)
-        assert not r
+        @rgc.is_light_finalizer
+        def f():
+            lltype.malloc(S)
+        @rgc.is_light_finalizer
+        def g():
+            pass
+        self.analyze(g, []) # did not explode
+        py.test.raises(FinalizerError, self.analyze, f, [])
 
 class TestOOType(BaseFinalizerAnalyzerTests):
     type_system = 'ootype'


More information about the pypy-commit mailing list