[pypy-svn] r63711 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Mon Apr 6 12:40:18 CEST 2009
Author: arigo
Date: Mon Apr 6 12:40:17 2009
New Revision: 63711
Modified:
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtual.py
pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
Log:
Generate code for leaving a function too.
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py Mon Apr 6 12:40:17 2009
@@ -6,7 +6,8 @@
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.metainterp.history import TreeLoop, log, Box, History
-from pypy.jit.metainterp.history import AbstractDescr
+from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr
+from pypy.jit.metainterp.specnode import NotSpecNode
def compile_new_loop(metainterp, old_loops, greenkey):
"""Try to compile a new loop by closing the current history back
@@ -56,7 +57,7 @@
else:
if target_loop is not None:
show_loop(metainterp, target_loop)
- if target_loop is not None:
+ if target_loop is not None and target_loop not in map_loop2descr:
target_loop.check_consistency()
return target_loop
@@ -69,7 +70,7 @@
errmsg += ': ' + str(error)
else:
errmsg = None
- if loop is None:
+ if loop is None or loop in map_loop2descr:
extraloops = []
else:
extraloops = [loop]
@@ -112,6 +113,53 @@
# ____________________________________________________________
+class DoneWithThisFrameDescr0(AbstractDescr):
+ def handle_fail_op(self, metainterp, fail_op):
+ raise metainterp.DoneWithThisFrame(None)
+
+class DoneWithThisFrameDescr1(AbstractDescr):
+ def handle_fail_op(self, metainterp, fail_op):
+ resultbox = fail_op.args[0]
+ raise metainterp.DoneWithThisFrame(resultbox)
+
+#XXX later:
+#class ExitFrameWithExceptionDescr(AbstractDescr):
+# def handle_fail_op(self, metainterp, fail_op):
+# typebox = fail_op.args[0]
+# valuebox = fail_op.args[1]
+# raise metainterp.ExitFrameWithException(typebox, valuebox)
+
+done_with_this_frame_descr_0 = DoneWithThisFrameDescr0()
+done_with_this_frame_descr_1 = DoneWithThisFrameDescr1()
+#exit_frame_with_exception_descr = ExitFrameWithExceptionDescr()
+map_loop2descr = {}
+
+# pseudo-loops to make the life of optimize.py easier
+_loop = TreeLoop('done_with_this_frame_int')
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxInt()]
+loops_done_with_this_frame_int = [_loop]
+map_loop2descr[_loop] = done_with_this_frame_descr_1
+
+_loop = TreeLoop('done_with_this_frame_ptr')
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxPtr()]
+loops_done_with_this_frame_ptr = [_loop]
+map_loop2descr[_loop] = done_with_this_frame_descr_1
+
+_loop = TreeLoop('done_with_this_frame_void')
+_loop.specnodes = []
+_loop.inputargs = []
+loops_done_with_this_frame_void = [_loop]
+map_loop2descr[_loop] = done_with_this_frame_descr_0
+
+#loop_exit_frame_with_exception = TreeLoop('exit_frame_with_exception')
+#loop_exit_frame_with_exception.specnodes = [NotSpecNode(), NotSpecNode()]
+#loop_exit_frame_with_exception.inputargs = [BoxInt(), BoxPtr()]
+#loops_exit_frame_with_exception = [loop_exit_frame_with_exception]
+#map_loop2descr[loop_exit_frame_with_exception]=exit_frame_with_exception_descr
+
+
class ResumeGuardDescr(AbstractDescr):
def __init__(self, guard_op, resume_info, history, history_guard_index):
self.resume_info = resume_info
@@ -121,6 +169,9 @@
assert history_guard_index >= 0
self.history_guard_index = history_guard_index
+ def handle_fail_op(self, metainterp, fail_op):
+ return metainterp.handle_guard_failure(fail_op, self)
+
def get_guard_op(self):
guard_op = self.guard_op
if guard_op.optimized is not None: # should always be the case,
@@ -193,11 +244,22 @@
if target_loop is not None:
# Yes, we managed to create a bridge. Dispatch to resumekey to
# know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
- op = new_loop.operations[-1]
- op.jump_target = target_loop
+ prepare_last_operation(new_loop, target_loop)
resumekey.compile_and_attach(metainterp, new_loop)
return target_loop
+def prepare_last_operation(new_loop, target_loop):
+ op = new_loop.operations[-1]
+ if target_loop not in map_loop2descr:
+ # normal case
+ op.jump_target = target_loop
+ else:
+ # The target_loop is a pseudo-loop done_with_this_frame. Replace
+ # the operation with the real operation we want, i.e. a FAIL.
+ descr = map_loop2descr[target_loop]
+ new_op = ResOperation(rop.FAIL, op.args, None, descr=descr)
+ new_loop.operations[-1] = new_op
+
def prepare_loop_from_bridge(metainterp, resumekey):
# To handle this case, we prepend to the history the unoptimized
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py Mon Apr 6 12:40:17 2009
@@ -84,6 +84,8 @@
raise NotImplementedError
class AbstractDescr(AbstractValue):
+ def handle_fail_op(self, metainterp, fail_op):
+ raise NotImplementedError
def compile_and_attach(self, metainterp, new_loop):
raise NotImplementedError
@@ -457,9 +459,11 @@
class Stats(object):
"""For tests."""
+ compiled_count = 0
+ enter_count = 0
+
def __init__(self):
self.loops = []
- self.compiled_count = 0
def get_all_loops(self):
return self.loops
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py Mon Apr 6 12:40:17 2009
@@ -869,6 +869,8 @@
jump.args = self._patch(jump.args, inpargs)
def update_loop(self, offsets, loop):
+ if loop.operations is None: # special loops 'done_with_this_frame'
+ return # and 'exit_frame_with_exception'
j = 0
new_inputargs = []
prev_ofs = 0
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py Mon Apr 6 12:40:17 2009
@@ -767,6 +767,8 @@
self.framestack[-1].make_result_box(resultbox)
return True
else:
+ if not isinstance(self.history, history.BlackHole):
+ self.compile_done_with_this_frame(resultbox)
raise self.DoneWithThisFrame(resultbox)
def finishframe_exception(self, exceptionbox, excvaluebox):
@@ -781,6 +783,9 @@
if not we_are_translated():
self._debug_history.append(['leave_exc', frame.jitcode, None])
self.framestack.pop()
+ #XXX later:
+ #if not isinstance(self.history, history..BlackHole):
+ # self.compile_exit_frame_with_exception(exceptionbox, excvaluebox)
raise self.ExitFrameWithException(exceptionbox, excvaluebox)
def create_empty_history(self):
@@ -831,6 +836,7 @@
text = ''
if not we_are_translated():
history.log.event('ENTER' + text)
+ self.stats.enter_count += 1
else:
debug_print('~~~ ENTER', text)
try:
@@ -867,9 +873,8 @@
except GenerateMergePoint, gmp:
return self.designate_target_loop(gmp)
- def handle_guard_failure(self, guard_failure):
+ def handle_guard_failure(self, guard_failure, key):
self.initialize_state_from_guard_failure(guard_failure)
- key = guard_failure.descr
assert isinstance(key, compile.ResumeGuardDescr)
top_history = key.find_toplevel_history()
source_loop = top_history.source_link
@@ -979,6 +984,21 @@
raise GenerateMergePoint(live_arg_boxes, target_loop)
self.history.operations.pop() # remove the JUMP
+ def compile_done_with_this_frame(self, exitbox):
+ # temporarily put a JUMP to a pseudo-loop
+ if exitbox is not None:
+ exits = [exitbox]
+ if isinstance(exitbox, BoxInt) or isinstance(exitbox, ConstInt):
+ loops = compile.loops_done_with_this_frame_int
+ else:
+ loops = compile.loops_done_with_this_frame_ptr
+ else:
+ exits = []
+ loops = compile.loops_done_with_this_frame_void
+ self.history.record(rop.JUMP, exits, None)
+ target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
+ assert target_loop is loops[0]
+
def get_residual_args(self, loop, args):
if loop.specnodes is None: # it is None only for tests
return args
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py Mon Apr 6 12:40:17 2009
@@ -86,7 +86,6 @@
_FINAL_FIRST = 1
JUMP = 1
FAIL = 2
- #RAISE = 3
_FINAL_LAST = 9
_GUARD_FIRST = 10 # ----- start of guard operations -----
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py Mon Apr 6 12:40:17 2009
@@ -29,7 +29,8 @@
def check_loops(self, expected=None, **check):
get_stats().check_loops(expected=expected, **check)
def check_loop_count(self, count):
- """NB. This is a hack; use check_tree_loop_count() for the real thing.
+ """NB. This is a hack; use check_tree_loop_count() or
+ check_enter_count() for the real thing.
This counts as 1 every bridge in addition to every loop; and it does
not count at all the entry bridges from interpreter, although they
are TreeLoops as well."""
@@ -38,6 +39,8 @@
assert len(get_stats().loops) == count
def check_loop_count_at_most(self, count):
assert get_stats().compiled_count <= count
+ def check_enter_count(self, count):
+ assert get_stats().enter_count == count
def check_jumps(self, maxcount):
assert get_stats().exec_jumps <= maxcount
@@ -53,8 +56,9 @@
class DoneWithThisFrame(Exception):
pass
- class FakeWarmRunnderDesc:
- num_green_args = 0
+ class FakeWarmRunnerDesc:
+ def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
+ pass
if policy is None:
policy = JitPolicy()
@@ -69,14 +73,14 @@
cw.make_one_bytecode(graph, False, called_from)
metainterp.portal_code = maingraph
metainterp.delete_history()
- metainterp.warmrunnerdesc = FakeWarmRunnderDesc
+ metainterp.state = FakeWarmRunnerDesc()
metainterp.DoneWithThisFrame = DoneWithThisFrame
self.metainterp = metainterp
try:
metainterp.compile_and_run_once(*args)
except DoneWithThisFrame, e:
- if conftest.option.view:
- metainterp.stats.view()
+ #if conftest.option.view:
+ # metainterp.stats.view()
return e.args[0].value
else:
raise Exception("FAILED")
@@ -366,8 +370,13 @@
n -= 1
self.meta_interp(f, [20], repeat=7)
- py.test.skip("in-progress")
- self.check_loop_count(3) # the loop, the entry path, the exit path
+ self.check_tree_loop_count(2) # the loop and the entry path
+ # we get:
+ # ENTER - compile the new loop
+ # ENTER (BlackHole) - leave
+ # ENTER - compile the entry bridge
+ # ENTER - compile the leaving path
+ self.check_enter_count(4)
def test_casts(self):
from pypy.rpython.lltypesystem import lltype, llmemory
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtual.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtual.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtual.py Mon Apr 6 12:40:17 2009
@@ -265,8 +265,14 @@
res = self.meta_interp(f, [21], repeat=7)
assert res.inst_n == f(21).n
- py.test.skip("in-progress")
- self.check_loop_count(3) # the loop, the entry path, the exit path
+ self.check_tree_loop_count(2) # the loop and the entry path
+ # we get:
+ # ENTER - compile the new loop
+ # ENTER (BlackHole) - leave
+ # ENTER - compile the entry bridge
+ # ENTER - compile the leaving path
+ self.check_enter_count(4)
+
##class TestOOtype(VirtualTests, OOJitMixin):
## _new = staticmethod(ootype.new)
Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py Mon Apr 6 12:40:17 2009
@@ -483,8 +483,8 @@
# ---------- execute assembler ----------
while True: # until interrupted by an exception
metainterp = warmrunnerdesc.metainterp
- guard_failure = metainterp.cpu.execute_operations(loop, boxes)
- loop, boxes = metainterp.handle_guard_failure(guard_failure)
+ fail_op = metainterp.cpu.execute_operations(loop, boxes)
+ loop, boxes = fail_op.descr.handle_fail_op(metainterp, fail_op)
maybe_compile_and_run._dont_inline_ = True
def handle_hash_collision(self, cell, argshash, *args):
More information about the Pypy-commit
mailing list