[pypy-commit] pypy py3.6: merge default

cfbolz pypy.commits at gmail.com
Wed Jun 5 05:32:05 EDT 2019


Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: py3.6
Changeset: r96747:0ffff10dd2bc
Date: 2019-06-05 11:31 +0200
http://bitbucket.org/pypy/pypy/changeset/0ffff10dd2bc/

Log:	merge default

diff too long, truncating to 2000 out of 7324 lines

diff --git a/extra_tests/cffi_tests/cffi0/test_parsing.py b/extra_tests/cffi_tests/cffi0/test_parsing.py
--- a/extra_tests/cffi_tests/cffi0/test_parsing.py
+++ b/extra_tests/cffi_tests/cffi0/test_parsing.py
@@ -410,7 +410,17 @@
 def test_enum():
     ffi = FFI()
     ffi.cdef("""
-        enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1, OP = (POS+TWO)-1};
+        enum Enum {
+            POS = +1,
+            TWO = 2,
+            NIL = 0,
+            NEG = -1,
+            ADDSUB = (POS+TWO)-1,
+            DIVMULINT = (3 * 3) / 2,
+            SHIFT = (1 << 3) >> 1,
+            BINOPS = (0x7 & 0x1) | 0x8,
+            XOR = 0xf ^ 0xa
+        };
         """)
     needs_dlopen_none()
     C = ffi.dlopen(None)
@@ -418,7 +428,11 @@
     assert C.TWO == 2
     assert C.NIL == 0
     assert C.NEG == -1
-    assert C.OP == 2
+    assert C.ADDSUB == 2
+    assert C.DIVMULINT == 4
+    assert C.SHIFT == 4
+    assert C.BINOPS == 0b1001
+    assert C.XOR == 0b0101
 
 def test_stdcall():
     ffi = FFI()
diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py
--- a/extra_tests/cffi_tests/cffi0/test_verify.py
+++ b/extra_tests/cffi_tests/cffi0/test_verify.py
@@ -2535,3 +2535,29 @@
         x.p = p
         x.cyclic = x
         del p, x
+
+def test_arithmetic_in_cdef():
+    for a in [0, 11, 15]:
+        ffi = FFI()
+        ffi.cdef("""
+            enum FOO {
+                DIVNN = ((-?) / (-3)),
+                DIVNP = ((-?) / (+3)),
+                DIVPN = ((+?) / (-3)),
+                MODNN = ((-?) % (-3)),
+                MODNP = ((-?) % (+3)),
+                MODPN = ((+?) % (-3)),
+                };
+        """.replace('?', str(a)))
+        lib = ffi.verify("""
+            enum FOO {
+                DIVNN = ((-?) / (-3)),
+                DIVNP = ((-?) / (+3)),
+                DIVPN = ((+?) / (-3)),
+                MODNN = ((-?) % (-3)),
+                MODNP = ((-?) % (+3)),
+                MODPN = ((+?) % (-3)),
+                };
+        """.replace('?', str(a)))
+        # the verify() crashes if the values in the enum are different from
+        # the values we computed ourselves from the cdef()
diff --git a/extra_tests/cffi_tests/cffi0/test_zintegration.py b/extra_tests/cffi_tests/cffi0/test_zintegration.py
--- a/extra_tests/cffi_tests/cffi0/test_zintegration.py
+++ b/extra_tests/cffi_tests/cffi0/test_zintegration.py
@@ -2,11 +2,13 @@
 import py, os, sys, shutil
 import subprocess
 from extra_tests.cffi_tests.udir import udir
+import pytest
 
 if sys.platform == 'win32':
-    py.test.skip('snippets do not run on win32')
+    pytestmark = pytest.mark.skip('snippets do not run on win32')
 if sys.version_info < (2, 7):
-    py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
+    pytestmark = pytest.mark.skip(
+                 'fails e.g. on a Debian/Ubuntu which patches virtualenv'
                  ' in a non-2.6-friendly way')
 
 def create_venv(name):
diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py
--- a/extra_tests/cffi_tests/cffi1/test_recompiler.py
+++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py
@@ -2339,3 +2339,24 @@
         typedef int foo_t; struct foo_s { void (*x)(foo_t); };
     """)
     py.test.raises(TypeError, ffi.new, "struct foo_s *")
+
+def test_from_buffer_struct():
+    ffi = FFI()
+    ffi.cdef("""struct foo_s { int a, b; };""")
+    lib = verify(ffi, "test_from_buffer_struct_p", """
+        struct foo_s { int a, b; };
+    """)
+    p = ffi.new("struct foo_s *", [-219239, 58974983])
+    q = ffi.from_buffer("struct foo_s[]", ffi.buffer(p))
+    assert ffi.typeof(q) == ffi.typeof("struct foo_s[]")
+    assert len(q) == 1
+    assert q[0].a == p.a
+    assert q[0].b == p.b
+    assert q == p
+    q = ffi.from_buffer("struct foo_s *", ffi.buffer(p))
+    assert ffi.typeof(q) == ffi.typeof("struct foo_s *")
+    assert q.a == p.a
+    assert q.b == p.b
+    assert q[0].a == p.a
+    assert q[0].b == p.b
+    assert q == p
diff --git a/extra_tests/cffi_tests/embedding/test_basic.py b/extra_tests/cffi_tests/embedding/test_basic.py
--- a/extra_tests/cffi_tests/embedding/test_basic.py
+++ b/extra_tests/cffi_tests/embedding/test_basic.py
@@ -64,8 +64,8 @@
         output = popen.stdout.read()
         err = popen.wait()
         if err:
-            raise OSError("popen failed with exit code %r: %r" % (
-                err, args))
+            raise OSError(("popen failed with exit code %r: %r\n\n%s" % (
+                err, args, output)).rstrip())
         print(output.rstrip())
         return output
 
diff --git a/extra_tests/cffi_tests/embedding/test_performance.py b/extra_tests/cffi_tests/embedding/test_performance.py
--- a/extra_tests/cffi_tests/embedding/test_performance.py
+++ b/extra_tests/cffi_tests/embedding/test_performance.py
@@ -3,8 +3,8 @@
 from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
 
 if sys.platform == 'win32':
-    import py
-    py.test.skip("written with POSIX functions")
+    import pytest
+    pytestmark = pytest.mark.skip("written with POSIX functions")
 
 
 class TestPerformance(EmbeddingTests):
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.12.3
+Version: 1.13.0
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -5,8 +5,8 @@
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 from .error import PkgConfigError
 
-__version__ = "1.12.3"
-__version_info__ = (1, 12, 3)
+__version__ = "1.13.0"
+__version_info__ = (1, 13, 0)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -145,6 +145,7 @@
     int result;
     PyGILState_STATE state;
     PyObject *pycode=NULL, *global_dict=NULL, *x;
+    PyObject *builtins;
 
     state = PyGILState_Ensure();
 
@@ -169,7 +170,7 @@
     global_dict = PyDict_New();
     if (global_dict == NULL)
         goto error;
-    PyObject *builtins = PyEval_GetBuiltins();
+    builtins = PyEval_GetBuiltins();
     if (builtins == NULL)
         goto error;
     if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
@@ -223,7 +224,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.12.3"
+                               "\ncompiled with cffi version: 1.13.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -858,19 +858,39 @@
                            "the actual array length in this context"
                            % exprnode.coord.line)
         #
-        if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and
-                exprnode.op == '+'):
-            return (self._parse_constant(exprnode.left) +
-                    self._parse_constant(exprnode.right))
-        #
-        if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and
-                exprnode.op == '-'):
-            return (self._parse_constant(exprnode.left) -
-                    self._parse_constant(exprnode.right))
+        if isinstance(exprnode, pycparser.c_ast.BinaryOp):
+            left = self._parse_constant(exprnode.left)
+            right = self._parse_constant(exprnode.right)
+            if exprnode.op == '+':
+                return left + right
+            elif exprnode.op == '-':
+                return left - right
+            elif exprnode.op == '*':
+                return left * right
+            elif exprnode.op == '/':
+                return self._c_div(left, right)
+            elif exprnode.op == '%':
+                return left - self._c_div(left, right) * right
+            elif exprnode.op == '<<':
+                return left << right
+            elif exprnode.op == '>>':
+                return left >> right
+            elif exprnode.op == '&':
+                return left & right
+            elif exprnode.op == '|':
+                return left | right
+            elif exprnode.op == '^':
+                return left ^ right
         #
         raise FFIError(":%d: unsupported expression: expected a "
                        "simple numeric constant" % exprnode.coord.line)
 
+    def _c_div(self, a, b):
+        result = a // b
+        if ((a < 0) ^ (b < 0)) and (a % b) != 0:
+            result += 1
+        return result
+
     def _build_enum_type(self, explicit_name, decls):
         if decls is not None:
             partial = False
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -38,3 +38,7 @@
 .. branch: fix-vmprof-memory-tracking
 
 Fix a bug that prevent memory-tracking in vmprof working on PyPy.
+
+.. branch: optimizeopt-cleanup
+
+Cleanup optimizeopt
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.12.3"
+VERSION = "1.13.0"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -670,11 +670,14 @@
         return self.length
 
     def _repr_extra(self):
-        if self.w_keepalive is not None:
-            name = self.space.type(self.w_keepalive).name
+        from pypy.module._cffi_backend import ctypearray
+        if self.w_keepalive is None:
+            return "buffer RELEASED"
+        obj_tp_name = self.space.type(self.w_keepalive).name
+        if isinstance(self.ctype, ctypearray.W_CTypeArray):
+            return "buffer len %d from '%s' object" % (self.length, obj_tp_name)
         else:
-            name = "(released)"
-        return "buffer len %d from '%s' object" % (self.length, name)
+            return "buffer from '%s' object" % (obj_tp_name,)
 
     def enter_exit(self, exit_now):
         # for now, limited effect on PyPy
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -112,9 +112,10 @@
 
 @unwrap_spec(w_ctype=ctypeobj.W_CType, require_writable=int)
 def from_buffer(space, w_ctype, w_x, require_writable=0):
-    from pypy.module._cffi_backend import ctypearray
-    if not isinstance(w_ctype, ctypearray.W_CTypeArray):
-        raise oefmt(space.w_TypeError, "expected an array ctype, got '%s'",
+    from pypy.module._cffi_backend import ctypeptr, ctypearray
+    if not isinstance(w_ctype, ctypeptr.W_CTypePtrOrArray):
+        raise oefmt(space.w_TypeError,
+                    "expected a poiunter or array ctype, got '%s'",
                     w_ctype.name)
     if space.isinstance_w(w_x, space.w_unicode):
         raise oefmt(space.w_TypeError,
@@ -135,33 +136,36 @@
                         "raw address on PyPy", w_x)
     #
     buffersize = buf.getlength()
-    arraylength = w_ctype.length
-    if arraylength >= 0:
-        # it's an array with a fixed length; make sure that the
-        # buffer contains enough bytes.
-        if buffersize < w_ctype.size:
-            raise oefmt(space.w_ValueError,
-                "buffer is too small (%d bytes) for '%s' (%d bytes)",
-                buffersize, w_ctype.name, w_ctype.size)
+    if not isinstance(w_ctype, ctypearray.W_CTypeArray):
+        arraylength = buffersize   # number of bytes, not used so far
     else:
-        # it's an open 'array[]'
-        itemsize = w_ctype.ctitem.size
-        if itemsize == 1:
-            # fast path, performance only
-            arraylength = buffersize
-        elif itemsize > 0:
-            # give it as many items as fit the buffer.  Ignore a
-            # partial last element.
-            arraylength = buffersize / itemsize
+        arraylength = w_ctype.length
+        if arraylength >= 0:
+            # it's an array with a fixed length; make sure that the
+            # buffer contains enough bytes.
+            if buffersize < w_ctype.size:
+                raise oefmt(space.w_ValueError,
+                    "buffer is too small (%d bytes) for '%s' (%d bytes)",
+                    buffersize, w_ctype.name, w_ctype.size)
         else:
-            # it's an array 'empty[]'.  Unsupported obscure case:
-            # the problem is that setting the length of the result
-            # to anything large (like SSIZE_T_MAX) is dangerous,
-            # because if someone tries to loop over it, it will
-            # turn effectively into an infinite loop.
-            raise oefmt(space.w_ZeroDivisionError,
-                "from_buffer('%s', ..): the actual length of the array "
-                "cannot be computed", w_ctype.name)
+            # it's an open 'array[]'
+            itemsize = w_ctype.ctitem.size
+            if itemsize == 1:
+                # fast path, performance only
+                arraylength = buffersize
+            elif itemsize > 0:
+                # give it as many items as fit the buffer.  Ignore a
+                # partial last element.
+                arraylength = buffersize / itemsize
+            else:
+                # it's an array 'empty[]'.  Unsupported obscure case:
+                # the problem is that setting the length of the result
+                # to anything large (like SSIZE_T_MAX) is dangerous,
+                # because if someone tries to loop over it, it will
+                # turn effectively into an infinite loop.
+                raise oefmt(space.w_ZeroDivisionError,
+                    "from_buffer('%s', ..): the actual length of the array "
+                    "cannot be computed", w_ctype.name)
     #
     return cdataobj.W_CDataFromBuffer(space, _cdata, arraylength,
                                       w_ctype, buf, w_x)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.12.3", ("This test_c.py file is for testing a version"
+assert __version__ == "1.13.0", ("This test_c.py file is for testing a version"
                                  " of cffi that differs from the one that we"
                                  " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
@@ -3830,7 +3830,9 @@
     BIntP = new_pointer_type(BInt)
     BIntA = new_array_type(BIntP, None)
     lst = [-12345678, 87654321, 489148]
-    bytestring = buffer(newp(BIntA, lst))[:] + b'XYZ'
+    bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
+    lst2 = lst + [42, -999999999]
+    bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ')
     #
     p1 = from_buffer(BIntA, bytestring)      # int[]
     assert typeof(p1) is BIntA
@@ -3844,7 +3846,19 @@
         p1[-1]
     #
     py.test.raises(TypeError, from_buffer, BInt, bytestring)
-    py.test.raises(TypeError, from_buffer, BIntP, bytestring)
+    #
+    p2 = from_buffer(BIntP, bytestring)      # int *
+    assert p2 == p1 or 'PY_DOT_PY' in globals()
+    # note: on py.py ^^^, bytearray buffers are not emulated well enough
+    assert typeof(p2) is BIntP
+    assert p2[0] == lst[0]
+    assert p2[1] == lst[1]
+    assert p2[2] == lst[2]
+    # hopefully does not crash, but doesn't raise an exception:
+    p2[3]
+    p2[-1]
+    # not enough data even for one, but this is not enforced:
+    from_buffer(BIntP, b"")
     #
     BIntA2 = new_array_type(BIntP, 2)
     p2 = from_buffer(BIntA2, bytestring)     # int[2]
@@ -3856,7 +3870,7 @@
         p2[2]
     with pytest.raises(IndexError):
         p2[-1]
-    assert p2 == p1
+    assert p2 == p1 or 'PY_DOT_PY' in globals()
     #
     BIntA4 = new_array_type(BIntP, 4)        # int[4]: too big
     py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
@@ -3866,13 +3880,37 @@
                                        ('a2', BInt, -1)])
     BStructP = new_pointer_type(BStruct)
     BStructA = new_array_type(BStructP, None)
-    p1 = from_buffer(BStructA, bytestring)   # struct[]
-    assert len(p1) == 1
+    p1 = from_buffer(BStructA, bytestring2)   # struct[]
+    assert len(p1) == 2
     assert typeof(p1) is BStructA
-    assert p1[0].a1 == lst[0]
-    assert p1[0].a2 == lst[1]
+    assert p1[0].a1 == lst2[0]
+    assert p1[0].a2 == lst2[1]
+    assert p1[1].a1 == lst2[2]
+    assert p1[1].a2 == lst2[3]
     with pytest.raises(IndexError):
-        p1[1]
+        p1[2]
+    with pytest.raises(IndexError):
+        p1[-1]
+    assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>"
+    #
+    p2 = from_buffer(BStructP, bytestring2)    # 'struct *'
+    assert p2 == p1 or 'PY_DOT_PY' in globals()
+    assert typeof(p2) is BStructP
+    assert p2.a1 == lst2[0]
+    assert p2.a2 == lst2[1]
+    assert p2[0].a1 == lst2[0]
+    assert p2[0].a2 == lst2[1]
+    assert p2[1].a1 == lst2[2]
+    assert p2[1].a2 == lst2[3]
+    # does not crash:
+    p2[2]
+    p2[-1]
+    # not enough data even for one, but this is not enforced:
+    from_buffer(BStructP, b"")
+    from_buffer(BStructP, b"1234567")
+    #
+    release(p1)
+    assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>"
     #
     BEmptyStruct = new_struct_type("empty")
     complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
@@ -3886,7 +3924,37 @@
     p1 = from_buffer(BEmptyStructA5, bytestring)   # struct empty[5]
     assert typeof(p1) is BEmptyStructA5
     assert len(p1) == 5
-    assert cast(BIntP, p1) == from_buffer(BIntA, bytestring)
+    assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring)
+            or 'PY_DOT_PY' in globals())
+    #
+    BVarStruct = new_struct_type("varfoo")
+    BVarStructP = new_pointer_type(BVarStruct)
+    complete_struct_or_union(BVarStruct, [('a1', BInt, -1),
+                                          ('va', BIntA, -1)])
+    with pytest.raises(TypeError):
+        from_buffer(BVarStruct, bytestring)
+    pv = from_buffer(BVarStructP, bytestring)    # varfoo *
+    assert pv.a1 == lst[0]
+    assert pv.va[0] == lst[1]
+    assert pv.va[1] == lst[2]
+    assert sizeof(pv[0]) == 1 * size_of_int()
+    with pytest.raises(TypeError):
+        len(pv.va)
+    # hopefully does not crash, but doesn't raise an exception:
+    pv.va[2]
+    pv.va[-1]
+    # not enough data even for one, but this is not enforced:
+    from_buffer(BVarStructP, b"")
+    assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>"
+    assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
+    #
+    release(pv)
+    assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>"
+    assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
+    #
+    pv = from_buffer(BVarStructP, bytestring)    # make a fresh one
+    with pytest.raises(ValueError):
+        release(pv[0])
 
 def test_memmove():
     Short = new_primitive_type("short")
@@ -4312,8 +4380,10 @@
     BCharA = new_array_type(BCharP, None)
     p = from_buffer(BCharA, a)
     assert p[2] == b"z"
+    assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
     release(p)
     assert p[2] == b"z"  # true so far, but might change to raise RuntimeError
+    assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
     release(p)   # no effect
 
 def test_explicit_release_from_buffer_contextmgr():
@@ -4325,6 +4395,7 @@
     with p:
         assert p[2] == b"z"
     assert p[2] == b"z"  # true so far, but might change to raise RuntimeError
+    assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
     release(p)   # no effect
 
 def test_explicit_release_bytearray_on_cpython():
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -2,6 +2,8 @@
 
 import sys
 
+import sys
+
 from rpython.rlib.objectmodel import (
     compute_hash, compute_unique_id, import_from_mixin, always_inline,
     enforceargs, newlist_hint, specialize, we_are_translated)
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)
-


More information about the pypy-commit mailing list