[pypy-commit] pypy default: Merging jit-multilabel. This is mostly a cleanup of the handling of labels in optimizeop. It does add suppot for optimizing traces with multiple intermediate labels, but that feature is curently only used in tests.

hakanardo noreply at buildbot.pypy.org
Wed Dec 21 14:25:46 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: 
Changeset: r50798:d5d0c616af63
Date: 2011-12-21 14:25 +0100
http://bitbucket.org/pypy/pypy/changeset/d5d0c616af63/

Log:	Merging jit-multilabel. This is mostly a cleanup of the handling of
	labels in optimizeop. It does add suppot for optimizing traces with
	multiple intermediate labels, but that feature is curently only used
	in tests.

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
@@ -105,7 +105,7 @@
 
 def compile_loop(metainterp, greenkey, start,
                  inputargs, jumpargs,
-                 start_resumedescr, full_preamble_needed=True):
+                 resume_at_jump_descr, full_preamble_needed=True):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
@@ -126,10 +126,11 @@
         part = create_empty_loop(metainterp)
         part.inputargs = inputargs[:]
         h_ops = history.operations
-        part.start_resumedescr = start_resumedescr
+        part.resume_at_jump_descr = resume_at_jump_descr
         part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(jitcell_token))] + \
                           [h_ops[i].clone() for i in range(start, len(h_ops))] + \
-                          [ResOperation(rop.JUMP, jumpargs, None, descr=jitcell_token)]
+                          [ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)]
+
         try:
             optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
         except InvalidLoop:
@@ -184,7 +185,7 @@
 
 def compile_retrace(metainterp, greenkey, start,
                     inputargs, jumpargs,
-                    start_resumedescr, partial_trace, resumekey):
+                    resume_at_jump_descr, partial_trace, resumekey):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
@@ -200,7 +201,7 @@
 
     part = create_empty_loop(metainterp)
     part.inputargs = inputargs[:]
-    part.start_resumedescr = start_resumedescr
+    part.resume_at_jump_descr = resume_at_jump_descr
     h_ops = history.operations
 
     part.operations = [partial_trace.operations[-1]] + \
@@ -212,13 +213,12 @@
     try:
         optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
     except InvalidLoop:
-        #return None # XXX: Dissable for now
         # Fall back on jumping to preamble
         target_token = label.getdescr()
         assert isinstance(target_token, TargetToken)
         assert target_token.exported_state
         part.operations = [orignial_label] + \
-                          [ResOperation(rop.JUMP, target_token.exported_state.jump_args,
+                          [ResOperation(rop.JUMP, inputargs[:],
                                         None, descr=loop_jitcell_token)]
         try:
             optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts,
@@ -751,7 +751,7 @@
         metainterp_sd.stats.add_jitcell_token(jitcell_token)
 
 
-def compile_trace(metainterp, resumekey, start_resumedescr=None):
+def compile_trace(metainterp, resumekey, resume_at_jump_descr=None):
     """Try to compile a new bridge leading from the beginning of the history
     to some existing place.
     """
@@ -767,7 +767,7 @@
     # clone ops, as optimize_bridge can mutate the ops
 
     new_trace.operations = [op.clone() for op in metainterp.history.operations]
-    new_trace.start_resumedescr = start_resumedescr
+    new_trace.resume_at_jump_descr = resume_at_jump_descr
     metainterp_sd = metainterp.staticdata
     state = metainterp.jitdriver_sd.warmstate
     if isinstance(resumekey, ResumeAtPositionDescr):
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -705,6 +705,9 @@
 
         self.virtual_state = None
         self.exported_state = None
+
+    def repr_of_descr(self):
+        return 'TargetToken(%d)' % compute_unique_id(self)
         
 class TreeLoop(object):
     inputargs = None
@@ -712,7 +715,7 @@
     call_pure_results = None
     logops = None
     quasi_immutable_deps = None
-    start_resumedescr = None
+    resume_at_jump_descr = None
 
     def _token(*args):
         raise Exception("TreeLoop.token is killed")
diff --git a/pypy/jit/metainterp/logger.py b/pypy/jit/metainterp/logger.py
--- a/pypy/jit/metainterp/logger.py
+++ b/pypy/jit/metainterp/logger.py
@@ -5,7 +5,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.history import Const, ConstInt, Box, \
-     BoxInt, ConstFloat, BoxFloat, AbstractFailDescr
+     BoxInt, ConstFloat, BoxFloat, AbstractFailDescr, TargetToken
 
 class Logger(object):
 
@@ -135,6 +135,13 @@
             fail_args = ''
         return s_offset + res + op.getopname() + '(' + args + ')' + fail_args
 
+    def _log_inputarg_setup_ops(self, op):
+        target_token = op.getdescr()
+        if isinstance(target_token, TargetToken):
+            if target_token.exported_state:
+                for op in target_token.exported_state.inputarg_setup_ops:
+                    debug_print('    ' + self.repr_of_resop(op))
+        
     def _log_operations(self, inputargs, operations, ops_offset):
         if not have_debug_prints():
             return
@@ -146,6 +153,8 @@
         for i in range(len(operations)):
             op = operations[i]
             debug_print(self.repr_of_resop(operations[i], ops_offset))
+            if op.getopnum() == rop.LABEL:
+                self._log_inputarg_setup_ops(op)
         if ops_offset and None in ops_offset:
             offset = ops_offset[None]
             debug_print("+%d: --end of the loop--" % offset)
diff --git a/pypy/jit/metainterp/optimize.py b/pypy/jit/metainterp/optimize.py
--- a/pypy/jit/metainterp/optimize.py
+++ b/pypy/jit/metainterp/optimize.py
@@ -5,58 +5,3 @@
     """Raised when the optimize*.py detect that the loop that
     we are trying to build cannot possibly make sense as a
     long-running loop (e.g. it cannot run 2 complete iterations)."""
-
-class RetraceLoop(JitException):
-    """ Raised when inlining a short preamble resulted in an
-        InvalidLoop. This means the optimized loop is too specialized
-        to be useful here, so we trace it again and produced a second
-        copy specialized in some different way.
-    """
-
-# ____________________________________________________________
-
-def optimize_loop(metainterp_sd, old_loop_tokens, loop, enable_opts):
-    debug_start("jit-optimize")
-    try:
-        return _optimize_loop(metainterp_sd, old_loop_tokens, loop,
-                              enable_opts)
-    finally:
-        debug_stop("jit-optimize")
-
-def _optimize_loop(metainterp_sd, old_loop_tokens, loop, enable_opts):
-    from pypy.jit.metainterp.optimizeopt import optimize_loop_1
-    loop.logops = metainterp_sd.logger_noopt.log_loop(loop.inputargs,
-                                                      loop.operations)
-    # XXX do we really still need a list?
-    if old_loop_tokens:
-        return old_loop_tokens[0]
-    optimize_loop_1(metainterp_sd, loop, enable_opts)
-    return None
-
-# ____________________________________________________________
-
-def optimize_bridge(metainterp_sd, old_loop_tokens, bridge, enable_opts,
-                    inline_short_preamble=True, retraced=False):
-    debug_start("jit-optimize")
-    try:
-        return _optimize_bridge(metainterp_sd, old_loop_tokens, bridge,
-                                enable_opts,
-                                inline_short_preamble, retraced)
-    finally:
-        debug_stop("jit-optimize")
-
-def _optimize_bridge(metainterp_sd, old_loop_tokens, bridge, enable_opts,
-                     inline_short_preamble, retraced=False):
-    from pypy.jit.metainterp.optimizeopt import optimize_bridge_1
-    bridge.logops = metainterp_sd.logger_noopt.log_loop(bridge.inputargs,
-                                                        bridge.operations)
-    if old_loop_tokens:
-        old_loop_token = old_loop_tokens[0]
-        bridge.operations[-1].setdescr(old_loop_token)   # patch jump target
-        optimize_bridge_1(metainterp_sd, bridge, enable_opts,
-                          inline_short_preamble, retraced)
-        return old_loop_tokens[0]
-        #return bridge.operations[-1].getdescr()
-    return None
-
-# ____________________________________________________________
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -51,34 +51,6 @@
 
     return optimizations, unroll
 
-
-def optimize_loop_1(metainterp_sd, loop, enable_opts,
-                    inline_short_preamble=True, retraced=False):
-    """Optimize loop.operations to remove internal overheadish operations.
-    """
-
-    optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts,
-                                            inline_short_preamble, retraced)
-    if unroll:
-        optimize_unroll(metainterp_sd, loop, optimizations)
-    else:
-        optimizer = Optimizer(metainterp_sd, loop, optimizations)
-        optimizer.propagate_all_forward()
-
-def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
-                      inline_short_preamble=True, retraced=False):
-    """The same, but for a bridge. """
-    enable_opts = enable_opts.copy()
-    try:
-        del enable_opts['unroll']
-    except KeyError:
-        pass
-    optimize_loop_1(metainterp_sd, bridge, enable_opts,
-                    inline_short_preamble, retraced)
-
-if __name__ == '__main__':
-    print ALL_OPTS_NAMES
-
 def optimize_trace(metainterp_sd, loop, enable_opts, inline_short_preamble=True):
     """Optimize loop.operations to remove internal overheadish operations.
     """
@@ -96,3 +68,6 @@
     finally:
         debug_stop("jit-optimize")
         
+if __name__ == '__main__':
+    print ALL_OPTS_NAMES
+
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -453,6 +453,7 @@
 
     def clear_newoperations(self):
         self._newoperations = []
+        self.seen_results = {}
 
     def make_equal_to(self, box, value, replace=False):
         assert isinstance(value, OptValue)
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -35,6 +35,9 @@
         pass
 
     def optimize_LABEL(self, op):
+        descr = op.getdescr()
+        if isinstance(descr, JitCellToken):
+            return self.optimize_JUMP(op.copy_and_change(rop.JUMP))
         self.last_label_descr = op.getdescr()
         self.emit_operation(op)
         
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -9,14 +9,14 @@
 class BaseTestMultiLabel(BaseTest):
     enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
 
-    def optimize_loop(self, ops, expected):
+    def optimize_loop(self, ops, expected, expected_shorts=None):
         loop = self.parse(ops)
         if expected != "crash!":
             expected = self.parse(expected)
 
         part = TreeLoop('part')
         part.inputargs = loop.inputargs
-        part.start_resumedescr = FakeDescrWithSnapshot()
+        part.resume_at_jump_descr = FakeDescrWithSnapshot()
         token = loop.original_jitcell_token
 
         optimized = TreeLoop('optimized')
@@ -33,15 +33,17 @@
             if nxt < len(loop.operations):
                 label = loop.operations[nxt]
                 assert label.getopnum() == rop.LABEL
-                jumpop = ResOperation(rop.JUMP, label.getarglist(),
-                                      None, descr=token)
-                operations.append(jumpop)
+                if label.getdescr() is None:
+                    label.setdescr(token)
+                operations.append(label)
             part.operations = operations
+
             self._do_optimize_loop(part, None)
             if part.operations[-1].getopnum() == rop.LABEL:
                 last_label = [part.operations.pop()]
             else:
                 last_label = []
+            
             optimized.operations.extend(part.operations)
             prv = nxt + 1
         
@@ -54,9 +56,32 @@
             print 'Failed!'
         print
 
+        shorts = [op.getdescr().short_preamble
+                  for op in optimized.operations
+                  if op.getopnum() == rop.LABEL]
+
+        if expected_shorts:
+            for short in shorts:
+                print
+                print "Short preamble:"
+                print '\n'.join([str(o) for o in short])
+
+
         assert expected != "crash!", "should have raised an exception"
         self.assert_equal(optimized, expected)
 
+        if expected_shorts:
+            assert len(shorts) == len(expected_shorts)
+            for short, expected_short in zip(shorts, expected_shorts):
+                expected_short = self.parse(expected_short)
+                short_preamble = TreeLoop('short preamble')
+                assert short[0].getopnum() == rop.LABEL
+                short_preamble.inputargs = short[0].getarglist()
+                short_preamble.operations = short
+                self.assert_equal(short_preamble, expected_short,
+                                  text_right='expected short preamble')
+
+        
         return optimized
 
     def test_simple(self):
@@ -194,8 +219,168 @@
         """
         with raises(InvalidLoop):
             self.optimize_loop(ops, ops)
-        
+
+    def test_two_intermediate_labels_basic_1(self):
+        ops = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i1)
+        i3 = getfield_gc(p1, descr=valuedescr)
+        i4 = int_add(i1, i3)
+        label(p1, i4)
+        i5 = int_add(i4, 1)
+        jump(p1, i5)
+        """
+        expected = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i1, i2)
+        i4 = int_add(i1, i2)
+        label(p1, i4)
+        i5 = int_add(i4, 1)
+        jump(p1, i5)
+        """
+        short1 = """
+        [p1, i1]
+        label(p1, i1)
+        i2 = getfield_gc(p1, descr=valuedescr)
+        jump(p1, i1, i2)
+        """
+        short2 = """
+        [p1, i1]
+        label(p1, i1)
+        jump(p1, i1)
+        """
+        self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
+
+    def test_two_intermediate_labels_basic_2(self):
+        ops = """
+        [p1, i1]
+        i2 = int_add(i1, 1)
+        label(p1, i1)
+        i3 = getfield_gc(p1, descr=valuedescr)
+        i4 = int_add(i1, i3)
+        label(p1, i4)
+        i5 = getfield_gc(p1, descr=valuedescr)
+        i6 = int_add(i4, i5)
+        jump(p1, i6)
+        """
+        expected = """
+        [p1, i1]
+        i2 = int_add(i1, 1)
+        label(p1, i1)
+        i3 = getfield_gc(p1, descr=valuedescr)
+        i4 = int_add(i1, i3)
+        label(p1, i4, i3)
+        i6 = int_add(i4, i3)
+        jump(p1, i6, i3)
+        """
+        short1 = """
+        [p1, i1]
+        label(p1, i1)
+        jump(p1, i1)
+        """
+        short2 = """
+        [p1, i1]
+        label(p1, i1)
+        i2 = getfield_gc(p1, descr=valuedescr)
+        jump(p1, i1, i2)
+        """
+        self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
+
+    def test_two_intermediate_labels_both(self):
+        ops = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i1)
+        i3 = getfield_gc(p1, descr=valuedescr)
+        i4 = int_add(i1, i3)
+        label(p1, i4)
+        i5 = getfield_gc(p1, descr=valuedescr)
+        i6 = int_mul(i4, i5)
+        jump(p1, i6)
+        """
+        expected = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i1, i2)
+        i4 = int_add(i1, i2)
+        label(p1, i4, i2)
+        i6 = int_mul(i4, i2)
+        jump(p1, i6, i2)
+        """
+        short = """
+        [p1, i1]
+        label(p1, i1)
+        i2 = getfield_gc(p1, descr=valuedescr)        
+        jump(p1, i1, i2)
+        """
+        self.optimize_loop(ops, expected, expected_shorts=[short, short])
+
+    def test_import_across_multiple_labels_basic(self):
+        # Not supported, juts make sure we get a functional trace
+        ops = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i1)
+        i3 = int_add(i1, 1)
+        label(p1, i1)
+        i4 = getfield_gc(p1, descr=valuedescr)
+        i5 = int_add(i4, 1)
+        jump(p1, i5)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_import_across_multiple_labels_with_duplication(self):
+        # Not supported, juts make sure we get a functional trace
+        ops = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        label(p1, i2)
+        i3 = int_add(i2, 1)
+        label(p1, i2)
+        i4 = getfield_gc(p1, descr=valuedescr)
+        i5 = int_add(i4, 1)
+        jump(p1, i5)
+        """
+        exported = """
+        [p1, i1]
+        i2 = getfield_gc(p1, descr=valuedescr)
+        i6 = same_as(i2)
+        label(p1, i2)
+        i3 = int_add(i2, 1)
+        label(p1, i2)
+        i4 = getfield_gc(p1, descr=valuedescr)
+        i5 = int_add(i4, 1)
+        jump(p1, i5)
+        """
+        self.optimize_loop(ops, exported)
     
+    def test_import_virtual_across_multiple_labels(self):
+        ops = """
+        [p0, i1]
+        i1a = int_add(i1, 1)
+        pv = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(pv, i1a, descr=valuedescr)
+        label(pv, i1)
+        i2 = int_mul(i1, 3)
+        label(pv, i2)
+        i3 = getfield_gc(pv, descr=valuedescr)
+        i4 = int_add(i3, i2)
+        jump(pv, i4)
+        """
+        expected = """
+        [p0, i1]
+        i1a = int_add(i1, 1)
+        i5 = same_as(i1a)
+        label(i1a, i1)
+        i2 = int_mul(i1, 3)
+        label(i1a, i2)
+        i4 = int_add(i1a, i2)
+        jump(i1a, i4)
+        """
+        self.optimize_loop(ops, expected)
+
 class TestLLtype(BaseTestMultiLabel, LLtypeMixin):
     pass
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -4,7 +4,7 @@
     LLtypeMixin, BaseTest, Storage, _sortboxes, convert_old_style_to_targets)
 import pypy.jit.metainterp.optimizeopt.optimizer as optimizeopt
 import pypy.jit.metainterp.optimizeopt.virtualize as virtualize
-from pypy.jit.metainterp.optimizeopt import optimize_loop_1, ALL_OPTS_DICT, build_opt_chain
+from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT, build_opt_chain
 from pypy.jit.metainterp.optimize import InvalidLoop
 from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
 from pypy.jit.metainterp.history import TreeLoop, JitCellToken, TargetToken
@@ -4211,7 +4211,6 @@
         preamble = """
         [p0]
         i0 = strlen(p0)
-        i3 = same_as(i0) # Should be killed by backend        
         jump(p0)
         """
         expected = """
@@ -5668,8 +5667,7 @@
         p3 = newstr(i3)
         copystrcontent(p1, p3, 0, 0, i1)
         copystrcontent(p2, p3, 0, i1, i2)
-        i7 = same_as(i2)        
-        jump(p2, p3, i7)
+        jump(p2, p3, i2)
         """
         expected = """
         [p1, p2, i1]
@@ -5744,9 +5742,7 @@
         copystrcontent(p1, p5, 0, 0, i1)
         copystrcontent(p2, p5, 0, i1, i2)
         copystrcontent(p3, p5, 0, i12, i3)
-        i129 = same_as(i2)
-        i130 = same_as(i3)
-        jump(p2, p3, p5, i129, i130)
+        jump(p2, p3, p5, i2, i3)
         """
         expected = """
         [p1, p2, p3, i1, i2]
@@ -5959,8 +5955,7 @@
         p4 = newstr(i5)
         copystrcontent(p1, p4, i1, 0, i3)
         copystrcontent(p2, p4, 0, i3, i4)
-        i9 = same_as(i4)
-        jump(p4, i1, i2, p2, i5, i3, i9)
+        jump(p4, i1, i2, p2, i5, i3, i4)
         """
         expected = """
         [p1, i1, i2, p2, i5, i3, i4]
@@ -6082,9 +6077,7 @@
         copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
-        i11 = same_as(i1)
-        i12 = same_as(i2)
-        jump(p1, p2, p3, i3, i11, i12)
+        jump(p1, p2, p3, i3, i1, i2)
         """
         expected = """
         [p1, p2, p3, i3, i1, i2]
@@ -6304,7 +6297,6 @@
         i1 = strlen(p1)
         i0 = int_eq(i1, 0)
         escape(i0)
-        i3 = same_as(i1)        
         jump(p1, i0)
         """
         self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
@@ -6350,9 +6342,7 @@
         copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
         escape(i0)
-        i11 = same_as(i1)
-        i12 = same_as(i2)
-        jump(p1, p2, i3, i11, i12)
+        jump(p1, p2, i3, i1, i2)
         """
         expected = """
         [p1, p2, i3, i1, i2]
@@ -6925,8 +6915,7 @@
         [p9]
         i843 = strlen(p9)
         call(i843, descr=nonwritedescr)
-        i0 = same_as(i843)
-        jump(p9, i0)
+        jump(p9, i843)
         """
         short = """
         [p9]
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -430,18 +430,18 @@
 
         preamble = TreeLoop('preamble')
         preamble.inputargs = inputargs
-        preamble.start_resumedescr = FakeDescrWithSnapshot()
+        preamble.resume_at_jump_descr = FakeDescrWithSnapshot()
 
         token = JitCellToken() 
         preamble.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(token))] + \
                               operations +  \
-                              [ResOperation(rop.JUMP, jump_args, None, descr=token)]
+                              [ResOperation(rop.LABEL, jump_args, None, descr=token)]
         self._do_optimize_loop(preamble, call_pure_results)
 
         assert preamble.operations[-1].getopnum() == rop.LABEL
 
         inliner = Inliner(inputargs, jump_args)
-        loop.start_resumedescr = preamble.start_resumedescr
+        loop.resume_at_jump_descr = preamble.resume_at_jump_descr
         loop.operations = [preamble.operations[-1]] + \
                           [inliner.inline_op(op, clone=False) for op in cloned_operations] + \
                           [ResOperation(rop.JUMP, [inliner.inline_arg(a) for a in jump_args],
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
@@ -3,7 +3,7 @@
 from pypy.jit.metainterp.compile import ResumeGuardDescr
 from pypy.jit.metainterp.history import TreeLoop, TargetToken, JitCellToken
 from pypy.jit.metainterp.jitexc import JitException
-from pypy.jit.metainterp.optimize import InvalidLoop, RetraceLoop
+from pypy.jit.metainterp.optimize import InvalidLoop
 from pypy.jit.metainterp.optimizeopt.optimizer import *
 from pypy.jit.metainterp.optimizeopt.generalize import KillHugeIntBounds
 from pypy.jit.metainterp.inliner import Inliner
@@ -51,10 +51,10 @@
     distinction anymore)"""
 
     inline_short_preamble = True
-    did_import = False
     
     def __init__(self, metainterp_sd, loop, optimizations):
         self.optimizer = UnrollableOptimizer(metainterp_sd, loop, optimizations)
+        self.boxes_created_this_iteration = None
 
     def fix_snapshot(self, jump_args, snapshot):
         if snapshot is None:
@@ -71,7 +71,6 @@
         loop = self.optimizer.loop
         self.optimizer.clear_newoperations()
 
-
         start_label = loop.operations[0]
         if start_label.getopnum() == rop.LABEL:
             loop.operations = loop.operations[1:]
@@ -82,7 +81,7 @@
             start_label = None            
 
         jumpop = loop.operations[-1]
-        if jumpop.getopnum() == rop.JUMP:
+        if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL:
             loop.operations = loop.operations[:-1]
         else:
             jumpop = None
@@ -91,48 +90,87 @@
         self.optimizer.propagate_all_forward(clear=False)
 
         if not jumpop:
-            return 
-        if self.jump_to_already_compiled_trace(jumpop):
-            # Found a compiled trace to jump to
-            if self.did_import:
-
-                self.close_bridge(start_label)
-                self.finilize_short_preamble(start_label)
             return
 
         cell_token = jumpop.getdescr()
         assert isinstance(cell_token, JitCellToken)
         stop_label = ResOperation(rop.LABEL, jumpop.getarglist(), None, TargetToken(cell_token))
 
-        if not self.did_import: # Enforce the previous behaviour of always peeling  exactly one iteration (for now)
-            self.optimizer.flush()
-            KillHugeIntBounds(self.optimizer).apply()
+        
+        if jumpop.getopnum() == rop.JUMP:
+            if self.jump_to_already_compiled_trace(jumpop):
+                # Found a compiled trace to jump to
+                if self.short:
+                    # Construct our short preamble
+                    assert start_label
+                    self.close_bridge(start_label)
+                return
 
-            loop.operations = self.optimizer.get_newoperations()
-            self.export_state(stop_label)
-            loop.operations.append(stop_label)            
-        else:
-            assert stop_label
+            if start_label and self.jump_to_start_label(start_label, stop_label):
+                # Initial label matches, jump to it
+                jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None,
+                                      descr=start_label.getdescr())
+                if self.short:
+                    # Construct our short preamble
+                    self.close_loop(start_label, jumpop)
+                else:
+                    self.optimizer.send_extra_operation(jumpop)
+                return
+
+            if cell_token.target_tokens:
+                limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
+                if cell_token.retraced_count < limit:
+                    cell_token.retraced_count += 1
+                    debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit))
+                else:
+                    debug_print("Retrace count reached, jumping to preamble")
+                    assert cell_token.target_tokens[0].virtual_state is None
+                    jumpop.setdescr(cell_token.target_tokens[0])
+                    self.optimizer.send_extra_operation(jumpop)
+                    return
+
+        # Found nothing to jump to, emit a label instead
+        
+        if self.short:
+            # Construct our short preamble
             assert start_label
-            stop_target = stop_label.getdescr()
-            start_target = start_label.getdescr()
-            assert isinstance(stop_target, TargetToken)
-            assert isinstance(start_target, TargetToken)
-            assert stop_target.targeting_jitcell_token is start_target.targeting_jitcell_token
-            jumpop = ResOperation(rop.JUMP, stop_label.getarglist(), None, descr=start_label.getdescr())
+            self.close_bridge(start_label)
 
-            self.close_loop(jumpop)
-            self.finilize_short_preamble(start_label)
+        self.optimizer.flush()
+        KillHugeIntBounds(self.optimizer).apply()
+
+        loop.operations = self.optimizer.get_newoperations()
+        self.export_state(stop_label)
+        loop.operations.append(stop_label)
+
+    def jump_to_start_label(self, start_label, stop_label):
+        if not start_label or not stop_label:
+            return False
+        
+        stop_target = stop_label.getdescr()
+        start_target = start_label.getdescr()
+        assert isinstance(stop_target, TargetToken)
+        assert isinstance(start_target, TargetToken)
+        if stop_target.targeting_jitcell_token is not start_target.targeting_jitcell_token:
+            return False
+
+        return True
+
+        #args = stop_label.getarglist()
+        #modifier = VirtualStateAdder(self.optimizer)
+        #virtual_state = modifier.get_virtual_state(args)
+        #if self.initial_virtual_state.generalization_of(virtual_state):
+        #    return True
+        
 
     def export_state(self, targetop):
         original_jump_args = targetop.getarglist()
         jump_args = [self.getvalue(a).get_key_box() for a in original_jump_args]
 
-        assert self.optimizer.loop.start_resumedescr
-        start_resumedescr = self.optimizer.loop.start_resumedescr.clone_if_mutable()
-        assert isinstance(start_resumedescr, ResumeGuardDescr)
-        start_resumedescr.rd_snapshot = self.fix_snapshot(jump_args, start_resumedescr.rd_snapshot)
-        # FIXME: I dont thnik we need fix_snapshot anymore
+        assert self.optimizer.loop.resume_at_jump_descr
+        resume_at_jump_descr = self.optimizer.loop.resume_at_jump_descr.clone_if_mutable()
+        assert isinstance(resume_at_jump_descr, ResumeGuardDescr)
+        resume_at_jump_descr.rd_snapshot = self.fix_snapshot(jump_args, resume_at_jump_descr.rd_snapshot)
 
         modifier = VirtualStateAdder(self.optimizer)
         virtual_state = modifier.get_virtual_state(jump_args)
@@ -141,26 +179,21 @@
         inputargs = virtual_state.make_inputargs(values, self.optimizer)
         short_inputargs = virtual_state.make_inputargs(values, self.optimizer, keyboxes=True)
 
-        constant_inputargs = {}
-        for box in jump_args: 
-            const = self.get_constant_box(box)
-            if const:
-                constant_inputargs[box] = const
 
-        short_boxes = ShortBoxes(self.optimizer, inputargs + constant_inputargs.keys())
-        aliased_vrituals = {}
-        for i in range(len(original_jump_args)):
-            if original_jump_args[i] is not jump_args[i]:
-                if values[i].is_virtual():
-                    aliased_vrituals[original_jump_args[i]] = jump_args[i] 
-                else:
-                    short_boxes.alias(original_jump_args[i], jump_args[i])
+        if self.boxes_created_this_iteration is not None:
+            for box in self.inputargs:
+                self.boxes_created_this_iteration[box] = True
+
+        short_boxes = ShortBoxes(self.optimizer, inputargs,
+                                 self.boxes_created_this_iteration)
 
         self.optimizer.clear_newoperations()
-        for box in short_inputargs:
-            value = self.getvalue(box)
-            if value.is_virtual():
-                value.force_box(self.optimizer)
+        for i in range(len(original_jump_args)):
+            if values[i].is_virtual():
+                values[i].force_box(self.optimizer)
+            if original_jump_args[i] is not jump_args[i]:
+                op = ResOperation(rop.SAME_AS, [jump_args[i]], original_jump_args[i])
+                self.optimizer.emit_operation(op)
         inputarg_setup_ops = self.optimizer.get_newoperations()
 
         target_token = targetop.getdescr()
@@ -168,78 +201,76 @@
         targetop.initarglist(inputargs)
         target_token.virtual_state = virtual_state
         target_token.short_preamble = [ResOperation(rop.LABEL, short_inputargs, None)]
-        target_token.start_resumedescr = start_resumedescr
-        target_token.exported_state = ExportedState(constant_inputargs, short_boxes,
-                                                    inputarg_setup_ops, self.optimizer,
-                                                    aliased_vrituals, jump_args)
+        target_token.resume_at_jump_descr = resume_at_jump_descr
+
+        exported_values = {}
+        for box in inputargs:
+            exported_values[box] = self.optimizer.getvalue(box)
+        for op in short_boxes.operations():
+            if op and op.result:
+                box = op.result
+                exported_values[box] = self.optimizer.getvalue(box)
+            
+        target_token.exported_state = ExportedState(short_boxes, inputarg_setup_ops,
+                                                    exported_values)
 
     def import_state(self, targetop):
-        self.did_import = False
-        if not targetop:
-            # FIXME: Set up some sort of empty state with no virtuals?
+        if not targetop: # Trace did not start with a label
+            self.inputargs = self.optimizer.loop.inputargs
+            self.short = None
+            self.initial_virtual_state = None
             return
+
+        self.inputargs = targetop.getarglist()
         target_token = targetop.getdescr()
-        if not target_token:
-            return
         assert isinstance(target_token, TargetToken)
         exported_state = target_token.exported_state
         if not exported_state:
-            # FIXME: Set up some sort of empty state with no virtuals
+            # No state exported, construct one without virtuals
+            self.short = None
+            modifier = VirtualStateAdder(self.optimizer)
+            virtual_state = modifier.get_virtual_state(self.inputargs)
+            self.initial_virtual_state = virtual_state
             return
-        self.did_import = True
         
         self.short = target_token.short_preamble[:]
         self.short_seen = {}
-        self.short_boxes = exported_state.short_boxes.clone()
-        for box, const in exported_state.constant_inputargs.items():
-            self.short_seen[box] = True
-        self.imported_state = exported_state
-        self.inputargs = targetop.getarglist()
+        self.short_boxes = exported_state.short_boxes
+        self.short_resume_at_jump_descr = target_token.resume_at_jump_descr
         self.initial_virtual_state = target_token.virtual_state
-        self.start_resumedescr = target_token.start_resumedescr
 
         seen = {}
         for box in self.inputargs:
             if box in seen:
                 continue
             seen[box] = True
-            preamble_value = exported_state.optimizer.getvalue(box)
+            preamble_value = exported_state.exported_values[box]
             value = self.optimizer.getvalue(box)
             value.import_from(preamble_value, self.optimizer)
 
-        for newbox, oldbox in self.short_boxes.aliases.items():
-            self.optimizer.make_equal_to(newbox, self.optimizer.getvalue(oldbox))
-        
         # Setup the state of the new optimizer by emiting the
         # short operations and discarding the result
         self.optimizer.emitting_dissabled = True
         for op in exported_state.inputarg_setup_ops:
             self.optimizer.send_extra_operation(op)
+
         seen = {}
-        
         for op in self.short_boxes.operations():
             self.ensure_short_op_emitted(op, self.optimizer, seen)
             if op and op.result:
-                preamble_value = exported_state.optimizer.getvalue(op.result)
+                preamble_value = exported_state.exported_values[op.result]
                 value = self.optimizer.getvalue(op.result)
                 if not value.is_virtual():
                     imp = ValueImporter(self, preamble_value, op)
                     self.optimizer.importable_values[value] = imp
                 newvalue = self.optimizer.getvalue(op.result)
                 newresult = newvalue.get_key_box()
-                if newresult is not op.result and not newvalue.is_constant():
-                    self.short_boxes.alias(newresult, op.result)
-                    op = ResOperation(rop.SAME_AS, [op.result], newresult)
-                    self.optimizer._newoperations = [op] + self.optimizer._newoperations # XXX
-                    #self.optimizer.getvalue(op.result).box = op.result # FIXME: HACK!!!
+                assert newresult is op.result or newvalue.is_constant()
         self.optimizer.flush()
         self.optimizer.emitting_dissabled = False
 
-        for box, key_box in exported_state.aliased_vrituals.items():
-            self.optimizer.make_equal_to(box, self.getvalue(key_box))
-
     def close_bridge(self, start_label):
-        inputargs = self.inputargs        
+        inputargs = self.inputargs
         short_jumpargs = inputargs[:]
 
         # We dont need to inline the short preamble we are creating as we are conneting
@@ -249,8 +280,6 @@
         newoperations = self.optimizer.get_newoperations()
         self.boxes_created_this_iteration = {}
         i = 0
-        while newoperations[i].getopnum() != rop.LABEL:
-            i += 1
         while i < len(newoperations):
             op = newoperations[i]
             self.boxes_created_this_iteration[op.result] = True
@@ -262,11 +291,11 @@
             i += 1
             newoperations = self.optimizer.get_newoperations()
         self.short.append(ResOperation(rop.JUMP, short_jumpargs, None, descr=start_label.getdescr()))
-        
-    def close_loop(self, jumpop):
+        self.finilize_short_preamble(start_label)
+
+    def close_loop(self, start_label, jumpop):
         virtual_state = self.initial_virtual_state
         short_inputargs = self.short[0].getarglist()
-        constant_inputargs = self.imported_state.constant_inputargs
         inputargs = self.inputargs
         short_jumpargs = inputargs[:]
 
@@ -289,8 +318,6 @@
                     raise InvalidLoop
             args[short_inputargs[i]] = jmp_to_short_args[i]
         self.short_inliner = Inliner(short_inputargs, jmp_to_short_args)
-        for box, const in constant_inputargs.items():
-            self.short_inliner.argmap[box] = const
         for op in self.short[1:]:
             newop = self.short_inliner.inline_op(op)
             self.optimizer.send_extra_operation(newop)
@@ -299,8 +326,6 @@
         newoperations = self.optimizer.get_newoperations()
         self.boxes_created_this_iteration = {}
         i = j = 0
-        while newoperations[i].getopnum() != rop.LABEL:
-            i += 1
         while i < len(newoperations) or j < len(jumpargs):
             if i == len(newoperations):
                 while j < len(jumpargs):
@@ -353,6 +378,8 @@
             assert isinstance(target_token, TargetToken)
             target_token.targeting_jitcell_token.retraced_count = sys.maxint
             
+        self.finilize_short_preamble(start_label)
+            
     def finilize_short_preamble(self, start_label):
         short = self.short
         assert short[-1].getopnum() == rop.JUMP
@@ -365,7 +392,7 @@
             if op.is_guard():
                 op = op.clone()
                 op.setfailargs(None)
-                descr = target_token.start_resumedescr.clone_if_mutable()
+                descr = target_token.resume_at_jump_descr.clone_if_mutable()
                 op.setdescr(descr)
                 short[i] = op
 
@@ -381,13 +408,11 @@
                 newargs[i] = a.clonebox()
                 boxmap[a] = newargs[i]
         inliner = Inliner(short_inputargs, newargs)
-        for box, const in self.imported_state.constant_inputargs.items():
-            inliner.argmap[box] = const
         for i in range(len(short)):
             short[i] = inliner.inline_op(short[i])
 
-        target_token.start_resumedescr = self.start_resumedescr.clone_if_mutable()            
-        inliner.inline_descr_inplace(target_token.start_resumedescr)
+        target_token.resume_at_jump_descr = target_token.resume_at_jump_descr.clone_if_mutable()
+        inliner.inline_descr_inplace(target_token.resume_at_jump_descr)
 
         # Forget the values to allow them to be freed
         for box in short[0].getarglist():
@@ -398,31 +423,6 @@
         target_token.short_preamble = self.short
         target_token.exported_state = None
 
-        
-    def FIXME_old_stuff():
-            preamble_optimizer = self.optimizer
-            loop.preamble.quasi_immutable_deps = (
-                self.optimizer.quasi_immutable_deps)
-            self.optimizer = self.optimizer.new()
-            loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
-
-            
-            loop.inputargs = inputargs
-            args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box(preamble_optimizer)\
-                    for a in inputargs]
-            jmp = ResOperation(rop.JUMP, args, None)
-            jmp.setdescr(loop.token)
-            loop.preamble.operations.append(jmp)
-
-            loop.operations = self.optimizer.get_newoperations()
-            maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards
-            
-            if self.optimizer.emitted_guards > maxguards:
-                loop.preamble.token.retraced_count = sys.maxint
-
-            if short:
-                pass
-
     def ensure_short_op_emitted(self, op, optimizer, seen):
         if op is None:
             return
@@ -450,7 +450,7 @@
             if not isinstance(a, Const) and a not in self.short_seen:
                 self.add_op_to_short(self.short_boxes.producer(a), emit, guards_needed)
         if op.is_guard():
-            descr = self.start_resumedescr.clone_if_mutable()
+            descr = self.short_resume_at_jump_descr.clone_if_mutable()
             op.setdescr(descr)
 
         if guards_needed and self.short_boxes.has_producer(op.result):
@@ -549,7 +549,7 @@
 
                 for guard in extra_guards:
                     if guard.is_guard():
-                        descr = target.start_resumedescr.clone_if_mutable()
+                        descr = target.resume_at_jump_descr.clone_if_mutable()
                         inliner.inline_descr_inplace(descr)
                         guard.setdescr(descr)
                     self.optimizer.send_extra_operation(guard)
@@ -566,20 +566,7 @@
                     self.optimizer.send_extra_operation(jumpop)
                 return True
         debug_stop('jit-log-virtualstate')
-
-        if self.did_import:
-            return False
-        limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
-        if cell_token.retraced_count<limit:
-            cell_token.retraced_count += 1
-            debug_print('Retracing (%d/%d)' % (cell_token.retraced_count, limit))
-            return False
-        else:
-            debug_print("Retrace count reached, jumping to preamble")
-            assert cell_token.target_tokens[0].virtual_state is None
-            jumpop.setdescr(cell_token.target_tokens[0])
-            self.optimizer.send_extra_operation(jumpop)
-            return True
+        return False
 
 class ValueImporter(object):
     def __init__(self, unroll, value, op):
@@ -592,12 +579,7 @@
         self.unroll.add_op_to_short(self.op, False, True)        
 
 class ExportedState(object):
-    def __init__(self, constant_inputargs,
-                 short_boxes, inputarg_setup_ops, optimizer, aliased_vrituals,
-                 jump_args):
-        self.constant_inputargs = constant_inputargs
+    def __init__(self, short_boxes, inputarg_setup_ops, exported_values):
         self.short_boxes = short_boxes
         self.inputarg_setup_ops = inputarg_setup_ops
-        self.optimizer = optimizer
-        self.aliased_vrituals = aliased_vrituals
-        self.jump_args = jump_args
+        self.exported_values = exported_values
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -559,13 +559,13 @@
     pass
 
 class ShortBoxes(object):
-    def __init__(self, optimizer, surviving_boxes):
+    def __init__(self, optimizer, surviving_boxes, availible_boxes=None):
         self.potential_ops = {}
         self.alternatives = {}
         self.synthetic = {}
-        self.aliases = {}
         self.rename = {}
         self.optimizer = optimizer
+        self.availible_boxes = availible_boxes
 
         if surviving_boxes is not None:
             for box in surviving_boxes:
@@ -581,12 +581,9 @@
                 except BoxNotProducable:
                     pass
 
-    def clone(self):
-        sb = ShortBoxes(self.optimizer, None)
-        sb.aliases.update(self.aliases)
-        sb.short_boxes = {}
-        sb.short_boxes.update(self.short_boxes)
-        return sb
+            self.short_boxes_in_production = None # Not needed anymore
+        else:
+            self.short_boxes = {}
 
     def prioritized_alternatives(self, box):
         if box not in self.alternatives:
@@ -639,6 +636,8 @@
             return
         if box in self.short_boxes_in_production:
             raise BoxNotProducable
+        if self.availible_boxes is not None and box not in self.availible_boxes:
+            raise BoxNotProducable
         self.short_boxes_in_production[box] = True
         
         if box in self.potential_ops:
@@ -690,13 +689,3 @@
 
     def has_producer(self, box):
         return box in self.short_boxes
-
-    def alias(self, newbox, oldbox):
-        if not isinstance(oldbox, Const) and newbox not in self.short_boxes:
-            self.short_boxes[newbox] = self.short_boxes[oldbox]
-        self.aliases[newbox] = oldbox
-
-    def original(self, box):
-        while box in self.aliases:
-            box = self.aliases[box]
-        return box
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -44,7 +44,7 @@
 class __extend__(optimizer.OptValue):
     """New methods added to the base class OptValue for this file."""
 
-    def getstrlen(self, string_optimizer, mode):
+    def getstrlen(self, string_optimizer, mode, lengthbox):
         if mode is mode_string:
             s = self.get_constant_string_spec(mode_string)
             if s is not None:
@@ -57,7 +57,8 @@
             return None
         self.ensure_nonnull()
         box = self.force_box(string_optimizer)
-        lengthbox = BoxInt()
+        if lengthbox is None:
+            lengthbox = BoxInt()
         string_optimizer.emit_operation(ResOperation(mode.STRLEN, [box], lengthbox))
         return lengthbox
 
@@ -73,7 +74,7 @@
         # Copies the pointer-to-string 'self' into the target string
         # given by 'targetbox', at the specified offset.  Returns the offset
         # at the end of the copy.
-        lengthbox = self.getstrlen(string_optimizer, mode)
+        lengthbox = self.getstrlen(string_optimizer, mode, None)
         srcbox = self.force_box(string_optimizer)
         return copy_str_content(string_optimizer, srcbox, targetbox,
                                 CONST_0, offsetbox, lengthbox, mode)
@@ -102,7 +103,7 @@
                 return
         assert self.source_op is not None
         self.box = box = self.source_op.result
-        lengthbox = self.getstrlen(optforce, self.mode)
+        lengthbox = self.getstrlen(optforce, self.mode, None)
         op = ResOperation(self.mode.NEWSTR, [lengthbox], box)
         if not we_are_translated():
             op.name = 'FORCE'
@@ -135,7 +136,7 @@
         self._chars = longerlist[start:stop]
         # slice the 'longerlist', which may also contain Nones
 
-    def getstrlen(self, _, mode):
+    def getstrlen(self, _, mode, lengthbox):
         if self._lengthbox is None:
             self._lengthbox = ConstInt(len(self._chars))
         return self._lengthbox
@@ -216,12 +217,12 @@
         self.left = left
         self.right = right
 
-    def getstrlen(self, string_optimizer, mode):
+    def getstrlen(self, string_optimizer, mode, lengthbox):
         if self.lengthbox is None:
-            len1box = self.left.getstrlen(string_optimizer, mode)
+            len1box = self.left.getstrlen(string_optimizer, mode, None)
             if len1box is None:
                 return None
-            len2box = self.right.getstrlen(string_optimizer, mode)
+            len2box = self.right.getstrlen(string_optimizer, mode, None)
             if len2box is None:
                 return None
             self.lengthbox = _int_add(string_optimizer, len1box, len2box)
@@ -268,7 +269,7 @@
         self.vstart = vstart
         self.vlength = vlength
 
-    def getstrlen(self, optforce, mode):
+    def getstrlen(self, optforce, mode, lengthbox):
         return self.vlength.force_box(optforce)
 
     @specialize.arg(1)
@@ -285,7 +286,7 @@
         return None
 
     def string_copy_parts(self, string_optimizer, targetbox, offsetbox, mode):
-        lengthbox = self.getstrlen(string_optimizer, mode)
+        lengthbox = self.getstrlen(string_optimizer, mode, None)
         return copy_str_content(string_optimizer,
                                 self.vstr.force_box(string_optimizer), targetbox,
                                 self.vstart.force_box(string_optimizer), offsetbox,
@@ -360,7 +361,7 @@
     string_optimizer.emit_operation(ResOperation(rop.INT_SUB, [box1, box2], resbox))
     return resbox
 
-def _strgetitem(string_optimizer, strbox, indexbox, mode):
+def _strgetitem(string_optimizer, strbox, indexbox, mode, resbox=None):
     if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
         if mode is mode_string:
             s = strbox.getref(lltype.Ptr(rstr.STR))
@@ -368,7 +369,8 @@
         else:
             s = strbox.getref(lltype.Ptr(rstr.UNICODE))
             return ConstInt(ord(s.chars[indexbox.getint()]))
-    resbox = BoxInt()
+    if resbox is None:
+        resbox = BoxInt()
     string_optimizer.emit_operation(ResOperation(mode.STRGETITEM, [strbox, indexbox],
                                                  resbox))
     return resbox
@@ -434,10 +436,13 @@
     def _optimize_STRGETITEM(self, op, mode):
         value = self.getvalue(op.getarg(0))
         vindex = self.getvalue(op.getarg(1))
-        vresult = self.strgetitem(value, vindex, mode)
-        self.make_equal_to(op.result, vresult)
+        vresult = self.strgetitem(value, vindex, mode, op.result)
+        if op.result in self.optimizer.values:
+            assert self.getvalue(op.result) is vresult
+        else:
+            self.make_equal_to(op.result, vresult)
 
-    def strgetitem(self, value, vindex, mode):
+    def strgetitem(self, value, vindex, mode, resbox=None):
         value.ensure_nonnull()
         #
         if value.is_virtual() and isinstance(value, VStringSliceValue):
@@ -454,7 +459,7 @@
                     return result
         #
         if isinstance(value, VStringConcatValue) and vindex.is_constant():
-            len1box = value.left.getstrlen(self, mode)
+            len1box = value.left.getstrlen(self, mode, None)
             if isinstance(len1box, ConstInt):
                 index = vindex.box.getint()
                 len1 = len1box.getint()
@@ -464,7 +469,7 @@
                     vindex = optimizer.ConstantValue(ConstInt(index - len1))
                     return self.strgetitem(value.right, vindex, mode)
         #
-        resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode)
+        resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode, resbox)
         return self.getvalue(resbox)
 
     def optimize_STRLEN(self, op):
@@ -474,8 +479,11 @@
 
     def _optimize_STRLEN(self, op, mode):
         value = self.getvalue(op.getarg(0))
-        lengthbox = value.getstrlen(self, mode)
-        self.make_equal_to(op.result, self.getvalue(lengthbox))
+        lengthbox = value.getstrlen(self, mode, op.result)
+        if op.result in self.optimizer.values:
+            assert self.getvalue(op.result) is self.getvalue(lengthbox)
+        elif op.result is not lengthbox:
+            self.make_equal_to(op.result, self.getvalue(lengthbox))
 
     def optimize_COPYSTRCONTENT(self, op):
         self._optimize_COPYSTRCONTENT(op, mode_string)
@@ -594,8 +602,8 @@
         v1 = self.getvalue(op.getarg(1))
         v2 = self.getvalue(op.getarg(2))
         #
-        l1box = v1.getstrlen(None, mode)
-        l2box = v2.getstrlen(None, mode)
+        l1box = v1.getstrlen(None, mode, None)
+        l2box = v2.getstrlen(None, mode, None)
         if (l1box is not None and l2box is not None and
             isinstance(l1box, ConstInt) and
             isinstance(l2box, ConstInt) and
@@ -624,15 +632,15 @@
         return False
 
     def handle_str_equal_level1(self, v1, v2, resultbox, mode):
-        l2box = v2.getstrlen(None, mode)
+        l2box = v2.getstrlen(None, mode, None)
         if isinstance(l2box, ConstInt):
             if l2box.value == 0:
-                lengthbox = v1.getstrlen(self, mode)
+                lengthbox = v1.getstrlen(self, mode, None)
                 seo = self.optimizer.send_extra_operation
                 seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
                 return True
             if l2box.value == 1:
-                l1box = v1.getstrlen(None, mode)
+                l1box = v1.getstrlen(None, mode, None)
                 if isinstance(l1box, ConstInt) and l1box.value == 1:
                     # comparing two single chars
                     vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO, mode)
@@ -668,7 +676,7 @@
         return False
 
     def handle_str_equal_level2(self, v1, v2, resultbox, mode):
-        l2box = v2.getstrlen(None, mode)
+        l2box = v2.getstrlen(None, mode, None)
         if isinstance(l2box, ConstInt):
             if l2box.value == 1:
                 vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1548,11 +1548,6 @@
 
 # ____________________________________________________________
 
-class RetraceState(object):
-    def __init__(self, metainterp, live_arg_boxes):
-        self.merge_point = len(metainterp.current_merge_points) - 1
-        self.live_arg_boxes = live_arg_boxes
-
 class MetaInterp(object):
     in_recursion = 0
 
@@ -2062,7 +2057,7 @@
         cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
         return cell.get_procedure_token()
         
-    def compile_loop(self, original_boxes, live_arg_boxes, start, start_resumedescr):
+    def compile_loop(self, original_boxes, live_arg_boxes, start, resume_at_jump_descr):
         num_green_args = self.jitdriver_sd.num_green_args
         greenkey = original_boxes[:num_green_args]
         if not self.partial_trace:
@@ -2072,13 +2067,13 @@
             target_token = compile.compile_retrace(self, greenkey, start,
                                                    original_boxes[num_green_args:],
                                                    live_arg_boxes[num_green_args:],
-                                                   start_resumedescr, self.partial_trace,
+                                                   resume_at_jump_descr, self.partial_trace,
                                                    self.resumekey)
         else:
             target_token = compile.compile_loop(self, greenkey, start,
                                                 original_boxes[num_green_args:],
                                                 live_arg_boxes[num_green_args:],
-                                                start_resumedescr)
+                                                resume_at_jump_descr)
             if target_token is not None:
                 assert isinstance(target_token, TargetToken)
                 self.jitdriver_sd.warmstate.attach_procedure_to_interp(greenkey, target_token.targeting_jitcell_token)
@@ -2090,7 +2085,7 @@
             jitcell_token = target_token.targeting_jitcell_token
             self.raise_continue_running_normally(live_arg_boxes, jitcell_token)
 
-    def compile_trace(self, live_arg_boxes, start_resumedescr):
+    def compile_trace(self, live_arg_boxes, resume_at_jump_descr):
         num_green_args = self.jitdriver_sd.num_green_args
         greenkey = live_arg_boxes[:num_green_args]
         target_jitcell_token = self.get_procedure_token(greenkey)
@@ -2102,7 +2097,7 @@
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None,
                             descr=target_jitcell_token)
         try:
-            target_token = compile.compile_trace(self, self.resumekey, start_resumedescr)
+            target_token = compile.compile_trace(self, self.resumekey, resume_at_jump_descr)
         finally:
             self.history.operations.pop()     # remove the JUMP
         if target_token is not None: # raise if it *worked* correctly
@@ -2110,43 +2105,6 @@
             jitcell_token = target_token.targeting_jitcell_token
             self.raise_continue_running_normally(live_arg_boxes, jitcell_token)
 
-    def compile_bridge_and_loop(self, original_boxes, live_arg_boxes, start,
-                                bridge_arg_boxes, start_resumedescr):
-        num_green_args = self.jitdriver_sd.num_green_args
-        original_inputargs = self.history.inputargs
-        greenkey = original_boxes[:num_green_args]
-        old_loop_tokens = self.get_compiled_merge_points(greenkey)
-        original_operations = self.history.operations
-        self.history.inputargs = original_boxes[num_green_args:]
-        greenkey = original_boxes[:num_green_args]
-        self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
-        loop_token = compile.compile_new_loop(self, [], greenkey, start,
-                                              start_resumedescr, False)
-        self.history.operations.pop()     # remove the JUMP
-        if loop_token is None:
-            self.history.inputargs = original_inputargs
-            self.history.operations = original_operations
-            return
-
-        if loop_token.short_preamble:
-            old_loop_tokens[0].short_preamble.extend(loop_token.short_preamble)
-
-        self.history.inputargs = original_inputargs
-        self.history.operations = self.history.operations[:start]
-
-        self.history.record(rop.JUMP, bridge_arg_boxes[num_green_args:], None)
-        try:
-            target_loop_token = compile.compile_new_bridge(self,
-                                                           #[loop_token],
-                                                           old_loop_tokens,
-                                                           self.resumekey,
-                                                           True)
-        except RetraceLoop:
-            assert False
-        assert target_loop_token is not None
-        self.raise_continue_running_normally(live_arg_boxes,
-                                             old_loop_tokens[0])
-
     def compile_done_with_this_frame(self, exitbox):
         self.gen_store_back_in_virtualizable()
         # temporarily put a JUMP to a pseudo-loop
diff --git a/pypy/jit/metainterp/test/test_virtualstate.py b/pypy/jit/metainterp/test/test_virtualstate.py
--- a/pypy/jit/metainterp/test/test_virtualstate.py
+++ b/pypy/jit/metainterp/test/test_virtualstate.py
@@ -11,7 +11,6 @@
 from pypy.jit.metainterp.optimizeopt.intutils import IntBound
 from pypy.jit.metainterp.history import TreeLoop, JitCellToken
 from pypy.jit.metainterp.optimizeopt.test.test_optimizeopt import FakeMetaInterpStaticData
-from pypy.jit.metainterp.optimize import RetraceLoop
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 
 class TestBasic:
@@ -449,7 +448,7 @@
         if hasattr(self, 'callinfocollection'):
             metainterp_sd.callinfocollection = self.callinfocollection
         #
-        bridge.start_resumedescr = FakeDescrWithSnapshot()
+        bridge.resume_at_jump_descr = FakeDescrWithSnapshot()
         optimize_trace(metainterp_sd, bridge, self.enable_opts)
 
         


More information about the pypy-commit mailing list