[pypy-svn] r27142 - in pypy/dist/pypy/translator: backendopt stackless stackless/test

mwh at codespeak.net mwh at codespeak.net
Fri May 12 17:31:42 CEST 2006


Author: mwh
Date: Fri May 12 17:31:41 2006
New Revision: 27142

Modified:
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
don't stackless transform graphs that don't need it, and don't protect calls to
such graphs.


Modified: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/graphanalyze.py	(original)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Fri May 12 17:31:41 2006
@@ -20,13 +20,19 @@
     def analyze_startblock(self, block, seen=None):
         return False
 
+    def analyze_external_call(self, op):
+        return True
+
+    def analyze_link(self, graph, link):
+        return False
+
     # general methods
 
     def analyze(self, op, seen=None):
         if op.opname == "direct_call":
             graph = get_graph(op.args[0], self.translator)
             if graph is None:
-                return True
+                return self.analyze_external_call(op)
             return self.analyze_direct_call(graph, seen)
         elif op.opname == "indirect_call":
             if op.args[-1].value is None:
@@ -58,6 +64,9 @@
                 if self.analyze(op, seen):
                     self.analyzed_calls[graph] = True
                     return True
+            for exit in block.exits:
+                if self.analyze_link(graph, exit):
+                    return True
         self.analyzed_calls[graph] = False
         return False
 

Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Fri May 12 17:31:41 2006
@@ -205,6 +205,27 @@
     res = llinterp_stackless_function(f)
     assert res == 106
 
+def test_dont_transform_too_much():
+    def check(x):
+        if x:
+            raise code.UnwindException
+    check.stackless_explicit = True
+    def f(x):
+        return x + 2
+    def g(x):
+        check(x)
+        return f(x) + x + 1
+    def example():
+        return g(one()) + 1
+    res, t = llinterp_stackless_function(example, returntranslator=True)
+    assert res == 6
+
+    ggraph = graphof(t, g)
+    for block, op in ggraph.iterblockops():
+        if op.opname == 'direct_call':
+            if op.args[0].value._obj._callable is f:
+                assert op != block.operations[-1]
+
 def rtype_stackless_function(fn):
     s_list_of_strings = annmodel.SomeList(ListDef(None, annmodel.SomeString()))
     s_list_of_strings.listdef.resize()
@@ -241,7 +262,7 @@
     res = cbuilder.cmdexec('')
     return int(res.strip())
 
-def llinterp_stackless_function(fn):
+def llinterp_stackless_function(fn, returntranslator=False):
     def wrapper(argv):
         return fn()
     t = rtype_stackless_function(wrapper)
@@ -256,4 +277,7 @@
     ll_list = r_list_of_strings.convert_const([''])
     interp = llinterp.LLInterpreter(t.rtyper)
     res = interp.eval_graph(graph, [ll_list])
-    return res
+    if returntranslator:
+        return res, t
+    else:
+        return res

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 17:31:41 2006
@@ -111,15 +111,35 @@
         return T, fieldnames
 
 class StacklessAnalyzer(graphanalyze.GraphAnalyzer):
+    def __init__(self, translator, unwindtype):
+        graphanalyze.GraphAnalyzer.__init__(self, translator)
+        self.unwindtype = unwindtype
+
     def operation_is_true(self, op):
-        return True
+        return op.opname == 'yield_current_frame_to_caller'
+
+    def analyze_link(self, graph, link):
+        if link.target is graph.exceptblock:
+            # XXX is this the right way to do this?
+            op = link.prevblock.operations[-1]
+            if op.opname == 'cast_pointer':
+                ct = op.args[0].concretetype
+                return ct is self.unwindtype
+        return False
+
+    def analyze_external_call(self, op):
+        callable = op.args[0].value._obj._callable
+        #assert getattr(callable, 'suggested_primitive', False)
+        return callable in [ll_stack.ll_stack_unwind,
+                            ll_stackless.ll_stackless_stack_frames_depth,
+                            ll_stackless.ll_stackless_switch]
+                            
 
 class StacklessTransformer(object):
     def __init__(self, translator, entrypoint):
         self.translator = translator
 
         self.frametyper = FrameTyper()
-        self.analyzer = StacklessAnalyzer(translator)
         self.curr_graph = None
         
         bk = translator.annotator.bookkeeper
@@ -127,6 +147,8 @@
         self.unwind_exception_type = getinstancerepr(
             self.translator.rtyper,
             bk.getuniqueclassdef(code.UnwindException)).lowleveltype
+        self.analyzer = StacklessAnalyzer(translator,
+                                          self.unwind_exception_type)
 
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
@@ -363,6 +385,10 @@
                     if func in self.suggested_primitives:
                         op = replace_with_call(self.suggested_primitives[func])
 
+                if not self.analyzer.analyze(op):
+                    i += 1
+                    continue
+
                 if i == len(block.operations) - 1 \
                        and block.exitswitch == model.c_last_exception:
                     link = block.exits[0]



More information about the Pypy-commit mailing list