[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