[pypy-svn] r25834 - pypy/dist/pypy/translator/backendopt

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Apr 14 21:49:17 CEST 2006


Author: cfbolz
Date: Fri Apr 14 21:49:15 2006
New Revision: 25834

Added:
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
Modified:
   pypy/dist/pypy/translator/backendopt/canraise.py
Log:
factor out class to analyze graphs in a generic way


Modified: pypy/dist/pypy/translator/backendopt/canraise.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/canraise.py	(original)
+++ pypy/dist/pypy/translator/backendopt/canraise.py	Fri Apr 14 21:49:15 2006
@@ -1,48 +1,18 @@
 from pypy.translator.simplify import get_graph
 from pypy.rpython.lltypesystem.lloperation import llop, LL_OPERATIONS
 from pypy.rpython.lltypesystem import lltype
+from pypy.translator.backendopt import graphanalyze
 
-class RaiseAnalyzer(object):
-    def __init__(self, translator):
-        self.translator = translator
-        self.call_can_raise = {}
-
-    def can_raise(self, op, seen=None):
-        if op.opname == "direct_call":
-            graph = get_graph(op.args[0], self.translator)
-            ##print "graph", graph
-            if graph is None:
-                return True
-            return self.direct_call_can_raise(graph, seen)
-        elif op.opname == "indirect_call":
-            return self.indirect_call_can_raise(op.args[-1].value, seen)
-        else:
+class RaiseAnalyzer(graphanalyze.GraphAnalyzer):
+    def operation_is_true(self, op):
+        try:
             return bool(LL_OPERATIONS[op.opname].canraise)
+        except KeyError:
+            return True
 
-    def direct_call_can_raise(self, graph, seen=None):
-        if graph in self.call_can_raise:
-            return self.call_can_raise[graph]
-        if seen is None:
-            seen = {}
-        if graph in seen:
-            self.call_can_raise[graph] = False
-            return False
-        else:
-            seen[graph] = True
-        for block in graph.iterblocks():
-            if block is graph.exceptblock:
-                return True # the except block is reached
-            for op in block.operations:
-                if self.can_raise(op, seen):
-                    self.call_can_raise[graph] = True
-                    return True
-        self.call_can_raise[graph] = False
-        return False
+    def analyze_exceptblock(self, block, seen=None):
+        return True
 
-    def indirect_call_can_raise(self, graphs, seen=None):
-        if graphs is None:
-            return True
-        for graph in graphs:
-            if self.direct_call_can_raise(graph, seen):
-                return True
-        return False
+    # backward compatible interface
+    def can_raise(self, op, seen=None):
+        return self.analyze(op, seen)

Added: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Fri Apr 14 21:49:15 2006
@@ -0,0 +1,75 @@
+from pypy.translator.simplify import get_graph
+from pypy.rpython.lltypesystem.lloperation import llop, LL_OPERATIONS
+from pypy.rpython.lltypesystem import lltype
+
+class GraphAnalyzer(object):
+    """generic way to analyze graphs: recursively follow it until the first
+    operation is found on which self.bad_op returns True"""
+    def __init__(self, translator):
+        self.translator = translator
+        self.analyzed_calls = {}
+
+    # methods to be overridden by subclass
+
+    def operation_is_true(self, op):
+        raise NotImplementedError("abstract base class")
+
+    def analyze_exceptblock(self, block, seen=None):
+        return False
+
+    def analyze_startblock(self, block, seen=None):
+        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_direct_call(graph, seen)
+        elif op.opname == "indirect_call":
+            if op.args[-1].value is None:
+                return True
+            return self.analyze_indirect_call(op.args[-1].value, seen)
+        if self.operation_is_true(op):
+            return True
+
+    def analyze_direct_call(self, graph, seen=None):
+        if graph in self.analyzed_calls:
+            return self.analyzed_calls[graph]
+        if seen is None:
+            seen = {}
+        if graph in seen:
+            self.analyzed_calls[graph] = False
+            return False
+        else:
+            seen[graph] = True
+        for block in graph.iterblocks():
+            if block is graph.startblock:
+                if self.analyze_startblock(block, seen):
+                    self.analyzed_calls[graph] = True
+                    return True
+            if block is graph.exceptblock:
+                if self.analyze_exceptblock(block, seen):
+                    self.analyzed_calls[graph] = True
+                    return True
+            for op in block.operations:
+                if self.analyze(op, seen):
+                    self.analyzed_calls[graph] = True
+                    return True
+        self.analyzed_calls[graph] = False
+        return False
+
+    def analyze_indirect_call(self, graphs, seen=None):
+        for graph in graphs:
+            if self.analyze_direct_call(graph, seen):
+                return True
+        return False
+
+    def analyze_all(self, graphs=None):
+        if graphs is None:
+            graphs = self.translator.graphs
+        for graph in graphs:
+            for block, op in graph.iterblockops():
+                self.analyze(op)



More information about the Pypy-commit mailing list