[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