[pypy-commit] pypy stmgc-c4: move rgc.no_release_gil to backendopt
Raemi
noreply at buildbot.pypy.org
Wed Aug 28 18:14:12 CEST 2013
Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c4
Changeset: r66405:27b6cc609d16
Date: 2013-08-28 17:55 +0200
http://bitbucket.org/pypy/pypy/changeset/27b6cc609d16/
Log: move rgc.no_release_gil to backendopt
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
@@ -46,34 +46,6 @@
return (op.opname in LL_OPERATIONS and
LL_OPERATIONS[op.opname].canmallocgc)
-class GilAnalyzer(graphanalyze.BoolGraphAnalyzer):
-
- def analyze_direct_call(self, graph, seen=None):
- try:
- func = graph.func
- except AttributeError:
- pass
- else:
- if getattr(func, '_gctransformer_hint_close_stack_', False):
- return True
- if getattr(func, '_transaction_break_', False):
- return True
-
- return graphanalyze.BoolGraphAnalyzer.analyze_direct_call(
- self, graph, seen)
-
- def analyze_external_call(self, op, seen=None):
- funcobj = op.args[0].value._obj
- if getattr(funcobj, 'transactionsafe', False):
- return False
- else:
- return False
-
- def analyze_instantiate_call(self, seen=None):
- return False
-
- def analyze_simple_operation(self, op, graphinfo):
- return False
def find_initializing_stores(collect_analyzer, graph):
@@ -281,9 +253,6 @@
self.collect_analyzer = CollectAnalyzer(self.translator)
self.collect_analyzer.analyze_all()
- self.gil_analyzer = GilAnalyzer(self.translator)
- self.gil_analyzer.analyze_all()
-
s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
r_gc = self.translator.rtyper.getrepr(s_gc)
self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
@@ -673,27 +642,6 @@
raise Exception("'no_collect' function can trigger collection:"
" %s\n%s" % (func, err.getvalue()))
- if func and getattr(func, '_no_release_gil_', False):
- if self.gil_analyzer.analyze_direct_call(graph):
- # 'no_release_gil' function can release the gil
- import cStringIO
- err = cStringIO.StringIO()
- import sys
- prev = sys.stdout
- try:
- sys.stdout = err
- ca = GilAnalyzer(self.translator)
- ca.verbose = True
- ca.analyze_direct_call(graph) # print the "traceback" here
- sys.stdout = prev
- except:
- sys.stdout = prev
- # ^^^ for the dump of which operation in which graph actually
- # causes it to return True
- raise Exception("'no_release_gil' function can release the GIL:"
- " %s\n%s" % (func, err.getvalue()))
-
-
if self.write_barrier_ptr:
self.clean_sets = (
find_initializing_stores(self.collect_analyzer, graph))
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
@@ -5,7 +5,7 @@
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.memory.gc.semispace import SemiSpaceGC
from rpython.memory.gctransform.framework import (CollectAnalyzer,
- find_initializing_stores, find_clean_setarrayitems, GilAnalyzer)
+ find_initializing_stores, find_clean_setarrayitems)
from rpython.memory.gctransform.shadowstack import (
ShadowStackFrameworkGCTransformer)
from rpython.memory.gctransform.test.test_transform import rtype
@@ -99,36 +99,6 @@
t = rtype(g, [])
gg = graphof(t, g)
assert CollectAnalyzer(t).analyze_direct_call(gg)
-
-def test_canrelease_external():
- for ths in ['auto', True, False]:
- for sbxs in [True, False]:
- fext = rffi.llexternal('fext2', [], lltype.Void,
- threadsafe=ths, sandboxsafe=sbxs)
- def g():
- fext()
- t = rtype(g, [])
- gg = graphof(t, g)
-
- releases = (ths == 'auto' and not sbxs) or ths is True
- assert releases == GilAnalyzer(t).analyze_direct_call(gg)
-
-def test_canrelease_instantiate():
- class O:
- pass
- class A(O):
- pass
- class B(O):
- pass
-
- classes = [A, B]
- def g(i):
- classes[i]()
-
- t = rtype(g, [int])
- gg = graphof(t, g)
- assert not GilAnalyzer(t).analyze_direct_call(gg)
-
def test_no_collect(gc="minimark"):
from rpython.rlib import rgc
@@ -155,60 +125,6 @@
def test_no_collect_stm():
test_no_collect("stmgc")
-def test_no_release_gil(gc="minimark"):
- from rpython.rlib import rgc
- from rpython.translator.c.genc import CStandaloneBuilder
-
- @rgc.no_release_gil
- def g():
- return 1
-
- assert g._dont_inline_
- assert g._no_release_gil_
-
- def entrypoint(argv):
- return g() + 2
-
- t = rtype(entrypoint, [s_list_of_strings])
- if gc == "stmgc":
- t.config.translation.stm = True
- t.config.translation.gc = gc
- cbuild = CStandaloneBuilder(t, entrypoint, t.config,
- gcpolicy=FrameworkGcPolicy2)
- db = cbuild.generate_graphs_for_llinterp()
-
-def test_no_release_gil_stm():
- test_no_release_gil("stmgc")
-
-def test_no_release_gil_detect(gc="minimark"):
- from rpython.rlib import rgc
- from rpython.translator.c.genc import CStandaloneBuilder
-
- fext1 = rffi.llexternal('fext1', [], lltype.Void, threadsafe=True)
- @rgc.no_release_gil
- def g():
- fext1()
- return 1
-
- assert g._dont_inline_
- assert g._no_release_gil_
-
- def entrypoint(argv):
- return g() + 2
-
- t = rtype(entrypoint, [s_list_of_strings])
- if gc == "stmgc":
- t.config.translation.stm = True
- t.config.translation.gc = gc
- cbuild = CStandaloneBuilder(t, entrypoint, t.config,
- gcpolicy=FrameworkGcPolicy2)
- f = py.test.raises(Exception, cbuild.generate_graphs_for_llinterp)
- expected = "'no_release_gil' function can release the GIL: <function g at "
- assert str(f.value).startswith(expected)
-
-def test_no_release_gil_detect_stm():
- test_no_release_gil_detect("stmgc")
-
def test_no_collect_detection(gc="minimark"):
from rpython.rlib import rgc
from rpython.translator.c.genc import CStandaloneBuilder
diff --git a/rpython/translator/backendopt/all.py b/rpython/translator/backendopt/all.py
--- a/rpython/translator/backendopt/all.py
+++ b/rpython/translator/backendopt/all.py
@@ -11,6 +11,7 @@
from rpython.translator.backendopt.support import log
from rpython.translator.backendopt.checkvirtual import check_virtual_methods
from rpython.translator.backendopt.storesink import storesink_graph
+from rpython.translator.backendopt import gilanalysis
from rpython.flowspace.model import checkgraph
INLINE_THRESHOLD_FOR_TEST = 33
@@ -142,6 +143,9 @@
for graph in graphs:
checkgraph(graph)
+ gilanalysis.analyze(graphs, translator)
+
+
def constfold(config, graphs):
if config.constfold:
for graph in graphs:
diff --git a/rpython/translator/backendopt/gilanalysis.py b/rpython/translator/backendopt/gilanalysis.py
new file mode 100644
--- /dev/null
+++ b/rpython/translator/backendopt/gilanalysis.py
@@ -0,0 +1,56 @@
+from rpython.translator.backendopt import graphanalyze
+
+class GilAnalyzer(graphanalyze.BoolGraphAnalyzer):
+
+ def analyze_direct_call(self, graph, seen=None):
+ try:
+ func = graph.func
+ except AttributeError:
+ pass
+ else:
+ if getattr(func, '_gctransformer_hint_close_stack_', False):
+ return True
+ if getattr(func, '_transaction_break_', False):
+ return True
+
+ return graphanalyze.BoolGraphAnalyzer.analyze_direct_call(
+ self, graph, seen)
+
+ def analyze_external_call(self, op, seen=None):
+ funcobj = op.args[0].value._obj
+ if getattr(funcobj, 'transactionsafe', False):
+ return False
+ else:
+ return False
+
+ def analyze_instantiate_call(self, seen=None):
+ return False
+
+ def analyze_simple_operation(self, op, graphinfo):
+ return False
+
+def analyze(graphs, translator):
+ gilanalyzer = GilAnalyzer(translator)
+ for graph in graphs:
+ func = getattr(graph, 'func', None)
+ if func and getattr(func, '_no_release_gil_', False):
+ if gilanalyzer.analyze_direct_call(graph):
+ # 'no_release_gil' function can release the gil
+ import cStringIO
+ err = cStringIO.StringIO()
+ import sys
+ prev = sys.stdout
+ try:
+ sys.stdout = err
+ ca = GilAnalyzer(translator)
+ ca.verbose = True
+ ca.analyze_direct_call(graph) # print the "traceback" here
+ sys.stdout = prev
+ except:
+ sys.stdout = prev
+ # ^^^ for the dump of which operation in which graph actually
+ # causes it to return True
+ raise Exception("'no_release_gil' function can release the GIL:"
+ " %s\n%s" % (func, err.getvalue()))
+
+
diff --git a/rpython/translator/backendopt/test/test_gilanalysis.py b/rpython/translator/backendopt/test/test_gilanalysis.py
new file mode 100644
--- /dev/null
+++ b/rpython/translator/backendopt/test/test_gilanalysis.py
@@ -0,0 +1,80 @@
+import py
+
+from rpython.annotator.listdef import s_list_of_strings
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.translator.backendopt import gilanalysis
+from rpython.memory.gctransform.test.test_transform import rtype
+from rpython.translator.translator import graphof
+
+def test_canrelease_external():
+ for ths in ['auto', True, False]:
+ for sbxs in [True, False]:
+ fext = rffi.llexternal('fext2', [], lltype.Void,
+ threadsafe=ths, sandboxsafe=sbxs)
+ def g():
+ fext()
+ t = rtype(g, [])
+ gg = graphof(t, g)
+
+ releases = (ths == 'auto' and not sbxs) or ths is True
+ assert releases == gilanalysis.GilAnalyzer(t).analyze_direct_call(gg)
+
+def test_canrelease_instantiate():
+ class O:
+ pass
+ class A(O):
+ pass
+ class B(O):
+ pass
+
+ classes = [A, B]
+ def g(i):
+ classes[i]()
+
+ t = rtype(g, [int])
+ gg = graphof(t, g)
+ assert not gilanalysis.GilAnalyzer(t).analyze_direct_call(gg)
+
+
+
+def test_no_release_gil():
+ from rpython.rlib import rgc
+
+ @rgc.no_release_gil
+ def g():
+ return 1
+
+ assert g._dont_inline_
+ assert g._no_release_gil_
+
+ def entrypoint(argv):
+ return g() + 2
+
+ t = rtype(entrypoint, [s_list_of_strings])
+ gilanalysis.analyze(t.graphs, t)
+
+
+
+def test_no_release_gil_detect(gc="minimark"):
+ from rpython.rlib import rgc
+
+ fext1 = rffi.llexternal('fext1', [], lltype.Void, threadsafe=True)
+ @rgc.no_release_gil
+ def g():
+ fext1()
+ return 1
+
+ assert g._dont_inline_
+ assert g._no_release_gil_
+
+ def entrypoint(argv):
+ return g() + 2
+
+ t = rtype(entrypoint, [s_list_of_strings])
+ f = py.test.raises(Exception, gilanalysis.analyze, t.graphs, t)
+ expected = "'no_release_gil' function can release the GIL: <function g at "
+ assert str(f.value).startswith(expected)
+
+
+
+
More information about the pypy-commit
mailing list