[pypy-commit] pypy default: Merged in optimizeopt-cleanup (pull request #646)

rlamy pypy.commits at gmail.com
Tue Jun 4 15:25:55 EDT 2019


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: 
Changeset: r96739:4ab755b28b85
Date: 2019-06-04 19:25 +0000
http://bitbucket.org/pypy/pypy/changeset/4ab755b28b85/

Log:	Merged in optimizeopt-cleanup (pull request #646)

	Optimizeopt cleanup

diff too long, truncating to 2000 out of 6785 lines

diff --git a/rpython/doc/jit/optimizer.rst b/rpython/doc/jit/optimizer.rst
--- a/rpython/doc/jit/optimizer.rst
+++ b/rpython/doc/jit/optimizer.rst
@@ -13,7 +13,7 @@
 
 Before some optimizations are explained in more detail, it is essential to
 understand how traces look like.
-The optimizer comes with a test suit. It contains many trace
+The optimizer comes with a test suite. It contains many trace
 examples and you might want to take a look at it
 (in `rpython/jit/metainterp/optimizeopt/test/*.py`).
 The allowed operations can be found in `rpython/jit/metainterp/resoperation.py`.
@@ -21,7 +21,7 @@
 
     [p0,i0,i1]
     label(p0, i0, i1)
-    i2 = getarray_item_raw(p0, i0, descr=<Array Signed>)
+    i2 = getarrayitem_raw(p0, i0, descr=<Array Signed>)
     i3 = int_add(i1,i2)
     i4 = int_add(i0,1)
     i5 = int_le(i4, 100) # lower-or-equal
@@ -32,7 +32,7 @@
 to compare the Python code that constructed the trace::
 
     from array import array
-    a = array('i',range(101))
+    a = array('i', range(101))
     sum = 0; i = 0
     while i <= 100: # can be seen as label
         sum += a[i]
@@ -131,20 +131,16 @@
 
 Whenever such an operation is encountered (e.g. ``y = x & 0``), no operation is
 emitted. Instead the variable y is made equal to 0
-(= ``make_equal_to(op.result, 0)``). The variables found in a trace are
-instances of Box classes that can be found in
-`rpython/jit/metainterp/history.py`. `OptValue` wraps those variables again
-and maps the boxes to the optimization values in the optimizer. When a
-value is made equal, the two variable's boxes are made to point to the same
-`OptValue` instance.
+(= ``make_constant_int(op, 0)``). The variables found in a trace are instances
+of classes that can be found in `rpython/jit/metainterp/history.py`. When a
+value is made equal to another, its box is made to point to the other one.
 
-**NOTE: this OptValue organization is currently being refactored in a branch.**
 
 Pure optimization
 -----------------
 
-Is interwoven into the basic optimizer. It saves operations, results,
-arguments to be known to have pure semantics.
+The 'pure' optimizations interwoven into the basic optimizer. It saves
+operations, results, arguments to be known to have pure semantics.
 
 "Pure" here means the same as the ``jit.elidable`` decorator:
 free of "observable" side effects and referentially transparent
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -3,23 +3,22 @@
 from rpython.rtyper.annlowlevel import (
     cast_instance_to_gcref, cast_gcref_to_instance)
 from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.debug import debug_start, debug_stop, debug_print, have_debug_prints
+from rpython.rlib.debug import (
+    debug_start, debug_stop, debug_print, have_debug_prints)
 from rpython.rlib.rarithmetic import r_uint, intmask
 from rpython.rlib import rstack
 from rpython.rlib.jit import JitDebugInfo, Counters, dont_look_inside
 from rpython.rlib.rjitlog import rjitlog as jl
-from rpython.rlib.objectmodel import compute_unique_id
-from rpython.conftest import option
 
-from rpython.jit.metainterp.resoperation import ResOperation, rop,\
-     get_deep_immutable_oplist, OpHelpers, InputArgInt, InputArgRef,\
-     InputArgFloat
-from rpython.jit.metainterp.history import (TreeLoop, Const, JitCellToken,
+from rpython.jit.metainterp.resoperation import (
+    ResOperation, rop, get_deep_immutable_oplist, OpHelpers, InputArgInt,
+    InputArgRef, InputArgFloat)
+from rpython.jit.metainterp.history import (TreeLoop, JitCellToken,
     TargetToken, AbstractFailDescr, ConstInt)
 from rpython.jit.metainterp import history, jitexc
 from rpython.jit.metainterp.optimize import InvalidLoop
-from rpython.jit.metainterp.resume import (PENDINGFIELDSP,
-        ResumeDataDirectReader, AccumInfo)
+from rpython.jit.metainterp.resume import (
+    PENDINGFIELDSP, ResumeDataDirectReader)
 from rpython.jit.metainterp.resumecode import NUMBERING
 from rpython.jit.metainterp.support import adr2int
 from rpython.jit.codewriter import longlong
@@ -30,6 +29,9 @@
     raise SwitchToBlackhole(Counters.ABORT_BRIDGE)
 
 class CompileData(object):
+    """ An object that accumulates all of the necessary info for
+    the optimization phase, but does not actually have any other state
+    """
     memo = None
     log_noopt = True
 
@@ -37,10 +39,28 @@
         for arg in self.trace.inputargs:
             arg.set_forwarded(None)
 
-class LoopCompileData(CompileData):
-    """ An object that accumulates all of the necessary info for
-    the optimization phase, but does not actually have any other state
+    def optimize_trace(self, metainterp_sd, jitdriver_sd, memo):
+        """Optimize loop.operations to remove internal overheadish operations.
+        """
+        from rpython.jit.metainterp.optimizeopt import build_opt_chain
+        # mark that a new trace has been started
+        log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None)
+        log.write_trace(self.trace)
+        if self.log_noopt:
+            metainterp_sd.logger_noopt.log_loop_from_trace(self.trace, memo=memo)
 
+        self.box_names_memo = memo
+        optimizations = build_opt_chain(self.enable_opts)
+        debug_start("jit-optimize")
+        try:
+            return self.optimize(metainterp_sd, jitdriver_sd, optimizations)
+        finally:
+            self.forget_optimization_info()
+            debug_stop("jit-optimize")
+
+
+class PreambleCompileData(CompileData):
+    """
     This is the case of label() ops label()
     """
     def __init__(self, trace, runtime_boxes, call_pure_results=None,
@@ -51,19 +71,12 @@
         assert runtime_boxes is not None
         self.runtime_boxes = runtime_boxes
 
-    def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
-        from rpython.jit.metainterp.optimizeopt.unroll import (UnrollOptimizer,
-                                                               Optimizer)
-
-        if unroll:
-            opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
-            return opt.optimize_preamble(self.trace,
-                                         self.runtime_boxes,
-                                         self.call_pure_results,
-                                         self.box_names_memo)
-        else:
-            opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations)
-            return opt.propagate_all_forward(self.trace, self.call_pure_results)
+    def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
+        from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
+        opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
+        return opt.optimize_preamble(
+            self.trace, self.runtime_boxes, self.call_pure_results,
+            self.box_names_memo)
 
 class SimpleCompileData(CompileData):
     """ This represents label() ops jump with no extra info associated with
@@ -76,26 +89,19 @@
         self.call_pure_results = call_pure_results
         self.enable_opts = enable_opts
 
-    def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+    def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
         from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
-        from rpython.jit.metainterp.optimizeopt.bridgeopt import deserialize_optimizer_knowledge
-
-        #assert not unroll
         opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations)
-        traceiter = self.trace.get_iter()
-        if self.resumestorage:
-            frontend_inputargs = self.trace.inputargs
-            deserialize_optimizer_knowledge(opt, self.resumestorage,
-                                            frontend_inputargs,
-                                            traceiter.inputargs)
-        return opt.propagate_all_forward(traceiter, self.call_pure_results)
+        return opt.optimize_loop(
+            self.trace, self.resumestorage, self.call_pure_results)
 
 class BridgeCompileData(CompileData):
     """ This represents ops() with a jump at the end that goes to some
     loop, we need to deal with virtual state and inlining of short preamble
     """
-    def __init__(self, trace, runtime_boxes, resumestorage=None, call_pure_results=None,
-                 enable_opts=None, inline_short_preamble=False):
+    def __init__(self, trace, runtime_boxes, resumestorage=None,
+                 call_pure_results=None, enable_opts=None,
+                 inline_short_preamble=False):
         self.trace = trace
         self.runtime_boxes = runtime_boxes
         self.call_pure_results = call_pure_results
@@ -103,7 +109,7 @@
         self.inline_short_preamble = inline_short_preamble
         self.resumestorage = resumestorage
 
-    def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+    def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
         from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
 
         opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
@@ -115,29 +121,26 @@
 
 class UnrolledLoopData(CompileData):
     """ This represents label() ops jump with extra info that's from the
-    run of LoopCompileData. Jump goes to the same label
+    run of PreambleCompileData. Jump goes to the same label
     """
     log_noopt = False
 
     def __init__(self, trace, celltoken, state,
-                 call_pure_results=None, enable_opts=None,
-                 inline_short_preamble=True):
+                 call_pure_results=None, enable_opts=None):
         self.trace = trace
         self.celltoken = celltoken
         self.enable_opts = enable_opts
         self.state = state
         self.call_pure_results = call_pure_results
-        self.inline_short_preamble = inline_short_preamble
 
-    def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+    def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
         from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
-
-        assert unroll # we should not be here if it's disabled
         opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
-        return opt.optimize_peeled_loop(self.trace, self.celltoken, self.state,
-            self.call_pure_results, self.inline_short_preamble)
+        return opt.optimize_peeled_loop(
+            self.trace, self.celltoken, self.state, self.call_pure_results)
 
 def show_procedures(metainterp_sd, procedure=None, error=None):
+    from rpython.conftest import option
     # debugging
     if option and (option.view or option.viewloops):
         if error:
@@ -173,19 +176,14 @@
     original_jitcell_token = loop.original_jitcell_token
     assert original_jitcell_token is not None
     if metainterp_sd.warmrunnerdesc is not None:    # for tests
-        assert original_jitcell_token.generation > 0     # has been registered with memmgr
+        assert original_jitcell_token.generation > 0  # has been registered with memmgr
     wref = weakref.ref(original_jitcell_token)
     clt = original_jitcell_token.compiled_loop_token
     clt.loop_token_wref = wref
     for op in loop.operations:
         descr = op.getdescr()
-        # not sure what descr.index is about
         if isinstance(descr, ResumeDescr):
             descr.rd_loop_token = clt   # stick it there
-            #n = descr.index
-            #if n >= 0:       # we also record the resumedescr number
-            #    original_jitcell_token.compiled_loop_token.record_faildescr_index(n)
-        #    pass
         if isinstance(descr, JitCellToken):
             # for a CALL_ASSEMBLER: record it as a potential jump.
             if descr is not original_jitcell_token:
@@ -215,11 +213,8 @@
 
 # ____________________________________________________________
 
-
 def compile_simple_loop(metainterp, greenkey, trace, runtime_args, enable_opts,
                         cut_at):
-    from rpython.jit.metainterp.optimizeopt import optimize_trace
-
     jitdriver_sd = metainterp.jitdriver_sd
     metainterp_sd = metainterp.staticdata
     jitcell_token = make_jitcell_token(jitdriver_sd)
@@ -227,8 +222,8 @@
     data = SimpleCompileData(trace, call_pure_results=call_pure_results,
                              enable_opts=enable_opts)
     try:
-        loop_info, ops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                        data, metainterp.box_names_memo)
+        loop_info, ops = data.optimize_trace(
+            metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
     except InvalidLoop:
         metainterp_sd.jitlog.trace_aborted()
         trace.cut_at(cut_at)
@@ -253,12 +248,10 @@
     return target_token
 
 def compile_loop(metainterp, greenkey, start, inputargs, jumpargs,
-                 full_preamble_needed=True, try_disabling_unroll=False):
+                 use_unroll=True):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
-    from rpython.jit.metainterp.optimizeopt import optimize_trace
-
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
     history = metainterp.history
@@ -269,28 +262,21 @@
             faildescr=None, entry_bridge=False)
     #
     enable_opts = jitdriver_sd.warmstate.enable_opts
-    if try_disabling_unroll:
-        if 'unroll' not in enable_opts:
-            return None
-        enable_opts = enable_opts.copy()
-        del enable_opts['unroll']
-
     jitcell_token = make_jitcell_token(jitdriver_sd)
     cut_at = history.get_trace_position()
     history.record(rop.JUMP, jumpargs, None, descr=jitcell_token)
     if start != (0, 0, 0):
         trace = trace.cut_trace_from(start, inputargs)
-    if 'unroll' not in enable_opts or not metainterp.cpu.supports_guard_gc_type:
+    if not use_unroll:
         return compile_simple_loop(metainterp, greenkey, trace, jumpargs,
                                    enable_opts, cut_at)
     call_pure_results = metainterp.call_pure_results
-    preamble_data = LoopCompileData(trace, jumpargs,
+    preamble_data = PreambleCompileData(trace, jumpargs,
                                     call_pure_results=call_pure_results,
                                     enable_opts=enable_opts)
     try:
-        start_state, preamble_ops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                                   preamble_data,
-                                                   metainterp.box_names_memo)
+        start_state, preamble_ops = preamble_data.optimize_trace(
+            metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
     except InvalidLoop:
         metainterp_sd.jitlog.trace_aborted()
         history.cut(cut_at)
@@ -305,9 +291,8 @@
                                  call_pure_results=call_pure_results,
                                  enable_opts=enable_opts)
     try:
-        loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                             loop_data,
-                                             metainterp.box_names_memo)
+        loop_info, loop_ops = loop_data.optimize_trace(
+            metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
     except InvalidLoop:
         metainterp_sd.jitlog.trace_aborted()
         history.cut(cut_at)
@@ -354,8 +339,6 @@
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
-    from rpython.jit.metainterp.optimizeopt import optimize_trace
-
     trace = metainterp.history.trace.cut_trace_from(start, inputargs)
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
@@ -375,29 +358,14 @@
                                  call_pure_results=call_pure_results,
                                  enable_opts=enable_opts)
     try:
-        loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                             loop_data,
-                                             metainterp.box_names_memo)
+        loop_info, loop_ops = loop_data.optimize_trace(
+            metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
     except InvalidLoop:
-        # Fall back on jumping directly to preamble
+        metainterp_sd.jitlog.trace_aborted()
         history.cut(cut)
-        history.record(rop.JUMP, jumpargs[:], None, descr=loop_jitcell_token)
-        loop_data = UnrolledLoopData(trace, loop_jitcell_token, start_state,
-                                     call_pure_results=call_pure_results,
-                                     enable_opts=enable_opts,
-                                     inline_short_preamble=False)
-        try:
-            loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                                 loop_data,
-                                                 metainterp.box_names_memo)
-        except InvalidLoop:
-            metainterp_sd.jitlog.trace_aborted()
-            history.cut(cut)
-            return None
+        return None
 
     label_op = loop_info.label_op
-    if label_op is None:
-        assert False, "unreachable code" # hint for some strange tests
     label_token = label_op.getdescr()
     assert isinstance(label_token, TargetToken)
     if label_token.short_preamble:
@@ -405,9 +373,8 @@
             label_token.short_preamble, metainterp.box_names_memo)
     loop = partial_trace
     loop.original_jitcell_token = loop_jitcell_token
-    loop.operations = (loop.operations + loop_info.extra_same_as +
-                       [loop_info.label_op]
-                       + loop_ops)
+    loop.operations = (
+        loop.operations + loop_info.extra_same_as + [label_op] + loop_ops)
 
     quasi_immutable_deps = {}
     if loop_info.quasi_immutable_deps:
@@ -419,8 +386,6 @@
 
     target_token = loop.operations[-1].getdescr()
     resumekey.compile_and_attach(metainterp, loop, inputargs)
-
-    record_loop_or_bridge(metainterp_sd, loop)
     return target_token
 
 def get_box_replacement(op, allow_none=False):
@@ -828,6 +793,7 @@
                                self, inputargs, new_loop.operations,
                                new_loop.original_jitcell_token,
                                metainterp.box_names_memo)
+        record_loop_or_bridge(metainterp.staticdata, new_loop)
 
     def make_a_counter_per_value(self, guard_value_op, index):
         assert guard_value_op.getopnum() == rop.GUARD_VALUE
@@ -1038,18 +1004,16 @@
         jitdriver_sd.warmstate.attach_procedure_to_interp(
             self.original_greenkey, jitcell_token)
         metainterp_sd.stats.add_jitcell_token(jitcell_token)
+        record_loop_or_bridge(metainterp_sd, new_loop)
 
     def get_resumestorage(self):
         return None
 
 
-def compile_trace(metainterp, resumekey, runtime_boxes):
+def compile_trace(metainterp, resumekey, runtime_boxes, ends_with_jump=False):
     """Try to compile a new bridge leading from the beginning of the history
     to some existing place.
     """
-
-    from rpython.jit.metainterp.optimizeopt import optimize_trace
-
     # The history contains new operations to attach as the code for the
     # failure of 'resumekey.guard_op'.
     #
@@ -1058,11 +1022,6 @@
 
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
-    #
-    jd_name = jitdriver_sd.jitdriver.name
-    metainterp_sd.jitlog.start_new_trace(metainterp_sd,
-            faildescr=resumekey, entry_bridge=False, jd_name=jd_name)
-    #
     if isinstance(resumekey, ResumeAtPositionDescr):
         inline_short_preamble = False
     else:
@@ -1071,11 +1030,15 @@
     trace = metainterp.history.trace
     jitdriver_sd = metainterp.jitdriver_sd
     enable_opts = jitdriver_sd.warmstate.enable_opts
-
     call_pure_results = metainterp.call_pure_results
     resumestorage = resumekey.get_resumestorage()
 
-    if metainterp.history.ends_with_jump:
+    trace.tracing_done()
+    metainterp_sd.jitlog.start_new_trace(metainterp_sd,
+        faildescr=resumekey, entry_bridge=False,
+        jd_name=jitdriver_sd.jitdriver.name)
+
+    if ends_with_jump:
         data = BridgeCompileData(trace, runtime_boxes, resumestorage,
                                  call_pure_results=call_pure_results,
                                  enable_opts=enable_opts,
@@ -1085,12 +1048,10 @@
                                  call_pure_results=call_pure_results,
                                  enable_opts=enable_opts)
     try:
-        info, newops = optimize_trace(metainterp_sd, jitdriver_sd,
-                                      data, metainterp.box_names_memo)
+        info, newops = data.optimize_trace(
+            metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
     except InvalidLoop:
         metainterp_sd.jitlog.trace_aborted()
-        #pdb.post_mortem(sys.exc_info()[2])
-        debug_print("compile_new_bridge: got an InvalidLoop")
         # XXX I am fairly convinced that optimize_bridge cannot actually raise
         # InvalidLoop
         debug_print('InvalidLoop in compile_new_bridge')
@@ -1104,7 +1065,6 @@
         new_trace.inputargs = info.inputargs
         target_token = new_trace.operations[-1].getdescr()
         resumekey.compile_and_attach(metainterp, new_trace, inputargs)
-        record_loop_or_bridge(metainterp_sd, new_trace)
         return target_token
     new_trace.inputargs = info.renamed_inputargs
     metainterp.retrace_needed(new_trace, info)
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -689,7 +689,6 @@
 
 
 class History(object):
-    ends_with_jump = False
     trace = None
 
     def __init__(self):
diff --git a/rpython/jit/metainterp/opencoder.py b/rpython/jit/metainterp/opencoder.py
--- a/rpython/jit/metainterp/opencoder.py
+++ b/rpython/jit/metainterp/opencoder.py
@@ -7,12 +7,13 @@
 """
 
 from rpython.jit.metainterp.history import (
-    ConstInt, Const, ConstFloat, ConstPtr, new_ref_dict)
+    ConstInt, Const, ConstFloat, ConstPtr, new_ref_dict, SwitchToBlackhole)
 from rpython.jit.metainterp.resoperation import AbstractResOp, AbstractInputArg,\
     ResOperation, oparity, rop, opwithdescr, GuardResOp, IntOp, FloatOp, RefOp,\
     opclasses
 from rpython.rlib.rarithmetic import intmask, r_uint
 from rpython.rlib.objectmodel import we_are_translated, specialize
+from rpython.rlib.jit import Counters
 from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
 
 TAGINT, TAGCONSTPTR, TAGCONSTOTHER, TAGBOX = range(4)
@@ -301,7 +302,8 @@
 
     def tracing_done(self):
         from rpython.rlib.debug import debug_start, debug_stop, debug_print
-        assert not self.tag_overflow
+        if self.tag_overflow:
+            raise SwitchToBlackhole(Counters.ABORT_TOO_LONG)
 
         self._bigints_dict = {}
         self._refs_dict = new_ref_dict()
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -1,4 +1,3 @@
-from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
 from rpython.jit.metainterp.optimizeopt.rewrite import OptRewrite
 from rpython.jit.metainterp.optimizeopt.intbounds import OptIntBounds
 from rpython.jit.metainterp.optimizeopt.virtualize import OptVirtualize
@@ -7,10 +6,8 @@
 from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify
 from rpython.jit.metainterp.optimizeopt.pure import OptPure
 from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce
-from rpython.rlib.rjitlog import rjitlog as jl
 from rpython.rlib.jit import PARAMETERS, ENABLE_ALL_OPTS
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.debug import debug_start, debug_stop, debug_print
 
 
 ALL_OPTS = [('intbounds', OptIntBounds),
@@ -31,45 +28,17 @@
 assert ENABLE_ALL_OPTS == ALL_OPTS_NAMES, (
     'please fix rlib/jit.py to say ENABLE_ALL_OPTS = %r' % (ALL_OPTS_NAMES,))
 
-def build_opt_chain(metainterp_sd, enable_opts):
+def build_opt_chain(enable_opts):
     optimizations = []
-    unroll = 'unroll' in enable_opts    # 'enable_opts' is normally a dict
-    if (metainterp_sd.cpu is not None and
-        not metainterp_sd.cpu.supports_guard_gc_type):
-        unroll = False
     for name, opt in unroll_all_opts:
         if name in enable_opts:
             if opt is not None:
                 o = opt()
                 optimizations.append(o)
-
-    if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts
-        or 'heap' not in enable_opts or 'pure' not in enable_opts):
-        optimizations.append(OptSimplify(unroll))
-
-    return optimizations, unroll
-
-def optimize_trace(metainterp_sd, jitdriver_sd, compile_data, memo=None):
-    """Optimize loop.operations to remove internal overheadish operations.
-    """
-    debug_start("jit-optimize")
-    try:
-        # mark that a new trace has been started
-        log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None)
-        log.write_trace(compile_data.trace)
-        if compile_data.log_noopt:
-            metainterp_sd.logger_noopt.log_loop_from_trace(compile_data.trace, memo=memo)
-        if memo is None:
-            memo = {}
-        compile_data.box_names_memo = memo
-        optimizations, unroll = build_opt_chain(metainterp_sd,
-                                                compile_data.enable_opts)
-        return compile_data.optimize(metainterp_sd, jitdriver_sd,
-                                     optimizations, unroll)
-    finally:
-        compile_data.forget_optimization_info()
-        debug_stop("jit-optimize")
+    if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts or
+            'heap' not in enable_opts or 'pure' not in enable_opts):
+        optimizations.append(OptSimplify())
+    return optimizations
 
 if __name__ == '__main__':
     print ALL_OPTS_NAMES
-
diff --git a/rpython/jit/metainterp/optimizeopt/bridgeopt.py b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
--- a/rpython/jit/metainterp/optimizeopt/bridgeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
@@ -3,6 +3,7 @@
 
 from rpython.jit.metainterp import resumecode
 from rpython.jit.metainterp.history import Const, ConstInt, CONST_NULL
+from .info import getptrinfo
 
 
 # adds the following sections at the end of the resume code:
@@ -75,7 +76,7 @@
     for box in liveboxes:
         if box is None or box.type != "r":
             continue
-        info = optimizer.getptrinfo(box)
+        info = getptrinfo(box)
         known_class = info is not None and info.get_known_class(optimizer.cpu) is not None
         bitfield <<= 1
         bitfield |= known_class
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -1,26 +1,19 @@
-import os
 from collections import OrderedDict
 
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.optimizeopt.util import args_dict
-from rpython.jit.metainterp.history import Const, ConstInt, new_ref_dict
-from rpython.jit.metainterp.jitexc import JitException
+from rpython.jit.metainterp.history import new_ref_dict
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimizeopt.util import (
+    make_dispatcher_method, get_box_replacement)
 from rpython.jit.metainterp.optimizeopt.intutils import IntBound
 from rpython.jit.metainterp.optimizeopt.shortpreamble import PreambleOp
 from rpython.jit.metainterp.optimize import InvalidLoop
-from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers,\
-     GuardResOp
+from rpython.jit.metainterp.resoperation import rop
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.jit.metainterp.optimizeopt import info
 
 
-
-class BogusImmutableField(JitException):
-    pass
-
-
 class AbstractCachedEntry(object):
     """ abstract base class abstracting over the difference between caching
     struct fields and array items. """
@@ -56,40 +49,32 @@
                                              descr, index=-1):
         assert self._lazy_set is None
         for i, info in enumerate(self.cached_infos):
-            structbox = optimizer.get_box_replacement(self.cached_structs[i])
+            structbox = get_box_replacement(self.cached_structs[i])
             info.produce_short_preamble_ops(structbox, descr, index, optimizer,
                                             shortboxes)
 
-    def possible_aliasing(self, optheap, opinfo):
+    def possible_aliasing(self, opinfo):
         # If lazy_set is set and contains a setfield on a different
         # structvalue, then we are annoyed, because it may point to either
         # the same or a different structure at runtime.
         # XXX constants?
         return (self._lazy_set is not None
-                and (not optheap.getptrinfo(
-                    self._lazy_set.getarg(0)).same_info(opinfo)))
+            and not info.getptrinfo(self._lazy_set.getarg(0)).same_info(opinfo))
 
     def do_setfield(self, optheap, op):
         # Update the state with the SETFIELD_GC/SETARRAYITEM_GC operation 'op'.
         structinfo = optheap.ensure_ptr_info_arg0(op)
-        arg1 = optheap.get_box_replacement(self._get_rhs_from_set_op(op))
-        if self.possible_aliasing(optheap, structinfo):
+        arg1 = get_box_replacement(self._get_rhs_from_set_op(op))
+        if self.possible_aliasing(structinfo):
             self.force_lazy_set(optheap, op.getdescr())
-            assert not self.possible_aliasing(optheap, structinfo)
+            assert not self.possible_aliasing(structinfo)
         cached_field = self._getfield(structinfo, op.getdescr(), optheap, False)
         if cached_field is not None:
-            cached_field = optheap.get_box_replacement(cached_field)
-
-        # Hack to ensure constants are imported from the preamble
-        # XXX no longer necessary?
-        #if cached_fieldvalue and fieldvalue.is_constant():
-        #    optheap.optimizer.ensure_imported(cached_fieldvalue)
-        #    cached_fieldvalue = self._cached_fields.get(structvalue, None)
+            cached_field = cached_field.get_box_replacement()
 
         if not cached_field or not cached_field.same_box(arg1):
             # common case: store the 'op' as lazy_set
             self._lazy_set = op
-
         else:
             # this is the case where the pending setfield ends up
             # storing precisely the value that is already there,
@@ -104,11 +89,11 @@
 
     def getfield_from_cache(self, optheap, opinfo, descr):
         # Returns the up-to-date field's value, or None if not cached.
-        if self.possible_aliasing(optheap, opinfo):
+        if self.possible_aliasing(opinfo):
             self.force_lazy_set(optheap, descr)
         if self._lazy_set is not None:
             op = self._lazy_set
-            return optheap.get_box_replacement(self._get_rhs_from_set_op(op))
+            return get_box_replacement(self._get_rhs_from_set_op(op))
         else:
             res = self._getfield(opinfo, descr, optheap)
             if res is not None:
@@ -140,7 +125,6 @@
         elif not can_cache:
             self.invalidate(descr)
 
-
     # abstract methods
 
     def _get_rhs_from_set_op(self, op):
@@ -167,8 +151,8 @@
         return op.getarg(1)
 
     def put_field_back_to_info(self, op, opinfo, optheap):
-        arg = optheap.get_box_replacement(op.getarg(1))
-        struct = optheap.get_box_replacement(op.getarg(0))
+        arg = get_box_replacement(op.getarg(1))
+        struct = get_box_replacement(op.getarg(0))
         opinfo.setfield(op.getdescr(), struct, arg, optheap=optheap, cf=self)
 
     def _getfield(self, opinfo, descr, optheap, true_force=True):
@@ -216,8 +200,8 @@
         return res
 
     def put_field_back_to_info(self, op, opinfo, optheap):
-        arg = optheap.get_box_replacement(op.getarg(2))
-        struct = optheap.get_box_replacement(op.getarg(0))
+        arg = get_box_replacement(op.getarg(2))
+        struct = get_box_replacement(op.getarg(0))
         opinfo.setitem(op.getdescr(), self.index, struct, arg, optheap=optheap, cf=self)
 
     def invalidate(self, descr):
@@ -412,8 +396,8 @@
             d = self.cached_dict_reads[descr1] = args_dict()
             self.corresponding_array_descrs[descrs[1]] = descr1
         #
-        key = [self.optimizer.get_box_replacement(op.getarg(1)),   # dict
-               self.optimizer.get_box_replacement(op.getarg(2))]   # key
+        key = [get_box_replacement(op.getarg(1)),   # dict
+               get_box_replacement(op.getarg(2))]   # key
                # other args can be ignored here (hash, store_flag)
         try:
             res_v = d[key]
@@ -525,7 +509,7 @@
                 # guards' resume data is that of a virtual object that is stored
                 # into a field of a non-virtual object.  Here, 'op' in either
                 # SETFIELD_GC or SETARRAYITEM_GC.
-                opinfo = self.getptrinfo(op.getarg(0))
+                opinfo = info.getptrinfo(op.getarg(0))
                 assert not opinfo.is_virtual()      # it must be a non-virtual
                 if self.optimizer.is_virtual(op.getarg(2)):
                     pendingfields.append(op)
@@ -564,13 +548,6 @@
 
     def optimize_SETFIELD_GC(self, op):
         self.setfield(op)
-        #opnum = OpHelpers.getfield_pure_for_descr(op.getdescr())
-        #if self.has_pure_result(opnum, [op.getarg(0)],
-        #                        op.getdescr()):
-        #    os.write(2, '[bogus _immutable_field_ declaration: %s]\n' %
-        #             (op.getdescr().repr_of_descr()))
-        #    raise BogusImmutableField
-        #
 
     def setfield(self, op):
         cf = self.field_cache(op.getdescr())
@@ -606,8 +583,8 @@
             index = indexb.getint()
             cf = self.arrayitem_cache(op.getdescr(), index)
             arrayinfo.setitem(op.getdescr(), indexb.getint(),
-                              self.get_box_replacement(op.getarg(0)),
-                              self.get_box_replacement(op), optheap=self,
+                              get_box_replacement(op.getarg(0)),
+                              get_box_replacement(op), optheap=self,
                               cf=cf)
     optimize_GETARRAYITEM_GC_R = optimize_GETARRAYITEM_GC_I
     optimize_GETARRAYITEM_GC_F = optimize_GETARRAYITEM_GC_I
@@ -639,13 +616,6 @@
     optimize_GETARRAYITEM_GC_PURE_F = optimize_GETARRAYITEM_GC_PURE_I
 
     def optimize_SETARRAYITEM_GC(self, op):
-        #opnum = OpHelpers.getarrayitem_pure_for_descr(op.getdescr())
-        #if self.has_pure_result(opnum, [op.getarg(0), op.getarg(1)],
-        #                        op.getdescr()):
-        #    os.write(2, '[bogus immutable array declaration: %s]\n' %
-        #             (op.getdescr().repr_of_descr()))
-        #    raise BogusImmutableField
-        #
         indexb = self.getintbound(op.getarg(1))
         if indexb.is_constant():
             arrayinfo = self.ensure_ptr_info_arg0(op)
@@ -680,8 +650,7 @@
         # check that the value is still correct; it could have changed
         # already between the tracing and now.  In this case, we mark the loop
         # as invalid
-        if not qmutdescr.is_still_valid_for(
-                self.get_box_replacement(op.getarg(0))):
+        if not qmutdescr.is_still_valid_for(get_box_replacement(op.getarg(0))):
             raise InvalidLoop('quasi immutable field changed during tracing')
         # record as an out-of-line guard
         if self.optimizer.quasi_immutable_deps is None:
@@ -701,10 +670,10 @@
         result_getfield = []
         for descr, cf in self.cached_fields.iteritems():
             if cf._lazy_set:
-                continue # XXX safe default for now
+                continue  # XXX safe default for now
             parent_descr = descr.get_parent_descr()
             if not parent_descr.is_object():
-                continue # XXX could be extended to non-instance objects
+                continue  # XXX could be extended to non-instance objects
             for i, box1 in enumerate(cf.cached_structs):
                 if not box1.is_constant() and box1 not in available_boxes:
                     continue
@@ -721,7 +690,7 @@
         for descr, indexdict in self.cached_arrayitems.iteritems():
             for index, cf in indexdict.iteritems():
                 if cf._lazy_set:
-                    continue # XXX safe default for now
+                    continue  # XXX safe default for now
                 for i, box1 in enumerate(cf.cached_structs):
                     if not box1.is_constant() and box1 not in available_boxes:
                         continue
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -1,13 +1,14 @@
 
-from rpython.rlib.objectmodel import specialize, we_are_translated, compute_hash
-from rpython.jit.metainterp.resoperation import AbstractValue, ResOperation,\
-     rop, OpHelpers
-from rpython.jit.metainterp.history import ConstInt, Const
-from rpython.rtyper.lltypesystem import lltype, llmemory
-from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation
+from rpython.rlib.objectmodel import specialize, compute_hash
+from rpython.jit.metainterp.resoperation import (
+    AbstractValue, ResOperation, rop, OpHelpers)
+from rpython.jit.metainterp.history import ConstInt, ConstPtr, Const
+from rpython.rtyper.lltypesystem import lltype
+from rpython.jit.metainterp.optimizeopt.rawbuffer import (
+    RawBuffer, InvalidRawOperation)
 from rpython.jit.metainterp.executor import execute
 from rpython.jit.metainterp.optimize import InvalidLoop
-
+from .util import get_box_replacement
 
 INFO_NULL = 0
 INFO_NONNULL = 1
@@ -51,7 +52,7 @@
 
     def force_at_the_end_of_preamble(self, op, optforce, rec):
         if not self.is_virtual():
-            return optforce.get_box_replacement(op)
+            return get_box_replacement(op)
         return self._force_at_the_end_of_preamble(op, optforce, rec)
 
     def get_known_class(self, cpu):
@@ -84,7 +85,7 @@
 
     @specialize.arg(2)
     def get_constant_string_spec(self, string_optimizer, mode):
-        return None # can't be constant
+        return None  # can't be constant
 
 class NonNullPtrInfo(PtrInfo):
     _attrs_ = ('last_guard_pos',)
@@ -109,7 +110,7 @@
 
     def mark_last_guard(self, optimizer):
         if (optimizer.getlastop() is None or
-            not optimizer.getlastop().is_guard()):
+                not optimizer.getlastop().is_guard()):
             # there can be a really emitted operation that's not a guard
             # e.g. a setfield, ignore those
             return
@@ -140,12 +141,12 @@
                 constptr = optforce.optimizer.constant_fold(op)
                 op.set_forwarded(constptr)
                 self._is_virtual = False
-                self._force_elements_immutable(self.descr, constptr, optforce)
+                self._force_elements_immutable(self.descr, constptr, optforce.optimizer)
                 return constptr
             #
             op.set_forwarded(None)
             optforce.emit_extra(op)
-            newop = optforce.getlastop()
+            newop = optforce.optimizer.getlastop()
             if newop is not op:
                 op.set_forwarded(newop)
             newop.set_forwarded(self)
@@ -161,14 +162,14 @@
     def is_virtual(self):
         return self._is_virtual
 
-    def _visitor_walk_recursive(self, op, visitor, optimizer):
+    def _visitor_walk_recursive(self, op, visitor):
         raise NotImplementedError("abstract")
 
-    def visitor_walk_recursive(self, instbox, visitor, optimizer):
+    def visitor_walk_recursive(self, instbox, visitor):
         instbox = instbox.get_box_replacement()
         if visitor.already_seen_virtual(instbox):
             return
-        return self._visitor_walk_recursive(instbox, visitor, optimizer)
+        return self._visitor_walk_recursive(instbox, visitor)
 
 
 class AbstractStructPtrInfo(AbstractVirtualPtrInfo):
@@ -181,7 +182,7 @@
             self.descr = descr
             self._fields = [None] * len(descr.get_all_fielddescrs())
         if index >= len(self._fields):
-            self.descr = descr # a more precise descr
+            self.descr = descr  # a more precise descr
             # we found out a subclass with more fields
             extra_len = len(descr.get_all_fielddescrs()) - len(self._fields)
             self._fields = self._fields + [None] * extra_len
@@ -218,7 +219,7 @@
         for i, fielddescr in enumerate(descr.get_all_fielddescrs()):
             fld = self._fields[i]
             if fld is not None:
-                subbox = optforce.force_box(fld)
+                subbox = optforce.optimizer.force_box(fld)
                 setfieldop = ResOperation(rop.SETFIELD_GC, [op, subbox],
                                           descr=fielddescr)
                 self._fields[i] = None
@@ -226,31 +227,30 @@
 
     def _force_at_the_end_of_preamble(self, op, optforce, rec):
         if self._fields is None:
-            return optforce.get_box_replacement(op)
+            return get_box_replacement(op)
         if self in rec:
-            return optforce.get_box_replacement(op)
+            return get_box_replacement(op)
         rec[self] = None
         for i, fldbox in enumerate(self._fields):
             if fldbox is not None:
-                info = optforce.getptrinfo(fldbox)
+                info = getptrinfo(fldbox)
                 if info is not None:
                     fldbox = info.force_at_the_end_of_preamble(fldbox, optforce,
                                                                rec)
                     self._fields[i] = fldbox
         return op
 
-    def _visitor_walk_recursive(self, instbox, visitor, optimizer):
+    def _visitor_walk_recursive(self, instbox, visitor):
         lst = self.descr.get_all_fielddescrs()
         assert self.is_virtual()
-        visitor.register_virtual_fields(instbox,
-                                        [optimizer.get_box_replacement(box)
-                                         for box in self._fields])
+        visitor.register_virtual_fields(
+            instbox, [get_box_replacement(box) for box in self._fields])
         for i in range(len(lst)):
             op = self._fields[i]
             if op:
-                fieldinfo = optimizer.getptrinfo(op)
+                fieldinfo = getptrinfo(op)
                 if fieldinfo and fieldinfo.is_virtual():
-                    fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
+                    fieldinfo.visitor_walk_recursive(op, visitor)
 
     def produce_short_preamble_ops(self, structbox, fielddescr, index, optimizer,
                                    shortboxes):
@@ -259,7 +259,7 @@
         if fielddescr.get_index() >= len(self._fields):
             # we don't know about this item
             return
-        op = optimizer.get_box_replacement(self._fields[fielddescr.get_index()])
+        op = get_box_replacement(self._fields[fielddescr.get_index()])
         if op is None:
             # XXX same bug as in serialize_opt:
             # op should never be None, because that's an invariant violation in
@@ -290,7 +290,7 @@
             if op.is_constant():
                 pass            # it is a constant value: ok
             else:
-                fieldinfo = optimizer.getptrinfo(op)
+                fieldinfo = getptrinfo(op)
                 if fieldinfo and fieldinfo.is_virtual():
                     # recursive check
                     if memo is None:
@@ -302,12 +302,12 @@
                     return False    # not a constant at all
         return True
 
-    def _force_elements_immutable(self, descr, constptr, optforce):
+    def _force_elements_immutable(self, descr, constptr, optimizer):
         for i, fielddescr in enumerate(descr.get_all_fielddescrs()):
             fld = self._fields[i]
-            subbox = optforce.force_box(fld)
+            subbox = optimizer.force_box(fld)
             assert isinstance(subbox, Const)
-            execute(optforce.optimizer.cpu, None, rop.SETFIELD_GC,
+            execute(optimizer.cpu, None, rop.SETFIELD_GC,
                     fielddescr, constptr, subbox)
 
 class InstancePtrInfo(AbstractStructPtrInfo):
@@ -435,8 +435,8 @@
                               [op, ConstInt(offset), itembox], descr=descr)
             optforce.emit_extra(setfield_op)
 
-    def _visitor_walk_recursive(self, op, visitor, optimizer):
-        itemboxes = [optimizer.get_box_replacement(box)
+    def _visitor_walk_recursive(self, op, visitor):
+        itemboxes = [get_box_replacement(box)
                      for box in self._get_buffer().values]
         visitor.register_virtual_fields(op, itemboxes)
         # there can be no virtuals stored in raw buffer
@@ -465,21 +465,21 @@
         return self.parent is not None
 
     def getitem_raw(self, offset, itemsize, descr):
-        return self.parent.getitem_raw(self.offset+offset, itemsize, descr)
+        return self.parent.getitem_raw(self.offset + offset, itemsize, descr)
 
     def setitem_raw(self, offset, itemsize, descr, itemop):
-        self.parent.setitem_raw(self.offset+offset, itemsize, descr, itemop)
+        self.parent.setitem_raw(self.offset + offset, itemsize, descr, itemop)
 
     def _force_elements(self, op, optforce, descr):
         if self.parent.is_virtual():
             self.parent._force_elements(op, optforce, descr)
         self.parent = None
 
-    def _visitor_walk_recursive(self, op, visitor, optimizer):
-        source_op = optimizer.get_box_replacement(op.getarg(0))
+    def _visitor_walk_recursive(self, op, visitor):
+        source_op = get_box_replacement(op.getarg(0))
         visitor.register_virtual_fields(op, [source_op])
         if self.parent.is_virtual():
-            self.parent.visitor_walk_recursive(source_op, visitor, optimizer)
+            self.parent.visitor_walk_recursive(source_op, visitor)
 
     @specialize.argtype(1)
     def visitor_dispatch_virtual_type(self, visitor):
@@ -534,7 +534,7 @@
     def _force_elements(self, op, optforce, descr):
         # XXX
         descr = op.getdescr()
-        const = optforce.new_const_item(self.descr)
+        const = optforce.optimizer.new_const_item(self.descr)
         for i in range(self.length):
             item = self._items[i]
             if item is None:
@@ -543,7 +543,7 @@
                 # clear the item so we don't know what's there
                 self._items[i] = None
                 continue
-            subbox = optforce.force_box(item)
+            subbox = optforce.optimizer.force_box(item)
             setop = ResOperation(rop.SETARRAYITEM_GC,
                                  [op, ConstInt(i), subbox],
                                   descr=descr)
@@ -570,17 +570,15 @@
     def getlength(self):
         return self.length
 
-    def _visitor_walk_recursive(self, instbox, visitor, optimizer):
-        itemops = [optimizer.get_box_replacement(item)
-                   for item in self._items]
+    def _visitor_walk_recursive(self, instbox, visitor):
+        itemops = [get_box_replacement(item) for item in self._items]
         visitor.register_virtual_fields(instbox, itemops)
         for i in range(self.getlength()):
             itemop = self._items[i]
-            if (itemop is not None and
-                not isinstance(itemop, Const)):
-                ptrinfo = optimizer.getptrinfo(itemop)
+            if (itemop is not None and not isinstance(itemop, Const)):
+                ptrinfo = getptrinfo(itemop)
                 if ptrinfo and ptrinfo.is_virtual():
-                    ptrinfo.visitor_walk_recursive(itemop, visitor, optimizer)
+                    ptrinfo.visitor_walk_recursive(itemop, visitor)
 
     @specialize.argtype(1)
     def visitor_dispatch_virtual_type(self, visitor):
@@ -596,7 +594,7 @@
         item = self._items[index]
         if item is not None:
             # see comment in AbstractStructPtrInfo.produce_short_preamble_ops
-            op = optimizer.get_box_replacement(item)
+            op = get_box_replacement(item)
             opnum = OpHelpers.getarrayitem_for_descr(descr)
             getarrayitem_op = ResOperation(opnum, [structbox, ConstInt(index)],
                                            descr=descr)
@@ -604,13 +602,13 @@
 
     def _force_at_the_end_of_preamble(self, op, optforce, rec):
         if self._items is None:
-            return optforce.get_box_replacement(op)
+            return get_box_replacement(op)
         if self in rec:
-            return optforce.get_box_replacement(op)
+            return get_box_replacement(op)
         rec[self] = None
         for i, fldbox in enumerate(self._items):
             if fldbox is not None:
-                info = optforce.getptrinfo(fldbox)
+                info = getptrinfo(fldbox)
                 if info is not None:
                     fldbox = info.force_at_the_end_of_preamble(fldbox, optforce,
                                                                rec)
@@ -640,7 +638,7 @@
     def _compute_index(self, index, fielddescr):
         all_fdescrs = fielddescr.get_arraydescr().get_all_fielddescrs()
         if all_fdescrs is None:
-            return 0 # annotation hack
+            return 0  # annotation hack
         one_size = len(all_fdescrs)
         return index * one_size + fielddescr.get_field_descr().get_index()
 
@@ -659,7 +657,7 @@
             for fielddescr in fielddescrs:
                 fld = self._items[i]
                 if fld is not None:
-                    subbox = optforce.force_box(fld)
+                    subbox = optforce.optimizer.force_box(fld)
                     setfieldop = ResOperation(rop.SETINTERIORFIELD_GC,
                                               [op, ConstInt(index), subbox],
                                               descr=fielddescr)
@@ -668,21 +666,18 @@
                     # if it does, we would need a fix here
                 i += 1
 
-    def _visitor_walk_recursive(self, instbox, visitor, optimizer):
-        itemops = [optimizer.get_box_replacement(item)
-                   for item in self._items]
+    def _visitor_walk_recursive(self, instbox, visitor):
+        itemops = [get_box_replacement(item) for item in self._items]
         visitor.register_virtual_fields(instbox, itemops)
         fielddescrs = self.descr.get_all_fielddescrs()
         i = 0
         for index in range(self.getlength()):
             for fielddescr in fielddescrs:
                 itemop = self._items[i]
-                if (itemop is not None and
-                    not isinstance(itemop, Const)):
-                    ptrinfo = optimizer.getptrinfo(itemop)
+                if (itemop is not None and not isinstance(itemop, Const)):
+                    ptrinfo = getptrinfo(itemop)
                     if ptrinfo and ptrinfo.is_virtual():
-                        ptrinfo.visitor_walk_recursive(itemop, visitor,
-                                                       optimizer)
+                        ptrinfo.visitor_walk_recursive(itemop, visitor)
                 i += 1
 
     @specialize.argtype(1)
@@ -705,7 +700,8 @@
 
     def _get_info(self, descr, optheap):
         ref = self._const.getref_base()
-        if not ref: raise InvalidLoop   # null protection
+        if not ref:
+            raise InvalidLoop   # null protection
         info = optheap.const_infos.get(ref, None)
         if info is None:
             info = StructPtrInfo(descr)
@@ -714,7 +710,8 @@
 
     def _get_array_info(self, descr, optheap):
         ref = self._const.getref_base()
-        if not ref: raise InvalidLoop   # null protection
+        if not ref:
+            raise InvalidLoop   # null protection
         info = optheap.const_infos.get(ref, None)
         if info is None:
             info = ArrayPtrInfo(descr)
@@ -780,8 +777,8 @@
         return self._unpack_str(mode)
 
     def getlenbound(self, mode):
-        from rpython.jit.metainterp.optimizeopt.intutils import ConstIntBound,\
-                IntLowerBound
+        from rpython.jit.metainterp.optimizeopt.intutils import (
+            ConstIntBound, IntLowerBound)
 
         length = self.getstrlen1(mode)
         if length < 0:
@@ -848,3 +845,36 @@
 
     def make_guards(self, op, short, optimizer):
         short.append(ResOperation(rop.GUARD_VALUE, [op, self._const]))
+
+
+def getrawptrinfo(op):
+    from rpython.jit.metainterp.optimizeopt.intutils import IntBound
+    assert op.type == 'i'
+    op = op.get_box_replacement()
+    assert op.type == 'i'
+    if isinstance(op, ConstInt):
+        return ConstPtrInfo(op)
+    fw = op.get_forwarded()
+    if isinstance(fw, IntBound):
+        return None
+    if fw is not None:
+        assert isinstance(fw, AbstractRawPtrInfo)
+        return fw
+    return None
+
+def getptrinfo(op):
+    if op.type == 'i':
+        return getrawptrinfo(op)
+    elif op.type == 'f':
+        return None
+    assert op.type == 'r'
+    op = get_box_replacement(op)
+    assert op.type == 'r'
+    if isinstance(op, ConstPtr):
+        return ConstPtrInfo(op)
+    fw = op.get_forwarded()
+    if fw is not None:
+        assert isinstance(fw, PtrInfo)
+        return fw
+    return None
+
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -5,7 +5,9 @@
     IntLowerBound, IntUpperBound, ConstIntBound)
 from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, CONST_1,
     CONST_0)
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimizeopt.util import (
+    make_dispatcher_method, get_box_replacement)
+from .info import getptrinfo
 from rpython.jit.metainterp.resoperation import rop
 from rpython.jit.metainterp.optimizeopt import vstring
 from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -64,8 +66,8 @@
     postprocess_GUARD_VALUE = _postprocess_guard_true_false_value
 
     def optimize_INT_OR_or_XOR(self, op):
-        v1 = self.get_box_replacement(op.getarg(0))
-        v2 = self.get_box_replacement(op.getarg(1))
+        v1 = get_box_replacement(op.getarg(0))
+        v2 = get_box_replacement(op.getarg(1))
         if v1 is v2:
             if op.getopnum() == rop.INT_OR:
                 self.make_equal_to(op, v1)
@@ -75,9 +77,9 @@
         return self.emit(op)
 
     def postprocess_INT_OR_or_XOR(self, op):
-        v1 = self.get_box_replacement(op.getarg(0))
+        v1 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(v1)
-        v2 = self.get_box_replacement(op.getarg(1))
+        v2 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(v2)
         b = b1.or_bound(b2)
         self.getintbound(op).intersect(b)
@@ -108,8 +110,8 @@
             self.getintbound(op).intersect(b)
 
     def optimize_INT_ADD(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         if self.is_raw_ptr(arg1) or self.is_raw_ptr(arg2):
             return self.emit(op)
         v1 = self.getintbound(arg1)
@@ -130,8 +132,8 @@
             arg1 = self.optimizer.as_operation(arg1)
             if arg1 is not None:
                 if arg1.getopnum() == rop.INT_ADD:
-                    prod_arg1 = self.get_box_replacement(arg1.getarg(0))
-                    prod_arg2 = self.get_box_replacement(arg1.getarg(1))
+                    prod_arg1 = get_box_replacement(arg1.getarg(0))
+                    prod_arg2 = get_box_replacement(arg1.getarg(1))
                     prod_v1 = self.getintbound(prod_arg1)
                     prod_v2 = self.getintbound(prod_arg2)
 
@@ -196,9 +198,9 @@
         return self.emit(op)
 
     def postprocess_INT_LSHIFT(self, op):
-        arg0 = self.get_box_replacement(op.getarg(0))
+        arg0 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg0)
-        arg1 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(arg1)
         r = self.getintbound(op)
         b = b1.lshift_bound(b2)
@@ -290,8 +292,8 @@
         r.intersect(resbound)
 
     def optimize_INT_SUB_OVF(self, op):
-        arg0 = self.get_box_replacement(op.getarg(0))
-        arg1 = self.get_box_replacement(op.getarg(1))
+        arg0 = get_box_replacement(op.getarg(0))
+        arg1 = get_box_replacement(op.getarg(1))
         b0 = self.getintbound(arg0)
         b1 = self.getintbound(arg1)
         if arg0.same_box(arg1):
@@ -304,8 +306,8 @@
         return self.emit(op)
 
     def postprocess_INT_SUB_OVF(self, op):
-        arg0 = self.get_box_replacement(op.getarg(0))
-        arg1 = self.get_box_replacement(op.getarg(1))
+        arg0 = get_box_replacement(op.getarg(0))
+        arg1 = get_box_replacement(op.getarg(1))
         b0 = self.getintbound(arg0)
         b1 = self.getintbound(arg1)
         resbound = b0.sub_bound(b1)
@@ -329,8 +331,8 @@
         r.intersect(resbound)
 
     def optimize_INT_LT(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         b1 = self.getintbound(arg1)
         b2 = self.getintbound(arg2)
         if b1.known_lt(b2):
@@ -341,8 +343,8 @@
             return self.emit(op)
 
     def optimize_INT_GT(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         b1 = self.getintbound(arg1)
         b2 = self.getintbound(arg2)
         if b1.known_gt(b2):
@@ -353,8 +355,8 @@
             return self.emit(op)
 
     def optimize_INT_LE(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         b1 = self.getintbound(arg1)
         b2 = self.getintbound(arg2)
         if b1.known_le(b2) or arg1 is arg2:
@@ -365,8 +367,8 @@
             return self.emit(op)
 
     def optimize_INT_GE(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         b1 = self.getintbound(arg1)
         b2 = self.getintbound(arg2)
         if b1.known_ge(b2) or arg1 is arg2:
@@ -377,9 +379,9 @@
             return self.emit(op)
 
     def optimize_INT_EQ(self, op):
-        arg0 = self.get_box_replacement(op.getarg(0))
+        arg0 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg0)
-        arg1 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(arg1)
         if b1.known_gt(b2):
             self.make_constant_int(op, 0)
@@ -391,9 +393,9 @@
             return self.emit(op)
 
     def optimize_INT_NE(self, op):
-        arg0 = self.get_box_replacement(op.getarg(0))
+        arg0 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg0)
-        arg1 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(arg1)
         if b1.known_gt(b2):
             self.make_constant_int(op, 1)
@@ -442,7 +444,7 @@
 
     def postprocess_STRLEN(self, op):
         self.make_nonnull_str(op.getarg(0), vstring.mode_string)
-        array = self.getptrinfo(op.getarg(0))
+        array = getptrinfo(op.getarg(0))
         self.optimizer.setintbound(op, array.getlenbound(vstring.mode_string))
 
     def optimize_UNICODELEN(self, op):
@@ -450,7 +452,7 @@
 
     def postprocess_UNICODELEN(self, op):
         self.make_nonnull_str(op.getarg(0), vstring.mode_unicode)
-        array = self.getptrinfo(op.getarg(0))
+        array = getptrinfo(op.getarg(0))
         self.optimizer.setintbound(op, array.getlenbound(vstring.mode_unicode))
 
     def optimize_STRGETITEM(self, op):
@@ -458,7 +460,7 @@
 
     def postprocess_STRGETITEM(self, op):
         v1 = self.getintbound(op)
-        v2 = self.getptrinfo(op.getarg(0))
+        v2 = getptrinfo(op.getarg(0))
         intbound = self.getintbound(op.getarg(1))
         if (intbound.has_lower and v2 is not None and
             v2.getlenbound(vstring.mode_string) is not None):
@@ -523,7 +525,7 @@
     def postprocess_UNICODEGETITEM(self, op):
         b1 = self.getintbound(op)
         b1.make_ge(IntLowerBound(0))
-        v2 = self.getptrinfo(op.getarg(0))
+        v2 = getptrinfo(op.getarg(0))
         intbound = self.getintbound(op.getarg(1))
         if (intbound.has_lower and v2 is not None and
             v2.getlenbound(vstring.mode_unicode) is not None):
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -1,16 +1,19 @@
 from rpython.jit.metainterp import jitprof, resume, compile
 from rpython.jit.metainterp.executor import execute_nonspec_const
 from rpython.jit.metainterp.history import (
-    Const, ConstInt, ConstPtr, CONST_NULL, new_ref_dict)
-from rpython.jit.metainterp.optimizeopt.intutils import IntBound,\
-     ConstIntBound, MININT, MAXINT, IntUnbounded
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from rpython.jit.metainterp.resoperation import rop, AbstractResOp, GuardResOp,\
-     OpHelpers
+    Const, ConstInt, CONST_NULL, new_ref_dict)
+from rpython.jit.metainterp.optimizeopt.intutils import (
+    IntBound, ConstIntBound, MININT, MAXINT, IntUnbounded)
+from rpython.jit.metainterp.optimizeopt.util import (
+    make_dispatcher_method, get_box_replacement)
+from rpython.jit.metainterp.optimizeopt.bridgeopt import (
+    deserialize_optimizer_knowledge)
+from rpython.jit.metainterp.resoperation import (
+    rop, AbstractResOp, GuardResOp, OpHelpers)
+from .info import getrawptrinfo, getptrinfo
 from rpython.jit.metainterp.optimizeopt import info
 from rpython.jit.metainterp.optimize import InvalidLoop
 from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib.debug import debug_print
 from rpython.rtyper import rclass
 from rpython.rtyper.lltypesystem import llmemory
 from rpython.jit.metainterp.optimize import SpeculativeError
@@ -57,9 +60,6 @@
     def __init__(self):
         pass # make rpython happy
 
-    def send_extra_operation(self, op, opt=None):
-        self.optimizer.send_extra_operation(op, opt)
-
     def propagate_forward(self, op):
         raise NotImplementedError
 
@@ -79,11 +79,11 @@
     def emit_extra(self, op, emit=True):
         if emit:
             self.emit(op)
-        self.send_extra_operation(op, self.next_optimization)
+        self.optimizer.send_extra_operation(op, self.next_optimization)
 
     def getintbound(self, op):
         assert op.type == 'i'
-        op = self.get_box_replacement(op)
+        op = get_box_replacement(op)
         if isinstance(op, ConstInt):
             return ConstIntBound(op.getint())
         fw = op.get_forwarded()
@@ -99,7 +99,7 @@
 
     def setintbound(self, op, bound):
         assert op.type == 'i'
-        op = self.get_box_replacement(op)
+        op = get_box_replacement(op)
         if op.is_constant():
             return
         cur = op.get_forwarded()
@@ -111,7 +111,7 @@
 
     def getnullness(self, op):
         if op.type == 'r' or self.is_raw_ptr(op):
-            ptrinfo = self.getptrinfo(op)
+            ptrinfo = getptrinfo(op)
             if ptrinfo is None:
                 return info.INFO_UNKNOWN
             return ptrinfo.getnullness()
@@ -120,7 +120,7 @@
         assert False
 
     def make_constant_class(self, op, class_const, update_last_guard=True):
-        op = self.get_box_replacement(op)
+        op = op.get_box_replacement()
         opinfo = op.get_forwarded()
         if isinstance(opinfo, info.InstancePtrInfo):
             opinfo._known_class = class_const
@@ -136,55 +136,12 @@
             opinfo.mark_last_guard(self.optimizer)
         return opinfo
 
-    def getptrinfo(self, op, is_object=False):
-        if op.type == 'i':
-            return self.getrawptrinfo(op)
-        elif op.type == 'f':
-            return None
-        assert op.type == 'r'
-        op = self.get_box_replacement(op)
-        assert op.type == 'r'
-        if isinstance(op, ConstPtr):
-            return info.ConstPtrInfo(op)
-        fw = op.get_forwarded()
-        if fw is not None:
-            assert isinstance(fw, info.PtrInfo)
-            return fw
-        return None
-
     def is_raw_ptr(self, op):
-        fw = self.get_box_replacement(op).get_forwarded()
+        fw = get_box_replacement(op).get_forwarded()
         if isinstance(fw, info.AbstractRawPtrInfo):
             return True
         return False
 
-    def getrawptrinfo(self, op, create=False, is_object=False):
-        assert op.type == 'i'
-        op = self.get_box_replacement(op)
-        assert op.type == 'i'
-        if isinstance(op, ConstInt):
-            return info.ConstPtrInfo(op)
-        fw = op.get_forwarded()
-        if isinstance(fw, IntBound) and not create:
-            return None
-        if fw is not None:
-            if isinstance(fw, info.AbstractRawPtrInfo):
-                return fw
-            fw = info.RawStructPtrInfo()
-            op.set_forwarded(fw)
-            assert isinstance(fw, info.AbstractRawPtrInfo)
-            return fw
-        return None
-
-    def get_box_replacement(self, op):
-        return self.optimizer.get_box_replacement(op)
-
-    def getlastop(self):
-        return self.optimizer.getlastop()
-
-    def force_box(self, op, optforce=None):
-        return self.optimizer.force_box(op, optforce)
-
     def replace_op_with(self, op, newopnum, args=None, descr=None):
         return self.optimizer.replace_op_with(op, newopnum, args, descr)
 
@@ -209,18 +166,6 @@
     def get_constant_box(self, box):
         return self.optimizer.get_constant_box(box)
 
-    def new_box(self, fieldofs):
-        return self.optimizer.new_box(fieldofs)
-
-    def new_const(self, fieldofs):
-        return self.optimizer.new_const(fieldofs)
-
-    def new_box_item(self, arraydescr):
-        return self.optimizer.new_box_item(arraydescr)
-
-    def new_const_item(self, arraydescr):
-        return self.optimizer.new_const_item(arraydescr)
-
     def pure(self, opnum, result):
         if self.optimizer.optpure:
             self.optimizer.optpure.pure(opnum, result)
@@ -229,11 +174,6 @@
         if self.optimizer.optpure:
             self.optimizer.optpure.pure_from_args(opnum, args, op, descr)
 
-    def has_pure_result(self, opnum, args, descr):
-        if self.optimizer.optpure:
-            return self.optimizer.optpure.has_pure_result(opnum, args, descr)
-        return False
-
     def get_pure_result(self, key):
         if self.optimizer.optpure:
             return self.optimizer.optpure.get_pure_result(key)
@@ -308,6 +248,14 @@
 
         self.optimizations = optimizations
 
+    def optimize_loop(self, trace, resumestorage, call_pure_results):
+        traceiter = trace.get_iter()
+        if resumestorage:
+            frontend_inputargs = trace.inputargs
+            deserialize_optimizer_knowledge(
+                self, resumestorage, frontend_inputargs, traceiter.inputargs)
+        return self.propagate_all_forward(traceiter, call_pure_results)
+
     def force_op_from_preamble(self, op):
         return op
 
@@ -322,14 +270,14 @@
 
     def force_box_for_end_of_preamble(self, box):
         if box.type == 'r':
-            info = self.getptrinfo(box)
+            info = getptrinfo(box)
             if info is not None and info.is_virtual():
                 rec = {}
                 return info.force_at_the_end_of_preamble(box,
                                                 self.optearlyforce, rec)
             return box
         if box.type == 'i':
-            info = self.getrawptrinfo(box)
+            info = getrawptrinfo(box)
             if info is not None:
                 return info.force_at_the_end_of_preamble(box,
                                             self.optearlyforce, None)
@@ -345,14 +293,14 @@
 
     def getinfo(self, op):
         if op.type == 'r':
-            return self.getptrinfo(op)
+            return getptrinfo(op)
         elif op.type == 'i':
             if self.is_raw_ptr(op):
-                return self.getptrinfo(op)
+                return getptrinfo(op)
             return self.getintbound(op)
         elif op.type == 'f':
-            if self.get_box_replacement(op).is_constant():
-                return info.FloatConstInfo(self.get_box_replacement(op))
+            if get_box_replacement(op).is_constant():
+                return info.FloatConstInfo(get_box_replacement(op))
 
     def get_box_replacement(self, op):
         if op is None:
@@ -360,8 +308,9 @@
         return op.get_box_replacement()
 
     def force_box(self, op, optforce=None):
-        op = self.get_box_replacement(op)
+        op = get_box_replacement(op)
         if optforce is None:
+            #import pdb; pdb.set_trace()
             optforce = self
         info = op.get_forwarded()
         if self.optunroll and self.optunroll.potential_extra_ops:
@@ -387,7 +336,7 @@
         return None
 
     def get_constant_box(self, box):
-        box = self.get_box_replacement(box)
+        box = get_box_replacement(box)
         if isinstance(box, Const):
             return box
         if (box.type == 'i' and box.get_forwarded() and
@@ -396,16 +345,8 @@
         return None
         #self.ensure_imported(value)
 
-    def get_newoperations(self):
-        self.flush()
-        return self._newoperations
-
-    def clear_newoperations(self):
-        self._newoperations = []
-        self._emittedoperations = {}
-
     def make_equal_to(self, op, newop):
-        op = self.get_box_replacement(op)
+        op = get_box_replacement(op)
         if op is newop:
             return
         opinfo = op.get_forwarded()
@@ -420,7 +361,7 @@
     def replace_op_with(self, op, newopnum, args=None, descr=None):
         newop = op.copy_and_change(newopnum, args, descr)
         if newop.type != 'v':
-            op = self.get_box_replacement(op)
+            op = get_box_replacement(op)
             opinfo = op.get_forwarded()
             if opinfo is not None:
                 newop.set_forwarded(opinfo)
@@ -429,7 +370,7 @@
 
     def make_constant(self, box, constbox):
         assert isinstance(constbox, Const)
-        box = self.get_box_replacement(box)
+        box = get_box_replacement(box)
         # safety-check: if the constant is outside the bounds for the
         # box, then it is an invalid loop
         if (box.get_forwarded() is not None and
@@ -442,7 +383,7 @@
             return
         if box.type == 'r' and box.get_forwarded() is not None:
             opinfo = box.get_forwarded()
-            opinfo.copy_fields_to_const(self.getptrinfo(constbox), self.optheap)
+            opinfo.copy_fields_to_const(getptrinfo(constbox), self.optheap)
         box.set_forwarded(constbox)
 
     def make_constant_int(self, box, intvalue):
@@ -662,32 +603,6 @@
             self._last_guard_op = None
         return op
 
-    def potentially_change_ovf_op_to_no_ovf(self, op):
-        # if last emitted operations was int_xxx_ovf and we are not emitting
-        # a guard_no_overflow change to int_add
-        if op.getopnum() != rop.GUARD_NO_OVERFLOW:
-            return
-        if not self._newoperations:
-            # got optimized otherwise
-            return
-        op = self._newoperations[-1]
-        if not op.is_ovf():
-            return
-        newop = self.replace_op_with_no_ovf(op)
-        self._newoperations[-1] = newop
-        self._emittedoperations[newop] = None
-
-    def replace_op_with_no_ovf(self, op):
-        if op.getopnum() == rop.INT_MUL_OVF:
-            return self.replace_op_with(op, rop.INT_MUL)
-        elif op.getopnum() == rop.INT_ADD_OVF:
-            return self.replace_op_with(op, rop.INT_ADD)
-        elif op.getopnum() == rop.INT_SUB_OVF:
-            return self.replace_op_with(op, rop.INT_SUB)
-        else:
-            assert False
-
-
     def _copy_resume_data_from(self, guard_op, last_guard_op):
         last_descr = last_guard_op.getdescr()
         descr = compile.invent_fail_descr_for_op(guard_op.getopnum(), self, last_descr)
@@ -851,13 +766,8 @@
                 <= expected_class.subclassrange_max)
 
     def is_virtual(self, op):
-        if op.type == 'r':
-            opinfo = self.getptrinfo(op)
-            return opinfo is not None and opinfo.is_virtual()
-        if op.type == 'i':
-            opinfo = self.getrawptrinfo(op)
-            return opinfo is not None and opinfo.is_virtual()
-        return False
+        opinfo = getptrinfo(op)
+        return opinfo is not None and opinfo.is_virtual()
 
     # These are typically removed already by OptRewrite, but it can be
     # dissabled and unrolling emits some SAME_AS ops to setup the
@@ -869,4 +779,3 @@
 
 dispatch_opt = make_dispatcher_method(Optimizer, 'optimize_',
         default=Optimizer.optimize_default)
-
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -2,7 +2,8 @@
     Optimization, OptimizationResult, REMOVED)
 from rpython.jit.metainterp.resoperation import rop, OpHelpers, AbstractResOp,\
      ResOperation
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimizeopt.util import (
+    make_dispatcher_method, get_box_replacement)
 from rpython.jit.metainterp.optimizeopt.shortpreamble import PreambleOp
 from rpython.jit.metainterp.optimize import SpeculativeError
 
@@ -57,9 +58,9 @@
             op = self.lst[i]
             if op is None:
                 break
-            if box0.same_box(opt.get_box_replacement(op.getarg(0))) and op.getdescr() is descr:
+            if box0.same_box(get_box_replacement(op.getarg(0))) and op.getdescr() is descr:
                 op = self.force_preamble_op(opt, op, i)
-                return opt.get_box_replacement(op)
+                return get_box_replacement(op)
         return None
 
     def lookup2(self, opt, box0, box1, descr):
@@ -67,23 +68,23 @@
             op = self.lst[i]
             if op is None:
                 break
-            if (box0.same_box(opt.get_box_replacement(op.getarg(0))) and
-                box1.same_box(opt.get_box_replacement(op.getarg(1))) and
+            if (box0.same_box(get_box_replacement(op.getarg(0))) and
+                box1.same_box(get_box_replacement(op.getarg(1))) and
                 op.getdescr() is descr):
                 op = self.force_preamble_op(opt, op, i)
-                return opt.get_box_replacement(op)
+                return get_box_replacement(op)
         return None
 
     def lookup(self, optimizer, op):
         numargs = op.numargs()
         if numargs == 1:
             return self.lookup1(optimizer,
-                                optimizer.get_box_replacement(op.getarg(0)),
+                                get_box_replacement(op.getarg(0)),
                                 op.getdescr())
         elif numargs == 2:
             return self.lookup2(optimizer,
-                                optimizer.get_box_replacement(op.getarg(0)),
-                                optimizer.get_box_replacement(op.getarg(1)),
+                                get_box_replacement(op.getarg(0)),
+                                get_box_replacement(op.getarg(1)),
                                 op.getdescr())
         else:
             assert False
@@ -205,7 +206,7 @@
         old_start_index = OpHelpers.is_cond_call_value(old_op.opnum)
         for i in range(old_start_index, old_op.numargs()):
             box = old_op.getarg(i)
-            if not self.get_box_replacement(op.getarg(j)).same_box(box):
+            if not get_box_replacement(op.getarg(j)).same_box(box):
                 break
             j += 1
         else:
@@ -239,15 +240,11 @@
 
     def pure_from_args(self, opnum, args, op, descr=None):
         newop = ResOperation(opnum,
-                             [self.get_box_replacement(arg) for arg in args],
+                             [get_box_replacement(arg) for arg in args],
                              descr=descr)
         newop.set_forwarded(op)
         self.pure(opnum, newop)
 
-    def has_pure_result(self, opnum, args, descr):
-        return False
-    # XXX
-
     def get_pure_result(self, op):
         recentops = self.getrecentops(op.getopnum())
         return recentops.lookup(self.optimizer, op)
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -7,13 +7,13 @@
 from rpython.jit.metainterp.optimizeopt.intutils import IntBound
 from rpython.jit.metainterp.optimizeopt.optimizer import (
     Optimization, OptimizationResult, REMOVED, CONST_0, CONST_1)
-from rpython.jit.metainterp.optimizeopt.info import INFO_NONNULL, INFO_NULL
-from rpython.jit.metainterp.optimizeopt.util import _findall, make_dispatcher_method
-from rpython.jit.metainterp.resoperation import rop, ResOperation, opclasses,\
-     OpHelpers
+from rpython.jit.metainterp.optimizeopt.info import (
+    INFO_NONNULL, INFO_NULL, getptrinfo)
+from rpython.jit.metainterp.optimizeopt.util import (
+    _findall, make_dispatcher_method, get_box_replacement)
+from rpython.jit.metainterp.resoperation import (
+    rop, ResOperation, opclasses, OpHelpers)
 from rpython.rlib.rarithmetic import highest_bit
-from rpython.rtyper.lltypesystem import llmemory
-from rpython.rtyper import rclass
 import math
 
 
@@ -68,7 +68,6 @@
                 return True
         return False
 
-
     def find_rewritable_bool(self, op):
         oldopnum = op.boolinverse
         arg0 = op.getarg(0)
@@ -78,7 +77,7 @@
             if self.try_boolinvers(op, top):
                 return True
 
-        oldopnum = op.boolreflex # FIXME: add INT_ADD, INT_MUL
+        oldopnum = op.boolreflex  # FIXME: add INT_ADD, INT_MUL
         if oldopnum != -1:
             top = ResOperation(oldopnum, [arg1, arg0])
             oldop = self.get_pure_result(top)
@@ -128,8 +127,8 @@
             return self.emit(op)
 
     def optimize_INT_SUB(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg1 = get_box_replacement(op.getarg(0))
+        arg2 = get_box_replacement(op.getarg(1))
         b1 = self.getintbound(arg1)
         b2 = self.getintbound(arg2)
         if b2.equal(0):
@@ -162,9 +161,9 @@
     def optimize_INT_ADD(self, op):
         if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
             return self.emit(op)
-        arg1 = self.get_box_replacement(op.getarg(0))
+        arg1 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg1)
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg2 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(arg2)
 
         # If one side of the op is 0 the result is the other side.
@@ -204,9 +203,9 @@
         self.optimizer.pure_from_args(rop.INT_ADD, [inv_arg0, op], arg1)
 
     def optimize_INT_MUL(self, op):
-        arg1 = self.get_box_replacement(op.getarg(0))
+        arg1 = get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg1)
-        arg2 = self.get_box_replacement(op.getarg(1))
+        arg2 = get_box_replacement(op.getarg(1))
         b2 = self.getintbound(arg2)
 
         # If one side of the op is 1 the result is the other side.
@@ -276,8 +275,8 @@
         # Constant fold f0 * 1.0 and turn f0 * -1.0 into a FLOAT_NEG, these
         # work in all cases, including NaN and inf
         for lhs, rhs in [(arg1, arg2), (arg2, arg1)]:
-            v1 = self.get_box_replacement(lhs)
-            v2 = self.get_box_replacement(rhs)
+            v1 = get_box_replacement(lhs)
+            v2 = get_box_replacement(rhs)
 
             if v1.is_constant():
                 if v1.getfloat() == 1.0:
@@ -295,7 +294,7 @@
     def optimize_FLOAT_TRUEDIV(self, op):
         arg1 = op.getarg(0)
         arg2 = op.getarg(1)
-        v2 = self.get_box_replacement(arg2)
+        v2 = get_box_replacement(arg2)
 
         # replace "x / const" by "x * (1/const)" if possible
         newop = op
@@ -331,7 +330,7 @@
                                       'was proven to always fail' % r)
                 return
         elif box.type == 'r':
-            box = self.get_box_replacement(box)
+            box = get_box_replacement(box)
             if box.is_constant():
                 if not box.same_constant(constbox):
                     r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(
@@ -343,7 +342,7 @@
         return self.emit(op)
 
     def optimize_GUARD_ISNULL(self, op):
-        info = self.getptrinfo(op.getarg(0))
+        info = getptrinfo(op.getarg(0))
         if info is not None:
             if info.is_null():
                 return
@@ -357,11 +356,11 @@
         self.make_constant(op.getarg(0), CONST_NULL)
 
     def optimize_GUARD_IS_OBJECT(self, op):
-        info = self.getptrinfo(op.getarg(0))
+        info = getptrinfo(op.getarg(0))
         if info and info.is_constant():
             if info.is_null():
                 raise InvalidLoop("A GUARD_IS_OBJECT(NULL) found")
-            c = self.get_box_replacement(op.getarg(0))
+            c = get_box_replacement(op.getarg(0))
             if self.optimizer.cpu.check_is_object(c.getref_base()):
                 return
             raise InvalidLoop("A GUARD_IS_OBJECT(not-an-object) found")
@@ -373,9 +372,9 @@
         return self.emit(op)
 
     def optimize_GUARD_GC_TYPE(self, op):
-        info = self.getptrinfo(op.getarg(0))
+        info = getptrinfo(op.getarg(0))
         if info and info.is_constant():
-            c = self.get_box_replacement(op.getarg(0))
+            c = get_box_replacement(op.getarg(0))
             tid = self.optimizer.cpu.get_actual_typeid(c.getref_base())
             if tid != op.getarg(1).getint():
                 raise InvalidLoop("wrong GC type ID found on a constant")
@@ -387,12 +386,12 @@
         return self.emit(op)
 
     def optimize_GUARD_SUBCLASS(self, op):
-        info = self.getptrinfo(op.getarg(0))
+        info = getptrinfo(op.getarg(0))
         optimizer = self.optimizer
         # must raise 'InvalidLoop' in all cases where 'info' shows the
         # class cannot possibly match (see test_issue2926)
         if info and info.is_constant():
-            c = self.get_box_replacement(op.getarg(0))
+            c = get_box_replacement(op.getarg(0))
             vtable = optimizer.cpu.cls_of_box(c).getint()
             if optimizer._check_subclass(vtable, op.getarg(1).getint()):
                 return
@@ -426,7 +425,7 @@
         return self.emit(op)


More information about the pypy-commit mailing list