[pypy-commit] pypy jit-targets: fall back on jumping to preamble if retracing fails

hakanardo noreply at buildbot.pypy.org
Sat Dec 10 14:27:55 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r50343:f78f16899afb
Date: 2011-12-10 14:27 +0100
http://bitbucket.org/pypy/pypy/changeset/f78f16899afb/

Log:	fall back on jumping to preamble if retracing fails

diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -209,7 +209,18 @@
     try:
         optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
     except InvalidLoop:
-        return None
+        # Fall back on jumping to preamble
+        target_token = label.getdescr()
+        assert isinstance(target_token, TargetToken)
+        assert target_token.exported_state
+        part.operations = [label] + \
+                          [ResOperation(rop.JUMP, target_token.exported_state.original_jump_args,
+                                        None, descr=loop_jitcell_token)]
+        try:
+            optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts,
+                           inline_short_preamble=False)
+        except InvalidLoop:
+            return None
     assert part.operations[-1].getopnum() != rop.LABEL
     target_token = label.getdescr()
     assert isinstance(target_token, TargetToken)
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -171,7 +171,7 @@
         target_token.start_resumedescr = start_resumedescr
         target_token.exported_state = ExportedState(constant_inputargs, short_boxes,
                                                     inputarg_setup_ops, self.optimizer,
-                                                    aliased_vrituals)
+                                                    aliased_vrituals, original_jump_args)
 
     def import_state(self, targetop):
         self.did_import = False
@@ -275,7 +275,6 @@
         try:
             jumpargs = virtual_state.make_inputargs(values, self.optimizer)
         except BadVirtualState:
-            # FIXME: Produce jump to preamble instead (see test_retrace_not_matching_bridge)
             raise InvalidLoop
         jumpop.initarglist(jumpargs)
 
@@ -340,13 +339,11 @@
         if not virtual_state.generalization_of(final_virtual_state, bad):
             # We ended up with a virtual state that is not compatible
             # and we are thus unable to jump to the start of the loop
-            # XXX Is it possible to end up here? If so, consider:
-            #    - Fallback on having the preamble jump to itself?
-            #    - Would virtual_state.generate_guards make sense here?
             final_virtual_state.debug_print("Bad virtual state at end of loop, ",
                                             bad)
             debug_stop('jit-log-virtualstate')
             raise InvalidLoop
+            
         debug_stop('jit-log-virtualstate')
 
         maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards
@@ -595,9 +592,11 @@
 
 class ExportedState(object):
     def __init__(self, constant_inputargs,
-                 short_boxes, inputarg_setup_ops, optimizer, aliased_vrituals):
+                 short_boxes, inputarg_setup_ops, optimizer, aliased_vrituals,
+                 original_jump_args):
         self.constant_inputargs = constant_inputargs
         self.short_boxes = short_boxes
         self.inputarg_setup_ops = inputarg_setup_ops
         self.optimizer = optimizer
         self.aliased_vrituals = aliased_vrituals
+        self.original_jump_args = original_jump_args
diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -820,6 +820,91 @@
             return node.value 
         res = self.meta_interp(f, [10], repeat=10)
         assert res == f(10)
+        self.check_resops(jump=2)
+
+    def test_nested_loops(self):
+        class Int(object):
+            def __init__(self, val):
+                self.val = val
+        myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'sa', 'i', 'j'])
+        bytecode = "iajb+JI"
+        def f(n):
+            pc = sa = 0
+            i = j = Int(0)
+            while pc < len(bytecode):
+                myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i, j=j)
+                op = bytecode[pc]
+                if op == 'i':
+                    i = Int(0)
+                elif op == 'j':
+                    j = Int(0)
+                elif op == '+':
+                    sa += i.val * j.val
+                elif op == 'a':
+                    i = Int(i.val + 1)
+                elif op == 'b':
+                    j = Int(j.val + 1)
+                elif op == 'J':
+                    if j.val < n:
+                        pc -= 2
+                        myjitdriver.can_enter_jit(pc=pc, n=n, sa=sa, i=i, j=j)
+                        continue
+                elif op == 'I':
+                    if i.val < n:
+                        pc -= 5
+                        myjitdriver.can_enter_jit(pc=pc, n=n, sa=sa, i=i, j=j)
+                        continue
+                pc += 1
+            return sa
+
+        res = self.meta_interp(f, [10])
+        assert res == f(10)
+        self.check_aborted_count(0)
+        self.check_target_token_count(3)
+
+    def test_nested_loops_bridge(self):
+        class Int(object):
+            def __init__(self, val):
+                self.val = val
+        myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'sa', 'i', 'j'])
+        bytecode = "iajb+JI"
+        def f(n):
+            pc = sa = 0
+            i = j = Int(0)
+            while pc < len(bytecode):
+                myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i, j=j)
+                op = bytecode[pc]
+                if op == 'i':
+                    i = Int(0)
+                elif op == 'j':
+                    j = Int(0)
+                elif op == '+':
+                    if i.val < n-8:
+                        sa += 7
+                    if j.val < n-16:
+                        sa += 42
+                    sa += i.val * j.val
+                elif op == 'a':
+                    i = Int(i.val + 1)
+                elif op == 'b':
+                    j = Int(j.val + 1)
+                elif op == 'J':
+                    if j.val < n:
+                        pc -= 2
+                        myjitdriver.can_enter_jit(pc=pc, n=n, sa=sa, i=i, j=j)
+                        continue
+                elif op == 'I':
+                    if i.val < n:
+                        pc -= 5
+                        myjitdriver.can_enter_jit(pc=pc, n=n, sa=sa, i=i, j=j)
+                        continue
+                pc += 1
+            return sa
+
+        res = self.meta_interp(f, [32])
+        assert res == f(32)
+        self.check_aborted_count(0)
+        self.check_target_token_count(3)
 
 class VirtualMiscTests:
 


More information about the pypy-commit mailing list