[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