[pypy-svn] r20397 - in pypy/branch/somepbc-refactoring/pypy: rpython translator/c translator/c/test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 29 16:54:54 CET 2005


Author: arigo
Date: Tue Nov 29 16:54:52 2005
New Revision: 20397

Modified:
   pypy/branch/somepbc-refactoring/pypy/rpython/rptr.py
   pypy/branch/somepbc-refactoring/pypy/rpython/rtyper.py
   pypy/branch/somepbc-refactoring/pypy/translator/c/stackless.py
   pypy/branch/somepbc-refactoring/pypy/translator/c/test/test_stackless.py
Log:
Fix test_stackless: stackless.py needs to handle graphs instead of
funcs, and there was a way for the call graph to miss some edges --
more precisely, ll helpers calling other ll helpers.


Modified: pypy/branch/somepbc-refactoring/pypy/rpython/rptr.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/rptr.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/rptr.py	Tue Nov 29 16:54:52 2005
@@ -59,6 +59,9 @@
         if not isinstance(self.lowleveltype.TO, FuncType):
             raise TyperError("calling a non-function %r", self.lowleveltype.TO)
         vlist = hop.inputargs(*hop.args_r)
+        if isinstance(vlist[0], flowmodel.Constant):
+            if hasattr(vlist[0].value, 'graph'):
+                hop.llops.record_extra_call(vlist[0].value.graph)
         hop.exception_is_here()
         return hop.genop('direct_call', vlist,
                          resulttype = self.lowleveltype.TO.RESULT)

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/rtyper.py	Tue Nov 29 16:54:52 2005
@@ -719,6 +719,13 @@
     def hasparentgraph(self):
         return self.originalblock is not None
 
+    def record_extra_call(self, graph):
+        if self.hasparentgraph():
+            self.rtyper.annotator.translator.update_call_graph(
+                caller_graph = self.getparentgraph(),
+                callee_graph = graph,
+                position_tag = object())
+
     def convertvar(self, v, r_from, r_to):
         assert isinstance(v, (Variable, Constant))
         if r_from != r_to:
@@ -778,11 +785,7 @@
             ll_function = ll_function.im_func
 
         graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s)
-        if self.hasparentgraph():
-            rtyper.annotator.translator.update_call_graph(
-                caller_graph = self.getparentgraph(),
-                callee_graph = graph,
-                position_tag = object())
+        self.record_extra_call(graph)
 
         # build the 'direct_call' operation
         f = self.rtyper.getcallable(graph)

Modified: pypy/branch/somepbc-refactoring/pypy/translator/c/stackless.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/c/stackless.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/c/stackless.py	Tue Nov 29 16:54:52 2005
@@ -8,6 +8,7 @@
 from pypy.objspace.flow.model import Variable
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory.lladdress import Address
+from pypy.rpython.module import ll_stack, ll_stackless
 from pypy.translator.c.support import cdecl
 from pypy.translator.c.funcgen import FunctionCodeGenerator
 
@@ -21,21 +22,26 @@
 
         # start the decoding table with entries for the functions that
         # are written manually in ll_stackless.h
-        def reg(name):
-            self.stackless_roots[name.lower()] = True
-            return name
+        def reg(llfn):
+            """Register the given ll_ primitive function as being able to unwing
+            the stack.  Required to compute 'can_reach_unwind' correctly."""
+            assert llfn.suggested_primitive
+            self.stackless_roots[llfn] = True
+            name = llfn.__name__
+            assert name.startswith('ll_')
+            return 'LL_' + name[3:]
 
-        reg('LL_stack_unwind')
-        self.registerunwindable(reg('LL_stackless_stack_unwind'),
+        reg(ll_stack.ll_stack_unwind)
+        self.registerunwindable('LL_stackless_stack_unwind',
                                 lltype.FuncType([], lltype.Void),
                                 resume_points=1)
-        self.registerunwindable(reg('LL_stackless_stack_frames_depth'),
+        self.registerunwindable(reg(ll_stackless.ll_stackless_stack_frames_depth),
                                 lltype.FuncType([], lltype.Signed),
                                 resume_points=1)
-        self.registerunwindable(reg('LL_stackless_switch'),
+        self.registerunwindable(reg(ll_stackless.ll_stackless_switch),
                                 lltype.FuncType([Address], Address),
                                 resume_points=1)
-        self.registerunwindable(reg('slp_end_of_yielding_function'),
+        self.registerunwindable('slp_end_of_yielding_function',
                                 lltype.FuncType([], Address),
                                 resume_points=1)
 
@@ -43,11 +49,11 @@
         self.database = database
         self.count_calls = [0, 0]
 
-    def unwind_reachable(self, func):
+    def unwind_reachable(self, graph):
         reach_dict = self.can_reach_unwind
-        if func not in reach_dict:
+        if graph not in reach_dict:
             self.setup()
-        return reach_dict[func]
+        return reach_dict[graph]
 
     def setup(self):
         # to be called after database is complete, or we would
@@ -58,28 +64,28 @@
         callers = {}
         assert self.database.completed
         translator = self.database.translator
-        here = len(translator.functions)
-        for func in translator.functions:
-            callers[func] = []
-        for caller, callee in translator.complete_callgraph.values():
-            callers[caller].append(callee)
-        # add newly generated ones
-        for func in translator.functions[here:]:
-            callers.setdefault(func, [])
+        for graph in translator.graphs:
+            callers[graph] = []
+        for caller, callee in translator.callgraph.values():
+            # ignore calls issued suggested_primitives -- they are not
+            # compiled in, and they typically contain pseudo-recursions
+            try:
+                suggprim = caller.func.suggested_primitive
+            except AttributeError:
+                suggprim = False
+            if not suggprim:
+                callers[caller].append(callee)
         # check all callees if they can reach unwind
         seen = self.can_reach_unwind
         
         pending = {}
         ext = self.database.externalfuncs
-        def check_unwind(func):
-            if func in pending:
-                ret = func not in ext
-                # typical pseudo-recursion of externals
-                # but true recursions do unwind
-                seen[func] = ret
-                return ret
-            pending[func] = func
-            for callee in callers[func]:
+        def check_unwind(graph):
+            if graph in pending:
+                seen[graph] = True
+                return True
+            pending[graph] = graph
+            for callee in callers[graph]:
                 if callee in seen:
                     ret = seen[callee]
                 else:
@@ -87,9 +93,9 @@
                 if ret:
                     break
             else:
-                ret = func.__name__ in self.stackless_roots
-            del pending[func]
-            seen[func] = ret
+                ret = graph.func in self.stackless_roots
+            del pending[graph]
+            seen[graph] = ret
             return ret
         [check_unwind(caller) for caller in callers if caller not in seen]
 
@@ -251,10 +257,10 @@
         slp = self.db.stacklessdata
         # don't generate code for calls that cannot unwind
         if not specialreturnvalue:
-            need_stackless = slp.unwind_reachable(self.graph.func)
+            need_stackless = slp.unwind_reachable(self.graph)
             if need_stackless:
                 try:
-                    callee = op.args[0].value._obj.graph.func
+                    callee = op.args[0].value._obj.graph
                 except AttributeError:
                     pass # assume we need it really
                 else:

Modified: pypy/branch/somepbc-refactoring/pypy/translator/c/test/test_stackless.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/c/test/test_stackless.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/c/test/test_stackless.py	Tue Nov 29 16:54:52 2005
@@ -1,4 +1,5 @@
-from pypy.translator.translator import Translator
+from pypy.translator.translator import TranslationContext
+from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.annotation.model import SomeList, SomeString
 from pypy.annotation.listdef import ListDef
 from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big
@@ -10,12 +11,13 @@
         os.write(1, str(fn())+"\n")
         return 0
 
-    t = Translator(entry_point)
     s_list_of_strings = SomeList(ListDef(None, SomeString()))
     s_list_of_strings.listdef.resize()
-    ann = t.annotate([s_list_of_strings])
-    t.specialize()
-    cbuilder = t.cbuilder(standalone=True)
+    t = TranslationContext()
+    t.buildannotator().build_types(entry_point, [s_list_of_strings])
+    t.buildrtyper().specialize()
+
+    cbuilder = CStandaloneBuilder(t, entry_point)
     cbuilder.stackless = True
     cbuilder.generate_source()
     cbuilder.compile()



More information about the Pypy-commit mailing list