Author: Maciej Fijalkowski <[email protected]>
Branch: vmprof
Changeset: r74968:060eabccb5b8
Date: 2014-12-17 14:01 +0100
http://bitbucket.org/pypy/pypy/changeset/060eabccb5b8/

Log:    merge default

diff too long, truncating to 2000 out of 2100 lines

diff --git a/lib-python/2.7/sqlite3/test/dbapi.py 
b/lib-python/2.7/sqlite3/test/dbapi.py
--- a/lib-python/2.7/sqlite3/test/dbapi.py
+++ b/lib-python/2.7/sqlite3/test/dbapi.py
@@ -478,6 +478,29 @@
         except TypeError:
             pass
 
+    def CheckCurDescription(self):
+        self.cu.execute("select * from test")
+
+        actual = self.cu.description
+        expected = [
+            ('id', None, None, None, None, None, None),
+            ('name', None, None, None, None, None, None),
+            ('income', None, None, None, None, None, None),
+        ]
+        self.assertEqual(expected, actual)
+
+    def CheckCurDescriptionVoidStatement(self):
+        self.cu.execute("insert into test(name) values (?)", ("foo",))
+        self.assertIsNone(self.cu.description)
+
+    def CheckCurDescriptionWithoutStatement(self):
+        cu = self.cx.cursor()
+        try:
+            self.assertIsNone(cu.description)
+        finally:
+            cu.close()
+
+
 @unittest.skipUnless(threading, 'This test requires threading.')
 class ThreadTests(unittest.TestCase):
     def setUp(self):
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -1175,8 +1175,9 @@
         try:
             return self.__description
         except AttributeError:
-            self.__description = self.__statement._get_description()
-            return self.__description
+            if self.__statement:
+                self.__description = self.__statement._get_description()
+                return self.__description
     description = property(__get_description)
 
     def __get_lastrowid(self):
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -125,6 +125,8 @@
         else:
             return self.space.builtin
 
+    _NO_CELLS = []
+
     @jit.unroll_safe
     def initialize_frame_scopes(self, outer_func, code):
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
@@ -143,7 +145,7 @@
         nfreevars = len(code.co_freevars)
         if not nfreevars:
             if not ncellvars:
-                self.cells = []
+                self.cells = self._NO_CELLS
                 return            # no self.cells needed - fast path
         elif outer_func is None:
             space = self.space
diff --git a/pypy/module/cpyext/frameobject.py 
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -58,7 +58,7 @@
     w_globals = from_ref(space, py_frame.c_f_globals)
 
     frame = space.FrameClass(space, code, w_globals, outer_func=None)
-    frame.f_lineno = py_frame.c_f_lineno
+    frame.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno')
     w_obj = space.wrap(frame)
     track_reference(space, py_obj, w_obj)
     return w_obj
diff --git a/pypy/module/micronumpy/flagsobj.py 
b/pypy/module/micronumpy/flagsobj.py
--- a/pypy/module/micronumpy/flagsobj.py
+++ b/pypy/module/micronumpy/flagsobj.py
@@ -5,46 +5,26 @@
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.module.micronumpy import constants as NPY
-
+from pypy.module.micronumpy.strides import is_c_contiguous, is_f_contiguous
 
 def enable_flags(arr, flags):
     arr.flags |= flags
 
-
 def clear_flags(arr, flags):
     arr.flags &= ~flags
 
-
[email protected]_safe
 def _update_contiguous_flags(arr):
-    shape = arr.shape
-    strides = arr.strides
-
-    is_c_contig = True
-    sd = arr.dtype.elsize
-    for i in range(len(shape) - 1, -1, -1):
-        dim = shape[i]
-        if strides[i] != sd:
-            is_c_contig = False
-            break
-        if dim == 0:
-            break
-        sd *= dim
+    is_c_contig = is_c_contiguous(arr)
     if is_c_contig:
         enable_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
     else:
         clear_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
 
-    sd = arr.dtype.elsize
-    for i in range(len(shape)):
-        dim = shape[i]
-        if strides[i] != sd:
-            clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
-            return
-        if dim == 0:
-            break
-        sd *= dim
-    enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
+    is_f_contig = is_f_contiguous(arr)
+    if is_f_contig:
+        enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
+    else:
+        clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
 
 
 class W_FlagsObject(W_Root):
diff --git a/pypy/module/micronumpy/ndarray.py 
b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -19,7 +19,7 @@
     order_converter, shape_converter, searchside_converter
 from pypy.module.micronumpy.flagsobj import W_FlagsObject
 from pypy.module.micronumpy.strides import get_shape_from_iterable, \
-    shape_agreement, shape_agreement_multiple
+    shape_agreement, shape_agreement_multiple, is_c_contiguous, is_f_contiguous
 
 
 def _match_dot_shapes(space, left, right):
@@ -837,7 +837,15 @@
                 raise OperationError(space.w_ValueError, space.wrap(
                     "new type not compatible with array."))
         else:
-            if dims == 1 or impl.get_strides()[0] < impl.get_strides()[-1]:
+            if not is_c_contiguous(impl) and not is_f_contiguous(impl):
+                if old_itemsize != new_itemsize:
+                    raise OperationError(space.w_ValueError, space.wrap(
+                        "new type not compatible with array."))
+                # Strides, shape does not change
+                v = impl.astype(space, dtype)
+                return wrap_impl(space, w_type, self, v) 
+            strides = impl.get_strides()
+            if dims == 1 or strides[0] <strides[-1]:
                 # Column-major, resize first dimension
                 if new_shape[0] * old_itemsize % new_itemsize != 0:
                     raise OperationError(space.w_ValueError, space.wrap(
diff --git a/pypy/module/micronumpy/strides.py 
b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -429,3 +429,35 @@
                     n_old_elems_to_use *= old_shape[oldI]
     assert len(new_strides) == len(new_shape)
     return new_strides[:]
+
[email protected]_safe
+def is_c_contiguous(arr):
+    shape = arr.get_shape()
+    strides = arr.get_strides()
+    ret = True
+    sd = arr.dtype.elsize
+    for i in range(len(shape) - 1, -1, -1):
+        dim = shape[i]
+        if strides[i] != sd:
+            ret = False
+            break
+        if dim == 0:
+            break
+        sd *= dim
+    return ret
+
[email protected]_safe
+def is_f_contiguous(arr):
+    shape = arr.get_shape()
+    strides = arr.get_strides()
+    ret = True
+    sd = arr.dtype.elsize
+    for i in range(len(shape)):
+        dim = shape[i]
+        if strides[i] != sd:
+            ret = False
+            break
+        if dim == 0:
+            break
+        sd *= dim
+    return ret
diff --git a/pypy/module/micronumpy/test/test_iterators.py 
b/pypy/module/micronumpy/test/test_iterators.py
--- a/pypy/module/micronumpy/test/test_iterators.py
+++ b/pypy/module/micronumpy/test/test_iterators.py
@@ -13,6 +13,11 @@
         self.strides = strides
         self.start = start
 
+    def get_shape(self):
+        return self.shape
+
+    def get_strides(self):
+        return self.strides
 
 class TestIterDirect(object):
     def test_iterator_basic(self):
diff --git a/pypy/module/micronumpy/test/test_ndarray.py 
b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -1807,6 +1807,17 @@
         x = array([], dtype=[('a', 'int8'), ('b', 'int8')])
         y = x.view(dtype='int16')
 
+    def test_view_of_slice(self):
+        from numpy import empty
+        x = empty([6], 'uint32')
+        x.fill(0xdeadbeef)
+        s = x[::3]
+        exc = raises(ValueError, s.view, 'uint8')
+        assert exc.value[0] == 'new type not compatible with array.'
+        s[...] = 2
+        v = s.view(x.__class__)
+        assert (v == 2).all()
+    
     def test_tolist_scalar(self):
         from numpy import dtype
         int32 = dtype('int32').type
@@ -2912,11 +2923,7 @@
         a = empty(10, dtype=[(_, int) for _ in 'abcde'])
         a.fill(123)
         for i in a:
-            import sys
-            if '__pypy__' in sys.builtin_module_names:
-                assert tuple(i) == (123,) + (0,) * 4
-            else:
-                assert tuple(i) == (123,) * 5
+            assert tuple(i) == (123,) * 5
 
         a = zeros(3, dtype=dtype(complex).newbyteorder())
         a.fill(1.5+2.5j)
@@ -3846,7 +3853,7 @@
         a = np.array([b, b, b], dtype=dt)
         assert a.shape == (3, 2)
         for i in a.flat:
-            assert tuple(i) == (True, False)
+            assert tuple(i) == (True, True)
 
         dt = np.dtype([('A', '<i8'), ('B', '<f8'), ('C', '<c16')])
         b = np.array((999999, 1e+20, 1e+20+0j), dtype=dt)
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -311,26 +311,26 @@
     BoxType = boxes.W_BoolBox
     format_code = "?"
 
-    True = BoxType(True)
-    False = BoxType(False)
+    _True = BoxType(True)
+    _False = BoxType(False)
 
     @specialize.argtype(1)
     def box(self, value):
         box = Primitive.box(self, value)
         if box.value:
-            return self.True
+            return self._True
         else:
-            return self.False
+            return self._False
 
     @specialize.argtype(1, 2)
     def box_complex(self, real, imag):
         box = Primitive.box(self, real)
         if box.value:
-            return self.True
+            return self._True
         box = Primitive.box(self, imag)
         if box.value:
-            return self.True
-        return self.False
+            return self._True
+        return self._False
 
     def coerce_subtype(self, space, w_subtype, w_item):
         # Doesn't return subclasses so it can return the constants.
@@ -1869,7 +1869,7 @@
                 items_w = space.fixedview(w_item.get_scalar_value())
             else:
                 # XXX support initializing from readable buffers
-                items_w = [w_item]
+                items_w = [w_item] * len(dtype.fields)
         else:
             items_w = [None] * len(dtype.fields)
         arr = VoidBoxStorage(dtype.elsize, dtype)
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py 
b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -415,9 +415,12 @@
         self.match_descr(op.descr, exp_descr)
 
 
-    def _next_op(self, iter_ops, assert_raises=False):
+    def _next_op(self, iter_ops, assert_raises=False, ignore_ops=set()):
         try:
-            op = iter_ops.next()
+            while True:
+                op = iter_ops.next()
+                if op.name not in ignore_ops:
+                    break
         except StopIteration:
             self._assert(assert_raises, "not enough operations")
             return
@@ -454,9 +457,7 @@
         else:
             assert 0, "'{{{' not followed by '}}}'"
         while exp_ops:
-            op = self._next_op(iter_ops)
-            if op.name in ignore_ops:
-                continue
+            op = self._next_op(iter_ops, ignore_ops=ignore_ops)
             # match 'op' against any of the exp_ops; the first successful
             # match is kept, and the exp_op gets removed from the list
             for i, exp_op in enumerate(exp_ops):
@@ -491,10 +492,7 @@
                     self.match_any_order(iter_exp_ops, iter_ops, ignore_ops)
                     continue
                 else:
-                    while True:
-                        op = self._next_op(iter_ops)
-                        if op.name not in ignore_ops:
-                            break
+                    op = self._next_op(iter_ops, ignore_ops=ignore_ops)
                 self.match_op(op, exp_op)
             except InvalidMatch, e:
                 if type(exp_op) is not str and exp_op[4] is False:    # 
optional operation
@@ -504,7 +502,7 @@
                 raise
         #
         # make sure we exhausted iter_ops
-        self._next_op(iter_ops, assert_raises=True)
+        self._next_op(iter_ops, assert_raises=True, ignore_ops=ignore_ops)
 
     def match(self, expected_src, ignore_ops=[]):
         def format(src, opindex=None):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py 
b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -318,6 +318,16 @@
             jump(i4, descr=...)
         """
         assert self.match(loop, expected, ignore_ops=['force_token'])
+        #
+        loop = """
+            [i0]
+            i1 = int_add(i0, 1)
+            i4 = force_token()
+        """
+        expected = """
+            i1 = int_add(i0, 1)
+        """
+        assert self.match(loop, expected, ignore_ops=['force_token'])
 
     def test_match_dots_in_arguments(self):
         loop = """
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py 
b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -342,9 +342,9 @@
         guard_false(i114, descr=...)
         --TICK--
         i119 = call(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, 
descr=<Calli . i EF=4 OS=110>)
-        raw_store(i119, 0, i112, descr=<ArrayS 2>)
-        raw_store(i119, 2, i112, descr=<ArrayS 2>)
-        raw_store(i119, 4, i112, descr=<ArrayS 2>)
+        raw_store(i119, 0, i160, descr=<ArrayS 2>)
+        raw_store(i119, 2, i160, descr=<ArrayS 2>)
+        raw_store(i119, 4, i160, descr=<ArrayS 2>)
         setfield_gc(p167, i119, descr=<FieldU 
pypy.module._cffi_backend.cdataobj.W_CData.inst__cdata .+>)
         i123 = arraylen_gc(p67, descr=<ArrayP .>)
         jump(..., descr=...)
diff --git a/pypy/module/test_lib_pypy/test_datetime.py 
b/pypy/module/test_lib_pypy/test_datetime.py
--- a/pypy/module/test_lib_pypy/test_datetime.py
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -3,6 +3,7 @@
 from __future__ import absolute_import
 import py
 
+
 class BaseTestDatetime:
     def test_repr(self):
         print datetime
@@ -210,11 +211,13 @@
             naive == aware
         assert str(e.value) == "can't compare offset-naive and offset-aware 
times"
 
-class TestDatetimeCPython(BaseTestDatetime):
+
+class TestDatetimeHost(BaseTestDatetime):
     def setup_class(cls):
         global datetime
         import datetime
 
+
 class TestDatetimePyPy(BaseTestDatetime):
     def setup_class(cls):
         global datetime
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py 
b/pypy/module/test_lib_pypy/test_sqlite3.py
--- a/pypy/module/test_lib_pypy/test_sqlite3.py
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -1,267 +1,285 @@
 # -*- coding: utf-8 -*-
 """Tests for _sqlite3.py"""
 
-import pytest, sys
+from __future__ import absolute_import
+import pytest
+import sys
 
-if sys.version_info < (2, 7):
-    pytest.skip("_sqlite3 requires Python 2.7")
-try:
-    import _cffi_backend
-except ImportError:
-    # On CPython, "pip install cffi".  On old PyPy's, no chance
-    pytest.skip("_sqlite3 requires _cffi_backend to be installed")
-
-from lib_pypy import _sqlite3
 
 def pytest_funcarg__con(request):
     con = _sqlite3.connect(':memory:')
     request.addfinalizer(lambda: con.close())
     return con
 
-def test_list_ddl(con):
-    """From issue996.  Mostly just looking for lack of exceptions."""
-    cursor = con.cursor()
-    cursor.execute('CREATE TABLE foo (bar INTEGER)')
-    result = list(cursor)
-    assert result == []
-    cursor.execute('INSERT INTO foo (bar) VALUES (42)')
-    result = list(cursor)
-    assert result == []
-    cursor.execute('SELECT * FROM foo')
-    result = list(cursor)
-    assert result == [(42,)]
 
-def test_connect_takes_same_positional_args_as_Connection(con):
-    from inspect import getargspec
-    clsargs = getargspec(_sqlite3.Connection.__init__).args[1:]  # ignore self
-    conargs = getargspec(_sqlite3.connect).args
-    assert clsargs == conargs
+class BaseTestSQLite:
+    def test_list_ddl(self, con):
+        """From issue996.  Mostly just looking for lack of exceptions."""
+        cursor = con.cursor()
+        cursor.execute('CREATE TABLE foo (bar INTEGER)')
+        result = list(cursor)
+        assert result == []
+        cursor.execute('INSERT INTO foo (bar) VALUES (42)')
+        result = list(cursor)
+        assert result == []
+        cursor.execute('SELECT * FROM foo')
+        result = list(cursor)
+        assert result == [(42,)]
 
-def test_total_changes_after_close(con):
-    con.close()
-    pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
+    def test_connect_takes_same_positional_args_as_Connection(self, con):
+        if not hasattr(_sqlite3, '_ffi'):
+            pytest.skip("only works for lib_pypy _sqlite3")
+        from inspect import getargspec
+        clsargs = getargspec(_sqlite3.Connection.__init__).args[1:]  # ignore 
self
+        conargs = getargspec(_sqlite3.connect).args
+        assert clsargs == conargs
 
-def test_connection_check_init():
-    class Connection(_sqlite3.Connection):
-        def __init__(self, name):
+    def test_total_changes_after_close(self, con):
+        con.close()
+        pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
+
+    def test_connection_check_init(self):
+        class Connection(_sqlite3.Connection):
+            def __init__(self, name):
+                pass
+
+        con = Connection(":memory:")
+        e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()")
+        assert '__init__' in e.value.message
+
+    def test_cursor_check_init(self, con):
+        class Cursor(_sqlite3.Cursor):
+            def __init__(self, name):
+                pass
+
+        cur = Cursor(con)
+        e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')")
+        assert '__init__' in e.value.message
+
+    def test_connection_after_close(self, con):
+        pytest.raises(TypeError, "con()")
+        con.close()
+        # raises ProgrammingError because should check closed before check args
+        pytest.raises(_sqlite3.ProgrammingError, "con()")
+
+    def test_cursor_iter(self, con):
+        cur = con.cursor()
+        with pytest.raises(StopIteration):
+            next(cur)
+
+        cur.execute('select 1')
+        next(cur)
+        with pytest.raises(StopIteration):
+            next(cur)
+
+        cur.execute('select 1')
+        con.commit()
+        next(cur)
+        with pytest.raises(StopIteration):
+            next(cur)
+
+        with pytest.raises(_sqlite3.ProgrammingError):
+            cur.executemany('select 1', [])
+        with pytest.raises(StopIteration):
+            next(cur)
+
+        cur.execute('select 1')
+        cur.execute('create table test(ing)')
+        with pytest.raises(StopIteration):
+            next(cur)
+
+        cur.execute('select 1')
+        cur.execute('insert into test values(1)')
+        con.commit()
+        with pytest.raises(StopIteration):
+            next(cur)
+
+    def test_cursor_after_close(self, con):
+        cur = con.execute('select 1')
+        cur.close()
+        con.close()
+        pytest.raises(_sqlite3.ProgrammingError, "cur.close()")
+        # raises ProgrammingError because should check closed before check args
+        pytest.raises(_sqlite3.ProgrammingError, "cur.execute(1,2,3,4,5)")
+        pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)")
+
+    @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')")
+    def test_connection_del(self, tmpdir):
+        """For issue1325."""
+        import os
+        import gc
+        try:
+            import resource
+        except ImportError:
+            pytest.skip("needs resource module")
+
+        limit = resource.getrlimit(resource.RLIMIT_NOFILE)
+        try:
+            fds = 0
+            while True:
+                fds += 1
+                resource.setrlimit(resource.RLIMIT_NOFILE, (fds, limit[1]))
+                try:
+                    for p in os.pipe(): os.close(p)
+                except OSError:
+                    assert fds < 100
+                else:
+                    break
+
+            def open_many(cleanup):
+                con = []
+                for i in range(3):
+                    con.append(_sqlite3.connect(str(tmpdir.join('test.db'))))
+                    if cleanup:
+                        con[i] = None
+                        gc.collect(); gc.collect()
+
+            pytest.raises(_sqlite3.OperationalError, open_many, False)
+            gc.collect(); gc.collect()
+            open_many(True)
+        finally:
+            resource.setrlimit(resource.RLIMIT_NOFILE, limit)
+
+    def test_on_conflict_rollback_executemany(self, con):
+        major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
+        if (int(major), int(minor), int(micro)) < (3, 2, 2):
+            pytest.skip("requires sqlite3 version >= 3.2.2")
+        con.execute("create table foo(x, unique(x) on conflict rollback)")
+        con.execute("insert into foo(x) values (1)")
+        try:
+            con.executemany("insert into foo(x) values (?)", [[1]])
+        except _sqlite3.DatabaseError:
             pass
+        con.execute("insert into foo(x) values (2)")
+        try:
+            con.commit()
+        except _sqlite3.OperationalError:
+            pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
 
-    con = Connection(":memory:")
-    e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()")
-    assert '__init__' in e.value.message
+    def test_statement_arg_checking(self, con):
+        with pytest.raises(_sqlite3.Warning) as e:
+            con(123)
+        assert str(e.value) == 'SQL is of wrong type. Must be string or 
unicode.'
+        with pytest.raises(ValueError) as e:
+            con.execute(123)
+        assert str(e.value) == 'operation parameter must be str or unicode'
+        with pytest.raises(ValueError) as e:
+            con.executemany(123, 123)
+        assert str(e.value) == 'operation parameter must be str or unicode'
+        with pytest.raises(ValueError) as e:
+            con.executescript(123)
+        assert str(e.value) == 'script argument must be unicode or string.'
 
-def test_cursor_check_init(con):
-    class Cursor(_sqlite3.Cursor):
-        def __init__(self, name):
-            pass
+    def test_statement_param_checking(self, con):
+        con.execute('create table foo(x)')
+        con.execute('insert into foo(x) values (?)', [2])
+        con.execute('insert into foo(x) values (?)', (2,))
+        class seq(object):
+            def __len__(self):
+                return 1
+            def __getitem__(self, key):
+                return 2
+        con.execute('insert into foo(x) values (?)', seq())
+        del seq.__len__
+        with pytest.raises(_sqlite3.ProgrammingError):
+            con.execute('insert into foo(x) values (?)', seq())
+        with pytest.raises(_sqlite3.ProgrammingError):
+            con.execute('insert into foo(x) values (?)', {2:2})
+        with pytest.raises(ValueError) as e:
+            con.execute('insert into foo(x) values (?)', 2)
+        assert str(e.value) == 'parameters are of unsupported type'
 
-    cur = Cursor(con)
-    e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')")
-    assert '__init__' in e.value.message
+    def test_explicit_begin(self, con):
+        con.execute('BEGIN')
+        con.execute('BEGIN ')
+        con.execute('BEGIN')
+        con.commit()
+        con.execute('BEGIN')
+        con.commit()
 
-def test_connection_after_close(con):
-    pytest.raises(TypeError, "con()")
-    con.close()
-    # raises ProgrammingError because should check closed before check args
-    pytest.raises(_sqlite3.ProgrammingError, "con()")
+    def test_row_factory_use(self, con):
+        con.row_factory = 42
+        con.execute('select 1')
 
-def test_cursor_iter(con):
-    cur = con.cursor()
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_returning_blob_must_own_memory(self, con):
+        import gc
+        con.create_function("returnblob", 0, lambda: buffer("blob"))
+        cur = con.execute("select returnblob()")
+        val = cur.fetchone()[0]
+        for i in range(5):
+            gc.collect()
+            got = (val[0], val[1], val[2], val[3])
+            assert got == ('b', 'l', 'o', 'b')
+        # in theory 'val' should be a read-write buffer
+        # but it's not right now
+        if not hasattr(_sqlite3, '_ffi'):
+            val[1] = 'X'
+            got = (val[0], val[1], val[2], val[3])
+            assert got == ('b', 'X', 'o', 'b')
 
-    cur.execute('select 1')
-    next(cur)
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_description_after_fetchall(self, con):
+        cur = con.cursor()
+        assert cur.description is None
+        cur.execute("select 42").fetchall()
+        assert cur.description is not None
 
-    cur.execute('select 1')
-    con.commit()
-    next(cur)
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_executemany_lastrowid(self, con):
+        cur = con.cursor()
+        cur.execute("create table test(a)")
+        cur.executemany("insert into test values (?)", [[1], [2], [3]])
+        assert cur.lastrowid is None
 
-    with pytest.raises(_sqlite3.ProgrammingError):
-        cur.executemany('select 1', [])
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_authorizer_bad_value(self, con):
+        def authorizer_cb(action, arg1, arg2, dbname, source):
+            return 42
+        con.set_authorizer(authorizer_cb)
+        with pytest.raises(_sqlite3.OperationalError) as e:
+            con.execute('select 123')
+        major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
+        if (int(major), int(minor), int(micro)) >= (3, 6, 14):
+            assert str(e.value) == 'authorizer malfunction'
+        else:
+            assert str(e.value) == \
+                ("illegal return value (1) from the authorization function - "
+                 "should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY")
 
-    cur.execute('select 1')
-    cur.execute('create table test(ing)')
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_issue1573(self, con):
+        cur = con.cursor()
+        cur.execute(u'SELECT 1 as m&#233;il')
+        assert cur.description[0][0] == u"m&#233;il".encode('utf-8')
 
-    cur.execute('select 1')
-    cur.execute('insert into test values(1)')
-    con.commit()
-    with pytest.raises(StopIteration):
-        next(cur)
+    def test_adapter_exception(self, con):
+        def cast(obj):
+            raise ZeroDivisionError
 
-def test_cursor_after_close(con):
-    cur = con.execute('select 1')
-    cur.close()
-    con.close()
-    pytest.raises(_sqlite3.ProgrammingError, "cur.close()")
-    # raises ProgrammingError because should check closed before check args
-    pytest.raises(_sqlite3.ProgrammingError, "cur.execute(1,2,3,4,5)")
-    pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)")
+        _sqlite3.register_adapter(int, cast)
+        try:
+            cur = con.cursor()
+            cur.execute("select ?", (4,))
+            val = cur.fetchone()[0]
+            # Adapter error is ignored, and parameter is passed as is.
+            assert val == 4
+            assert type(val) is int
+        finally:
+            del _sqlite3.adapters[(int, _sqlite3.PrepareProtocol)]
 
[email protected]("not hasattr(sys, 'pypy_translation_info')")
-def test_connection_del(tmpdir):
-    """For issue1325."""
-    import os
-    import gc
-    try:
-        import resource
-    except ImportError:
-        pytest.skip("needs resource module")
 
-    limit = resource.getrlimit(resource.RLIMIT_NOFILE)
-    try:
-        fds = 0
-        while True:
-            fds += 1
-            resource.setrlimit(resource.RLIMIT_NOFILE, (fds, limit[1]))
-            try:
-                for p in os.pipe(): os.close(p)
-            except OSError:
-                assert fds < 100
-            else:
-                break
-        def open_many(cleanup):
-            con = []
-            for i in range(3):
-                con.append(_sqlite3.connect(str(tmpdir.join('test.db'))))
-                if cleanup:
-                    con[i] = None
-                    gc.collect(); gc.collect()
+class TestSQLiteHost(BaseTestSQLite):
+    def setup_class(cls):
+        global _sqlite3
+        import _sqlite3
 
-        pytest.raises(_sqlite3.OperationalError, open_many, False)
-        gc.collect(); gc.collect()
-        open_many(True)
-    finally:
-        resource.setrlimit(resource.RLIMIT_NOFILE, limit)
 
-def test_on_conflict_rollback_executemany(con):
-    major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
-    if (int(major), int(minor), int(micro)) < (3, 2, 2):
-        pytest.skip("requires sqlite3 version >= 3.2.2")
-    con.execute("create table foo(x, unique(x) on conflict rollback)")
-    con.execute("insert into foo(x) values (1)")
-    try:
-        con.executemany("insert into foo(x) values (?)", [[1]])
-    except _sqlite3.DatabaseError:
-        pass
-    con.execute("insert into foo(x) values (2)")
-    try:
-        con.commit()
-    except _sqlite3.OperationalError:
-        pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
+class TestSQLitePyPy(BaseTestSQLite):
+    def setup_class(cls):
+        if sys.version_info < (2, 7):
+            pytest.skip("_sqlite3 requires Python 2.7")
 
-def test_statement_arg_checking(con):
-    with pytest.raises(_sqlite3.Warning) as e:
-        con(123)
-    assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.'
-    with pytest.raises(ValueError) as e:
-        con.execute(123)
-    assert str(e.value) == 'operation parameter must be str or unicode'
-    with pytest.raises(ValueError) as e:
-        con.executemany(123, 123)
-    assert str(e.value) == 'operation parameter must be str or unicode'
-    with pytest.raises(ValueError) as e:
-        con.executescript(123)
-    assert str(e.value) == 'script argument must be unicode or string.'
+        try:
+            import _cffi_backend
+        except ImportError:
+            # On CPython, "pip install cffi".  On old PyPy's, no chance
+            pytest.skip("_sqlite3 requires _cffi_backend to be installed")
 
-def test_statement_param_checking(con):
-    con.execute('create table foo(x)')
-    con.execute('insert into foo(x) values (?)', [2])
-    con.execute('insert into foo(x) values (?)', (2,))
-    class seq(object):
-        def __len__(self):
-            return 1
-        def __getitem__(self, key):
-            return 2
-    con.execute('insert into foo(x) values (?)', seq())
-    del seq.__len__
-    with pytest.raises(_sqlite3.ProgrammingError):
-        con.execute('insert into foo(x) values (?)', seq())
-    with pytest.raises(_sqlite3.ProgrammingError):
-        con.execute('insert into foo(x) values (?)', {2:2})
-    with pytest.raises(ValueError) as e:
-        con.execute('insert into foo(x) values (?)', 2)
-    assert str(e.value) == 'parameters are of unsupported type'
-
-def test_explicit_begin(con):
-    con.execute('BEGIN')
-    con.execute('BEGIN ')
-    con.execute('BEGIN')
-    con.commit()
-    con.execute('BEGIN')
-    con.commit()
-
-def test_row_factory_use(con):
-    con.row_factory = 42
-    con.execute('select 1')
-
-def test_returning_blob_must_own_memory(con):
-    import gc
-    con.create_function("returnblob", 0, lambda: buffer("blob"))
-    cur = con.execute("select returnblob()")
-    val = cur.fetchone()[0]
-    for i in range(5):
-        gc.collect()
-        got = (val[0], val[1], val[2], val[3])
-        assert got == ('b', 'l', 'o', 'b')
-    # in theory 'val' should be a read-write buffer
-    # but it's not right now
-    pytest.skip("in theory 'val' should be a read-write buffer")
-    val[1] = 'X'
-    got = (val[0], val[1], val[2], val[3])
-    assert got == ('b', 'X', 'o', 'b')
-
-def test_description_after_fetchall(con):
-    cur = con.cursor()
-    cur.execute("select 42").fetchall()
-    assert cur.description is not None
-
-def test_executemany_lastrowid(con):
-    cur = con.cursor()
-    cur.execute("create table test(a)")
-    cur.executemany("insert into test values (?)", [[1], [2], [3]])
-    assert cur.lastrowid is None
-
-
-def test_authorizer_bad_value(con):
-    def authorizer_cb(action, arg1, arg2, dbname, source):
-        return 42
-    con.set_authorizer(authorizer_cb)
-    with pytest.raises(_sqlite3.OperationalError) as e:
-        con.execute('select 123')
-    major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
-    if (int(major), int(minor), int(micro)) >= (3, 6, 14):
-        assert str(e.value) == 'authorizer malfunction'
-    else:
-        assert str(e.value) == \
-            ("illegal return value (1) from the authorization function - "
-             "should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY")
-
-
-def test_issue1573(con):
-    cur = con.cursor()
-    cur.execute(u'SELECT 1 as m&#233;il')
-    assert cur.description[0][0] == u"m&#233;il".encode('utf-8')
-
-def test_adapter_exception(con):
-    def cast(obj):
-        raise ZeroDivisionError
-
-    _sqlite3.register_adapter(int, cast)
-    try:
-        cur = con.cursor()
-        cur.execute("select ?", (4,))
-        val = cur.fetchone()[0]
-        # Adapter error is ignored, and parameter is passed as is.
-        assert val == 4
-        assert type(val) is int
-    finally:
-        del _sqlite3.adapters[(int, _sqlite3.PrepareProtocol)]
+        global _sqlite3
+        from lib_pypy import _sqlite3
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -366,8 +366,12 @@
             tup = w_self._lookup_where(name)
             return tup
         name = promote_string(name)
-        w_class, w_value = w_self._pure_lookup_where_with_method_cache(name, 
version_tag)
-        return w_class, unwrap_cell(space, w_value)
+        tup_w = w_self._pure_lookup_where_with_method_cache(name, version_tag)
+        w_class, w_value = tup_w
+        if (space.config.objspace.std.withtypeversion and
+                isinstance(w_value, TypeCell)):
+            return w_class, w_value.w_value
+        return tup_w   # don't make a new tuple, reuse the old one
 
     def _pure_lookup_where_possibly_with_method_cache(w_self, name, 
version_tag):
         if w_self.space.config.objspace.std.withmethodcache:
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -19,7 +19,7 @@
 from rpython.annotator import description
 from rpython.annotator.signature import annotationoftype
 from rpython.annotator.argument import simple_args
-from rpython.rlib.objectmodel import r_dict, Symbolic
+from rpython.rlib.objectmodel import r_dict, r_ordereddict, Symbolic
 from rpython.tool.algo.unionfind import UnionFind
 from rpython.rtyper import extregistry
 
@@ -260,21 +260,23 @@
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
-        elif tp is dict or tp is r_dict or tp is SomeOrderedDict.knowntype:
-            if tp is SomeOrderedDict.knowntype:
-                cls = SomeOrderedDict
-            else:
-                cls = SomeDict
+        elif (tp is dict or tp is r_dict or
+              tp is SomeOrderedDict.knowntype or tp is r_ordereddict):
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
+                if tp is SomeOrderedDict.knowntype or tp is r_ordereddict:
+                    cls = SomeOrderedDict
+                else:
+                    cls = SomeDict
+                is_r_dict = issubclass(tp, r_dict)
                 result = cls(DictDef(self,
                                         s_ImpossibleValue,
                                         s_ImpossibleValue,
-                                        is_r_dict = tp is r_dict))
+                                        is_r_dict = is_r_dict))
                 self.immutable_cache[key] = result
-                if tp is r_dict:
+                if is_r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(s_eqfn,
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
@@ -74,7 +74,6 @@
             # for a CALL_ASSEMBLER: record it as a potential jump.
             if descr is not original_jitcell_token:
                 original_jitcell_token.record_jump_to(descr)
-            descr.exported_state = None
             op.cleardescr()    # clear reference, mostly for tests
         elif isinstance(descr, TargetToken):
             # for a JUMP: record it as a potential jump.
@@ -84,10 +83,6 @@
             if descr.original_jitcell_token is not original_jitcell_token:
                 assert descr.original_jitcell_token is not None
                 
original_jitcell_token.record_jump_to(descr.original_jitcell_token)
-            # exported_state is clear by optimizeopt when the short preamble is
-            # constrcucted. if that did not happen the label should not show up
-            # in a trace that will be used
-            assert descr.exported_state is None
             if not we_are_translated():
                 op._descr_wref = weakref.ref(op._descr)
             op.cleardescr()    # clear reference to prevent the history.Stats
@@ -133,7 +128,7 @@
                       [ResOperation(rop.LABEL, jumpargs, None, 
descr=jitcell_token)]
 
     try:
-        optimize_trace(metainterp_sd, part, enable_opts)
+        start_state = optimize_trace(metainterp_sd, part, enable_opts)
     except InvalidLoop:
         return None
     target_token = part.operations[0].getdescr()
@@ -146,7 +141,7 @@
     loop.quasi_immutable_deps = {}
     if part.quasi_immutable_deps:
         loop.quasi_immutable_deps.update(part.quasi_immutable_deps)
-    while part.operations[-1].getopnum() == rop.LABEL:
+    if part.operations[-1].getopnum() == rop.LABEL:
         inliner = Inliner(inputargs, jumpargs)
         part.quasi_immutable_deps = None
         part.operations = [part.operations[-1]] + \
@@ -160,13 +155,15 @@
         jumpargs = part.operations[-1].getarglist()
 
         try:
-            optimize_trace(metainterp_sd, part, enable_opts)
+            optimize_trace(metainterp_sd, part, enable_opts,
+                           start_state=start_state)
         except InvalidLoop:
             return None
 
         loop.operations = loop.operations[:-1] + part.operations
         if part.quasi_immutable_deps:
             loop.quasi_immutable_deps.update(part.quasi_immutable_deps)
+    assert part.operations[-1].getopnum() != rop.LABEL
 
     if not loop.quasi_immutable_deps:
         loop.quasi_immutable_deps = None
@@ -186,7 +183,7 @@
 
 def compile_retrace(metainterp, greenkey, start,
                     inputargs, jumpargs,
-                    partial_trace, resumekey):
+                    partial_trace, resumekey, start_state):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
@@ -211,18 +208,19 @@
     orignial_label = label.clone()
     assert label.getopnum() == rop.LABEL
     try:
-        optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
+        optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts,
+                       start_state=start_state)
     except InvalidLoop:
         # Fall back on jumping to preamble
         target_token = label.getdescr()
         assert isinstance(target_token, TargetToken)
-        assert target_token.exported_state
         part.operations = [orignial_label] + \
                           [ResOperation(rop.JUMP, inputargs[:],
                                         None, descr=loop_jitcell_token)]
         try:
-            optimize_trace(metainterp_sd, part, 
jitdriver_sd.warmstate.enable_opts,
-                           inline_short_preamble=False)
+            optimize_trace(metainterp_sd, part,
+                           jitdriver_sd.warmstate.enable_opts,
+                           inline_short_preamble=False, 
start_state=start_state)
         except InvalidLoop:
             return None
     assert part.operations[-1].getopnum() != rop.LABEL
@@ -791,7 +789,7 @@
     else:
         inline_short_preamble = True
     try:
-        optimize_trace(metainterp_sd, new_trace, state.enable_opts, 
inline_short_preamble)
+        state = optimize_trace(metainterp_sd, new_trace, state.enable_opts, 
inline_short_preamble)
     except InvalidLoop:
         debug_print("compile_new_bridge: got an InvalidLoop")
         # XXX I am fairly convinced that optimize_bridge cannot actually raise
@@ -807,7 +805,7 @@
         record_loop_or_bridge(metainterp_sd, new_trace)
         return target_token
     else:
-        metainterp.retrace_needed(new_trace)
+        metainterp.retrace_needed(new_trace, state)
         return None
 
 # ____________________________________________________________
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
@@ -617,7 +617,6 @@
         self.original_jitcell_token = None
 
         self.virtual_state = None
-        self.exported_state = None
         self.short_preamble = None
 
     def repr_of_descr(self):
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -178,13 +178,6 @@
             fail_args = ''
         return s_offset + res + op.getopname() + '(' + args + ')' + fail_args
 
-    def _log_inputarg_setup_ops(self, op):
-        target_token = op.getdescr()
-        if isinstance(target_token, TargetToken):
-            if target_token.exported_state:
-                for op in target_token.exported_state.inputarg_setup_ops:
-                    debug_print('    ' + self.repr_of_resop(op))
-
     def _log_operations(self, inputargs, operations, ops_offset):
         if not have_debug_prints():
             return
@@ -194,10 +187,10 @@
             args = ", ".join([self.repr_of_arg(arg) for arg in inputargs])
             debug_print('[' + args + ']')
         for i in range(len(operations)):
-            op = operations[i]
+            #op = operations[i]
             debug_print(self.repr_of_resop(operations[i], ops_offset))
-            if op.getopnum() == rop.LABEL:
-                self._log_inputarg_setup_ops(op)
+            #if op.getopnum() == rop.LABEL:
+            #    self._log_inputarg_setup_ops(op)
         if ops_offset and None in ops_offset:
             offset = ops_offset[None]
             debug_print("+%d: --end of the loop--" % offset)
diff --git a/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
@@ -47,7 +47,8 @@
 
     return optimizations, unroll
 
-def optimize_trace(metainterp_sd, loop, enable_opts, 
inline_short_preamble=True):
+def optimize_trace(metainterp_sd, loop, enable_opts,
+                   inline_short_preamble=True, start_state=None):
     """Optimize loop.operations to remove internal overheadish operations.
     """
 
@@ -57,7 +58,8 @@
                                                           loop.operations)
         optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts)
         if unroll:
-            optimize_unroll(metainterp_sd, loop, optimizations, 
inline_short_preamble)
+            return optimize_unroll(metainterp_sd, loop, optimizations,
+                                   inline_short_preamble, start_state)
         else:
             optimizer = Optimizer(metainterp_sd, loop, optimizations)
             optimizer.propagate_all_forward()
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
@@ -42,8 +42,9 @@
             oldop = self.pure_operations.get(args, None)
             if oldop is not None and oldop.getdescr() is op.getdescr():
                 assert oldop.getopnum() == op.getopnum()
-                self.optimizer.make_equal_to(op.result, 
self.getvalue(oldop.result),
-                                   True)
+                self.optimizer.make_equal_to(op.result,
+                                             self.getvalue(oldop.result),
+                                             True)
                 return
             else:
                 self.pure_operations[args] = op
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py 
b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -32,6 +32,7 @@
                   if op.getopnum()==rop.LABEL]
         prv = 0
         last_label = []
+        state = None
         for nxt in labels + [len(loop.operations)]:
             assert prv != nxt
             operations = last_label + loop.operations[prv:nxt]
@@ -44,7 +45,7 @@
             part.operations = operations
 
             self.add_guard_future_condition(part)
-            self._do_optimize_loop(part, None)
+            state = self._do_optimize_loop(part, None, state)
             if part.operations[-1].getopnum() == rop.LABEL:
                 last_label = [part.operations.pop()]
             else:
@@ -496,7 +497,7 @@
 
 class BaseTestOptimizerRenamingBoxes(BaseTestMultiLabel):
 
-    def _do_optimize_loop(self, loop, call_pure_results):
+    def _do_optimize_loop(self, loop, call_pure_results, state):
         from rpython.jit.metainterp.optimizeopt.unroll import optimize_unroll
         from rpython.jit.metainterp.optimizeopt.util import args_dict
         from rpython.jit.metainterp.optimizeopt.pure import OptPure
@@ -504,7 +505,7 @@
         self.loop = loop
         loop.call_pure_results = args_dict()
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
-        optimize_unroll(metainterp_sd, loop, [OptRewrite(), OptRenameStrlen(), 
OptHeap(), OptPure()], True)
+        return optimize_unroll(metainterp_sd, loop, [OptRewrite(), 
OptRenameStrlen(), OptHeap(), OptPure()], True, state)
 
     def test_optimizer_renaming_boxes1(self):
         ops = """
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py 
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -390,7 +390,7 @@
         assert equaloplists(optimized.operations,
                             expected.operations, False, remap, text_right)
 
-    def _do_optimize_loop(self, loop, call_pure_results):
+    def _do_optimize_loop(self, loop, call_pure_results, start_state=None):
         from rpython.jit.metainterp.optimizeopt import optimize_trace
         from rpython.jit.metainterp.optimizeopt.util import args_dict
 
@@ -405,7 +405,8 @@
         if hasattr(self, 'callinfocollection'):
             metainterp_sd.callinfocollection = self.callinfocollection
         #
-        optimize_trace(metainterp_sd, loop, self.enable_opts)
+        return optimize_trace(metainterp_sd, loop, self.enable_opts,
+                              start_state=start_state)
 
     def unroll_and_optimize(self, loop, call_pure_results=None):
         self.add_guard_future_condition(loop)
@@ -425,7 +426,7 @@
         preamble.operations = [ResOperation(rop.LABEL, inputargs, None, 
descr=TargetToken(token))] + \
                               operations +  \
                               [ResOperation(rop.LABEL, jump_args, None, 
descr=token)]
-        self._do_optimize_loop(preamble, call_pure_results)
+        start_state = self._do_optimize_loop(preamble, call_pure_results)
 
         assert preamble.operations[-1].getopnum() == rop.LABEL
 
@@ -439,7 +440,7 @@
         assert loop.operations[0].getopnum() == rop.LABEL
         loop.inputargs = loop.operations[0].getarglist()
 
-        self._do_optimize_loop(loop, call_pure_results)
+        self._do_optimize_loop(loop, call_pure_results, start_state)
         extra_same_as = []
         while loop.operations[0].getopnum() != rop.LABEL:
             extra_same_as.append(loop.operations[0])
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py 
b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -15,10 +15,11 @@
 
 # FIXME: Introduce some VirtualOptimizer super class instead
 
-def optimize_unroll(metainterp_sd, loop, optimizations, 
inline_short_preamble=True):
+def optimize_unroll(metainterp_sd, loop, optimizations,
+                    inline_short_preamble=True, start_state=None):
     opt = UnrollOptimizer(metainterp_sd, loop, optimizations)
     opt.inline_short_preamble = inline_short_preamble
-    opt.propagate_all_forward()
+    return opt.propagate_all_forward(start_state)
 
 
 class UnrollableOptimizer(Optimizer):
@@ -69,7 +70,7 @@
         prev = self.fix_snapshot(jump_args, snapshot.prev)
         return Snapshot(prev, new_snapshot_args)
 
-    def propagate_all_forward(self):
+    def propagate_all_forward(self, starting_state):
         loop = self.optimizer.loop
         self.optimizer.clear_newoperations()
 
@@ -94,7 +95,7 @@
         else:
             jumpop = None
 
-        self.import_state(start_label)
+        self.import_state(start_label, starting_state)
         self.optimizer.propagate_all_forward(clear=False)
 
         if not jumpop:
@@ -147,8 +148,9 @@
         KillHugeIntBounds(self.optimizer).apply()
 
         loop.operations = self.optimizer.get_newoperations()
-        self.export_state(stop_label)
+        final_state = self.export_state(stop_label)
         loop.operations.append(stop_label)
+        return final_state
 
     def jump_to_start_label(self, start_label, stop_label):
         if not start_label or not stop_label:
@@ -202,10 +204,9 @@
                 box = op.result
                 exported_values[box] = self.optimizer.getvalue(box)
 
-        target_token.exported_state = ExportedState(short_boxes, 
inputarg_setup_ops,
-                                                    exported_values)
+        return ExportedState(short_boxes, inputarg_setup_ops, exported_values)
 
-    def import_state(self, targetop):
+    def import_state(self, targetop, exported_state):
         if not targetop: # Trace did not start with a label
             self.inputargs = self.optimizer.loop.inputargs
             self.short = None
@@ -215,7 +216,6 @@
         self.inputargs = targetop.getarglist()
         target_token = targetop.getdescr()
         assert isinstance(target_token, TargetToken)
-        exported_state = target_token.exported_state
         if not exported_state:
             # No state exported, construct one without virtuals
             self.short = None
@@ -413,7 +413,6 @@
             if op.result:
                 op.result.forget_value()
         target_token.short_preamble = self.short
-        target_token.exported_state = None
 
     def ensure_short_op_emitted(self, op, optimizer, seen):
         if op is None:
@@ -561,7 +560,9 @@
 
             try:
                 # NB: the short_preamble ends with a jump
-                self._inline_short_preamble(target.short_preamble, inliner, 
patchguardop, target.assumed_classes)
+                self._inline_short_preamble(target.short_preamble, inliner,
+                                            patchguardop,
+                                            target.assumed_classes)
             except InvalidLoop:
                 #debug_print("Inlining failed unexpectedly",
                 #            "jumping to preamble instead")
@@ -572,7 +573,8 @@
         debug_stop('jit-log-virtualstate')
         return False
 
-    def _inline_short_preamble(self, short_preamble, inliner, patchguardop, 
assumed_classes):
+    def _inline_short_preamble(self, short_preamble, inliner, patchguardop,
+                               assumed_classes):
         i = 1
         # XXX this is intentiontal :-(. short_preamble can change during the
         # loop in some cases
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -585,13 +585,13 @@
 
 
 class ShortBoxes(object):
-    def __init__(self, optimizer, surviving_boxes, availible_boxes=None):
+    def __init__(self, optimizer, surviving_boxes, available_boxes=None):
         self.potential_ops = {}
         self.alternatives = {}
         self.synthetic = {}
         self.rename = {}
         self.optimizer = optimizer
-        self.availible_boxes = availible_boxes
+        self.available_boxes = available_boxes
         self.assumed_classes = {}
 
         if surviving_boxes is not None:
@@ -663,7 +663,7 @@
             return
         if box in self.short_boxes_in_production:
             raise BoxNotProducable
-        if self.availible_boxes is not None and box not in 
self.availible_boxes:
+        if self.available_boxes is not None and box not in 
self.available_boxes:
             raise BoxNotProducable
         self.short_boxes_in_production[box] = None
 
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1730,6 +1730,7 @@
 class MetaInterp(object):
     portal_call_depth = 0
     cancel_count = 0
+    exported_state = None
 
     def __init__(self, staticdata, jitdriver_sd):
         self.staticdata = staticdata
@@ -1750,9 +1751,10 @@
         self.call_ids = []
         self.current_call_id = 0
 
-    def retrace_needed(self, trace):
+    def retrace_needed(self, trace, exported_state):
         self.partial_trace = trace
         self.retracing_from = len(self.history.operations) - 1
+        self.exported_state = exported_state
         self.heapcache.reset()
 
 
@@ -2249,7 +2251,9 @@
                         raise SwitchToBlackhole(Counters.ABORT_BAD_LOOP) # For 
now
                 # Found!  Compile it as a loop.
                 # raises in case it works -- which is the common case
-                self.compile_loop(original_boxes, live_arg_boxes, start)
+                self.compile_loop(original_boxes, live_arg_boxes, start,
+                                  exported_state=self.exported_state)
+                self.exported_state = None
                 # creation of the loop was cancelled!
                 self.cancel_count += 1
                 if self.staticdata.warmrunnerdesc:
@@ -2363,7 +2367,7 @@
         return token
 
     def compile_loop(self, original_boxes, live_arg_boxes, start,
-                     try_disabling_unroll=False):
+                     try_disabling_unroll=False, exported_state=None):
         num_green_args = self.jitdriver_sd.num_green_args
         greenkey = original_boxes[:num_green_args]
         if not self.partial_trace:
@@ -2377,7 +2381,8 @@
                                                    
original_boxes[num_green_args:],
                                                    
live_arg_boxes[num_green_args:],
                                                    self.partial_trace,
-                                                   self.resumekey)
+                                                   self.resumekey,
+                                                   exported_state)
         else:
             target_token = compile.compile_loop(self, greenkey, start,
                                                 
original_boxes[num_green_args:],
diff --git a/rpython/rlib/test/test_objectmodel.py 
b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -329,6 +329,18 @@
         res = self.interpret(g, [3])
         assert res == 42     # "did not crash"
 
+    def test_prepare_dict_update_2(self):
+        try:
+            from collections import OrderedDict
+        except ImportError:     # Python 2.6
+            py.test.skip("requires collections.OrderedDict")
+        def g(n):
+            d = OrderedDict()
+            prepare_dict_update(d, n)
+            return 42
+        res = self.interpret(g, [3])
+        assert res == 42     # "did not crash"
+
     def test_compute_hash(self):
         class Foo(object):
             pass
diff --git a/rpython/rtyper/lltypesystem/rdict.py 
b/rpython/rtyper/lltypesystem/rdict.py
--- a/rpython/rtyper/lltypesystem/rdict.py
+++ b/rpython/rtyper/lltypesystem/rdict.py
@@ -669,6 +669,7 @@
     d.num_items = 0
     d.resize_counter = DICT_INITSIZE * 2
     return d
+DictRepr.ll_newdict = staticmethod(ll_newdict)
 
 def ll_newdict_size(DICT, length_estimate):
     length_estimate = (length_estimate // 2) * 3
@@ -692,26 +693,6 @@
     pass
 
 
-def rtype_r_dict(hop, i_force_non_null=None):
-    r_dict = hop.r_result
-    if not r_dict.custom_eq_hash:
-        raise TyperError("r_dict() call does not return an r_dict instance")
-    v_eqfn = hop.inputarg(r_dict.r_rdict_eqfn, arg=0)
-    v_hashfn = hop.inputarg(r_dict.r_rdict_hashfn, arg=1)
-    if i_force_non_null is not None:
-        assert i_force_non_null == 2
-        hop.inputarg(lltype.Void, arg=2)
-    cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    hop.exception_cannot_occur()
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
-    if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyeq')
-        hop.genop('setfield', [v_result, cname, v_eqfn])
-    if r_dict.r_rdict_hashfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyhash')
-        hop.genop('setfield', [v_result, cname, v_hashfn])
-    return v_result
-
 # ____________________________________________________________
 #
 #  Iteration.
diff --git a/rpython/rtyper/lltypesystem/rordereddict.py 
b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -156,7 +156,7 @@
 
     def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
                  custom_eq_hash=None, force_non_null=False):
-        assert not force_non_null
+        #assert not force_non_null
         self.rtyper = rtyper
         self.finalized = False
         self.DICT = lltype.GcForwardReference()
@@ -232,6 +232,7 @@
                 raise TypeError("No prebuilt dicts of address keys")
             r_value = self.value_repr
             if isinstance(dictobj, objectmodel.r_dict):
+
                 if self.r_rdict_eqfn.lowleveltype != lltype.Void:
                     l_fn = self.r_rdict_eqfn.convert_const(dictobj.key_eq)
                     l_dict.fnkeyeq = l_fn
@@ -289,6 +290,11 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(ll_dict_update, v_dic1, v_dic2)
 
+    def rtype_method__prepare_dict_update(self, hop):
+        v_dict, v_num = hop.inputargs(self, lltype.Signed)
+        hop.exception_cannot_occur()
+        hop.gendirectcall(ll_prepare_dict_update, v_dict, v_num)
+
     def _rtype_method_kvi(self, hop, ll_func):
         v_dic, = hop.inputargs(self)
         r_list = hop.r_result
@@ -594,10 +600,12 @@
     else:
         newitems = d.entries
     #
-    ENTRY = lltype.typeOf(d).TO.entries.TO.OF
+    ENTRIES = lltype.typeOf(d).TO.entries.TO
+    ENTRY = ENTRIES.OF
     isrc = 0
     idst = 0
-    while isrc < len(d.entries):
+    isrclimit = d.num_used_items
+    while isrc < isrclimit:
         if d.entries.valid(isrc):
             src = d.entries[isrc]
             dst = newitems[idst]
@@ -610,9 +618,21 @@
                 dst.f_valid = True
             idst += 1
         isrc += 1
-    d.entries = newitems
     assert d.num_items == idst
     d.num_used_items = idst
+    if ((ENTRIES.must_clear_key or ENTRIES.must_clear_value) and
+            d.entries == newitems):
+        # must clear the extra entries: they may contain valid pointers
+        # which would create a temporary memory leak
+        while idst < isrclimit:
+            entry = newitems[idst]
+            if ENTRIES.must_clear_key:
+                entry.key = lltype.nullptr(ENTRY.key.TO)
+            if ENTRIES.must_clear_value:
+                entry.value = lltype.nullptr(ENTRY.value.TO)
+            idst += 1
+    else:
+        d.entries = newitems
 
     ll_dict_reindex(d, _ll_len_of_d_indexes(d))
 
@@ -653,11 +673,14 @@
     # make a 'new_size' estimate and shrink it if there are many
     # deleted entry markers.  See CPython for why it is a good idea to
     # quadruple the dictionary size as long as it's not too big.
-    num_items = d.num_items
-    if num_items > 50000:
-        new_estimate = num_items * 2
-    else:
-        new_estimate = num_items * 4
+    # (Quadrupling comes from '(d.num_items + d.num_items + 1) * 2'
+    # as long as num_items is not too large.)
+    num_extra = min(d.num_items + 1, 30000)
+    _ll_dict_resize_to(d, num_extra)
+ll_dict_resize.oopspec = 'odict.resize(d)'
+
+def _ll_dict_resize_to(d, num_extra):
+    new_estimate = (d.num_items + num_extra) * 2
     new_size = DICT_INITSIZE
     while new_size <= new_estimate:
         new_size *= 2
@@ -666,7 +689,6 @@
         ll_dict_remove_deleted_items(d)
     else:
         ll_dict_reindex(d, new_size)
-ll_dict_resize.oopspec = 'odict.resize(d)'
 
 def ll_dict_reindex(d, new_size):
     ll_malloc_indexes_and_choose_lookup(d, new_size)
@@ -831,6 +853,7 @@
     d.num_used_items = 0
     d.resize_counter = DICT_INITSIZE * 2
     return d
+OrderedDictRepr.ll_newdict = staticmethod(ll_newdict)
 
 def ll_newdict_size(DICT, orig_length_estimate):
     length_estimate = (orig_length_estimate // 2) * 3
@@ -856,23 +879,6 @@
     pass
 
 
-def rtype_r_dict(hop):
-    r_dict = hop.r_result
-    if not r_dict.custom_eq_hash:
-        raise TyperError("r_dict() call does not return an r_dict instance")
-    v_eqfn = hop.inputarg(r_dict.r_rdict_eqfn, arg=0)
-    v_hashfn = hop.inputarg(r_dict.r_rdict_hashfn, arg=1)
-    cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    hop.exception_cannot_occur()
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
-    if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyeq')
-        hop.genop('setfield', [v_result, cname, v_eqfn])
-    if r_dict.r_rdict_hashfn.lowleveltype != lltype.Void:
-        cname = hop.inputconst(lltype.Void, 'fnkeyhash')
-        hop.genop('setfield', [v_result, cname, v_hashfn])
-    return v_result
-
 # ____________________________________________________________
 #
 #  Iteration.
@@ -981,6 +987,9 @@
 ll_dict_clear.oopspec = 'odict.clear(d)'
 
 def ll_dict_update(dic1, dic2):
+    if dic1 == dic2:
+        return
+    ll_prepare_dict_update(dic1, dic2.num_items)
     i = 0
     while i < dic2.num_used_items:
         entries = dic2.entries
@@ -994,6 +1003,22 @@
         i += 1
 ll_dict_update.oopspec = 'odict.update(dic1, dic2)'
 
+def ll_prepare_dict_update(d, num_extra):
+    # Prescale 'd' for 'num_extra' items, assuming that most items don't
+    # collide.  If this assumption is false, 'd' becomes too large by at
+    # most 'num_extra'.  The logic is based on:
+    #      (d.resize_counter - 1) // 3 = room left in d
+    #  so, if num_extra == 1, we need d.resize_counter > 3
+    #      if num_extra == 2, we need d.resize_counter > 6  etc.
+    # Note however a further hack: if num_extra <= d.num_items,
+    # we avoid calling _ll_dict_resize_to here.  This is to handle
+    # the case where dict.update() actually has a lot of collisions.
+    # If num_extra is much greater than d.num_items the conditional_call
+    # will trigger anyway, which is really the goal.
+    x = num_extra - d.num_items
+    jit.conditional_call(d.resize_counter <= x * 3,
+                         _ll_dict_resize_to, d, num_extra)
+
 # this is an implementation of keys(), values() and items()
 # in a single function.
 # note that by specialization on func, three different
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -724,15 +724,16 @@
     raise TyperError("hasattr is only suported on a constant")
 
 @typer_for(annmodel.SomeOrderedDict.knowntype)
+@typer_for(objectmodel.r_dict)
 @typer_for(objectmodel.r_ordereddict)
-def rtype_ordered_dict(hop):
-    from rpython.rtyper.lltypesystem.rordereddict import ll_newdict
-
+def rtype_dict_constructor(hop, i_force_non_null=None):
+    # 'i_force_non_null' is ignored here; if it has any effect, it
+    # has already been applied to 'hop.r_result'
     hop.exception_cannot_occur()
     r_dict = hop.r_result
     cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
-    if hasattr(r_dict, 'r_dict_eqfn'):
+    v_result = hop.gendirectcall(r_dict.ll_newdict, cDICT)
+    if r_dict.custom_eq_hash:
         v_eqfn = hop.inputarg(r_dict.r_rdict_eqfn, arg=0)
         v_hashfn = hop.inputarg(r_dict.r_rdict_hashfn, arg=1)
         if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
@@ -743,9 +744,6 @@
             hop.genop('setfield', [v_result, cname, v_hashfn])
     return v_result
 
-from rpython.rtyper.lltypesystem.rdict import rtype_r_dict
-typer_for(objectmodel.r_dict)(rtype_r_dict)
-
 # _________________________________________________________________
 # weakrefs
 
diff --git a/rpython/rtyper/rdict.py b/rpython/rtyper/rdict.py
--- a/rpython/rtyper/rdict.py
+++ b/rpython/rtyper/rdict.py
@@ -57,11 +57,10 @@
 
 
 def rtype_newdict(hop):
-    from rpython.rtyper.lltypesystem.rdict import ll_newdict
     hop.inputargs()    # no arguments expected
     r_dict = hop.r_result
     cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
-    v_result = hop.gendirectcall(ll_newdict, cDICT)
+    v_result = hop.gendirectcall(r_dict.ll_newdict, cDICT)
     return v_result
 
 
diff --git a/rpython/rtyper/test/test_rdict.py 
b/rpython/rtyper/test/test_rdict.py
--- a/rpython/rtyper/test/test_rdict.py
+++ b/rpython/rtyper/test/test_rdict.py
@@ -878,6 +878,81 @@
         res = self.interpret(func, [])
         assert lltype.typeOf(res.item0) == lltype.typeOf(res.item1)
 
+    def test_r_dict(self):
+        class FooError(Exception):
+            pass
+        def myeq(n, m):
+            return n == m
+        def myhash(n):
+            if n < 0:
+                raise FooError
+            return -n
+        def f(n):
+            d = self.new_r_dict(myeq, myhash)
+            for i in range(10):
+                d[i] = i*i
+            try:
+                value1 = d[n]
+            except FooError:
+                value1 = 99
+            try:
+                value2 = n in d
+            except FooError:
+                value2 = 99
+            try:
+                value3 = d[-n]
+            except FooError:
+                value3 = 99
+            try:
+                value4 = (-n) in d
+            except FooError:
+                value4 = 99
+            return (value1 * 1000000 +
+                    value2 * 10000 +
+                    value3 * 100 +
+                    value4)
+        res = self.interpret(f, [5])
+        assert res == 25019999
+
+    def test_r_dict_popitem_hash(self):
+        def deq(n, m):
+            return n == m
+        def dhash(n):
+            return ~n
+        def func():
+            d = self.new_r_dict(deq, dhash)
+            d[5] = 2
+            d[6] = 3
+            k1, v1 = d.popitem()
+            assert len(d) == 1
+            k2, v2 = d.popitem()
+            try:
+                d.popitem()
+            except KeyError:
+                pass
+            else:
+                assert 0, "should have raised KeyError"
+            assert len(d) == 0
+            return k1*1000 + v1*100 + k2*10 + v2
+
+        res = self.interpret(func, [])
+        assert res in [5263, 6352]
+
+    def test_prebuilt_r_dict(self):
+        def deq(n, m):
+            return (n & 3) == (m & 3)
+        def dhash(n):
+            return n & 3
+        d = self.new_r_dict(deq, dhash)
+        d[0x123] = "abcd"
+        d[0x231] = "efgh"
+        def func():
+            return d[0x348973] + d[0x12981]
+
+        res = self.interpret(func, [])
+        res = self.ll_to_string(res)
+        assert res == "abcdefgh"
+
 
 class TestRDict(BaseTestRDict):
     @staticmethod
@@ -888,6 +963,10 @@
     def newdict2():
         return {}
 
+    @staticmethod
+    def new_r_dict(myeq, myhash):
+        return r_dict(myeq, myhash)
+
     def test_two_dicts_with_different_value_types(self):
         def func(i):
             d1 = {}
@@ -1043,66 +1122,6 @@
         assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2)
         assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3)
 
-    def test_r_dict(self):
-        class FooError(Exception):
-            pass
-        def myeq(n, m):
-            return n == m
-        def myhash(n):
-            if n < 0:
-                raise FooError
-            return -n
-        def f(n):
-            d = r_dict(myeq, myhash)
-            for i in range(10):
-                d[i] = i*i
-            try:
-                value1 = d[n]
-            except FooError:
-                value1 = 99
-            try:
-                value2 = n in d
-            except FooError:
-                value2 = 99
-            try:
-                value3 = d[-n]
-            except FooError:
-                value3 = 99
-            try:
-                value4 = (-n) in d
-            except FooError:
-                value4 = 99
-            return (value1 * 1000000 +
-                    value2 * 10000 +
-                    value3 * 100 +
-                    value4)
-        res = self.interpret(f, [5])
-        assert res == 25019999
-
-    def test_dict_popitem_hash(self):
-        def deq(n, m):
-            return n == m
-        def dhash(n):
-            return ~n
-        def func():
-            d = r_dict(deq, dhash)
-            d[5] = 2
-            d[6] = 3
-            k1, v1 = d.popitem()
-            assert len(d) == 1
-            k2, v2 = d.popitem()
-            try:
-                d.popitem()
-            except KeyError:
-                pass
-            else:
-                assert 0, "should have raised KeyError"
-            assert len(d) == 0
-            return k1*1000 + v1*100 + k2*10 + v2
-
-        res = self.interpret(func, [])
-        assert res in [5263, 6352]
-
     def test_nonnull_hint(self):
         def eq(a, b):
             return a == b
diff --git a/rpython/rtyper/test/test_rordereddict.py 
b/rpython/rtyper/test/test_rordereddict.py
--- a/rpython/rtyper/test/test_rordereddict.py
+++ b/rpython/rtyper/test/test_rordereddict.py
@@ -251,6 +251,16 @@
         assert rordereddict.ll_dict_pop_default(ll_d, llstr("k"), 40) == 40
         assert rordereddict.ll_dict_pop_default(ll_d, llstr("j"), 39) == 39
 
+    def test_bug_remove_deleted_items(self):
+        DICT = self._get_str_dict()
+        ll_d = rordereddict.ll_newdict(DICT)
+        for i in range(15):
+            rordereddict.ll_dict_setitem(ll_d, llstr(chr(i)), 5)
+        for i in range(15):
+            rordereddict.ll_dict_delitem(ll_d, llstr(chr(i)))
+        rordereddict.ll_prepare_dict_update(ll_d, 7)
+        # used to get UninitializedMemoryAccess
+
 class TestRDictDirectDummyKey(TestRDictDirect):
     class dummykeyobj:
         ll_dummy_value = llstr("dupa")
@@ -268,6 +278,10 @@
     def newdict2():
         return OrderedDict()
 
+    @staticmethod
+    def new_r_dict(myeq, myhash):
+        return objectmodel.r_ordereddict(myeq, myhash)
+
     def test_two_dicts_with_different_value_types(self):
         def func(i):
             d1 = OrderedDict()
@@ -285,62 +299,124 @@
         py.test.skip("I don't want to edit this file on two branches")
 
 
-    def test_r_dict(self):
-        class FooError(Exception):
-            pass
-        def myeq(n, m):
-            return n == m
-        def myhash(n):
-            if n < 0:
-                raise FooError
-            return -n
-        def f(n):
-            d = objectmodel.r_ordereddict(myeq, myhash)
-            for i in range(10):
-                d[i] = i*i
-            try:
-                value1 = d[n]
-            except FooError:
-                value1 = 99
-            try:
-                value2 = n in d
-            except FooError:
-                value2 = 99
-            try:
-                value3 = d[-n]
-            except FooError:
-                value3 = 99
-            try:
-                value4 = (-n) in d
-            except FooError:
-                value4 = 99
-            return (value1 * 1000000 +
-                    value2 * 10000 +
-                    value3 * 100 +
-                    value4)
-        res = self.interpret(f, [5])
-        assert res == 25019999
+class TestStress:
 
-    def test_dict_popitem_hash(self):
-        def deq(n, m):
-            return n == m
-        def dhash(n):
-            return ~n
-        def func():
-            d = objectmodel.r_ordereddict(deq, dhash)
-            d[5] = 2
-            d[6] = 3
-            k1, v1 = d.popitem()
-            assert len(d) == 1
-            k2, v2 = d.popitem()
-            try:
-                d.popitem()
-            except KeyError:
-                pass
+    def test_stress(self):
+        from rpython.annotator.dictdef import DictKey, DictValue
+        from rpython.annotator import model as annmodel
+        from rpython.rtyper import rint
+        from rpython.rtyper.test.test_rdict import not_really_random
+        rodct = rordereddict
+        dictrepr = rodct.OrderedDictRepr(
+                                  None, rint.signed_repr, rint.signed_repr,
+                                  DictKey(None, annmodel.SomeInteger()),
+                                  DictValue(None, annmodel.SomeInteger()))
+        dictrepr.setup()
+        l_dict = rodct.ll_newdict(dictrepr.DICT)
+        referencetable = [None] * 400
+        referencelength = 0
+        value = 0
+
+        def complete_check():
+            for n, refvalue in zip(range(len(referencetable)), referencetable):
+                try:
+                    gotvalue = rodct.ll_dict_getitem(l_dict, n)
+                except KeyError:
+                    assert refvalue is None
+                else:
+                    assert gotvalue == refvalue
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to