[pypy-commit] pypy default: redo the equivalent of 994b78f6c6eb in a way that works (can't use rgc.no_collect for various reasons)
arigo
noreply at buildbot.pypy.org
Sun Mar 29 21:30:01 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r76628:881354657952
Date: 2015-03-29 21:30 +0200
http://bitbucket.org/pypy/pypy/changeset/881354657952/
Log: redo the equivalent of 994b78f6c6eb in a way that works (can't use
rgc.no_collect for various reasons)
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -251,6 +251,8 @@
annhelper.finish() # at this point, annotate all mix-level helpers
annhelper.backend_optimize()
+ self.check_custom_trace_funcs(gcdata.gc, translator.rtyper)
+
self.collect_analyzer = CollectAnalyzer(self.translator)
self.collect_analyzer.analyze_all()
@@ -540,6 +542,24 @@
self.gcdata._has_got_custom_trace(self.get_type_id(TP))
specialize.arg(2)(func)
+ def check_custom_trace_funcs(self, gc, rtyper):
+ # detect if one of the custom trace functions uses the GC
+ # (it must not!)
+ for TP, func in rtyper.custom_trace_funcs:
+ def no_op_callback(obj, arg):
+ pass
+ def ll_check_no_collect(obj):
+ func(gc, obj, no_op_callback, None)
+ annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
+ graph1 = annhelper.getgraph(ll_check_no_collect, [SomeAddress()],
+ annmodel.s_None)
+ annhelper.finish()
+ collect_analyzer = CollectAnalyzer(self.translator)
+ if collect_analyzer.analyze_direct_call(graph1):
+ raise Exception(
+ "the custom trace hook %r for %r can cause "
+ "the GC to be called!" % (func, TP))
+
def consider_constant(self, TYPE, value):
self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc)
diff --git a/rpython/memory/gctransform/test/test_framework.py b/rpython/memory/gctransform/test/test_framework.py
--- a/rpython/memory/gctransform/test/test_framework.py
+++ b/rpython/memory/gctransform/test/test_framework.py
@@ -143,6 +143,31 @@
expected = "'no_collect' function can trigger collection: <function g at "
assert str(f.value).startswith(expected)
+def test_custom_trace_function_no_collect():
+ from rpython.rlib import rgc
+ from rpython.translator.c.genc import CStandaloneBuilder
+
+ S = lltype.GcStruct("MyStructure")
+ class Glob:
+ pass
+ glob = Glob()
+ def trace_func(gc, obj, callback, arg):
+ glob.foo = (gc, obj)
+ lambda_trace_func = lambda: trace_func
+ def entrypoint(argv):
+ lltype.malloc(S)
+ rgc.register_custom_trace_hook(S, lambda_trace_func)
+ return 0
+
+ t = rtype(entrypoint, [s_list_of_strings])
+ t.config.translation.gc = "minimark"
+ cbuild = CStandaloneBuilder(t, entrypoint, t.config,
+ gcpolicy=FrameworkGcPolicy2)
+ f = py.test.raises(Exception, cbuild.generate_graphs_for_llinterp)
+ assert 'can cause the GC to be called' in str(f.value)
+ assert 'trace_func' in str(f.value)
+ assert 'MyStructure' in str(f.value)
+
class WriteBarrierTransformer(ShadowStackFrameworkGCTransformer):
clean_sets = {}
GC_PARAMS = {}
More information about the pypy-commit
mailing list