Author: Amaury Forgeot d'Arc <[email protected]>
Branch: more-rposix
Changeset: r74907:f566a4468a10
Date: 2014-12-13 11:33 +0100
http://bitbucket.org/pypy/pypy/changeset/f566a4468a10/

Log:    hg merge default

diff too long, truncating to 2000 out of 2781 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/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -6,6 +6,10 @@
 C. It was developed in collaboration with Roberto De Ioris from the `uwsgi`_
 project. The `PyPy uwsgi plugin`_ is a good example of using the embedding API.
 
+**NOTE**: As of 1st of December, PyPy comes with ``--shared`` by default
+on linux, linux64 and windows. We will make it the default on all platforms
+by the time of the next release.
+
 The first thing that you need is to compile PyPy yourself with the option
 ``--shared``. We plan to make ``--shared`` the default in the future. Consult
 the `how to compile PyPy`_ doc for details. This will result in ``libpypy.so``
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -35,6 +35,13 @@
 PyPy's bytearray type is very inefficient. It would be an interesting
 task to look into possible optimizations on this.
 
+Implement AF_XXX packet types for PyPy
+--------------------------------------
+
+PyPy is missing AF_XXX types of sockets. Implementing it is easy-to-medium
+task. `bug report`_
+
+.. _`bug report`: 
https://bitbucket.org/pypy/pypy/issue/1942/support-for-af_xxx-sockets#more
 
 Implement copy-on-write list slicing
 ------------------------------------
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/_rawffi/alt/interp_funcptr.py 
b/pypy/module/_rawffi/alt/interp_funcptr.py
--- a/pypy/module/_rawffi/alt/interp_funcptr.py
+++ b/pypy/module/_rawffi/alt/interp_funcptr.py
@@ -14,6 +14,7 @@
 from rpython.rlib.objectmodel import we_are_translated
 from pypy.module._rawffi.alt.type_converter import FromAppLevelConverter, 
ToAppLevelConverter
 from pypy.module._rawffi.interp_rawffi import got_libffi_error, 
wrap_dlopenerror
+from pypy.module._rawffi import lasterror
 
 import os
 if os.name == 'nt':
@@ -201,11 +202,23 @@
         self.func = func
         self.argchain = argchain
 
+    def before(self):
+        lasterror.restore_last_error(self.space)
+
+    def after(self):
+        lasterror.save_last_error(self.space)
+
     def get_longlong(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.LONGLONG)
+        self.before()
+        x = self.func.call(self.argchain, rffi.LONGLONG)
+        self.after()
+        return x
 
     def get_ulonglong(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.ULONGLONG)
+        self.before()
+        x = self.func.call(self.argchain, rffi.ULONGLONG)
+        self.after()
+        return x
 
     def get_signed(self, w_ffitype):
         # if the declared return type of the function is smaller than LONG,
@@ -216,64 +229,94 @@
         # to space.wrap in order to get a nice applevel <int>.
         #
         restype = w_ffitype.get_ffitype()
+        self.before()
         call = self.func.call
         if restype is libffi.types.slong:
-            return call(self.argchain, rffi.LONG)
+            x = call(self.argchain, rffi.LONG)
         elif restype is libffi.types.sint:
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
         elif restype is libffi.types.sshort:
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
         elif restype is libffi.types.schar:
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
         else:
-            self.error(w_ffitype)
+            raise self.error(w_ffitype)
+        self.after()
+        return x
 
     def get_unsigned(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.ULONG)
+        self.before()
+        x = self.func.call(self.argchain, rffi.ULONG)
+        self.after()
+        return x
 
     def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
         # the same comment as get_signed apply
         restype = w_ffitype.get_ffitype()
+        self.before()
         call = self.func.call
         if restype is libffi.types.uint:
             assert not libffi.IS_32_BIT
             # on 32bit machines, we should never get here, because it's a case
             # which has already been handled by get_unsigned above.
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
         elif restype is libffi.types.ushort:
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
         elif restype is libffi.types.uchar:
-            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
+            x = rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
         else:
-            self.error(w_ffitype)
+            raise self.error(w_ffitype)
+        self.after()
+        return x
 
 
     def get_pointer(self, w_ffitype):
+        self.before()
         ptrres = self.func.call(self.argchain, rffi.VOIDP)
+        self.after()
         return rffi.cast(rffi.ULONG, ptrres)
 
     def get_char(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.UCHAR)
+        self.before()
+        x = self.func.call(self.argchain, rffi.UCHAR)
+        self.after()
+        return x
 
     def get_unichar(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.WCHAR_T)
+        self.before()
+        x = self.func.call(self.argchain, rffi.WCHAR_T)
+        self.after()
+        return x
 
     def get_float(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.DOUBLE)
+        self.before()
+        x = self.func.call(self.argchain, rffi.DOUBLE)
+        self.after()
+        return x
 
     def get_singlefloat(self, w_ffitype):
-        return self.func.call(self.argchain, rffi.FLOAT)
+        self.before()
+        x = self.func.call(self.argchain, rffi.FLOAT)
+        self.after()
+        return x
 
     def get_struct(self, w_ffitype, w_structdescr):
+        self.before()
         addr = self.func.call(self.argchain, rffi.LONG, is_struct=True)
+        self.after()
         return w_structdescr.fromaddress(self.space, addr)
 
     def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        self.before()
         uintval = self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+        self.after()
         return w_structdescr.fromaddress(self.space, uintval)
 
     def get_void(self, w_ffitype):
-        return self.func.call(self.argchain, lltype.Void)
+        self.before()
+        x = self.func.call(self.argchain, lltype.Void)
+        self.after()
+        return x
 
 
 def unpack_argtypes(space, w_argtypes, w_restype):
diff --git a/pypy/module/_rawffi/interp_rawffi.py 
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -18,6 +18,7 @@
 from rpython.rlib.rarithmetic import intmask, r_uint
 from pypy.module._rawffi.buffer import RawFFIBuffer
 from pypy.module._rawffi.tracker import tracker
+from pypy.module._rawffi import lasterror
 
 TYPEMAP = {
     # XXX A mess with unsigned/signed/normal chars :-/
@@ -495,10 +496,14 @@
         try:
             if self.resshape is not None:
                 result = self.resshape.allocate(space, 1, autofree=True)
+                lasterror.restore_last_error(space)
                 self.ptr.call(args_ll, result.ll_buffer)
+                lasterror.save_last_error(space)
                 return space.wrap(result)
             else:
+                lasterror.restore_last_error(space)
                 self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO))
+                lasterror.save_last_error(space)
                 return space.w_None
         except StackCheckError, e:
             raise OperationError(space.w_ValueError, space.wrap(e.message))
@@ -615,12 +620,10 @@
 
 if sys.platform == 'win32':
     def get_last_error(space):
-        from rpython.rlib.rwin32 import GetLastError
-        return space.wrap(GetLastError())
+        return space.wrap(lasterror.fetch_last_error(space))
     @unwrap_spec(error=int)
     def set_last_error(space, error):
-        from rpython.rlib.rwin32 import SetLastError
-        SetLastError(error)
+        lasterror.store_last_error(space, error)
 else:
     # always have at least a dummy version of these functions
     # (https://bugs.pypy.org/issue1242)
diff --git a/pypy/module/_rawffi/lasterror.py b/pypy/module/_rawffi/lasterror.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_rawffi/lasterror.py
@@ -0,0 +1,40 @@
+# For Windows only.
+# https://bitbucket.org/pypy/pypy/issue/1944/ctypes-on-windows-getlasterror
+
+import os
+
+_MS_WINDOWS = os.name == "nt"
+
+
+if _MS_WINDOWS:
+    from rpython.rlib import rwin32
+    from pypy.interpreter.executioncontext import ExecutionContext
+
+
+    ExecutionContext._rawffi_last_error = 0
+
+    def fetch_last_error(space):
+        ec = space.getexecutioncontext()
+        return ec._rawffi_last_error
+
+    def store_last_error(space, last_error):
+        ec = space.getexecutioncontext()
+        ec._rawffi_last_error = last_error
+
+    def restore_last_error(space):
+        ec = space.getexecutioncontext()
+        lasterror = ec._rawffi_last_error
+        rwin32.SetLastError(lasterror)
+
+    def save_last_error(space):
+        lasterror = rwin32.GetLastError()
+        ec = space.getexecutioncontext()
+        ec._rawffi_last_error = lasterror
+
+else:
+
+    def restore_last_error(space):
+        pass
+
+    def save_last_error(space):
+        pass
diff --git a/pypy/module/_rawffi/test/test__rawffi.py 
b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -16,6 +16,7 @@
         #include "src/precommondefs.h"
         #include <stdlib.h>
         #include <stdio.h>
+        #include <errno.h>
 
         struct x
         {
@@ -204,6 +205,24 @@
             return inp;
         }
 
+        RPY_EXPORTED
+        int check_errno(int incoming)
+        {
+            int old_errno = errno;
+            errno = incoming;
+            return old_errno;
+        }
+
+        #ifdef _WIN32
+        #include <Windows.h>
+        RPY_EXPORTED
+        int check_last_error(int incoming)
+        {
+            int old_errno = GetLastError();
+            SetLastError(incoming);
+            return old_errno;
+        }
+        #endif
         '''))
         eci = ExternalCompilationInfo(include_dirs=[cdir])
         return str(platform.compile([c_file], eci, 'x', standalone=False))
@@ -1150,6 +1169,37 @@
         raises(OverflowError, "arg1[0] = 10**900")
         arg1.free()
 
+    def test_errno(self):
+        import _rawffi
+        lib = _rawffi.CDLL(self.lib_name)
+        A = _rawffi.Array('i')
+        f = lib.ptr('check_errno', ['i'], 'i')
+        _rawffi.set_errno(42)
+        arg = A(1)
+        arg[0] = 43
+        res = f(arg)
+        assert res[0] == 42
+        z = _rawffi.get_errno()
+        assert z == 43
+        arg.free()
+
+    def test_last_error(self):
+        import sys
+        if sys.platform != 'win32':
+            skip("Windows test")
+        import _rawffi
+        lib = _rawffi.CDLL(self.lib_name)
+        A = _rawffi.Array('i')
+        f = lib.ptr('check_last_error', ['i'], 'i')
+        _rawffi.set_last_error(42)
+        arg = A(1)
+        arg[0] = 43
+        res = f(arg)
+        assert res[0] == 42
+        z = _rawffi.get_last_error()
+        assert z == 43
+        arg.free()
+
 
 class AppTestAutoFree:
     spaceconfig = dict(usemodules=['_rawffi', 'struct'])
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -52,7 +52,8 @@
 
 if not OPENSSL_NO_SSL2:
     constants["PROTOCOL_SSLv2"]  = PY_SSL_VERSION_SSL2
-constants["PROTOCOL_SSLv3"]  = PY_SSL_VERSION_SSL3
+if not OPENSSL_NO_SSL3:
+    constants["PROTOCOL_SSLv3"]  = PY_SSL_VERSION_SSL3
 constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_SSL23
 constants["PROTOCOL_TLSv1"]  = PY_SSL_VERSION_TLS1
 
@@ -656,7 +657,7 @@
     # set up context
     if protocol == PY_SSL_VERSION_TLS1:
         method = libssl_TLSv1_method()
-    elif protocol == PY_SSL_VERSION_SSL3:
+    elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
         method = libssl_SSLv3_method()
     elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
         method = libssl_SSLv2_method()
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/compile.py 
b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -34,8 +34,8 @@
 
 
 SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
-                        "unegative", "flat", "tostring","count_nonzero",
-                        "argsort"]
+                        "unegative", "flat", "tostring", "count_nonzero",
+                        "argsort", "cumsum", "logical_xor_reduce"]
 TWO_ARG_FUNCTIONS = ["dot", 'take', 'searchsorted']
 TWO_ARG_FUNCTIONS_OR_NONE = ['view', 'astype']
 THREE_ARG_FUNCTIONS = ['where']
@@ -559,6 +559,11 @@
                 w_res = arr.descr_any(interp.space)
             elif self.name == "all":
                 w_res = arr.descr_all(interp.space)
+            elif self.name == "cumsum":
+                w_res = arr.descr_cumsum(interp.space)
+            elif self.name == "logical_xor_reduce":
+                logical_xor = ufuncs.get(interp.space).logical_xor
+                w_res = logical_xor.reduce(interp.space, arr, None)
             elif self.name == "unegative":
                 neg = ufuncs.get(interp.space).negative
                 w_res = neg.call(interp.space, [arr])
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/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -166,6 +166,7 @@
 def compute_reduce_cumulative(space, obj, out, calc_dtype, func, identity):
     obj_iter, obj_state = obj.create_iter()
     out_iter, out_state = out.create_iter()
+    out_iter.track_index = False
     if identity is None:
         cur_value = obj_iter.getitem(obj_state).convert_to(space, calc_dtype)
         out_iter.setitem(out_state, cur_value)
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/test/test_zjit.py 
b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -183,6 +183,28 @@
             'raw_load': 1,
         })
 
+    def define_cumsum():
+        return """
+        a = |30|
+        b = cumsum(a)
+        b -> 5
+        """
+
+    def test_cumsum(self):
+        result = self.run("cumsum")
+        assert result == 15
+        self.check_trace_count(1)
+        self.check_simple_loop({
+            'float_add': 1,
+            'guard_false': 1,
+            'guard_not_invalidated': 1,
+            'int_add': 3,
+            'int_ge': 1,
+            'jump': 1,
+            'raw_load': 1,
+            'raw_store': 1,
+        })
+
     def define_axissum():
         return """
         a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
@@ -218,7 +240,7 @@
             'getfield_gc': 5,
             'getfield_gc_pure': 51,
             'guard_class': 3,
-            'guard_false': 12,
+            'guard_false': 13,
             'guard_nonnull': 11,
             'guard_nonnull_class': 3,
             'guard_not_invalidated': 2,
@@ -378,6 +400,7 @@
     def test_all(self):
         result = self.run("all")
         assert result == 1
+        self.check_trace_count(1)
         self.check_simple_loop({
             'cast_float_to_int': 1,
             'guard_false': 1,
@@ -390,6 +413,35 @@
             'raw_load': 1,
         })
 
+    def define_logical_xor_reduce():
+        return """
+        a = [1,1,1,1,1,1,1,1]
+        logical_xor_reduce(a)
+        """
+
+    def test_logical_xor_reduce(self):
+        result = self.run("logical_xor_reduce")
+        assert result == 0
+        self.check_trace_count(2)
+        # XXX fix this
+        self.check_simple_loop({
+            'cast_float_to_int': 1,
+            'getfield_gc': 2,
+            'getfield_gc_pure': 11,
+            'guard_class': 1,
+            'guard_false': 1,
+            'guard_not_invalidated': 1,
+            'guard_true': 5,
+            'int_add': 2,
+            'int_and': 1,
+            'int_ge': 1,
+            'int_is_true': 2,
+            'jump': 1,
+            'new_with_vtable': 1,
+            'raw_load': 1,
+            'setfield_gc': 4,
+        })
+
     def define_already_forced():
         return """
         a = |30|
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
@@ -285,7 +285,9 @@
 
     @raw_binary_op
     def logical_xor(self, v1, v2):
-        return bool(v1) ^ bool(v2)
+        a = bool(v1)
+        b = bool(v2)
+        return (not b and a) or (not a and b)
 
     @raw_unary_op
     def bool(self, v):
@@ -309,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.
@@ -1258,7 +1260,9 @@
 
     @raw_binary_op
     def logical_xor(self, v1, v2):
-        return self._bool(v1) ^ self._bool(v2)
+        a = self._bool(v1)
+        b = self._bool(v2)
+        return (not b and a) or (not a and b)
 
     def min(self, v1, v2):
         if self.le(v1, v2) or self.isnan(v1):
@@ -1733,7 +1737,9 @@
 
     @str_binary_op
     def logical_xor(self, v1, v2):
-        return bool(v1) ^ bool(v2)
+        a = bool(v1)
+        b = bool(v2)
+        return (not b and a) or (not a and b)
 
     def bool(self, v):
         return bool(self.to_str(v))
@@ -1863,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/pypyjit/test_pypy_c/test_micronumpy.py 
b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -30,9 +30,7 @@
             guard_true(i14, descr=...)
             i15 = getfield_gc_pure(p1, descr=<FieldU 
pypy.module.micronumpy.boxes.W_BoolBox.inst_value \d+>)
             i16 = int_is_true(i15)
-            i18 = int_xor(i16, 1)
-            i19 = int_is_true(i18)
-            guard_true(i19, descr=...)
+            guard_false(i16, descr=...)
             i20 = getfield_gc(p2, descr=<FieldS 
pypy.module.micronumpy.iterators.IterState.inst_index \d+>)
             i21 = getfield_gc_pure(p0, descr=<FieldU 
pypy.module.micronumpy.iterators.ArrayIter.inst_track_index \d+>)
             guard_true(i21, 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
 
@@ -261,21 +261,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/config/translationoption.py 
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -129,7 +129,8 @@
                default=False, cmdline=None),
 
     # misc
-    BoolOption("verbose", "Print extra information", default=False),
+    BoolOption("verbose", "Print extra information", default=False,
+               cmdline="--verbose"),
     StrOption("cc", "Specify compiler to use for compiling generated C", 
cmdline="--cc"),
     StrOption("profopt", "Specify profile based optimization script",
               cmdline="--profopt"),
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -528,6 +528,10 @@
     pyfunc = staticmethod(getattr)
 
     def constfold(self):
+        from rpython.flowspace.flowcontext import FlowingError
+        if len(self.args) == 3:
+            raise FlowingError(
+                "getattr() with three arguments not supported: %s" % (self,))
         w_obj, w_name = self.args
         # handling special things like sys
         if (w_obj in NOT_REALLY_CONST and
@@ -538,7 +542,6 @@
             try:
                 result = getattr(obj, name)
             except Exception as e:
-                from rpython.flowspace.flowcontext import FlowingError
                 etype = e.__class__
                 msg = "getattr(%s, %s) always raises %s: %s" % (
                     obj, name, etype, e)
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
@@ -964,9 +964,40 @@
         assembler_call = False
         if warmrunnerstate.inlining:
             if warmrunnerstate.can_inline_callable(greenboxes):
+                # We've found a potentially inlinable function; now we need to
+                # see if it's already on the stack. In other words: are we 
about
+                # to enter recursion? If so, we don't want to inline the
+                # recursion, which would be equivalent to unrolling a while
+                # loop.
                 portal_code = targetjitdriver_sd.mainjitcode
-                return self.metainterp.perform_call(portal_code, allboxes,
-                                                    greenkey=greenboxes)
+                count = 0
+                for f in self.metainterp.framestack:
+                    if f.jitcode is not portal_code:
+                        continue
+                    gk = f.greenkey
+                    if gk is None:
+                        continue
+                    assert len(gk) == len(greenboxes)
+                    i = 0
+                    for i in range(len(gk)):
+                        if not gk[i].same_constant(greenboxes[i]):
+                            break
+                    else:
+                        count += 1
+                memmgr = 
self.metainterp.staticdata.warmrunnerdesc.memory_manager
+                if count >= memmgr.max_unroll_recursion:
+                    # This function is recursive and has exceeded the
+                    # maximum number of unrollings we allow. We want to stop
+                    # inlining it further and to make sure that, if it
+                    # hasn't happened already, the function is traced
+                    # separately as soon as possible.
+                    if have_debug_prints():
+                        loc = 
targetjitdriver_sd.warmstate.get_location_str(greenboxes)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to