[pypy-svn] r62138 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Wed Feb 25 14:25:22 CET 2009
Author: arigo
Date: Wed Feb 25 14:25:20 2009
New Revision: 62138
Modified:
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
Log:
Test and fix for cases where the policy decides that, in an
indirect_call, some of the called graphs must be seen but
others not.
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 25 14:25:20 2009
@@ -210,9 +210,11 @@
def __init__(self, codewriter, graph, portal):
self.codewriter = codewriter
self.cpu = codewriter.metainterp.cpu
- self.graph = graph
self.portal = portal
- self.bytecode = self.codewriter.get_jitcode(self.graph)
+ self.bytecode = self.codewriter.get_jitcode(graph)
+ if not codewriter.policy.look_inside_graph(graph):
+ graph = make_calling_stub(codewriter.rtyper, graph)
+ self.graph = graph
def assemble(self):
"""Assemble the opcodes for self.bytecode."""
@@ -620,11 +622,11 @@
# return getattr(self, 'handle_%s_call' % color)(op)
def serialize_op_direct_call(self, op):
- self.minimize_variables()
color = self.codewriter.policy.guess_call_kind(op)
return getattr(self, 'handle_%s_call' % color)(op)
def handle_regular_call(self, op):
+ self.minimize_variables()
[targetgraph] = self.codewriter.policy.graphs_from(op)
jitbox = self.codewriter.get_jitcode(targetgraph)
self.emit('call')
@@ -633,15 +635,8 @@
if x.concretetype is not lltype.Void])
self.register_var(op.result)
-# def handle_green_call(self, op):
-# assert op.result.concretetype is not lltype.Void
-# self.emit('green_call_%s' % getkind_num(self.cpu,
-# op.result.concretetype))
-# self.emit_varargs([x for x in op.args
-# if x.concretetype is not lltype.Void])
-# self.register_var(op.result)
-
def handle_residual_call(self, op):
+ self.minimize_variables()
self.emit('residual_call_%s' % getkind_num(self.cpu,
op.result.concretetype))
self.emit_varargs([x for x in op.args
@@ -689,28 +684,6 @@
self.emit_varargs([c_func] + args)
self.register_var(op.result)
-# def serialize_op_indirect_call(self, op):
-# xxx
-# color = support.guess_call_kind(self.codewriter.hannotator, op)
-# return getattr(self, 'handle_%s_indirect_call' % color)(op)
-
-# def handle_red_indirect_call(self, op):
-# # indirect_call to a red function pointer
-# # XXX for now, this is handled as a residual call
-# self.handle_residual_indirect_call(op)
-
-# def handle_direct_indirect_call(self, op):
-# # indirect_call to a green function pointer
-# self.minimize_variables()
-# targets = support.graphs_from(self.codewriter.hannotator, op)
-# indirectcallset = self.codewriter.get_indirectcallset(targets)
-# self.emit('direct_indirect_call')
-# self.emit(self.get_position(indirectcallset))
-# self.emit(self.var_position(op.args[0]))
-# self.emit_varargs([x for x in op.args[1:-1]
-# if x.concretetype is not lltype.Void])
-# self.register_var(op.result)
-
def serialize_op_indirect_call(self, op):
self.minimize_variables()
targets = self.codewriter.policy.graphs_from(op)
@@ -840,3 +813,23 @@
result[i + 1] = chr((index >> 8) & 0xff)
result[i + 2] = chr(index & 0xff)
return "".join(result)
+
+# ____________________________________________________________
+
+def make_calling_stub(rtyper, graph):
+ from pypy.objspace.flow.model import Block, Link, FunctionGraph
+ from pypy.objspace.flow.model import SpaceOperation
+ from pypy.translator.unsimplify import copyvar
+ #
+ args_v = [copyvar(None, v) for v in graph.getargs()]
+ v_res = copyvar(None, graph.getreturnvar())
+ fnptr = rtyper.getcallable(graph)
+ v_ptr = Constant(fnptr, lltype.typeOf(fnptr))
+ newstartblock = Block(args_v)
+ newstartblock.operations.append(
+ SpaceOperation('direct_call', [v_ptr] + args_v, v_res))
+ newgraph = FunctionGraph('%s_ts_stub' % (graph.name,), newstartblock)
+ newgraph.getreturnvar().concretetype = v_res.concretetype
+ newstartblock.closeblock(Link([v_res], newgraph.returnblock))
+ newgraph.ts_stub_for = graph
+ return newgraph
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Wed Feb 25 14:25:20 2009
@@ -1,14 +1,32 @@
-class JitPolicy:
+class JitPolicy(object):
+
+ def look_inside_function(self, func):
+ # explicitly pure functions are always opaque
+ if getattr(func, '_pure_function_', False):
+ return False
+ return True
+
+ def look_inside_graph(self, graph):
+ try:
+ func = graph.func
+ except AttributeError:
+ return True
+ return self.look_inside_function(func)
+
def graphs_from(self, op):
if op.opname == 'direct_call':
graph = op.args[0].value._obj.graph
- # explicitly pure functions are always opaque
- if getattr(getattr(graph, 'func', None), '_pure_function_', False):
- return None
- return [graph]
- assert op.opname == 'indirect_call'
- return op.args[-1].value
+ if self.look_inside_graph(graph):
+ return [graph] # common case: look inside this graph
+ else:
+ assert op.opname == 'indirect_call'
+ graphs = op.args[-1].value
+ for graph in graphs:
+ if self.look_inside_graph(graph):
+ return graphs # common case: look inside at least 1 graph
+ # residual call case: we don't need to look into any graph
+ return None
def guess_call_kind(self, op):
targetgraphs = self.graphs_from(op)
@@ -26,11 +44,7 @@
def __init__(self, *funcs):
self.funcs = funcs
- def graphs_from(self, op):
- graphs = JitPolicy.graphs_from(self, op)
- if graphs is None or len(graphs) > 1: # XXX a hack
- return graphs
- [graph] = graphs
- if getattr(graph, 'func', None) in self.funcs:
- return None
- return [graph]
+ def look_inside_function(self, func):
+ if func in self.funcs:
+ return False
+ return super(StopAtXPolicy, self).look_inside_function(func)
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Wed Feb 25 14:25:20 2009
@@ -179,6 +179,28 @@
res = self.meta_interp(f, [31])
assert res == -4
+ def test_stopatxpolicy(self):
+ myjitdriver = JitDriver(greens = [], reds = ['y'])
+ def internfn(y):
+ return y * 3
+ def externfn(y):
+ return y % 4
+ def f(y):
+ while y >= 0:
+ myjitdriver.can_enter_jit(y=y)
+ myjitdriver.jit_merge_point(y=y)
+ if y & 7:
+ f = internfn
+ else:
+ f = externfn
+ f(y)
+ y -= 1
+ return 42
+ policy = StopAtXPolicy(externfn)
+ res = self.meta_interp(f, [31], policy=policy)
+ assert res == 42
+ self.check_loops(int_mul=1, int_mod=0)
+
class TestOOtype(BasicTests, OOJitMixin):
pass
More information about the Pypy-commit
mailing list