[pypy-svn] r35809 - in pypy/dist/pypy: rpython/lltypesystem translator translator/backendopt translator/backendopt/test

antocuni at codespeak.net antocuni at codespeak.net
Fri Dec 15 16:44:38 CET 2006


Author: antocuni
Date: Fri Dec 15 16:44:36 2006
New Revision: 35809

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/translator/backendopt/canraise.py
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/backendopt/test/test_inline.py
   pypy/dist/pypy/translator/simplify.py
Log:
Some steps in the direction of making inlining to work with
ootypesystem.



Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Fri Dec 15 16:44:36 2006
@@ -402,6 +402,11 @@
 
     # __________ instrumentation _________
     'instrument_count':     LLOp(),
+
+    # __________ ootype operations __________
+    'oosetfield':           LLOp(),
+    'oogetfield':           LLOp(),
+    'ooupcast':             LLOp(),
 }
 
     # __________ operations on PyObjects __________

Modified: pypy/dist/pypy/translator/backendopt/canraise.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/canraise.py	(original)
+++ pypy/dist/pypy/translator/backendopt/canraise.py	Fri Dec 15 16:44:36 2006
@@ -3,11 +3,17 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.translator.backendopt import graphanalyze
 
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("canraise") 
+py.log.setconsumer("canraise", ansi_log) 
+
 class RaiseAnalyzer(graphanalyze.GraphAnalyzer):
     def operation_is_true(self, op):
         try:
             return bool(LL_OPERATIONS[op.opname].canraise)
         except KeyError:
+            log.WARNING("Unknown operation: %s" % op.opname)
             return True
 
     def analyze_exceptblock(self, block, seen=None):

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Fri Dec 15 16:44:36 2006
@@ -1,6 +1,6 @@
 import sys
 from pypy.translator.simplify import join_blocks, cleanup_graph
-from pypy.translator.simplify import get_graph
+from pypy.translator.simplify import get_graph, get_funcobj
 from pypy.translator.unsimplify import copyvar
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, c_last_exception
@@ -21,7 +21,6 @@
 class CannotInline(Exception):
     pass
 
-
 def collect_called_graphs(graph, translator):
     graphs_or_something = {}
     for block in graph.iterblocks():
@@ -46,7 +45,7 @@
         for i, op in enumerate(block.operations):
             if not op.opname == "direct_call":
                 continue
-            funcobj = op.args[0].value._obj
+            funcobj = get_funcobj(op.args[0].value)
             graph = getattr(funcobj, 'graph', None)
             # accept a function or a graph as 'inline_func'
             if (graph is calling_what or
@@ -173,7 +172,7 @@
         self.varmap = {}
         self._copied_blocks = {}
         self.op = block.operations[index_operation]
-        self.graph_to_inline = self.op.args[0].value._obj.graph
+        self.graph_to_inline = get_funcobj(self.op.args[0].value).graph
         self.exception_guarded = False
         if (block.exitswitch == c_last_exception and
             index_operation == len(block.operations) - 1):
@@ -194,7 +193,7 @@
         for i, op in enumerate(block.operations):
             if not op.opname == "direct_call":
                 continue
-            funcobj = op.args[0].value._obj
+            funcobj = get_funcobj(op.args[0].value)
             graph = getattr(funcobj, 'graph', None)
             # accept a function or a graph as 'inline_func'
             if (graph is self.inline_func or
@@ -275,7 +274,7 @@
         linkfrominlined = Link(linkargs, afterblock)
         linkfrominlined.prevblock = copiedreturnblock
         copiedreturnblock.exitswitch = None
-        copiedreturnblock.exits = [linkfrominlined]
+        copiedreturnblock.exits = [linkfrominlined] ## HERE
         assert copiedreturnblock.exits[0].target == afterblock
        
     def rewire_exceptblock(self, afterblock):
@@ -288,8 +287,7 @@
             self.rewire_exceptblock_with_guard(afterblock, copiedexceptblock)
             # generate blocks that do generic matching for cases when the
             # heuristic did not work
-#            self.translator.view()
-            self.generic_exception_matching(afterblock, copiedexceptblock)
+            self.generic_exception_matching(afterblock, copiedexceptblock) # HERE
 
     def rewire_exceptblock_no_guard(self, afterblock, copiedexceptblock):
          # find all copied links that go to copiedexceptblock
@@ -336,7 +334,7 @@
 
     def generic_exception_matching(self, afterblock, copiedexceptblock):
         #XXXXX don't look: insert blocks that do exception matching
-        #for the cases where direct matching did not work
+        #for the cases where direct matching did not work        
         exc_match = Constant(
             self.translator.rtyper.getexceptiondata().fn_exception_match)
         exc_match.concretetype = typeOf(exc_match.value)
@@ -368,13 +366,14 @@
                 l.llexitcase = False
                 blocks[-1].exits.insert(0, l)
             blocks.append(block)
+
         blocks[-1].exits = blocks[-1].exits[:1]
         blocks[-1].operations = []
         blocks[-1].exitswitch = None
         blocks[-1].exits[0].exitcase = None
         del blocks[-1].exits[0].llexitcase
         linkargs = copiedexceptblock.inputargs
-        copiedexceptblock.closeblock(Link(linkargs, blocks[0]))
+        copiedexceptblock.closeblock(Link(linkargs, blocks[0])) ## HERE
         copiedexceptblock.operations += generate_keepalive(linkargs)
 
       
@@ -540,7 +539,7 @@
         for block in parentgraph.iterblocks():
             for op in block.operations:
                 if op.opname == "direct_call":
-                    funcobj = op.args[0].value._obj
+                    funcobj = get_funcobj(op.args[0].value)
                     graph = getattr(funcobj, 'graph', None)
                     if graph is not None:
                         if getattr(getattr(funcobj, '_callable', None),
@@ -572,7 +571,7 @@
                 op = ops[i]
                 i -= 1
                 if op.opname == "direct_call":
-                    funcobj = op.args[0].value._obj
+                    funcobj = get_funcobj(op.args[0].value)
                     graph = getattr(funcobj, 'graph', None)
                     if graph is not None:
                         if getattr(getattr(funcobj, '_callable', None),

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 Dec 15 16:44:36 2006
@@ -11,10 +11,12 @@
 from pypy.translator.backendopt.inline import instrument_inline_candidates
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.translator.test.snippet import is_perfect_number
 from pypy.conftest import option
 
+
 def no_missing_concretetype(node):
     if isinstance(node, Block):
         for v in node.inputargs:
@@ -39,95 +41,6 @@
         checkgraph(graph)
         traverse(no_missing_concretetype, graph)
 
-def translate(func, argtypes):
-    t = TranslationContext()
-    t.buildannotator().build_types(func, argtypes)
-    t.buildrtyper().specialize()
-    return t
-
-def check_inline(func, in_func, sig, entry=None, inline_guarded_calls=False):
-    if entry is None:
-        entry = in_func
-    t = translate(entry, sig)
-    # inline!
-    sanity_check(t)    # also check before inlining (so we don't blame it)
-    if option.view:
-        t.view()
-    raise_analyzer = canraise.RaiseAnalyzer(t)
-    inliner = Inliner(t, graphof(t, in_func), func,
-                      t.rtyper.lltype_to_classdef_mapping(),
-                      inline_guarded_calls,
-                      raise_analyzer=raise_analyzer)
-    inliner.inline_all()
-    if option.view:
-        t.view()
-    sanity_check(t)
-    interp = LLInterpreter(t.rtyper)
-    def eval_func(args):
-        return interp.eval_graph(graphof(t, entry), args)
-    return eval_func
-
-def check_auto_inlining(func, sig, multiplier=None, call_count_check=False):
-    t = translate(func, sig)
-    if option.view:
-        t.view()
-    # inline!
-    sanity_check(t)    # also check before inlining (so we don't blame it)
-
-    if multiplier is not None:
-        multiplier = {'multiplier': multiplier}
-    else:
-        multiplier = {}
-
-    call_count_pred = None
-    if call_count_check:
-        call_count_pred = lambda lbl: True
-        instrument_inline_candidates(t.graphs, **multiplier)
-
-    auto_inlining(t, call_count_pred=call_count_pred, **multiplier)
-    
-    sanity_check(t)
-    if option.view:
-        t.view()
-    interp = LLInterpreter(t.rtyper)
-    def eval_func(args):
-        return interp.eval_graph(graphof(t, func), args)
-    return eval_func, t
-
-
-def test_inline_simple():
-    def f(x, y):
-        return (g(x, y) + 1) * x
-    def g(x, y):
-        if x > 0:
-            return x * y
-        else:
-            return -x * y
-    eval_func = check_inline(g, f, [int, int])
-    result = eval_func([-1, 5])
-    assert result == f(-1, 5)
-    result = eval_func([2, 12])
-    assert result == f(2, 12)
-
-def test_nothing_to_inline():
-    def f():
-        return 1
-    def g():
-        return 2
-    eval_func = check_inline(g, f, [])
-    assert eval_func([]) == 1
-
-def test_inline_big():
-    def f(x):
-        result = []
-        for i in range(1, x+1):
-            if is_perfect_number(i):
-                result.append(i)
-        return result
-    eval_func = check_inline(is_perfect_number, f, [int])
-    result = eval_func([10])
-    assert result.length == len(f(10))
-
 class CustomError1(Exception):
     def __init__(self):
         self.data = 123
@@ -136,401 +49,507 @@
     def __init__(self):
         self.data2 = 456
 
-def test_inline_raising():
-    def f(x):
-        if x == 1:
-            raise CustomError1
-        return x
-    def g(x):
-        a = f(x)
-        if x == 2:
-            raise CustomError2
-    def h(x):
-        try:
-            g(x)
-        except CustomError1:
-            return 1
-        except CustomError2:
-            return 2
-        return x
-    eval_func = check_inline(f,g, [int], entry=h)
-    result = eval_func([0])
-    assert result == 0
-    result = eval_func([1])
-    assert result == 1
-    result = eval_func([2])
-    assert result == 2    
-
-def test_inline_several_times():
-    def f(x):
-        return (x + 1) * 2
-    def g(x):
-        if x:
-            a = f(x) + f(x)
+class BaseTestInline:
+    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, argtypes):
+        t = TranslationContext()
+        t.buildannotator().build_types(func, argtypes)
+        t.buildrtyper(type_system=self.type_system).specialize()
+        return t
+
+    def check_inline(self, func, in_func, sig, entry=None, inline_guarded_calls=False):
+        if entry is None:
+            entry = in_func
+        t = self.translate(entry, sig)
+        # inline!
+        sanity_check(t)    # also check before inlining (so we don't blame it)
+        if option.view:
+            t.view()
+        raise_analyzer = canraise.RaiseAnalyzer(t)
+        inliner = Inliner(t, graphof(t, in_func), func,
+                          t.rtyper.lltype_to_classdef_mapping(),
+                          inline_guarded_calls,
+                          raise_analyzer=raise_analyzer)
+        inliner.inline_all()
+        if option.view:
+            t.view()
+        sanity_check(t)
+        interp = LLInterpreter(t.rtyper)
+        def eval_func(args):
+            return interp.eval_graph(graphof(t, entry), args)
+        return eval_func
+
+    def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False):
+        t = self.translate(func, sig)
+        if option.view:
+            t.view()
+        # inline!
+        sanity_check(t)    # also check before inlining (so we don't blame it)
+
+        if multiplier is not None:
+            multiplier = {'multiplier': multiplier}
         else:
-            a = f(x) + 1
-        return a + f(x)
-    eval_func = check_inline(f, g, [int])
-    result = eval_func([0])
-    assert result == g(0)
-    result = eval_func([42])
-    assert result == g(42)
-
-def test_inline_exceptions():
-    def f(x):
-        if x == 0:
-            raise CustomError1
-        if x == 1:
-            raise CustomError2
-    def g(x):
-        try:
-            f(x)
-        except CustomError1:
-            return 2
-        except CustomError2:
-            return x+2
-        return 1
-    eval_func = check_inline(f, g, [int])
-    result = eval_func([0])
-    assert result == 2
-    result = eval_func([1])
-    assert result == 3
-    result = eval_func([42])
-    assert result == 1
-
-def test_inline_const_exceptions():
-    valueError = ValueError()
-    keyError = KeyError()
-    def f(x):
-        if x == 0:
-            raise valueError
-        if x == 1:
-            raise keyError
-    def g(x):
-        try:
-            f(x)
-        except ValueError:
-            return 2
-        except KeyError:
-            return x+2
-        return 1
-    eval_func = check_inline(f, g, [int])
-    result = eval_func([0])
-    assert result == 2
-    result = eval_func([1])
-    assert result == 3
-    result = eval_func([42])
-    assert result == 1
-
-def test_inline_exception_guarded():
-    def h(x):
-        if x == 1:
-            raise CustomError1()
-        elif x == 2:
-            raise CustomError2()
-        return 1
-    def f(x):
-        try:
-            return h(x)
-        except:
-            return 87
-    def g(x):
-        try:
-            return f(x)
-        except CustomError1:
-            return 2
-    eval_func = check_inline(f, g, [int], inline_guarded_calls=True)
-    result = eval_func([0])
-    assert result == 1
-    result = eval_func([1])
-    assert result == 87
-    result = eval_func([2])
-    assert result == 87
-
-def test_inline_var_exception():
-    def f(x):
-        e = None
-        if x == 0:
-            e = CustomError1()
-        elif x == 1:
-            e = KeyError()
-        if x == 0 or x == 1:
-            raise e
-    def g(x):
-        try:
-            f(x)
-        except CustomError1:
+            multiplier = {}
+
+        call_count_pred = None
+        if call_count_check:
+            call_count_pred = lambda lbl: True
+            instrument_inline_candidates(t.graphs, **multiplier)
+
+        auto_inlining(t, call_count_pred=call_count_pred, **multiplier)
+
+        sanity_check(t)
+        if option.view:
+            t.view()
+        interp = LLInterpreter(t.rtyper)
+        def eval_func(args):
+            return interp.eval_graph(graphof(t, func), args)
+        return eval_func, t
+
+
+    def test_inline_simple(self):
+        def f(x, y):
+            return (g(x, y) + 1) * x
+        def g(x, y):
+            if x > 0:
+                return x * y
+            else:
+                return -x * y
+        eval_func = self.check_inline(g, f, [int, int])
+        result = eval_func([-1, 5])
+        assert result == f(-1, 5)
+        result = eval_func([2, 12])
+        assert result == f(2, 12)
+
+    def test_nothing_to_inline(self):
+        def f():
+            return 1
+        def g():
             return 2
-        except KeyError:
-            return 3
-        return 1
-
-    eval_func, _ = check_auto_inlining(g, [int], multiplier=10)
-    result = eval_func([0])
-    assert result == 2
-    result = eval_func([1])
-    assert result == 3
-    result = eval_func([42])
-    assert result == 1
-
-def test_inline_nonraising_into_catching():
-    def f(x):
-        return x+1
-    def g(x):
-        try:
-            return f(x)
-        except KeyError:
-            return 42
-    eval_func = check_inline(f, g, [int])
-    result = eval_func([7654])
-    assert result == 7655
-
-def DONOTtest_call_call():
-    # for reference.  Just remove this test if we decide not to support
-    # catching exceptions while inlining a graph that contains further
-    # direct_calls.
-    def e(x):
-        if x < 0:
-            raise KeyError
-        return x+1
-    def f(x):
-        return e(x)+2
-    def g(x):
-        try:
-            return f(x)+3
-        except KeyError:
-            return -1
-    eval_func = check_inline(f, g, [int])
-    result = eval_func([100])
-    assert result == 106
-    result = eval_func(g, [-100])
-    assert result == -1
-
-def test_for_loop():
-    def f(x):
-        result = 0
-        for i in range(0, x):
-            result += i
-        return result
-    t = translate(f, [int])
-    sanity_check(t)    # also check before inlining (so we don't blame it)
-    for graph in t.graphs:
-        if graph.name.startswith('ll_rangenext'):
-            break
-    else:
-        assert 0, "cannot find ll_rangenext_*() function"
-    simple_inline_function(t, graph, graphof(t, f))
-    sanity_check(t)
-    interp = LLInterpreter(t.rtyper)
-    result = interp.eval_graph(graphof(t, f), [10])
-    assert result == 45
-
-def test_inline_constructor():
-    class A:
-        def __init__(self, x, y):
-            self.bounds = (x, y)
-        def area(self, height=10):
-            return height * (self.bounds[1] - self.bounds[0])
-    def f(i):
-        a = A(117, i)
-        return a.area()
-    eval_func = check_inline(A.__init__.im_func, f, [int])
-    result = eval_func([120])
-    assert result == 30
-
-def test_cannot_inline_recursive_function():
-    def factorial(n):
-        if n > 1:
-            return n * factorial(n-1)
-        else:
+        eval_func = self.check_inline(g, f, [])
+        assert eval_func([]) == 1
+
+    def test_inline_big(self):
+        def f(x):
+            result = []
+            for i in range(1, x+1):
+                if is_perfect_number(i):
+                    result.append(i)
+            return result
+        eval_func = self.check_inline(is_perfect_number, f, [int])
+        result = eval_func([10])
+        result = self.ll_to_list(result)
+        assert len(result) == len(f(10))
+
+    def test_inline_raising(self):
+        def f(x):
+            if x == 1:
+                raise CustomError1
+            return x
+        def g(x):
+            a = f(x)
+            if x == 2:
+                raise CustomError2
+        def h(x):
+            try:
+                g(x)
+            except CustomError1:
+                return 1
+            except CustomError2:
+                return 2
+            return x
+        eval_func = self.check_inline(f,g, [int], entry=h)
+        result = eval_func([0])
+        assert result == 0
+        result = eval_func([1])
+        assert result == 1
+        result = eval_func([2])
+        assert result == 2    
+
+    def test_inline_several_times(self):
+        def f(x):
+            return (x + 1) * 2
+        def g(x):
+            if x:
+                a = f(x) + f(x)
+            else:
+                a = f(x) + 1
+            return a + f(x)
+        eval_func = self.check_inline(f, g, [int])
+        result = eval_func([0])
+        assert result == g(0)
+        result = eval_func([42])
+        assert result == g(42)
+
+    def test_inline_exceptions(self):
+        def f(x):
+            if x == 0:
+                raise CustomError1
+            if x == 1:
+                raise CustomError2
+        def g(x):
+            try:
+                f(x)
+            except CustomError1:
+                return 2
+            except CustomError2:
+                return x+2
+            return 1
+        eval_func = self.check_inline(f, g, [int])
+        result = eval_func([0])
+        assert result == 2
+        result = eval_func([1])
+        assert result == 3
+        result = eval_func([42])
+        assert result == 1
+
+    def test_inline_const_exceptions(self):
+        valueError = ValueError()
+        keyError = KeyError()
+        def f(x):
+            if x == 0:
+                raise valueError
+            if x == 1:
+                raise keyError
+        def g(x):
+            try:
+                f(x)
+            except ValueError:
+                return 2
+            except KeyError:
+                return x+2
+            return 1
+        eval_func = self.check_inline(f, g, [int])
+        result = eval_func([0])
+        assert result == 2
+        result = eval_func([1])
+        assert result == 3
+        result = eval_func([42])
+        assert result == 1
+
+    def test_inline_exception_guarded(self):
+        def h(x):
+            if x == 1:
+                raise CustomError1()
+            elif x == 2:
+                raise CustomError2()
             return 1
-    def f(n):
-        return factorial(n//2)
-    py.test.raises(CannotInline, check_inline, factorial, f, [int])
-
-def test_auto_inlining_small_call_big():
-    def leaf(n):
-        total = 0
-        i = 0
-        while i < n:
-            total += i
-            if total > 100:
-                raise OverflowError
-            i += 1
-        return total
-    def g(n):
-        return leaf(n)
-    def f(n):
-        try:
-            return g(n)
-        except OverflowError:
-            return -1
-    eval_func, t = check_auto_inlining(f, [int], multiplier=10)
-    f_graph = graphof(t, f)
-    assert len(collect_called_graphs(f_graph, t)) == 0
-
-    result = eval_func([10])
-    assert result == 45
-    result = eval_func([15])
-    assert result == -1
-
-def test_auto_inlining_small_call_big_call_count():
-    def leaf(n):
-        total = 0
-        i = 0
-        while i < n:
-            total += i
-            if total > 100:
-                raise OverflowError
-            i += 1
-        return total
-    def g(n):
-        return leaf(n)
-    def f(n):
-        try:
-            return g(n)
-        except OverflowError:
-            return -1
-    eval_func, t = check_auto_inlining(f, [int], multiplier=10,
-                                       call_count_check=True)
-    f_graph = graphof(t, f)
-    assert len(collect_called_graphs(f_graph, t)) == 0
-
-    result = eval_func([10])
-    assert result == 45
-    result = eval_func([15])
-    assert result == -1
-
-def test_inline_exception_catching():
-    def f3():
-        raise CustomError1
-    def f2():
-        try:
-            f3()
-        except CustomError1:
-            return True
+        def f(x):
+            try:
+                return h(x)
+            except:
+                return 87
+        def g(x):
+            try:
+                return f(x)
+            except CustomError1:
+                return 2
+        eval_func = self.check_inline(f, g, [int], inline_guarded_calls=True)
+        result = eval_func([0])
+        assert result == 1
+        result = eval_func([1])
+        assert result == 87
+        result = eval_func([2])
+        assert result == 87
+
+    def test_inline_var_exception(self):
+        def f(x):
+            e = None
+            if x == 0:
+                e = CustomError1()
+            elif x == 1:
+                e = KeyError()
+            if x == 0 or x == 1:
+                raise e
+        def g(x):
+            try:
+                f(x)
+            except CustomError1:
+                return 2
+            except KeyError:
+                return 3
+            return 1
+
+        eval_func, _ = self.check_auto_inlining(g, [int], multiplier=10)
+        result = eval_func([0])
+        assert result == 2
+        result = eval_func([1])
+        assert result == 3
+        result = eval_func([42])
+        assert result == 1
+
+    def test_inline_nonraising_into_catching(self):
+        def f(x):
+            return x+1
+        def g(x):
+            try:
+                return f(x)
+            except KeyError:
+                return 42
+        eval_func = self.check_inline(f, g, [int])
+        result = eval_func([7654])
+        assert result == 7655
+
+    def DONOTtest_call_call(self):
+        # for reference.  Just remove this test if we decide not to support
+        # catching exceptions while inlining a graph that contains further
+        # direct_calls.
+        def e(x):
+            if x < 0:
+                raise KeyError
+            return x+1
+        def f(x):
+            return e(x)+2
+        def g(x):
+            try:
+                return f(x)+3
+            except KeyError:
+                return -1
+        eval_func = self.check_inline(f, g, [int])
+        result = eval_func([100])
+        assert result == 106
+        result = eval_func(g, [-100])
+        assert result == -1
+
+    def test_for_loop(self):
+        def f(x):
+            result = 0
+            for i in range(0, x):
+                result += i
+            return result
+        t = self.translate(f, [int])
+        sanity_check(t)    # also check before inlining (so we don't blame it)
+        for graph in t.graphs:
+            if graph.name.startswith('ll_rangenext'):
+                break
         else:
-            return False
-    def f():
-        return f2()
-    eval_func = check_inline(f2, f, [])
-    result = eval_func([])
-    assert result is True
-
-def test_inline_catching_different_exception():
-    d = {1: 2}
-    def f2(n):
-        try:
-            return ovfcheck(n+1)
-        except OverflowError:
-            raise
-    def f(n):
-        try:
-            return f2(n)
-        except ValueError:
-            return -1
-    eval_func = check_inline(f2, f, [int])
-    result = eval_func([54])
-    assert result == 55
-
-def test_auto_inline_os_path_isdir():
-    directory = "./."
-    def f():
-        return os.path.isdir(directory)
-    eval_func, _ = check_auto_inlining(f, [])
-    result = eval_func([])
-    assert result is True
-
-def test_inline_raiseonly():
-    def f2(x):
-        raise CustomError1
-    def f(x):
-        try:
-            return f2(x)
-        except CustomError1:
-            return 42
-    eval_func = check_inline(f2, f, [int])
-    result = eval_func([98371])
-    assert result == 42
-
-def test_measure_median_execution_cost():
-    def f(x):
-        x += 1
-        x += 1
-        x += 1
-        while True:
-            x += 1
-            x += 1
-            x += 1
-            if x: break
-            x += 1
+            assert 0, "cannot find ll_rangenext_*() function"
+        simple_inline_function(t, graph, graphof(t, f))
+        sanity_check(t)
+        interp = LLInterpreter(t.rtyper)
+        result = interp.eval_graph(graphof(t, f), [10])
+        assert result == 45
+
+    def test_inline_constructor(self):
+        class A:
+            def __init__(self, x, y):
+                self.bounds = (x, y)
+            def area(self, height=10):
+                return height * (self.bounds[1] - self.bounds[0])
+        def f(i):
+            a = A(117, i)
+            return a.area()
+        eval_func = self.check_inline(A.__init__.im_func, f, [int])
+        result = eval_func([120])
+        assert result == 30
+
+    def test_cannot_inline_recursive_function(self):
+        def factorial(n):
+            if n > 1:
+                return n * factorial(n-1)
+            else:
+                return 1
+        def f(n):
+            return factorial(n//2)
+        py.test.raises(CannotInline, self.check_inline, factorial, f, [int])
+
+    def test_auto_inlining_small_call_big(self):
+        self._skip_oo('exception rewiring')
+        def leaf(n):
+            total = 0
+            i = 0
+            while i < n:
+                total += i
+                if total > 100:
+                    raise OverflowError
+                i += 1
+            return total
+        def g(n):
+            return leaf(n)
+        def f(n):
+            try:
+                return g(n)
+            except OverflowError:
+                return -1
+        eval_func, t = self.check_auto_inlining(f, [int], multiplier=10)
+        f_graph = graphof(t, f)
+        assert len(collect_called_graphs(f_graph, t)) == 0
+
+        result = eval_func([10])
+        assert result == 45
+        result = eval_func([15])
+        assert result == -1
+
+    def test_auto_inlining_small_call_big_call_count(self):
+        self._skip_oo('exception rewiring')
+        def leaf(n):
+            total = 0
+            i = 0
+            while i < n:
+                total += i
+                if total > 100:
+                    raise OverflowError
+                i += 1
+            return total
+        def g(n):
+            return leaf(n)
+        def f(n):
+            try:
+                return g(n)
+            except OverflowError:
+                return -1
+        eval_func, t = self.check_auto_inlining(f, [int], multiplier=10,
+                                           call_count_check=True)
+        f_graph = graphof(t, f)
+        assert len(collect_called_graphs(f_graph, t)) == 0
+
+        result = eval_func([10])
+        assert result == 45
+        result = eval_func([15])
+        assert result == -1
+
+    def test_inline_exception_catching(self):
+        def f3():
+            raise CustomError1
+        def f2():
+            try:
+                f3()
+            except CustomError1:
+                return True
+            else:
+                return False
+        def f():
+            return f2()
+        eval_func = self.check_inline(f2, f, [])
+        result = eval_func([])
+        assert result is True
+
+    def test_inline_catching_different_exception(self):
+        d = {1: 2}
+        def f2(n):
+            try:
+                return ovfcheck(n+1)
+            except OverflowError:
+                raise
+        def f(n):
+            try:
+                return f2(n)
+            except ValueError:
+                return -1
+        eval_func = self.check_inline(f2, f, [int])
+        result = eval_func([54])
+        assert result == 55
+
+    def test_auto_inline_os_path_isdir(self):
+        directory = "./."
+        def f():
+            return os.path.isdir(directory)
+        eval_func, _ = self.check_auto_inlining(f, [])
+        result = eval_func([])
+        assert result is True
+
+    def test_inline_raiseonly(self):
+        def f2(x):
+            raise CustomError1
+        def f(x):
+            try:
+                return f2(x)
+            except CustomError1:
+                return 42
+        eval_func = self.check_inline(f2, f, [int])
+        result = eval_func([98371])
+        assert result == 42
+
+    def test_measure_median_execution_cost(self):
+        def f(x):
             x += 1
             x += 1
             x += 1
+            while True:
+                x += 1
+                x += 1
+                x += 1
+                if x: break
+                x += 1
+                x += 1
+                x += 1
+                x += 1
+                x += 1
             x += 1
-        x += 1
-        return x
-    t = TranslationContext()
-    graph = t.buildflowgraph(f)
-    res = measure_median_execution_cost(graph)
-    assert round(res, 5) == round(32.333333333, 5)
-
-def test_indirect_call_with_exception():
-    class Dummy:
-        pass
-    def x1():
-        return Dummy()   # can raise MemoryError
-    def x2():
-        return 2
-    def x3(x):
-        if x:
-            f = x1
-        else:
-            f = x2
-        return f()
-    def x4():
-        try:
-            x3(0)
-            x3(1)
-        except CustomError2:
-            return 0
-        return 1
-    assert x4() == 1
-    py.test.raises(CannotInline, check_inline, x3, x4, [])
-
-def test_keepalive_hard_case():
-    from pypy.rpython.lltypesystem import lltype
-    Y = lltype.Struct('y', ('n', lltype.Signed))
-    X = lltype.GcStruct('x', ('y', Y))
-    def g(x):
-        if x:
-            return 3
-        else:
-            return 4
-    def f():
-        x = lltype.malloc(X)
-        x.y.n = 2
-        y = x.y
-        z1 = g(y.n)
-        z = y.n
-        return z+z1
-    eval_func = check_inline(g, f, [])
-    res = eval_func([])
-    assert res == 5
-
-def test_correct_keepalive_placement():
-    def h(x):
-        if not x:
-            raise ValueError
-        return 1
-    def f(x):
-        s = "a %s" % (x, )
-        try:
-            h(len(s))
-        except ValueError:
+            return x
+        t = TranslationContext()
+        graph = t.buildflowgraph(f)
+        res = measure_median_execution_cost(graph)
+        assert round(res, 5) == round(32.333333333, 5)
+
+    def test_indirect_call_with_exception(self):
+        self._skip_oo('exception rewiring')
+        class Dummy:
             pass
-        return -42
-    eval_func, t = check_auto_inlining(f, [int])
-    res = eval_func([42])
-    assert res == -42
+        def x1():
+            return Dummy()   # can raise MemoryError
+        def x2():
+            return 2
+        def x3(x):
+            if x:
+                f = x1
+            else:
+                f = x2
+            return f()
+        def x4():
+            try:
+                x3(0)
+                x3(1)
+            except CustomError2:
+                return 0
+            return 1
+        assert x4() == 1
+        py.test.raises(CannotInline, self.check_inline, x3, x4, [])
+
+    def test_keepalive_hard_case(self):
+        from pypy.rpython.lltypesystem import lltype
+        Y = lltype.Struct('y', ('n', lltype.Signed))
+        X = lltype.GcStruct('x', ('y', Y))
+        def g(x):
+            if x:
+                return 3
+            else:
+                return 4
+        def f():
+            x = lltype.malloc(X)
+            x.y.n = 2
+            y = x.y
+            z1 = g(y.n)
+            z = y.n
+            return z+z1
+        eval_func = self.check_inline(g, f, [])
+        res = eval_func([])
+        assert res == 5
+
+    def test_correct_keepalive_placement(self):
+        def h(x):
+            if not x:
+                raise ValueError
+            return 1
+        def f(x):
+            s = "a %s" % (x, )
+            try:
+                h(len(s))
+            except ValueError:
+                pass
+            return -42
+        eval_func, t = self.check_auto_inlining(f, [int])
+        res = eval_func([42])
+        assert res == -42
+
+
+class TestInlineLLType(LLRtypeMixin, BaseTestInline):
+    pass
 
+class TestInlineOOType(OORtypeMixin, BaseTestInline):
+    pass

Modified: pypy/dist/pypy/translator/simplify.py
==============================================================================
--- pypy/dist/pypy/translator/simplify.py	(original)
+++ pypy/dist/pypy/translator/simplify.py	Fri Dec 15 16:44:36 2006
@@ -12,27 +12,39 @@
 from pypy.objspace.flow.model import checkgraph, traverse, mkentrymap
 from pypy.rpython.lltypesystem import lloperation
 
+def get_funcobj(func):
+    """
+    Return an object which is supposed to have attributes such as graph and _callable
+    """
+    if hasattr(func, '_obj'): 
+        return func._obj # lltypesystem
+    else:
+        return func # ootypesystem
+
+
 def get_graph(arg, translator):
     from pypy.translator.translator import graphof
     if isinstance(arg, Variable):
         return None
     f = arg.value
     from pypy.rpython.lltypesystem import lltype
-    if not isinstance(f, lltype._ptr):
+    from pypy.rpython.ootypesystem import ootype
+    if not isinstance(f, lltype._ptr) and not isinstance(f, ootype._callable):
         return None
+    funcobj = get_funcobj(f)
     try:
-        callable = f._obj._callable
+        callable = funcobj._callable
         # external function calls don't have a real graph
         if getattr(callable, "suggested_primitive", False):
             return None
     except (AttributeError, KeyError, AssertionError):
         return None
     try:
-        return f._obj.graph
+        return funcobj.graph
     except AttributeError:
         return None
     try:
-        callable = f._obj._callable
+        callable = funcobj._callable
         return graphof(translator, callable)
     except (AttributeError, KeyError, AssertionError):
         return None



More information about the Pypy-commit mailing list