[pypy-svn] r74784 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Wed May 26 18:32:11 CEST 2010
Author: arigo
Date: Wed May 26 18:32:09 2010
New Revision: 74784
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py
Log:
Some progress towards getting test_recursive to pass again.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py Wed May 26 18:32:09 2010
@@ -15,7 +15,8 @@
class CallControl(object):
- virtualref_info = None # optionally set from outside to a VirtualRefInfo()
+ virtualref_info = None # optionally set from outside
+ portal_runner_ptr = None # optionally set from outside
def __init__(self, cpu=None, portal_graph=None):
self.cpu = cpu
@@ -119,12 +120,12 @@
def guess_call_kind(self, op, is_candidate=None):
if op.opname == 'direct_call':
funcptr = op.args[0].value
+ if funcptr is self.portal_runner_ptr:
+ return 'recursive'
funcobj = get_funcobj(funcptr)
if getattr(funcobj, 'graph', None) is None:
return 'residual'
targetgraph = funcobj.graph
- if targetgraph is self.portal_graph:
- return 'recursive'
if (hasattr(targetgraph, 'func') and
hasattr(targetgraph.func, 'oopspec')):
return 'builtin'
@@ -164,8 +165,9 @@
because it is not needed there; it is only used by the blackhole
interp to really do the call corresponding to 'inline_call' ops.
"""
- fnptr = self.rtyper.getcallable(graph)
+ fnptr = self.rtyper.type_system.getcallable(graph)
FUNC = get_functype(lltype.typeOf(fnptr))
+ assert lltype.Ptr(lltype.PyObject) not in FUNC.ARGS
if self.rtyper.type_system.name == 'ootypesystem':
XXX
else:
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py Wed May 26 18:32:09 2010
@@ -71,6 +71,9 @@
def setup_vrefinfo(self, vrefinfo):
self.callcontrol.virtualref_info = vrefinfo
+ def setup_portal_runner_ptr(self, portal_runner_ptr):
+ self.callcontrol.portal_runner_ptr = portal_runner_ptr
+
def find_all_graphs(self, policy):
return self.callcontrol.find_all_graphs(policy)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py Wed May 26 18:32:09 2010
@@ -283,11 +283,12 @@
op1 = [op1, SpaceOperation('-live-', [], None)]
return op1
- def handle_regular_call(self, op):
+ def handle_regular_call(self, op, targetgraph=None):
"""A direct_call turns into the operation 'inline_call_xxx' if it
is calling a function that we want to JIT. The initial arg of
'inline_call_xxx' is the JitCode of the called function."""
- [targetgraph] = self.callcontrol.graphs_from(op)
+ if targetgraph is None:
+ [targetgraph] = self.callcontrol.graphs_from(op)
jitcode = self.callcontrol.get_jitcode(targetgraph,
called_from=self.graph)
op0 = self.rewrite_call(op, 'inline_call', [jitcode])
@@ -313,6 +314,11 @@
op1 = self.handle_residual_call(op1 or op)
return op1
+ def handle_recursive_call(self, op):
+ ops = self.promote_greens(op.args[1:])
+ targetgraph = self.callcontrol.portal_graph
+ return ops + self.handle_regular_call(op, targetgraph)
+
handle_residual_indirect_call = handle_residual_call
def handle_regular_indirect_call(self, op):
@@ -682,28 +688,34 @@
return Constant(value, lltype.Bool)
return op
- def rewrite_op_jit_marker(self, op):
- jitdriver = op.args[1].value
- self.callcontrol.found_jitdriver(jitdriver)
- key = op.args[0].value
- return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver)
-
- def handle_jit_marker__jit_merge_point(self, op, jitdriver):
- assert self.portal, "jit_merge_point in non-main graph!"
+ def promote_greens(self, args):
+ jitdriver = self.callcontrol.jitdriver
+ assert jitdriver is not None, "order dependency issue?"
ops = []
num_green_args = len(jitdriver.greens)
- for v in op.args[2:2+num_green_args]:
+ for v in args[:num_green_args]:
if isinstance(v, Variable) and v.concretetype is not lltype.Void:
kind = getkind(v.concretetype)
ops.append(SpaceOperation('-live-', [], None))
ops.append(SpaceOperation('%s_guard_value' % kind,
[v], None))
+ return ops
+
+ def rewrite_op_jit_marker(self, op):
+ self.callcontrol.found_jitdriver(op.args[1].value)
+ key = op.args[0].value
+ return getattr(self, 'handle_jit_marker__%s' % key)(op)
+
+ def handle_jit_marker__jit_merge_point(self, op):
+ assert self.portal, "jit_merge_point in non-main graph!"
+ ops = self.promote_greens(op.args[2:])
+ num_green_args = len(self.callcontrol.jitdriver.greens)
args = (self.make_three_lists(op.args[2:2+num_green_args]) +
self.make_three_lists(op.args[2+num_green_args:]))
- ops.append(SpaceOperation('jit_merge_point', args, None))
- return ops
+ op1 = SpaceOperation('jit_merge_point', args, None)
+ return ops + [op1]
- def handle_jit_marker__can_enter_jit(self, op, jitdriver):
+ def handle_jit_marker__can_enter_jit(self, op):
return SpaceOperation('can_enter_jit', [], None)
def rewrite_op_debug_assert(self, op):
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py Wed May 26 18:32:09 2010
@@ -86,6 +86,7 @@
do_call_pure = do_call
do_call_loopinvariant = do_call
+do_call_may_force = do_call
def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr):
array = arraybox.getref_base()
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Wed May 26 18:32:09 2010
@@ -603,13 +603,13 @@
@arguments("jitcode", "boxes")
def _opimpl_inline_call1(self, jitcode, argboxes):
- self.metainterp.perform_call(jitcode, argboxes)
+ return self.metainterp.perform_call(jitcode, argboxes)
@arguments("jitcode", "boxes2")
def _opimpl_inline_call2(self, jitcode, argboxes):
- self.metainterp.perform_call(jitcode, argboxes)
+ return self.metainterp.perform_call(jitcode, argboxes)
@arguments("jitcode", "boxes3")
def _opimpl_inline_call3(self, jitcode, argboxes):
- self.metainterp.perform_call(jitcode, argboxes)
+ return self.metainterp.perform_call(jitcode, argboxes)
opimpl_inline_call_r_i = _opimpl_inline_call1
opimpl_inline_call_r_r = _opimpl_inline_call1
@@ -760,32 +760,6 @@
self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
return clsbox
- def verify_green_args(self, varargs):
- num_green_args = self.metainterp.staticdata.num_green_args
- for i in range(num_green_args):
- assert isinstance(varargs[i], Const)
-
-## def blackhole_reached_merge_point(self, varargs):
-## if self.metainterp.in_recursion:
-## portal_code = self.metainterp.staticdata.portal_code
-## # small hack: fish for the result box
-## lenenv = len(self.env)
-## raised = self.perform_call(portal_code, varargs)
-## # in general this cannot be assumed, but when blackholing,
-## # perform_call returns True only if an exception is called. In
-## # this case perform_call has called finishframe_exception
-## # already, so we need to return.
-## if raised:
-## return
-## if lenenv == len(self.env):
-## res = None
-## else:
-## assert lenenv == len(self.env) - 1
-## res = self.env.pop()
-## self.metainterp.finishframe(res)
-## else:
-## raise self.metainterp.staticdata.ContinueRunningNormally(varargs)
-
@arguments()
def opimpl_can_enter_jit(self):
if self.metainterp.in_recursion:
@@ -795,7 +769,7 @@
@arguments("orgpc", "boxes3", "boxes3")
def opimpl_jit_merge_point(self, orgpc, greenboxes, redboxes):
- self.verify_green_args(greenboxes)
+ self.metainterp.verify_green_args(greenboxes)
# xxx we may disable the following line in some context later
self.debug_merge_point(greenboxes)
if self.metainterp.seen_can_enter_jit:
@@ -1022,7 +996,6 @@
effectinfo = descr.get_extra_info()
if (effectinfo is None or effectinfo.extraeffect ==
effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE):
- XXX
# residual calls require attention to keep virtualizables in-sync
self.metainterp.vable_and_vrefs_before_residual_call()
# xxx do something about code duplication
@@ -1030,12 +1003,10 @@
rop.CALL_MAY_FORCE, allboxes, descr=descr)
self.metainterp.vable_and_vrefs_after_residual_call()
if resbox is not None:
- self.make_result_box(resbox)
- self.generate_guard(self.pc, rop.GUARD_NOT_FORCED, None, [])
- if exc:
- return self.metainterp.handle_exception()
- else:
- return self.metainterp.assert_no_exception()
+ self.make_result_of_lastop(resbox)
+ self.generate_guard(rop.GUARD_NOT_FORCED, None)
+ self.metainterp.handle_possible_exception()
+ return resbox
else:
effect = effectinfo.extraeffect
if effect == effectinfo.EF_CANNOT_RAISE:
@@ -1248,12 +1219,25 @@
def is_blackholing(self):
return False # XXX get rid of this method
- def perform_call(self, jitcode, boxes, greenkey=None):
+ def perform_call(self, jitcode, boxes):
# causes the metainterp to enter the given subfunction
+ # with a special case for recursive portal calls
+ if jitcode is self.staticdata.portal_code:
+ return self.perform_recursive_call_to_portal(boxes)
+ else:
+ self._perform_call(jitcode, boxes)
+ # ^^^ always raises
+
+ def _perform_call(self, jitcode, boxes, greenkey=None):
f = self.newframe(jitcode, greenkey)
f.setup_call(boxes)
raise ChangeFrame
+ def verify_green_args(self, varargs):
+ num_green_args = self.staticdata.num_green_args
+ for i in range(num_green_args):
+ assert isinstance(varargs[i], Const)
+
def newframe(self, jitcode, greenkey=None):
if jitcode is self.staticdata.portal_code:
self.in_recursion += 1
@@ -2014,17 +1998,48 @@
max_key = key
return max_key
- def direct_assembler_call(self, pc, varargs, token, call_position):
+ def perform_recursive_call_to_portal(self, boxes):
+ warmrunnerstate = self.staticdata.state
+ portal_code = self.staticdata.portal_code
+ token = None
+ if not self.is_blackholing() and warmrunnerstate.inlining:
+ num_green_args = self.staticdata.num_green_args
+ greenkey = boxes[:num_green_args]
+ if warmrunnerstate.can_inline_callable(greenkey):
+ return self._perform_call(portal_code, boxes, greenkey)
+ token = warmrunnerstate.get_assembler_token(greenkey)
+ call_position = 0
+ if token is not None:
+ call_position = len(self.history.operations)
+ # verify that we have all green args, needed to make sure
+ # that assembler that we call is still correct
+ self.verify_green_args(boxes)
+ funcbox = ConstInt(llmemory.cast_adr_to_int(portal_code.fnaddr))
+ frame = self.framestack[-1]
+ resbox = frame.do_residual_call(funcbox, portal_code.calldescr, boxes)
+ if token is not None:
+ # XXX fix the call position, <UGLY!>
+ while True:
+ op = self.history.operations[call_position]
+ if op.opnum == rop.CALL or op.opnum == rop.CALL_MAY_FORCE:
+ break
+ call_position += 1
+ # </UGLY!>
+ # this will substitute the residual call with assembler call
+ self.direct_assembler_call(boxes, token, call_position)
+ return resbox
+
+ def direct_assembler_call(self, boxes, token, call_position):
""" Generate a direct call to assembler for portal entry point.
"""
assert not self.is_blackholing() # XXX
num_green_args = self.staticdata.num_green_args
- args = varargs[num_green_args + 1:]
+ args = boxes[num_green_args:]
resbox = self.history.operations[call_position].result
rest = self.history.slice_history_at(call_position)
if self.staticdata.virtualizable_info is not None:
vindex = self.staticdata.virtualizable_info.index_of_virtualizable
- vbox = args[vindex - num_green_args]
+ vbox = boxes[vindex]
args += self.gen_load_from_other_virtualizable(vbox)
self.history.record(rop.CALL_ASSEMBLER, args[:], resbox, descr=token)
self.history.operations += rest
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_recursive.py Wed May 26 18:32:09 2010
@@ -24,6 +24,7 @@
return 1
res = self.meta_interp(main, [20], optimizer=OPTIMIZER_SIMPLE)
assert res == main(20)
+ self.check_history(call=0)
def test_simple_recursion_with_exc(self):
myjitdriver = JitDriver(greens=[], reds=['n', 'm'])
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py Wed May 26 18:32:09 2010
@@ -554,6 +554,7 @@
self.PTR_PORTAL_FUNCTYPE.TO,
self.PTR_PORTAL_FUNCTYPE.TO.ARGS,
self.PTR_PORTAL_FUNCTYPE.TO.RESULT)
+ self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr)
vinfo = self.metainterp_sd.virtualizable_info
More information about the Pypy-commit
mailing list