[pypy-svn] r36654 - in pypy/dist/pypy/translator: . backendopt backendopt/test
antocuni at codespeak.net
antocuni at codespeak.net
Sat Jan 13 14:57:21 CET 2007
Author: antocuni
Date: Sat Jan 13 14:57:20 2007
New Revision: 36654
Modified:
pypy/dist/pypy/translator/backendopt/all.py
pypy/dist/pypy/translator/backendopt/checkvirtual.py
pypy/dist/pypy/translator/backendopt/inline.py
pypy/dist/pypy/translator/backendopt/test/test_all.py
pypy/dist/pypy/translator/backendopt/test/test_checkvirtual.py
pypy/dist/pypy/translator/backendopt/test/test_inline.py
pypy/dist/pypy/translator/backendopt/test/test_malloc.py
pypy/dist/pypy/translator/driver.py
Log:
Inline oosends we can dispatch at compile-time because they call
non-virtual methods.
Make backend_optimizations() always call check_virtual_methods when
using ootypesystem.
Make ootype.ROOT the default Instance where to start from when
checking virtual methods.
Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py (original)
+++ pypy/dist/pypy/translator/backendopt/all.py Sat Jan 13 14:57:20 2007
@@ -10,6 +10,7 @@
from pypy.translator.backendopt.mallocprediction import clever_inlining_and_malloc_removal
from pypy.translator.backendopt.removeassert import remove_asserts
from pypy.translator.backendopt.support import log
+from pypy.translator.backendopt.checkvirtual import check_virtual_methods
from pypy.objspace.flow.model import checkgraph
def backend_optimizations(translator, graphs=None, secondary=False, **kwds):
@@ -31,6 +32,9 @@
if config.raisingop2direct_call:
raisingop2direct_call(translator, graphs)
+ if translator.rtyper.type_system.name == 'ootypesystem':
+ check_virtual_methods()
+
# remove obvious no-ops
for graph in graphs:
removenoops.remove_same_as(graph)
Modified: pypy/dist/pypy/translator/backendopt/checkvirtual.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/checkvirtual.py (original)
+++ pypy/dist/pypy/translator/backendopt/checkvirtual.py Sat Jan 13 14:57:20 2007
@@ -7,7 +7,9 @@
non-virtual calls, such as JVM).
"""
-def check_virtual_methods(INSTANCE, super_methods = {}):
+from pypy.rpython.ootypesystem import ootype
+
+def check_virtual_methods(INSTANCE=ootype.ROOT, super_methods = {}):
my_methods = super_methods.copy()
for name, method in INSTANCE._methods.iteritems():
method._virtual = False
Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py (original)
+++ pypy/dist/pypy/translator/backendopt/inline.py Sat Jan 13 14:57:20 2007
@@ -22,6 +22,16 @@
class CannotInline(Exception):
pass
+def get_meth_from_oosend(op):
+ method_name = op.args[0].value
+ INSTANCE = op.args[1].concretetype
+ _, meth = INSTANCE._lookup(op.args[0].value)
+ virtual = getattr(meth, '_virtual', True)
+ if virtual:
+ return None
+ else:
+ return meth
+
def collect_called_graphs(graph, translator):
graphs_or_something = {}
for block in graph.iterblocks():
@@ -40,15 +50,23 @@
for graph in graphs:
graphs_or_something[graph] = True
if op.opname == 'oosend':
- graphs_or_something[op.args[0]] = True # XXX?
+ meth = get_meth_from_oosend(op)
+ key = getattr(meth, 'graph', op.args[0])
+ graphs_or_something[key] = True
return graphs_or_something
def iter_callsites(graph, calling_what):
for block in graph.iterblocks():
for i, op in enumerate(block.operations):
- if not op.opname == "direct_call":
+ if op.opname == "direct_call":
+ funcobj = get_funcobj(op.args[0].value)
+ elif op.opname == "oosend":
+ funcobj = get_meth_from_oosend(op)
+ if funcobj is None:
+ continue # cannot inline virtual methods
+ else:
continue
- 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
@@ -178,11 +196,18 @@
self.cleanup()
return count
+ def get_graph_from_op(self, op):
+ assert op.opname in ('direct_call', 'oosend')
+ if op.opname == 'direct_call':
+ return get_funcobj(self.op.args[0].value).graph
+ else:
+ return get_meth_from_oosend(op).graph
+
def inline_once(self, block, index_operation):
self.varmap = {}
self._copied_blocks = {}
self.op = block.operations[index_operation]
- self.graph_to_inline = get_funcobj(self.op.args[0].value).graph
+ self.graph_to_inline = self.get_graph_from_op(self.op)
self.exception_guarded = False
if (block.exitswitch == c_last_exception and
index_operation == len(block.operations) - 1):
@@ -201,9 +226,14 @@
def search_for_calls(self, block):
d = {}
for i, op in enumerate(block.operations):
- if not op.opname == "direct_call":
+ if op.opname == "direct_call":
+ funcobj = get_funcobj(op.args[0].value)
+ elif op.opname == "oosend":
+ funcobj = get_meth_from_oosend(op)
+ if funcobj is None:
+ continue
+ else:
continue
- 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
@@ -565,9 +595,13 @@
'dont_inline', False):
continue
result.append((parentgraph, graph))
+ if op.opname == "oosend":
+ meth = get_meth_from_oosend(op)
+ graph = getattr(meth, 'graph', None)
+ if graph is not None:
+ result.append((parentgraph, graph))
return result
-
-
+
def instrument_inline_candidates(graphs, multiplier):
threshold = BASE_INLINE_THRESHOLD * multiplier
cache = {None: False}
Modified: pypy/dist/pypy/translator/backendopt/test/test_all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_all.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_all.py Sat Jan 13 14:57:20 2007
@@ -217,5 +217,3 @@
type_system = 'ootype'
check_malloc_removed = OOTypeMallocRemovalTest.check_malloc_removed
- def test_big(self):
- py.test.skip('FIXME! It should pass as long as oosend is inlined')
Modified: pypy/dist/pypy/translator/backendopt/test/test_checkvirtual.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_checkvirtual.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_checkvirtual.py Sat Jan 13 14:57:20 2007
@@ -6,7 +6,7 @@
A = Instance("A", ROOT)
addMethods(A, {"foo": meth(Meth([], Void))})
- check_virtual_methods(ROOT)
+ check_virtual_methods()
assert A._methods["foo"]._virtual == False
def test_checkvirtual_simple():
@@ -18,7 +18,7 @@
addMethods(B, {"foo": meth(Meth([], Void))})
- check_virtual_methods(ROOT)
+ check_virtual_methods()
assert A._methods["foo"]._virtual == True
assert A._methods["bar"]._virtual == False
assert B._methods["foo"]._virtual == False
@@ -33,7 +33,7 @@
addMethods(C, {"foo": meth(Meth([], Void))})
- check_virtual_methods(ROOT)
+ check_virtual_methods()
assert A._methods["foo"]._virtual == True
assert A._methods["bar"]._virtual == False
assert "foo" not in B._methods
@@ -49,7 +49,7 @@
addMethods(B1, {"foo": meth(Meth([], Void))})
- check_virtual_methods(ROOT)
+ check_virtual_methods()
assert A._methods["foo"]._virtual == True
assert A._methods["bar"]._virtual == False
assert B1._methods["foo"]._virtual == False
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 Sat Jan 13 14:57:20 2007
@@ -9,6 +9,7 @@
from pypy.translator.backendopt.inline import collect_called_graphs
from pypy.translator.backendopt.inline import measure_median_execution_cost
from pypy.translator.backendopt.inline import instrument_inline_candidates
+from pypy.translator.backendopt.checkvirtual import check_virtual_methods
from pypy.translator.translator import TranslationContext, graphof
from pypy.rpython.llinterp import LLInterpreter
from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin
@@ -84,8 +85,11 @@
return interp.eval_graph(graphof(t, entry), args)
return eval_func
- def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False):
+ def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False,
+ checkvirtual=False):
t = self.translate(func, sig)
+ if checkvirtual:
+ check_virtual_methods()
if option.view:
t.view()
# inline!
@@ -585,3 +589,50 @@
expected = fn(0)
res = eval_func([0])
assert res == expected
+
+ def test_oosend(self):
+ class A:
+ def foo(self, x):
+ return x
+ def fn(x):
+ a = A()
+ return a.foo(x)
+
+ eval_func, t = self.check_auto_inlining(fn, [int], checkvirtual=True)
+ expected = fn(42)
+ res = eval_func([42])
+ assert res == expected
+
+ def test_not_inline_oosend(self):
+ class A:
+ def foo(self, x):
+ return x
+ class B(A):
+ def foo(self, x):
+ return x+1
+
+ def fn(flag, x):
+ if flag:
+ obj = A()
+ else:
+ obj = B()
+ return obj.foo(x)
+
+ eval_func, t = self.check_auto_inlining(fn, [bool, int], checkvirtual=True)
+ expected = fn(True, 42)
+ res = eval_func([True, 42])
+ assert res == expected
+
+ def test_classattr(self):
+ class A:
+ attr = 666
+ class B(A):
+ attr = 42
+ def fn5():
+ b = B()
+ return b.attr
+
+ eval_func, t = self.check_auto_inlining(fn5, [], checkvirtual=True)
+ res = eval_func([])
+ assert res == 42
+
Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Sat Jan 13 14:57:20 2007
@@ -104,7 +104,6 @@
self.check(fn4, [int], [42], 42)
def test_fn5(self):
- self._skip_oo('It will work as soon as trivial oosend are inlined')
class A:
attr = 666
class B(A):
@@ -352,3 +351,9 @@
return x.foo
self.check(fn, [], [], 42)
+ def test_fn5(self):
+ # don't test this in ootype because the class attribute access
+ # is turned into an oosend which prevents malloc removal to
+ # work unless we inline first. See test_classattr in
+ # test_inline.py
+ pass
Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py (original)
+++ pypy/dist/pypy/translator/driver.py Sat Jan 13 14:57:20 2007
@@ -355,9 +355,6 @@
heap2stack=False,
clever_malloc_removal=False)
if self.config.translation.backend == 'cli':
- from pypy.translator.backendopt.checkvirtual import check_virtual_methods
- from pypy.rpython.ootypesystem import ootype
- check_virtual_methods(ootype.ROOT)
opt['merge_if_blocks'] = True
opt['inline_threshold'] = 1
opt['mallocs'] = True
More information about the Pypy-commit
mailing list