[pypy-commit] pypy stm-thread: Remove the hand-waving uncertainty of gcsource, and instead

arigo noreply at buildbot.pypy.org
Tue Jun 5 09:58:59 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread
Changeset: r55306:62c2fc45c3a8
Date: 2012-06-04 16:51 +0200
http://bitbucket.org/pypy/pypy/changeset/62c2fc45c3a8/

Log:	Remove the hand-waving uncertainty of gcsource, and instead assume
	that it is able to find *all* calls to functions with a GC arg or
	result. Tentative: this should be true because external calls and
	callbacks are always with functions with no GC argument.

diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -134,6 +134,9 @@
 
         if self.config.translation.stm:
             from pypy.translator.stm import transform
+            self.getentrypointptr()    # build the wrapper first
+            # ^^ this is needed to make sure we see the no-GC wrapper function
+            # calling the GC entrypoint function.
             transformer = transform.STMTransformer(self.translator)
             transformer.transform()
 
diff --git a/pypy/translator/stm/gcsource.py b/pypy/translator/stm/gcsource.py
--- a/pypy/translator/stm/gcsource.py
+++ b/pypy/translator/stm/gcsource.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import Variable
+from pypy.objspace.flow.model import Variable, Constant
 from pypy.rpython.lltypesystem import lltype, rclass
 from pypy.translator.simplify import get_graph
 
@@ -25,23 +25,23 @@
     # We don't have to worry about external calls and callbacks.
     # This works by assuming that each graph's calls are fully tracked
     # by the last argument to 'indirect_call'.  Graphs for which we don't
-    # find any call like this are assumed to be called 'from the outside'
-    # passing any random arguments to it.
+    # find any call like this are assumed to be not called at all, e.g.
+    # as a result of having been inlined everywhere.
     resultlist = []
-    was_a_callee = set()
     #
     def call(graph, args, result):
         inputargs = graph.getargs()
         assert len(args) == len(inputargs)
         for v1, v2 in zip(args, inputargs):
-            if is_gc(v2):
-                assert is_gc(v1)
+            ig = is_gc(v1)
+            assert ig is is_gc(v2)
+            if ig:
                 resultlist.append((v1, v2))
-        if is_gc(result):
-            v = graph.getreturnvar()
-            assert is_gc(v)
+        v = graph.getreturnvar()
+        ig = is_gc(result)
+        assert ig is is_gc(v)
+        if ig:
             resultlist.append((v, result))
-        was_a_callee.add(graph)
     #
     for graph in translator.graphs:
         for block in graph.iterblocks():
@@ -61,6 +61,14 @@
                         continue
                 #
                 if op.opname == 'indirect_call':
+                    # any GC argument or result?
+                    for v in op.args[:-1]:
+                        if is_gc(v):
+                            break
+                    else:
+                        if not is_gc(op.result):
+                            continue    # no: ignore the indirect_call
+                    #
                     tographs = op.args[-1].value
                     if tographs is not None:
                         for tograph in tographs:
@@ -79,34 +87,21 @@
                     if is_instantiate:
                         resultlist.append(('instantiate', op.result))
                         continue
+                    #
+                    raise Exception("%r: unknown targets, passing GC "
+                                    "arguments or result" % (op,))
                 #
                 if is_gc(op.result):
                     resultlist.append((op, op.result))
             #
             for link in block.exits:
                 for v1, v2 in zip(link.args, link.target.inputargs):
-                    if is_gc(v2):
-                        assert is_gc(v1)
+                    ig = is_gc(v2)
+                    assert ig is is_gc(v1)
+                    if ig:
                         if v1 is link.last_exc_value:
                             v1 = 'last_exc_value'
                         resultlist.append((v1, v2))
-    #
-    # also add as a callee the graphs that are explicitly callees in the
-    # callgraph.  Useful because some graphs may end up not being called
-    # any more, if they were inlined.
-    was_originally_a_callee = set()
-    for _, graph in translator.callgraph.itervalues():
-        was_originally_a_callee.add(graph)
-    #
-    for graph in translator.graphs:
-        if graph not in was_a_callee:
-            if graph in was_originally_a_callee:
-                src = 'originally_a_callee'
-            else:
-                src = 'unknown'
-            for v in graph.getargs():
-                if is_gc(v):
-                    resultlist.append((src, v))
     return resultlist
 
 
@@ -130,13 +125,13 @@
         return set_of_variables
 
     def _backpropagate(self, variable):
+        if isinstance(variable, Constant):
+            return set([variable]), set()
         result = set()
         pending = [variable]
         seen = set(pending)
         for v2 in pending:
-            # we get a KeyError here if 'variable' is not found,
-            # or if one of the preceeding variables is not found
-            for v1 in self._backmapping[v2]:
+            for v1 in self._backmapping.get(v2, ()):
                 if isinstance(v1, Variable):
                     if v1 not in seen:
                         seen.add(v1)
diff --git a/pypy/translator/stm/localtracker.py b/pypy/translator/stm/localtracker.py
--- a/pypy/translator/stm/localtracker.py
+++ b/pypy/translator/stm/localtracker.py
@@ -41,17 +41,7 @@
         return True
 
     def _could_be_local(self, variable):
-        try:
-            srcs = self.gsrc[variable]
-        except KeyError:
-            if isinstance(variable, Constant):
-                srcs = [variable]
-            else:
-                # XXX we shouldn't get here, but we do translating the whole
-                # pypy.  We should investigate at some point.  In the meantime
-                # returning False is always safe.
-                self.reason = 'variable not in gsrc!'
-                return False
+        srcs = self.gsrc[variable]
         for src in srcs:
             if isinstance(src, SpaceOperation):
                 if src.opname in RETURNS_LOCAL_POINTER:
@@ -66,8 +56,6 @@
                     return False
             elif src == 'instantiate':
                 pass
-            elif src == 'originally_a_callee':
-                pass
             elif isinstance(src, str):
                 self.reason = src
                 return False
diff --git a/pypy/translator/stm/test/test_gcsource.py b/pypy/translator/stm/test/test_gcsource.py
--- a/pypy/translator/stm/test/test_gcsource.py
+++ b/pypy/translator/stm/test/test_gcsource.py
@@ -115,7 +115,7 @@
     gsrc = gcsource(main, [lltype.Ptr(lltype.GcStruct('S'))])
     v_result = gsrc.translator.graphs[0].getreturnvar()
     s = gsrc[v_result]
-    assert list(s) == ['unknown']
+    assert list(s) == []
 
 def test_exception():
     class FooError(Exception):


More information about the pypy-commit mailing list