Author: Maciej Fijalkowski <[email protected]>
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'
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit