[pypy-svn] r46796 - in pypy/dist/pypy: rpython/ootypesystem rpython/ootypesystem/test translator/backendopt translator/backendopt/test

antocuni at codespeak.net antocuni at codespeak.net
Fri Sep 21 15:56:53 CEST 2007


Author: antocuni
Date: Fri Sep 21 15:56:51 2007
New Revision: 46796

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
   pypy/dist/pypy/translator/backendopt/canraise.py
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
   pypy/dist/pypy/translator/backendopt/test/test_canraise.py
   pypy/dist/pypy/translator/backendopt/test/test_inline.py
Log:
properly analyze oosends.

This makes test_canraise.test_method and
test_inline.test_list_iteration passing again.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri Sep 21 15:56:51 2007
@@ -1,4 +1,5 @@
 import py
+from py.builtin import set
 from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char
 from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \
         Primitive, isCompatibleType, enforce, saferecursive, SignedLongLong, UnsignedLongLong
@@ -194,6 +195,15 @@
         all.update(self._fields)
         return all
 
+    def _lookup_graphs(self, meth_name):
+        _, meth = self._lookup(meth_name)
+        graphs = set()
+        graphs.add(meth.graph) # we assume there is always a graph
+        for SUBTYPE in self._subclasses:
+            graphs.update(SUBTYPE._lookup_graphs(meth_name))
+        return graphs
+
+
 class SpecializableType(OOType):
     def _specialize_type(self, TYPE, generic_types):
         if isinstance(TYPE, SpecializableType):
@@ -308,6 +318,9 @@
             meth._virtual = False
         return self, meth
 
+    def _lookup_graphs(self, meth_name):
+        return set()
+
 
 # WARNING: the name 'String' is rebound at the end of file
 class String(BuiltinADTType):

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	Fri Sep 21 15:56:51 2007
@@ -475,3 +475,37 @@
 def test_dead_wref():
     ref = new(WeakReference)
     assert ref.ll_deref() is null(ROOT)
+
+
+# we use the translator for this test because it's much easier to get
+# a class hierarchy with methods and graphs by using it than
+# constructing it by hand
+def test_lookup_graphs():
+    from pypy.translator.translator import TranslationContext, graphof
+    class A:
+        def foo(self):
+            pass
+        def bar(self):
+            pass
+
+    class B(A):
+        def foo(self):
+            pass
+
+    def fn(flag):
+        obj = flag and A() or B()
+        obj.foo()
+        obj.bar()
+        return obj
+
+    t = TranslationContext()
+    t.buildannotator().build_types(fn, [int])
+    t.buildrtyper(type_system='ootype').specialize()
+    graph = graphof(t, fn)
+    TYPE_A = graph.getreturnvar().concretetype
+    TYPE_B = TYPE_A._subclasses[0]
+    assert len(TYPE_A._lookup_graphs('ofoo')) == 2
+    assert len(TYPE_B._lookup_graphs('ofoo')) == 1
+    assert len(TYPE_A._lookup_graphs('obar')) == 1
+    assert len(TYPE_B._lookup_graphs('obar')) == 1
+        

Modified: pypy/dist/pypy/translator/backendopt/canraise.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/canraise.py	(original)
+++ pypy/dist/pypy/translator/backendopt/canraise.py	Fri Sep 21 15:56:51 2007
@@ -16,12 +16,15 @@
             log.WARNING("Unknown operation: %s" % op.opname)
             return True
 
-
     def analyze_external_call(self, op):
         deref = self.translator.rtyper.type_system_deref
         fnobj = deref(op.args[0].value)
         return getattr(fnobj, 'canraise', True)
 
+    def analyze_external_method(self, op, TYPE, meth):
+        assert op.opname == 'oosend'
+        return getattr(meth, '_can_raise', True)
+
     def analyze_exceptblock(self, block, seen=None):
         return True
 

Modified: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/graphanalyze.py	(original)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Fri Sep 21 15:56:51 2007
@@ -23,6 +23,9 @@
     def analyze_external_call(self, op):
         return True
 
+    def analyze_external_method(self, op, TYPE, meth):
+        return True
+
     def analyze_link(self, graph, link):
         return False
 
@@ -38,6 +41,14 @@
             if op.args[-1].value is None:
                 return True
             return self.analyze_indirect_call(op.args[-1].value, seen)
+        elif op.opname == "oosend":
+            name = op.args[0].value
+            TYPE = op.args[1].concretetype
+            _, meth = TYPE._lookup(name)
+            graph = getattr(meth, 'graph', None)
+            if graph is None:
+                return self.analyze_external_method(op, TYPE, meth)
+            return self.analyze_oosend(TYPE, name, seen=None)
         if self.operation_is_true(op):
             return True
 
@@ -77,6 +88,10 @@
                 return True
         return False
 
+    def analyze_oosend(self, TYPE, name, seen=None):
+        graphs = TYPE._lookup_graphs(name)
+        return self.analyze_indirect_call(graphs, seen)
+
     def analyze_all(self, graphs=None):
         if graphs is None:
             graphs = self.translator.graphs

Modified: pypy/dist/pypy/translator/backendopt/test/test_canraise.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_canraise.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_canraise.py	Fri Sep 21 15:56:51 2007
@@ -1,4 +1,5 @@
 from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.simplify import get_funcobj
 from pypy.translator.backendopt.canraise import RaiseAnalyzer
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin
@@ -6,9 +7,6 @@
 
 class BaseTestCanRaise(object):
     type_system = None
-    def _skip_oo(self, reason):
-        if self.type_system == 'ootype':
-            py.test.skip("ootypesystem doesn't support %s, yet" % reason)
 
     def translate(self, func, sig):
         t = TranslationContext()
@@ -74,26 +72,44 @@
         assert result
 
     def test_method(self):
-        self._skip_oo("oosend analysis")
         class A(object):
-            def f(x):
+            def f(self):
                 return 1
+            def m(self):
+                raise ValueError
         class B(A):
-            def f(x):
+            def f(self):
                 return 2
+            def m(self):
+                return 3
         def f(a):
             return a.f()
-        def h(x):
-            if x:
-                a = A()
+        def m(a):
+            return a.m()
+        def h(flag):
+            if flag:
+                obj = A()
             else:
-                a = B()
-            return f(a)
+                obj = B()
+            f(obj)
+            m(obj)
+        
         t, ra = self.translate(h, [int])
         hgraph = graphof(t, h)
         # fiiiish :-(
-        result = ra.can_raise(hgraph.startblock.exits[0].target.exits[0].target.operations[0])
-        assert not result
+        block = hgraph.startblock.exits[0].target.exits[0].target
+        op_call_f = block.operations[0]
+        op_call_m = block.operations[1]
+
+        # check that we fished the expected ops
+        def check_call(op, fname):
+            assert op.opname == "direct_call"
+            assert get_funcobj(op.args[0].value)._name == fname
+        check_call(op_call_f, "f")
+        check_call(op_call_m, "m")
+
+        assert not ra.can_raise(op_call_f)
+        assert ra.can_raise(op_call_m)
 
     def test_instantiate(self):
         # instantiate is interesting, because it leads to one of the few cases of

Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_inline.py	Fri Sep 21 15:56:51 2007
@@ -544,7 +544,6 @@
         py.test.raises(CannotInline, self.check_inline, x3, x4, [])
 
     def test_list_iteration(self):
-        self._skip_oo("graphanalyze properly!")
         def f():
             tot = 0
             for item in [1,2,3]:



More information about the Pypy-commit mailing list