[pypy-commit] pypy remove-intlong-smm: merge default

pjenvey noreply at buildbot.pypy.org
Sat Oct 12 01:29:20 CEST 2013


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: remove-intlong-smm
Changeset: r67331:5558c7f4430d
Date: 2013-10-09 17:27 -0700
http://bitbucket.org/pypy/pypy/changeset/5558c7f4430d/

Log:	merge default

diff too long, truncating to 2000 out of 3119 lines

diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -363,9 +363,11 @@
     pass
 
 
-def connect(database, **kwargs):
-    factory = kwargs.get("factory", Connection)
-    return factory(database, **kwargs)
+def connect(database, timeout=5.0, detect_types=0, isolation_level="",
+                 check_same_thread=True, factory=None, cached_statements=100):
+    factory = Connection if not factory else factory
+    return factory(database, timeout, detect_types, isolation_level,
+                    check_same_thread, factory, cached_statements)
 
 
 def _unicode_text_factory(x):
diff --git a/lib_pypy/_tkinter/tclobj.py b/lib_pypy/_tkinter/tclobj.py
--- a/lib_pypy/_tkinter/tclobj.py
+++ b/lib_pypy/_tkinter/tclobj.py
@@ -28,9 +28,11 @@
         return result
 
     elif value.typePtr == typeCache.BooleanType:
-        return result
+        return bool(value.internalRep.longValue)
     elif value.typePtr == typeCache.ByteArrayType:
-        return result
+        size = tkffi.new('int*')
+        data = tklib.Tcl_GetByteArrayFromObj(value, size)
+        return tkffi.buffer(data, size[0])[:]
     elif value.typePtr == typeCache.DoubleType:
         return value.internalRep.doubleValue
     elif value.typePtr == typeCache.IntType:
@@ -50,7 +52,7 @@
             result.append(FromObj(app, tcl_elem[0]))
         return tuple(result)
     elif value.typePtr == typeCache.ProcBodyType:
-        return result
+        pass  # fall through and return tcl object.
     elif value.typePtr == typeCache.StringType:
         buf = tklib.Tcl_GetUnicode(value)
         length = tklib.Tcl_GetCharLength(value)
diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py
--- a/lib_pypy/_tkinter/tklib.py
+++ b/lib_pypy/_tkinter/tklib.py
@@ -72,6 +72,7 @@
 int Tcl_GetBoolean(Tcl_Interp* interp, const char* src, int* boolPtr);
 char *Tcl_GetString(Tcl_Obj* objPtr);
 char *Tcl_GetStringFromObj(Tcl_Obj* objPtr, int* lengthPtr);
+unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj* objPtr, int* lengthPtr);
 
 Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj* objPtr);
 int Tcl_GetCharLength(Tcl_Obj* objPtr);
diff --git a/lib_pypy/numpypy/__init__.py b/lib_pypy/numpypy/__init__.py
--- a/lib_pypy/numpypy/__init__.py
+++ b/lib_pypy/numpypy/__init__.py
@@ -10,8 +10,35 @@
 
 import os
 def get_include():
-    head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
-    return os.path.join(head, '../include')
+    """
+    Return the directory that contains the NumPy \\*.h header files.
+
+    Extension modules that need to compile against NumPy should use this
+    function to locate the appropriate include directory.
+
+    Notes
+    -----
+    When using ``distutils``, for example in ``setup.py``.
+    ::
+
+        import numpy as np
+        ...
+        Extension('extension_name', ...
+                include_dirs=[np.get_include()])
+        ...
+
+    """
+    import numpy
+    if getattr(numpy, 'show_config', None) is None:
+        # running from numpy source directory
+        head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
+        return os.path.join(head, '../include')
+    else:
+        # using installed numpy core headers
+        import numpy.core as core
+        d = os.path.join(os.path.dirname(core.__file__), 'include')
+    return d
+
 
 
 __all__ = ['__version__', 'get_include']
diff --git a/lib_pypy/numpypy/core/numerictypes.py b/lib_pypy/numpypy/core/numerictypes.py
--- a/lib_pypy/numpypy/core/numerictypes.py
+++ b/lib_pypy/numpypy/core/numerictypes.py
@@ -1,1 +1,75 @@
 from _numpypy.numerictypes import *
+import numpypy
+
+def issubclass_(arg1, arg2):
+    """
+    Determine if a class is a subclass of a second class.
+
+    `issubclass_` is equivalent to the Python built-in ``issubclass``,
+    except that it returns False instead of raising a TypeError is one
+    of the arguments is not a class.
+
+    Parameters
+    ----------
+    arg1 : class
+        Input class. True is returned if `arg1` is a subclass of `arg2`.
+    arg2 : class or tuple of classes.
+        Input class. If a tuple of classes, True is returned if `arg1` is a
+        subclass of any of the tuple elements.
+
+    Returns
+    -------
+    out : bool
+        Whether `arg1` is a subclass of `arg2` or not.
+
+    See Also
+    --------
+    issubsctype, issubdtype, issctype
+
+    Examples
+    --------
+    >>> np.issubclass_(np.int32, np.int)
+    True
+    >>> np.issubclass_(np.int32, np.float)
+    False
+
+    """
+    try:
+        return issubclass(arg1, arg2)
+    except TypeError:
+        return False
+
+def issubdtype(arg1, arg2):
+    """
+    Returns True if first argument is a typecode lower/equal in type hierarchy.
+
+    Parameters
+    ----------
+    arg1, arg2 : dtype_like
+        dtype or string representing a typecode.
+
+    Returns
+    -------
+    out : bool
+
+    See Also
+    --------
+    issubsctype, issubclass_
+    numpy.core.numerictypes : Overview of numpy type hierarchy.
+
+    Examples
+    --------
+    >>> np.issubdtype('S1', str)
+    True
+    >>> np.issubdtype(np.float64, np.float32)
+    False
+
+    """
+    if issubclass_(arg2, generic):
+        return issubclass(numpypy.dtype(arg1).type, arg2)
+    mro = numpypy.dtype(arg2).type.mro()
+    if len(mro) > 1:
+        val = mro[1]
+    else:
+        val = mro[0]
+    return issubclass(numpypy.dtype(arg1).type, val)
diff --git a/pypy/TODO b/pypy/TODO
deleted file mode 100644
--- a/pypy/TODO
+++ /dev/null
@@ -1,2 +0,0 @@
-
-* ARM
diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst
--- a/pypy/doc/arm.rst
+++ b/pypy/doc/arm.rst
@@ -35,6 +35,11 @@
   * ``qemu-system``
   * ``qemu-user-static``
 
+- The dependencies above are in addition to the ones needed for a regular
+  translation, `listed here`_.
+
+.. _`listed here`: getting-started-python.html#translating-the-pypy-python-interpreter
+
 
 Creating a Qemu based ARM chroot
 --------------------------------
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -107,9 +107,15 @@
         for i in range(min(len(varnames), self.getfastscopelength())):
             name = varnames[i]
             w_value = fastscope_w[i]
+            w_name = self.space.wrap(name)
             if w_value is not None:
-                w_name = self.space.wrap(name)
                 self.space.setitem(self.w_locals, w_name, w_value)
+            else:
+                try:
+                    self.space.delitem(self.w_locals, w_name)
+                except OperationError as e:
+                    if not e.match(self.space, self.space.w_KeyError):
+                        raise
 
     def locals2fast(self):
         # Copy values from self.w_locals to the fastlocals
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -954,6 +954,8 @@
 
         sys.path.append(self.goal_dir)
         # make sure cwd does not contain a stdlib
+        if self.tmp_dir.startswith(self.trunkdir):
+            skip('TMPDIR is inside the PyPy source')
         os.chdir(self.tmp_dir)
         tmp_pypy_c = os.path.join(self.tmp_dir, 'pypy-c')
         try:
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -83,10 +83,21 @@
     def test_locals(self):
         def f():
             return locals()
+
         def g(c=0, b=0, a=0):
             return locals()
+
         assert f() == {}
-        assert g() == {'a':0, 'b':0, 'c':0}
+        assert g() == {'a': 0, 'b': 0, 'c': 0}
+
+    def test_locals_deleted_local(self):
+        def f():
+            a = 3
+            locals()
+            del a
+            return locals()
+
+        assert f() == {}
 
     def test_dir(self):
         def f():
@@ -252,25 +263,9 @@
         assert next(x) == 3
 
     def test_xrange_args(self):
-##        # xrange() attributes are deprecated and were removed in Python 2.3.
-##        x = xrange(2)
-##        assert x.start == 0
-##        assert x.stop == 2
-##        assert x.step == 1
-
-##        x = xrange(2,10,2)
-##        assert x.start == 2
-##        assert x.stop == 10
-##        assert x.step == 2
-
-##        x = xrange(2.3, 10.5, 2.4)
-##        assert x.start == 2
-##        assert x.stop == 10
-##        assert x.step == 2
-
         raises(ValueError, xrange, 0, 1, 0)
 
-    def test_xrange_repr(self): 
+    def test_xrange_repr(self):
         assert repr(xrange(1)) == 'xrange(1)'
         assert repr(xrange(1,2)) == 'xrange(1, 2)'
         assert repr(xrange(1,2,3)) == 'xrange(1, 4, 3)'
@@ -329,7 +324,7 @@
         raises(TypeError, xrange, 1, 3+2j)
         raises(TypeError, xrange, 1, 2, '1')
         raises(TypeError, xrange, 1, 2, 3+2j)
-    
+
     def test_sorted(self):
         l = []
         sorted_l = sorted(l)
@@ -348,7 +343,7 @@
         assert sorted_l is not l
         assert sorted_l == ['C', 'b', 'a']
         raises(TypeError, sorted, [], reverse=None)
-        
+
     def test_reversed_simple_sequences(self):
         l = range(5)
         rev = reversed(l)
@@ -364,8 +359,8 @@
                 return 42
         obj = SomeClass()
         assert reversed(obj) == 42
-    
-        
+
+
     def test_cmp(self):
         assert cmp(9,9) == 0
         assert cmp(0,9) < 0
@@ -398,7 +393,7 @@
         raises(RuntimeError, cmp, a, c)
         # okay, now break the cycles
         a.pop(); b.pop(); c.pop()
-        
+
     def test_coerce(self):
         assert coerce(1, 2)    == (1, 2)
         assert coerce(1L, 2L)  == (1L, 2L)
@@ -465,7 +460,7 @@
         assert eval("1+2") == 3
         assert eval(" \t1+2\n") == 3
         assert eval("len([])") == 0
-        assert eval("len([])", {}) == 0        
+        assert eval("len([])", {}) == 0
         # cpython 2.4 allows this (raises in 2.3)
         assert eval("3", None, None) == 3
         i = 4
@@ -683,15 +678,15 @@
         w_value = space.getitem(w_dict, space.wrap('i'))
         assert space.eq_w(w_value, space.wrap(42))
 
-    def test_execfile_different_lineendings(self, space): 
+    def test_execfile_different_lineendings(self, space):
         from rpython.tool.udir import udir
         d = udir.ensure('lineending', dir=1)
-        dos = d.join('dos.py') 
-        f = dos.open('wb') 
+        dos = d.join('dos.py')
+        f = dos.open('wb')
         f.write("x=3\r\n\r\ny=4\r\n")
-        f.close() 
+        f.close()
         space.appexec([space.wrap(str(dos))], """
-            (filename): 
+            (filename):
                 d = {}
                 execfile(filename, d)
                 assert d['x'] == 3
@@ -699,12 +694,12 @@
         """)
 
         unix = d.join('unix.py')
-        f = unix.open('wb') 
+        f = unix.open('wb')
         f.write("x=5\n\ny=6\n")
-        f.close() 
+        f.close()
 
         space.appexec([space.wrap(str(unix))], """
-            (filename): 
+            (filename):
                 d = {}
                 execfile(filename, d)
                 assert d['x'] == 5
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -400,6 +400,8 @@
     def test_socket_connect_ex(self):
         import _socket
         s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
+        # The following might fail if the DNS redirects failed requests to a
+        # catch-all address (i.e. opendns).
         # Make sure we get an app-level error, not an interp one.
         raises(_socket.gaierror, s.connect_ex, ("wrong.invalid", 80))
         s.close()
diff --git a/pypy/module/cpyext/ndarrayobject.py b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -149,14 +149,17 @@
          only used if the array is constructed that way. Almost always this
          parameter is NULL.
     """
-    if min_depth !=0 or max_depth != 0:
-        raise OperationError(space.w_NotImplementedError, space.wrap(
-            '_PyArray_FromAny called with not-implemented min_dpeth or max_depth argument'))
     if requirements not in (0, NPY_DEFAULT):
         raise OperationError(space.w_NotImplementedError, space.wrap(
             '_PyArray_FromAny called with not-implemented requirements argument'))
     w_array = array(space, w_obj, w_dtype=w_dtype, copy=False)
-    if w_array.is_scalar():
+    if min_depth !=0 and len(w_array.get_shape()) < min_depth:
+        raise OperationError(space.w_ValueError, space.wrap(
+            'object of too small depth for desired array'))
+    elif max_depth !=0 and len(w_array.get_shape()) > max_depth:
+        raise OperationError(space.w_ValueError, space.wrap(
+            'object of too deep for desired array'))
+    elif w_array.is_scalar():
         # since PyArray_DATA() fails on scalars, create a 1D array and set empty
         # shape. So the following combination works for *reading* scalars:
         #     PyObject *arr = PyArray_FromAny(obj);
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -103,11 +103,13 @@
     exc_p[0] = make_ref(space, operr.w_type)
     val_p[0] = make_ref(space, operr.get_w_value(space))
 
- at cpython_api([], lltype.Void)
+ at cpython_api([], rffi.INT_real, error=0)
 def PyErr_BadArgument(space):
     """This is a shorthand for PyErr_SetString(PyExc_TypeError, message), where
     message indicates that a built-in operation was invoked with an illegal
-    argument.  It is mostly for internal use."""
+    argument.  It is mostly for internal use. In CPython this function always
+    raises an exception and returns 0 in all cases, hence the (ab)use of the
+    error indicator."""
     raise OperationError(space.w_TypeError,
             space.wrap("bad argument type for built-in operation"))
 
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -90,15 +90,16 @@
     def test_FromAny(self, space, api):
         a = array(space, [10, 5, 3])
         assert api._PyArray_FromAny(a, NULL, 0, 0, 0, NULL) is a
-        self.raises(space, api, NotImplementedError, api._PyArray_FromAny,
-                    a, NULL, 0, 3, 0, NULL)
+        assert api._PyArray_FromAny(a, NULL, 1, 4, 0, NULL) is a
+        self.raises(space, api, ValueError, api._PyArray_FromAny,
+                    a, NULL, 4, 5, 0, NULL)
 
     def test_FromObject(self, space, api):
         a = array(space, [10, 5, 3])
         assert api._PyArray_FromObject(a, a.get_dtype().num, 0, 0) is a
-        exc = self.raises(space, api, NotImplementedError, api._PyArray_FromObject,
-                    a, 11, 0, 3)
-        assert exc.errorstr(space).find('FromObject') >= 0
+        exc = self.raises(space, api, ValueError, api._PyArray_FromObject,
+                    a, 11, 4, 5)
+        assert exc.errorstr(space).find('desired') >= 0
 
     def test_list_from_fixedptr(self, space, api):
         A = lltype.GcArray(lltype.Float)
diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -70,9 +70,10 @@
         api.PyErr_Clear()
 
     def test_BadArgument(self, space, api):
-        api.PyErr_BadArgument()
+        ret = api.PyErr_BadArgument()
         state = space.fromcache(State)
         assert space.eq_w(state.operror.w_type, space.w_TypeError)
+        assert ret == 0
         api.PyErr_Clear()
 
     def test_Warning(self, space, api, capfd):
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -91,6 +91,7 @@
         invalid = rffi.str2charp('invalid')
         utf_8 = rffi.str2charp('utf-8')
         prev_encoding = rffi.str2charp(space.unwrap(w_default_encoding))
+        self.raises(space, api, TypeError, api.PyUnicode_SetDefaultEncoding, lltype.nullptr(rffi.CCHARP.TO))
         assert api.PyUnicode_SetDefaultEncoding(invalid) == -1
         assert api.PyErr_Occurred() is space.w_LookupError
         api.PyErr_Clear()
@@ -316,6 +317,15 @@
         rffi.free_charp(b_text)
         rffi.free_charp(b_encoding)
 
+    def test_decode_null_encoding(self, space, api):
+        null_charp = lltype.nullptr(rffi.CCHARP.TO)
+        u_text = u'abcdefg'
+        s_text = space.str_w(api.PyUnicode_AsEncodedString(space.wrap(u_text), null_charp, null_charp))
+        b_text = rffi.str2charp(s_text)
+        assert space.unwrap(api.PyUnicode_Decode(b_text, len(s_text), null_charp, null_charp)) == u_text
+        self.raises(space, api, TypeError, api.PyUnicode_FromEncodedObject, space.wrap(u_text), null_charp, None)
+        rffi.free_charp(b_text)
+
     def test_leak(self):
         size = 50
         raw_buf, gc_buf = rffi.alloc_buffer(size)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -273,6 +273,8 @@
 def PyUnicode_SetDefaultEncoding(space, encoding):
     """Sets the currently active default encoding. Returns 0 on
     success, -1 in case of an error."""
+    if not encoding:
+        PyErr_BadArgument(space)
     w_encoding = space.wrap(rffi.charp2str(encoding))
     setdefaultencoding(space, w_encoding)
     default_encoding[0] = '\x00'
@@ -350,8 +352,11 @@
     in the unicode() built-in function.  The codec to be used is looked up
     using the Python codec registry.  Return NULL if an exception was raised by
     the codec."""
+    if not encoding:
+        # This tracks CPython 2.7, in CPython 3.4 'utf-8' is hardcoded instead
+        encoding = PyUnicode_GetDefaultEncoding(space)
+    w_encoding = space.wrap(rffi.charp2str(encoding))
     w_str = space.wrap(rffi.charpsize2str(s, size))
-    w_encoding = space.wrap(rffi.charp2str(encoding))
     if errors:
         w_errors = space.wrap(rffi.charp2str(errors))
     else:
@@ -379,6 +384,9 @@
 
     All other objects, including Unicode objects, cause a TypeError to be
     set."""
+    if not encoding:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("decoding Unicode is not supported"))
     w_encoding = space.wrap(rffi.charp2str(encoding))
     if errors:
         w_errors = space.wrap(rffi.charp2str(errors))
diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py
--- a/pypy/module/math/interp_math.py
+++ b/pypy/module/math/interp_math.py
@@ -334,9 +334,8 @@
             v = hi
         del partials[added:]
         if v != 0.0:
-            if rfloat.isinf(v) or rfloat.isnan(v):
-                if (not rfloat.isinf(original) and
-                    not rfloat.isnan(original)):
+            if not rfloat.isfinite(v):
+                if rfloat.isfinite(original):
                     raise OperationError(space.w_OverflowError,
                                          space.wrap("intermediate overflow"))
                 if rfloat.isinf(original):
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -319,6 +319,15 @@
         else:
             self.done_func = None
 
+    def are_common_types(self, dtype1, dtype2):
+        if dtype1.is_complex_type() and dtype2.is_complex_type():
+            return True
+        elif not (dtype1.is_complex_type() or dtype2.is_complex_type()) and \
+                (dtype1.is_int_type() and dtype2.is_int_type() or dtype1.is_float_type() and dtype2.is_float_type()) and \
+                not (dtype1.is_bool_type() or dtype2.is_bool_type()):
+            return True
+        return False
+
     @jit.unroll_safe
     def call(self, space, args_w):
         if len(args_w) > 2:
@@ -339,6 +348,12 @@
                  'unsupported operand dtypes %s and %s for "%s"' % \
                  (w_rdtype.get_name(), w_ldtype.get_name(),
                   self.name)))
+
+        if self.are_common_types(w_ldtype, w_rdtype):
+            if not w_lhs.is_scalar() and w_rhs.is_scalar():
+                w_rdtype = w_ldtype
+            elif w_lhs.is_scalar() and not w_rhs.is_scalar():
+                w_ldtype = w_rdtype
         calc_dtype = find_binop_result_dtype(space,
             w_ldtype, w_rdtype,
             int_only=self.int_only,
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -2965,6 +2965,17 @@
 
         assert len(list(a[0])) == 2
 
+    def test_issue_1589(self):
+        import numpypy as numpy
+        c = numpy.array([[(1, 2, 'a'), (3, 4, 'b')], [(5, 6, 'c'), (7, 8, 'd')]],
+                        dtype=[('bg', 'i8'), ('fg', 'i8'), ('char', 'S1')])
+        assert c[0][0]["char"] == 'a'
+
+    def test_scalar_coercion(self):
+        import numpypy as np
+        a = np.array([1,2,3], dtype=np.int16)
+        assert (a * 2).dtype == np.int16
+
 class AppTestPyPy(BaseNumpyAppTest):
     def setup_class(cls):
         if option.runappdirect and '__pypy__' not in sys.builtin_module_names:
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
@@ -1766,14 +1766,14 @@
 
     def store(self, arr, i, offset, box):
         assert isinstance(box, interp_boxes.W_StringBox)
-        # XXX simplify to range(box.dtype.get_size()) ?
         return self._store(arr.storage, i, offset, box)
 
     @jit.unroll_safe
     def _store(self, storage, i, offset, box):
         assert isinstance(box, interp_boxes.W_StringBox)
-        for k in range(min(self.size, box.arr.size-offset)):
-            storage[k + i] = box.arr.storage[k + offset]
+        # XXX simplify to range(box.dtype.get_size()) ?
+        for k in range(min(self.size, box.arr.size-box.ofs)):
+            storage[k + offset + i] = box.arr.storage[k + box.ofs]
 
     def read(self, arr, i, offset, dtype=None):
         if dtype is None:
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -149,6 +149,8 @@
         interpleveldefs['nice'] = 'interp_posix.nice'
     if hasattr(os, 'getlogin'):
         interpleveldefs['getlogin'] = 'interp_posix.getlogin'
+    if hasattr(os, 'ctermid'):
+        interpleveldefs['ctermid'] = 'interp_posix.ctermid'
 
     for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
                  'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp',
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -1218,3 +1218,10 @@
         return space.wrap(rurandom.urandom(context, n))
     except OSError, e:
         raise wrap_oserror(space, e)
+
+def ctermid(space):
+    """ctermid() -> string
+
+    Return the name of the controlling terminal for this process.
+    """
+    return space.wrap(os.ctermid())
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -110,7 +110,7 @@
                        '__pypy__', 'cStringIO', '_collections', 'struct',
                        'mmap', 'marshal', '_codecs', 'rctime', 'cppyy',
                        '_cffi_backend', 'pyexpat', '_continuation', '_io',
-                       'thread']:
+                       'thread', 'select']:
             if modname == 'pypyjit' and 'interp_resop' in rest:
                 return False
             return True
diff --git a/pypy/module/pypyjit/test/test_policy.py b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -49,12 +49,15 @@
     from pypy.module.thread.os_lock import Lock
     assert pypypolicy.look_inside_function(Lock.descr_lock_acquire.im_func)
 
+def test_select():
+    from pypy.module.select.interp_select import poll
+    assert pypypolicy.look_inside_function(poll)
+
 def test_pypy_module():
     from pypy.module._collections.interp_deque import W_Deque
     from pypy.module._random.interp_random import W_Random
     assert not pypypolicy.look_inside_function(W_Random.random)
     assert pypypolicy.look_inside_function(W_Deque.length)
-    assert not pypypolicy.look_inside_pypy_module('select.interp_epoll')
     assert pypypolicy.look_inside_pypy_module('__builtin__.operation')
     assert pypypolicy.look_inside_pypy_module('__builtin__.abstractinst')
     assert pypypolicy.look_inside_pypy_module('__builtin__.functional')
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
@@ -277,3 +277,28 @@
             f1 = call_release_gil(..., descr=<Calli 4 ii EF=6 OS=62>)
             ...
         """)
+
+    def test__cffi_bug1(self):
+        from rpython.rlib.test.test_clibffi import get_libm_name
+        def main(libm_name):
+            try:
+                import _cffi_backend
+            except ImportError:
+                sys.stderr.write('SKIP: cannot import _cffi_backend\n')
+                return 0
+
+            libm = _cffi_backend.load_library(libm_name)
+            BDouble = _cffi_backend.new_primitive_type("double")
+            BSin = _cffi_backend.new_function_type([BDouble], BDouble)
+            sin = libm.load_function(BSin, 'sin')
+
+            def f(*args):
+                for i in range(300):
+                    sin(*args)
+
+            f(1.0)
+            f(1)
+        #
+        libm_name = get_libm_name(sys.platform)
+        log = self.run(main, [libm_name])
+        # assert did not crash
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -113,7 +113,7 @@
             i13 = strgetitem(p9, 0)
             i15 = int_eq(i13, 45)
             guard_false(i15, descr=...)
-            i17 = int_sub(0, i10)
+            i17 = int_neg(i10)
             i19 = int_gt(i10, 23)
             guard_false(i19, descr=...)
             p21 = newstr(23)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -1,4 +1,3 @@
-import py
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 
 
@@ -51,7 +50,6 @@
         """)
 
     def test_lock_acquire_release(self):
-        py.test.skip("test too precise, please fix me")
         def main(n):
             import threading
             lock = threading.Lock()
@@ -62,35 +60,30 @@
         assert log.result == main(500)
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
-        i58 = int_gt(i43, 0)
-        guard_true(i58, descr=<Guard0x10483adb8>)
-        p59 = getfield_gc(p15, descr=<FieldP pypy.module.thread.os_lock.Lock.inst_lock 8>)
-        i60 = getfield_gc(p59, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
+        i55 = int_gt(i43, 0)
+        guard_true(i55, descr=...)
+        p56 = force_token()
+        setfield_gc(p0, p56, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+        i57 = call_release_gil(..., i36, 1, descr=<Calli 4 ii EF=6>)
+        guard_not_forced(descr=...)
+        guard_no_exception(descr=...)
+        i58 = int_is_true(i57)
+        guard_true(i58, descr=...)
+        i59 = int_sub(i43, 1)
+        guard_not_invalidated(descr=...)
         p61 = force_token()
-        setfield_gc(p0, p61, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
-        i62 = call_release_gil(4312440032, i60, 1, descr=<Calli 4 ii EF=6>)
-        guard_not_forced(descr=<Guard0x103f3cca0>)
-        guard_no_exception(descr=<Guard0x10483ad40>)
+        setfield_gc(p0, p61, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+        i62 = call_release_gil(..., i36, 0, descr=<Calli 4 ii EF=6>)
+        guard_not_forced(descr=...)
+        guard_no_exception(descr=...)
         i63 = int_is_true(i62)
-        guard_true(i63, descr=<Guard0x10483acc8>)
-        i64 = int_sub(i43, 1)
-        guard_not_invalidated(descr=<Guard0x10483ac50>)
-        p66 = getfield_gc(p15, descr=<FieldP pypy.module.thread.os_lock.Lock.inst_lock 8>)
-        i67 = getfield_gc(p66, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
-        p68 = force_token()
-        setfield_gc(p0, p68, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
-        i69 = call_release_gil(4312440032, i67, 0, descr=<Calli 4 ii EF=6>)
-        guard_not_forced(descr=<Guard0x103f3cc20>)
-        guard_no_exception(descr=<Guard0x10483aae8>)
-        i70 = int_is_true(i69)
-        guard_false(i70, descr=<Guard0x10483aa70>)
-        i71 = getfield_gc(p66, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
-        p72 = force_token()
-        setfield_gc(p0, p72, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
-        call_release_gil(4312441056, i71, descr=<Callv 0 i EF=6>)
-        guard_not_forced(descr=<Guard0x103f3cba0>)
-        guard_no_exception(descr=<Guard0x10483a9f8>)
-        guard_not_invalidated(descr=<Guard0x10483a980>)
+        guard_false(i63, descr=...)
+        p64 = force_token()
+        setfield_gc(p0, p64, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+        call_release_gil(..., i36, descr=<Callv 0 i EF=6>)
+        guard_not_forced(descr=...)
+        guard_no_exception(descr=...)
+        guard_not_invalidated(descr=...)
         --TICK--
-        jump(..., descr=TargetToken(4361239720))
+        jump(..., descr=...)
         """)
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -180,12 +180,12 @@
                         i = 0
                         for w_ev in space.listview(w_changelist):
                             ev = space.interp_w(W_Kevent, w_ev)
-                            changelist[i].c_ident = ev.event.c_ident
-                            changelist[i].c_filter = ev.event.c_filter
-                            changelist[i].c_flags = ev.event.c_flags
-                            changelist[i].c_fflags = ev.event.c_fflags
-                            changelist[i].c_data = ev.event.c_data
-                            changelist[i].c_udata = ev.event.c_udata
+                            changelist[i].c_ident = ev.ident
+                            changelist[i].c_filter = ev.filter
+                            changelist[i].c_flags = ev.flags
+                            changelist[i].c_fflags = ev.fflags
+                            changelist[i].c_data = ev.data
+                            changelist[i].c_udata = ev.udata
                             i += 1
                         pchangelist = changelist
                     else:
@@ -206,13 +206,12 @@
                             evt = eventlist[i]
 
                             w_event = W_Kevent(space)
-                            w_event.event = lltype.malloc(kevent, flavor="raw")
-                            w_event.event.c_ident = evt.c_ident
-                            w_event.event.c_filter = evt.c_filter
-                            w_event.event.c_flags = evt.c_flags
-                            w_event.event.c_fflags = evt.c_fflags
-                            w_event.event.c_data = evt.c_data
-                            w_event.event.c_udata = evt.c_udata
+                            w_event.ident = evt.c_ident
+                            w_event.filter = evt.c_filter
+                            w_event.flags = evt.c_flags
+                            w_event.fflags = evt.c_fflags
+                            w_event.data = evt.c_data
+                            w_event.udata = evt.c_udata
 
                             elist_w[i] = w_event
 
@@ -234,11 +233,12 @@
 
 class W_Kevent(W_Root):
     def __init__(self, space):
-        self.event = lltype.nullptr(kevent)
-
-    def __del__(self):
-        if self.event:
-            lltype.free(self.event, flavor="raw")
+        self.ident = rffi.cast(kevent.c_ident, 0)
+        self.filter = rffi.cast(kevent.c_filter, 0)
+        self.flags = rffi.cast(kevent.c_flags, 0)
+        self.fflags = rffi.cast(kevent.c_fflags, 0)
+        self.data = rffi.cast(kevent.c_data, 0)
+        self.udata = lltype.nullptr(rffi.VOIDP.TO)
 
     @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata=r_uint)
     def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=r_uint(0)):
@@ -247,35 +247,34 @@
         else:
             ident = r_uint(space.c_filedescriptor_w(w_ident))
 
-        self.event = lltype.malloc(kevent, flavor="raw")
-        rffi.setintfield(self.event, "c_ident", ident)
-        rffi.setintfield(self.event, "c_filter", filter)
-        rffi.setintfield(self.event, "c_flags", flags)
-        rffi.setintfield(self.event, "c_fflags", fflags)
-        rffi.setintfield(self.event, "c_data", data)
-        self.event.c_udata = rffi.cast(rffi.VOIDP, udata)
+        self.ident = rffi.cast(kevent.c_ident, ident)
+        self.filter = rffi.cast(kevent.c_filter, filter)
+        self.flags = rffi.cast(kevent.c_flags, flags)
+        self.fflags = rffi.cast(kevent.c_fflags, fflags)
+        self.data = rffi.cast(kevent.c_data, data)
+        self.udata = rffi.cast(rffi.VOIDP, udata)
 
     def _compare_all_fields(self, other, op):
         if IDENT_UINT:
-            l_ident = rffi.cast(lltype.Unsigned, self.event.c_ident)
-            r_ident = rffi.cast(lltype.Unsigned, other.event.c_ident)
+            l_ident = rffi.cast(lltype.Unsigned, self.ident)
+            r_ident = rffi.cast(lltype.Unsigned, other.ident)
         else:
-            l_ident = self.event.c_ident
-            r_ident = other.event.c_ident
-        l_filter = rffi.cast(lltype.Signed, self.event.c_filter)
-        r_filter = rffi.cast(lltype.Signed, other.event.c_filter)
-        l_flags = rffi.cast(lltype.Unsigned, self.event.c_flags)
-        r_flags = rffi.cast(lltype.Unsigned, other.event.c_flags)
-        l_fflags = rffi.cast(lltype.Unsigned, self.event.c_fflags)
-        r_fflags = rffi.cast(lltype.Unsigned, other.event.c_fflags)
+            l_ident = self.ident
+            r_ident = other.ident
+        l_filter = rffi.cast(lltype.Signed, self.filter)
+        r_filter = rffi.cast(lltype.Signed, other.filter)
+        l_flags = rffi.cast(lltype.Unsigned, self.flags)
+        r_flags = rffi.cast(lltype.Unsigned, other.flags)
+        l_fflags = rffi.cast(lltype.Unsigned, self.fflags)
+        r_fflags = rffi.cast(lltype.Unsigned, other.fflags)
         if IDENT_UINT:
-            l_data = rffi.cast(lltype.Signed, self.event.c_data)
-            r_data = rffi.cast(lltype.Signed, other.event.c_data)
+            l_data = rffi.cast(lltype.Signed, self.data)
+            r_data = rffi.cast(lltype.Signed, other.data)
         else:
-            l_data = self.event.c_data
-            r_data = other.event.c_data
-        l_udata = rffi.cast(lltype.Unsigned, self.event.c_udata)
-        r_udata = rffi.cast(lltype.Unsigned, other.event.c_udata)
+            l_data = self.data
+            r_data = other.data
+        l_udata = rffi.cast(lltype.Unsigned, self.udata)
+        r_udata = rffi.cast(lltype.Unsigned, other.udata)
 
         if op == "eq":
             return l_ident == r_ident and \
@@ -330,22 +329,22 @@
         return space.wrap(self.compare_all_fields(space, w_other, "gt"))
 
     def descr_get_ident(self, space):
-        return space.wrap(self.event.c_ident)
+        return space.wrap(self.ident)
 
     def descr_get_filter(self, space):
-        return space.wrap(self.event.c_filter)
+        return space.wrap(self.filter)
 
     def descr_get_flags(self, space):
-        return space.wrap(self.event.c_flags)
+        return space.wrap(self.flags)
 
     def descr_get_fflags(self, space):
-        return space.wrap(self.event.c_fflags)
+        return space.wrap(self.fflags)
 
     def descr_get_data(self, space):
-        return space.wrap(self.event.c_data)
+        return space.wrap(self.data)
 
     def descr_get_udata(self, space):
-        return space.wrap(rffi.cast(rffi.UINTPTR_T, self.event.c_udata))
+        return space.wrap(rffi.cast(rffi.UINTPTR_T, self.udata))
 
 
 W_Kevent.typedef = TypeDef("select.kevent",
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
@@ -31,6 +31,12 @@
     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
+
 def test_total_changes_after_close(con):
     con.close()
     pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -26,6 +26,8 @@
 class Lock(W_Root):
     "A box around an interp-level lock object."
 
+    _immutable_fields_ = ["lock"]
+
     def __init__(self, space):
         self.space = space
         try:
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -1,5 +1,5 @@
 import operator
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.objspace.std import model, newformat
 from pypy.objspace.std.floattype import float_typedef, W_AbstractFloatObject
 from pypy.objspace.std.multimethod import FailedToImplementArgs
@@ -424,21 +424,33 @@
     x = w_float1.floatval
     y = w_float2.floatval
 
+    try:
+        result = _pow(space, x, y)
+    except PowDomainError:
+        raise operationerrfmt(space.w_ValueError,
+                              "negative number cannot be raised to a "
+                              "fractional power")
+    return W_FloatObject(result)
+
+class PowDomainError(ValueError):
+    """Signals a negative number raised to a fractional power"""
+
+def _pow(space, x, y):
     # Sort out special cases here instead of relying on pow()
-    if y == 2.0:                      # special case for performance:
-        return W_FloatObject(x * x)   # x * x is always correct
+    if y == 2.0:       # special case for performance:
+        return x * x   # x * x is always correct
     if y == 0.0:
         # x**0 is 1, even 0**0
-        return W_FloatObject(1.0)
+        return 1.0
     if isnan(x):
         # nan**y = nan, unless y == 0
-        return W_FloatObject(x)
+        return x
     if isnan(y):
         # x**nan = nan, unless x == 1; x**nan = x
         if x == 1.0:
-            return W_FloatObject(1.0)
+            return 1.0
         else:
-            return W_FloatObject(y)
+            return y
     if isinf(y):
         # x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if
         # abs(x) > 1 (including case where x infinite)
@@ -447,11 +459,11 @@
         # abs(x) > 1 (including case where v infinite)
         x = abs(x)
         if x == 1.0:
-            return W_FloatObject(1.0)
+            return 1.0
         elif (y > 0.0) == (x > 1.0):
-            return W_FloatObject(INFINITY)
+            return INFINITY
         else:
-            return W_FloatObject(0.0)
+            return 0.0
     if isinf(x):
         # (+-inf)**w is: inf for w positive, 0 for w negative; in oth
         # cases, we need to add the appropriate sign if w is an odd
@@ -459,14 +471,14 @@
         y_is_odd = math.fmod(abs(y), 2.0) == 1.0
         if y > 0.0:
             if y_is_odd:
-                return W_FloatObject(x)
+                return x
             else:
-                return W_FloatObject(abs(x))
+                return abs(x)
         else:
             if y_is_odd:
-                return W_FloatObject(copysign(0.0, x))
+                return copysign(0.0, x)
             else:
-                return W_FloatObject(0.0)
+                return 0.0
 
     if x == 0.0:
         if y < 0.0:
@@ -475,16 +487,14 @@
                                             "a negative power"))
 
     negate_result = False
-    # special case: "(-1.0) ** bignum" should not raise ValueError,
+    # special case: "(-1.0) ** bignum" should not raise PowDomainError,
     # unlike "math.pow(-1.0, bignum)".  See http://mail.python.org/
     # -           pipermail/python-bugs-list/2003-March/016795.html
     if x < 0.0:
         if isnan(y):
-            return W_FloatObject(NAN)
+            return NAN
         if math.floor(y) != y:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("negative number cannot be "
-                                            "raised to a fractional power"))
+            raise PowDomainError
         # y is an exact integer, albeit perhaps a very large one.
         # Replace x by its absolute value and remember to negate the
         # pow result if y is odd.
@@ -494,9 +504,9 @@
     if x == 1.0:
         # (-1) ** large_integer also ends up here
         if negate_result:
-            return W_FloatObject(-1.0)
+            return -1.0
         else:
-            return W_FloatObject(1.0)
+            return 1.0
 
     try:
         # We delegate to our implementation of math.pow() the error detection.
@@ -510,7 +520,7 @@
 
     if negate_result:
         z = -z
-    return W_FloatObject(z)
+    return z
 
 
 def neg__Float(space, w_float1):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -30,7 +30,7 @@
 from rpython.rlib import debug, jit, rerased
 from rpython.rlib.listsort import make_timsort_class
 from rpython.rlib.objectmodel import (
-    instantiate, newlist_hint, resizelist_hint, specialize)
+    instantiate, newlist_hint, resizelist_hint, specialize, import_from_mixin)
 from rpython.tool.sourcetools import func_with_new_name
 
 __all__ = ['W_ListObject', 'make_range_list', 'make_empty_list_with_size']
@@ -1170,7 +1170,6 @@
 
 
 class AbstractUnwrappedStrategy(object):
-    _mixin_ = True
 
     def wrap(self, unwrapped):
         raise NotImplementedError
@@ -1329,7 +1328,6 @@
 
     def setslice(self, w_list, start, step, slicelength, w_other):
         assert slicelength >= 0
-        items = self.unerase(w_list.lstorage)
 
         if self is self.space.fromcache(ObjectListStrategy):
             w_other = w_other._temporarily_as_objects()
@@ -1341,6 +1339,7 @@
             w_list.setslice(start, step, slicelength, w_other_as_object)
             return
 
+        items = self.unerase(w_list.lstorage)
         oldsize = len(items)
         len2 = w_other.length()
         if step == 1:  # Support list resizing for non-extended slices
@@ -1456,7 +1455,9 @@
         self.unerase(w_list.lstorage).reverse()
 
 
-class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class ObjectListStrategy(ListStrategy):
+    import_from_mixin(AbstractUnwrappedStrategy)
+
     _none_value = None
     _applevel_repr = "object"
 
@@ -1489,7 +1490,9 @@
         return self.unerase(w_list.lstorage)
 
 
-class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class IntegerListStrategy(ListStrategy):
+    import_from_mixin(AbstractUnwrappedStrategy)
+
     _none_value = 0
     _applevel_repr = "int"
 
@@ -1520,7 +1523,30 @@
         return self.unerase(w_list.lstorage)
 
 
-class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+    _base_extend_from_list = _extend_from_list
+
+    def _extend_from_list(self, w_list, w_other):
+        if w_other.strategy is self.space.fromcache(RangeListStrategy):
+            l = self.unerase(w_list.lstorage)
+            other = w_other.getitems_int()
+            assert other is not None
+            l += other
+            return
+        return self._base_extend_from_list(w_list, w_other)
+
+
+    _base_setslice = setslice
+
+    def setslice(self, w_list, start, step, slicelength, w_other):
+        if w_other.strategy is self.space.fromcache(RangeListStrategy):
+            storage = self.erase(w_other.getitems_int())
+            w_other = W_ListObject.from_storage_and_strategy(
+                    self.space, storage, self)
+        return self._base_setslice(w_list, start, step, slicelength, w_other)
+
+class FloatListStrategy(ListStrategy):
+    import_from_mixin(AbstractUnwrappedStrategy)
+
     _none_value = 0.0
     _applevel_repr = "float"
 
@@ -1548,7 +1574,9 @@
             l.reverse()
 
 
-class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class StringListStrategy(ListStrategy):
+    import_from_mixin(AbstractUnwrappedStrategy)
+
     _none_value = None
     _applevel_repr = "str"
 
@@ -1579,7 +1607,9 @@
         return self.unerase(w_list.lstorage)
 
 
-class UnicodeListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class UnicodeListStrategy(ListStrategy):
+    import_from_mixin(AbstractUnwrappedStrategy)
+
     _none_value = None
     _applevel_repr = "unicode"
 
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -225,6 +225,15 @@
         l.setslice(0, 1, 2, W_ListObject(space, [w('a'), w(2), w(3)]))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+    def test_setslice_int_range(self):
+        space = self.space
+        w = space.wrap
+        l = W_ListObject(space, [w(1), w(2), w(3)])
+        assert isinstance(l.strategy, IntegerListStrategy)
+        l.setslice(0, 1, 2, make_range_list(space, 5, 1, 4))
+        assert isinstance(l.strategy, IntegerListStrategy)
+
+
     def test_setslice_List(self):
         space = self.space
 
@@ -467,6 +476,12 @@
         l4 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         assert self.space.eq_w(l3, l4)
 
+    def test_add_of_range_and_int(self):
+        l1 = make_range_list(self.space, 0, 1, 100)
+        l2 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+        l3 = self.space.add(l2, l1)
+        assert l3.strategy is l2.strategy
+
     def test_mul(self):
         l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         l2 = l1.mul(2)
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -197,10 +197,10 @@
 
 W_AbstractTupleObject.typedef = StdTypeDef(
     "tuple",
-    __doc__ = '''tuple() -> an empty tuple
+    __doc__ = """tuple() -> an empty tuple
 tuple(sequence) -> tuple initialized from sequence's items
 
-If the argument is a tuple, the return value is the same object.''',
+If the argument is a tuple, the return value is the same object.""",
     __new__ = interp2app(W_AbstractTupleObject.descr_new),
     __repr__ = interp2app(W_AbstractTupleObject.descr_repr),
     __hash__ = interpindirect2app(W_AbstractTupleObject.descr_hash),
diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py
--- a/pypy/pytest-A.py
+++ b/pypy/pytest-A.py
@@ -5,7 +5,6 @@
     'arm': ['interpreter/astcompiler/test',
             'interpreter/pyparser/test',
             'interpreter/test',
-            'interpreter/test2',
             'module/test_lib_pypy',
             'objspace/std/test',
     ],
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -3442,6 +3442,29 @@
 
         a.build_types(f, [str])
 
+    def test_negative_number_find(self):
+        def f(s, e):
+            return "xyz".find("x", s, e)
+
+        a = self.RPythonAnnotator()
+        py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+        a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+                          annmodel.SomeInteger(nonneg=True)])
+        def f(s, e):
+            return "xyz".rfind("x", s, e)
+
+        py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+        a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+                          annmodel.SomeInteger(nonneg=True)])
+
+        def f(s, e):
+            return "xyz".count("x", s, e)
+
+        py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+        a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+                          annmodel.SomeInteger(nonneg=True)])
+        
+
     def test_setslice(self):
         def f():
             lst = [2, 5, 7]
@@ -4080,7 +4103,7 @@
         with py.test.raises(annmodel.UnionError) as exc:
             a.build_types(f, [int])
 
-        assert ("RPython cannot unify instances with no common base class" 
+        assert ("RPython cannot unify instances with no common base class"
                 in exc.value.msg)
 
     def test_unionerror_iters(self):
@@ -4096,7 +4119,7 @@
         with py.test.raises(annmodel.UnionError) as exc:
             a.build_types(f, [int])
 
-        assert ("RPython cannot unify incompatible iterator variants" in 
+        assert ("RPython cannot unify incompatible iterator variants" in
                 exc.value.msg)
 
     def test_variable_getattr(self):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -10,7 +10,7 @@
     SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeFloat, SomeIterator,
     SomePBC, SomeTypedAddressAccess, SomeAddress, SomeType, s_ImpossibleValue,
     s_Bool, s_None, unionof, missing_operation, add_knowntypedata,
-    HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString)
+    HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString, SomeByteArray)
 from rpython.annotator.bookkeeper import getbookkeeper
 from rpython.annotator import builtin
 from rpython.annotator.binaryop import _clone ## XXX where to put this?
@@ -333,12 +333,13 @@
         check_negative_slice(s_start, s_stop)
         lst.listdef.resize()
 
-def check_negative_slice(s_start, s_stop):
+def check_negative_slice(s_start, s_stop, error="slicing"):
     if isinstance(s_start, SomeInteger) and not s_start.nonneg:
-        raise AnnotatorError("slicing: not proven to have non-negative start")
+        raise AnnotatorError("%s: not proven to have non-negative start" %
+                             error)
     if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \
            getattr(s_stop, 'const', 0) != -1:
-        raise AnnotatorError("slicing: not proven to have non-negative stop")
+        raise AnnotatorError("%s: not proven to have non-negative stop" % error)
 
 
 class __extend__(SomeDict):
@@ -448,12 +449,15 @@
         return s_Bool
 
     def method_find(str, frag, start=None, end=None):
+        check_negative_slice(start, end, "find")
         return SomeInteger()
 
     def method_rfind(str, frag, start=None, end=None):
+        check_negative_slice(start, end, "rfind")
         return SomeInteger()
 
     def method_count(str, frag, start=None, end=None):
+        check_negative_slice(start, end, "count")
         return SomeInteger(nonneg=True)
 
     def method_strip(str, chr):
@@ -520,6 +524,11 @@
     op_contains.can_only_throw = []
 
 
+class __extend__(SomeByteArray):
+    def getslice(ba, s_start, s_stop):
+        check_negative_slice(s_start, s_stop)
+        return SomeByteArray()
+
 class __extend__(SomeUnicodeString):
     def method_encode(uni, s_enc):
         if not s_enc.is_constant():
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -252,6 +252,23 @@
         from rpython.translator.tool.graphpage import try_show
         try_show(self)
 
+    def get_graph(self):
+        import gc
+        pending = [self]   # pending blocks
+        seen = {self: True, None: True}
+        for x in pending:
+            for y in gc.get_referrers(x):
+                if isinstance(y, FunctionGraph):
+                    return y
+                elif isinstance(y, Link):
+                    block = y.prevblock
+                    if block not in seen:
+                        pending.append(block)
+                        seen[block] = True
+                elif isinstance(y, dict):
+                    pending.append(y)   # go back from the dict to the real obj
+        return pending
+
     view = show
 
 
diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -1,3 +1,4 @@
+import os
 from rpython.flowspace.model import Constant, const
 
 SPECIAL_CASES = {}
@@ -37,6 +38,18 @@
     return space.frame.do_operation('simple_call', const(isinstance),
             w_instance, w_type)
 
+ at register_flow_sc(open)
+def sc_open(space, *args_w):
+    from rpython.rlib.rfile import create_file
+
+    return space.frame.do_operation("simple_call", const(create_file), *args_w)
+
+ at register_flow_sc(os.tmpfile)
+def sc_os_tmpfile(space):
+    from rpython.rlib.rfile import create_temp_rfile
+
+    return space.frame.do_operation("simple_call", const(create_temp_rfile))
+
 # _________________________________________________________________________
 # a simplified version of the basic printing routines, for RPython programs
 class StdOutBuffer:
diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1063,7 +1063,6 @@
         assert len(graph.startblock.exits) == 1
         assert graph.startblock.exits[0].target == graph.returnblock
 
-
     def test_global_variable(self):
         def global_var_missing():
             return a
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -381,6 +381,8 @@
             res = self.llinterp.eval_graph(ptr._obj.graph, args)
         else:
             res = ptr._obj._callable(*args)
+        if RESULT is lltype.Void:
+            return None
         return support.cast_result(RESULT, res)
 
     def _do_call(self, func, args_i, args_r, args_f, calldescr):
diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -87,9 +87,11 @@
     def _escape(self, box):
         if box in self.new_boxes:
             self.new_boxes[box] = False
-        if box in self.dependencies:
-            deps = self.dependencies[box]
-            del self.dependencies[box]
+        try:
+            deps = self.dependencies.pop(box)
+        except KeyError:
+            pass
+        else:
             for dep in deps:
                 self._escape(dep)
 
@@ -117,15 +119,18 @@
             # effects are so well defined.
             elif effectinfo.oopspecindex == effectinfo.OS_ARRAYCOPY:
                 # The destination box
-                if argboxes[2] in self.new_boxes:
-                    # XXX: no descr here so we invalidate any of them, not just
-                    # of the correct type
-                    # XXX: in theory the indices of the copy could be looked at
-                    # as well
-                    for descr, cache in self.heap_array_cache.iteritems():
+                if (
+                    argboxes[2] in self.new_boxes and
+                    len(effectinfo.write_descrs_arrays) == 1
+                ):
+                    # Fish the descr out of the effectinfo
+                    cache = self.heap_array_cache.get(effectinfo.write_descrs_arrays[0], None)
+                    if cache is not None:
+                        # XXX: in theory the indices of the copy could be
+                        # looked at
                         for idx, cache in cache.iteritems():
                             for frombox in cache.keys():
-                                if not self.new_boxes.get(frombox, False):
+                                if not self.is_unescaped(frombox):
                                     del cache[frombox]
                     return
             else:
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
@@ -32,7 +32,6 @@
     'please fix rlib/jit.py to say ENABLE_ALL_OPTS = %r' % (ALL_OPTS_NAMES,))
 
 def build_opt_chain(metainterp_sd, enable_opts):
-    config = metainterp_sd.config
     optimizations = []
     unroll = 'unroll' in enable_opts    # 'enable_opts' is normally a dict
     for name, opt in unroll_all_opts:
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -107,6 +107,11 @@
         v2 = self.getvalue(op.getarg(1))
         if v2.is_constant() and v2.box.getint() == 0:
             self.make_equal_to(op.result, v1)
+        elif v1.is_constant() and v1.box.getint() == 0:
+            op = op.copy_and_change(rop.INT_NEG, args=[v2.box])
+            self.emit_operation(op)
+        elif v1 is v2:
+            self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
             # Synthesize the reverse ops for optimize_default to reuse
@@ -166,6 +171,8 @@
 
         if v2.is_constant() and v2.box.getint() == 0:
             self.make_equal_to(op.result, v1)
+        elif v1.is_constant() and v1.box.getint() == 0:
+            self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
 
@@ -175,6 +182,8 @@
 
         if v2.is_constant() and v2.box.getint() == 0:
             self.make_equal_to(op.result, v1)
+        elif v1.is_constant() and v1.box.getint() == 0:
+            self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
 
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -45,7 +45,7 @@
                 return self.optimize_JUMP(op.copy_and_change(rop.JUMP))
             self.last_label_descr = op.getdescr()
         self.emit_operation(op)
-        
+
     def optimize_JUMP(self, op):
         if not self.unroll:
             descr = op.getdescr()
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -3735,6 +3735,33 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_sub_identity(self):
+        ops = """
+        [i0]
+        i1 = int_sub(i0, i0)
+        i2 = int_sub(i1, i0)
+        jump(i1, i2)
+        """
+        expected = """
+        [i0]
+        i2 = int_neg(i0)
+        jump(0, i2)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_shift_zero(self):
+        ops = """
+        [i0]
+        i1 = int_lshift(0, i0)
+        i2 = int_rshift(0, i0)
+        jump(i1, i2)
+        """
+        expected = """
+        [i0]
+        jump(0, 0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_bound_and(self):
         ops = """
         [i0]
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -45,6 +45,15 @@
             return value
         return OptValue(self.force_box(optforce))
 
+    def get_args_for_fail(self, modifier):
+        # checks for recursion: it is False unless
+        # we have already seen the very same keybox
+        if self.box is None and not modifier.already_seen_virtual(self.keybox):
+            self._get_args_for_fail(modifier)
+
+    def _get_args_for_fail(self, modifier):
+        raise NotImplementedError("abstract base")
+
     def make_virtual_info(self, modifier, fieldnums):
         if fieldnums is None:
             return self._make_virtual(modifier)
@@ -193,16 +202,13 @@
             self._cached_sorted_fields = lst
         return lst
 
-    def get_args_for_fail(self, modifier):
-        if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            # checks for recursion: it is False unless
-            # we have already seen the very same keybox
-            lst = self._get_field_descr_list()
-            fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
-            modifier.register_virtual_fields(self.keybox, fieldboxes)
-            for ofs in lst:
-                fieldvalue = self._fields[ofs]
-                fieldvalue.get_args_for_fail(modifier)
+    def _get_args_for_fail(self, modifier):
+        lst = self._get_field_descr_list()
+        fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
+        modifier.register_virtual_fields(self.keybox, fieldboxes)
+        for ofs in lst:
+            fieldvalue = self._fields[ofs]
+            fieldvalue.get_args_for_fail(modifier)
 
 class VirtualValue(AbstractVirtualStructValue):
     level = optimizer.LEVEL_KNOWNCLASS
@@ -254,18 +260,15 @@
     def set_item_value(self, i, newval):
         raise NotImplementedError
 
-    def get_args_for_fail(self, modifier):
-        if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            # checks for recursion: it is False unless
-            # we have already seen the very same keybox
-            itemboxes = []
-            for i in range(self.getlength()):
-                itemvalue = self.get_item_value(i)
-                itemboxes.append(itemvalue.get_key_box())
-            modifier.register_virtual_fields(self.keybox, itemboxes)
-            for i in range(self.getlength()):
-                itemvalue = self.get_item_value(i)
-                itemvalue.get_args_for_fail(modifier)
+    def _get_args_for_fail(self, modifier):
+        itemboxes = []
+        for i in range(self.getlength()):
+            itemvalue = self.get_item_value(i)
+            itemboxes.append(itemvalue.get_key_box())
+        modifier.register_virtual_fields(self.keybox, itemboxes)
+        for i in range(self.getlength()):
+            itemvalue = self.get_item_value(i)
+            itemvalue.get_args_for_fail(modifier)
 
 
 class VArrayValue(AbstractVArrayValue):
@@ -370,17 +373,16 @@
             descrs.append(item_descrs)
         return descrs
 
-    def get_args_for_fail(self, modifier):
-        if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            itemdescrs = self._get_list_of_descrs()
-            itemboxes = []
-            for i in range(len(self._items)):
-                for descr in itemdescrs[i]:
-                    itemboxes.append(self._items[i][descr].get_key_box())
-            modifier.register_virtual_fields(self.keybox, itemboxes)
-            for i in range(len(self._items)):
-                for descr in itemdescrs[i]:
-                    self._items[i][descr].get_args_for_fail(modifier)
+    def _get_args_for_fail(self, modifier):
+        itemdescrs = self._get_list_of_descrs()
+        itemboxes = []
+        for i in range(len(self._items)):
+            for descr in itemdescrs[i]:
+                itemboxes.append(self._items[i][descr].get_key_box())
+        modifier.register_virtual_fields(self.keybox, itemboxes)
+        for i in range(len(self._items)):
+            for descr in itemdescrs[i]:
+                self._items[i][descr].get_args_for_fail(modifier)
 
     def force_at_end_of_preamble(self, already_forced, optforce):
         if self in already_forced:
@@ -481,6 +483,15 @@
     def getitem_raw(self, offset, length, descr):
         return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr)
 
+    def _get_args_for_fail(self, modifier):
+        box = self.rawbuffer_value.get_key_box()
+        modifier.register_virtual_fields(self.keybox, [box])
+        self.rawbuffer_value.get_args_for_fail(modifier)
+
+    def _make_virtual(self, modifier):
+        return modifier.make_vrawslice(self.offset)
+
+
 class OptVirtualize(optimizer.Optimization):
     "Virtualize objects until they escape."
 
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -284,7 +284,10 @@
         return VArrayStructInfo(arraydescr, fielddescrs)
 
     def make_vrawbuffer(self, size, offsets, descrs):
-        return VRawBufferStateInfo(size, offsets, descrs)
+        return VRawBufferInfo(size, offsets, descrs)
+
+    def make_vrawslice(self, offset):
+        return VRawSliceInfo(offset)
 
     def make_vstrplain(self, is_unicode=False):
         if is_unicode:
@@ -554,10 +557,13 @@
             debug_print("\t\t", str(untag(i)))
 
 
-class VRawBufferStateInfo(AbstractVirtualInfo):
+class VAbstractRawInfo(AbstractVirtualInfo):
     kind = INT
     is_about_raw = True
 
+
+class VRawBufferInfo(VAbstractRawInfo):
+
     def __init__(self, size, offsets, descrs):
         self.size = size
         self.offsets = offsets
@@ -580,6 +586,25 @@
             debug_print("\t\t", str(untag(i)))
 
 
+class VRawSliceInfo(VAbstractRawInfo):
+
+    def __init__(self, offset):
+        self.offset = offset
+
+    @specialize.argtype(1)
+    def allocate_int(self, decoder, index):
+        assert len(self.fieldnums) == 1
+        base_buffer = decoder.decode_int(self.fieldnums[0])
+        buffer = decoder.int_add_const(base_buffer, self.offset)
+        decoder.virtuals_cache.set_int(index, buffer)
+        return buffer
+
+    def debug_prints(self):
+        debug_print("\tvrawsliceinfo", " at ",  compute_unique_id(self))
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
+
 class VArrayStructInfo(AbstractVirtualInfo):
     def __init__(self, arraydescr, fielddescrs):
         self.arraydescr = arraydescr
@@ -783,7 +808,8 @@
         v = self.virtuals_cache.get_int(index)
         if not v:
             v = self.rd_virtuals[index]
-            assert v.is_about_raw and isinstance(v, VRawBufferStateInfo)
+            ll_assert(bool(v), "resume.py: null rd_virtuals[index]")
+            assert v.is_about_raw and isinstance(v, VAbstractRawInfo)
             v = v.allocate_int(self, index)
             ll_assert(v == self.virtuals_cache.get_int(index), "resume.py: bad cache")
         return v
@@ -1116,6 +1142,10 @@
     def write_a_float(self, index, box):
         self.boxes_f[index] = box
 
+    def int_add_const(self, intbox, offset):
+        return self.metainterp.execute_and_record(rop.INT_ADD, None, intbox,
+                                                  ConstInt(offset))
+
 # ---------- when resuming for blackholing, get direct values ----------
 
 def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
@@ -1407,6 +1437,9 @@
     def write_a_float(self, index, float):
         self.blackholeinterp.setarg_f(index, float)
 
+    def int_add_const(self, base, offset):
+        return base + offset
+
 # ____________________________________________________________
 
 def dump_storage(storage, liveboxes):
diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -86,15 +86,17 @@
             data = rffi.ptradd(exchange_buffer, ofs)
             rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue
 
-        def f():
+        def f(i):
             exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16,
-                                  flavor='raw', zero=True)
-            ofs = 16
+                                  flavor='raw')
+
+            targetptr = rffi.ptradd(exbuf, 16)
             for avalue in unroll_avalues:
                 TYPE = rffi.CArray(lltype.typeOf(avalue))
-                data = rffi.ptradd(exbuf, ofs)
-                rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue
-                ofs += 16
+                if i >= 9:    # a guard that can fail
+                    pass
+                rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue
+                targetptr = rffi.ptradd(targetptr, 16)
 
             jit_ffi_call(cif_description, func_addr, exbuf)
 
@@ -102,8 +104,7 @@
                 res = 654321
             else:
                 TYPE = rffi.CArray(lltype.typeOf(rvalue))
-                data = rffi.ptradd(exbuf, ofs)
-                res = rffi.cast(lltype.Ptr(TYPE), data)[0]
+                res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0]
             lltype.free(exbuf, flavor='raw')
             if lltype.typeOf(res) is lltype.SingleFloat:
                 res = float(res)
@@ -117,9 +118,9 @@
             return res == rvalue
 
         with FakeFFI(fake_call_impl_any):
-            res = f()
+            res = f(-42)
             assert matching_result(res, rvalue)
-            res = self.interp_operations(f, [],
+            res = self.interp_operations(f, [-42],
                             supports_floats = supports_floats,
                           supports_longlong = supports_longlong,
                       supports_singlefloats = supports_singlefloats)
@@ -132,6 +133,19 @@
             self.check_operations_history(call_may_force=0,
                                           call_release_gil=expected_call_release_gil)
 
+            ##################################################
+            driver = jit.JitDriver(reds=['i'], greens=[])
+            def main():
+                i = 0
+                while 1:
+                    driver.jit_merge_point(i=i)
+                    res = f(i)
+                    i += 1
+                    if i == 12:
+                        return res
+            self.meta_interp(main, [])
+
+
     def test_simple_call_int(self):
         self._run([types.signed] * 2, types.signed, [456, 789], -42)
 
diff --git a/rpython/jit/metainterp/test/test_heapcache.py b/rpython/jit/metainterp/test/test_heapcache.py
--- a/rpython/jit/metainterp/test/test_heapcache.py
+++ b/rpython/jit/metainterp/test/test_heapcache.py
@@ -29,17 +29,24 @@
 
     OS_ARRAYCOPY = 0
 
-    def __init__(self, extraeffect, oopspecindex):
+    def __init__(self, extraeffect, oopspecindex, write_descrs_arrays):
         self.extraeffect = extraeffect
         self.oopspecindex = oopspecindex
+        self.write_descrs_arrays = write_descrs_arrays
+
 
 class FakeCallDescr(object):
-    def __init__(self, extraeffect, oopspecindex=None):
+    def __init__(self, extraeffect, oopspecindex=None, write_descrs_arrays=[]):
         self.extraeffect = extraeffect
         self.oopspecindex = oopspecindex
+        self.write_descrs_arrays = write_descrs_arrays
 
     def get_extra_info(self):
-        return FakeEffectinfo(self.extraeffect, self.oopspecindex)
+        return FakeEffectinfo(
+            self.extraeffect, self.oopspecindex,
+            write_descrs_arrays=self.write_descrs_arrays
+        )
+
 
 class TestHeapCache(object):
     def test_known_class_box(self):
@@ -364,13 +371,13 @@
         # Just need the destination box for this call
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
             [None, None, box2, None, None]
         )
         assert h.getarrayitem(box1, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
             [None, None, box3, None, None]
         )
         assert h.getarrayitem(box1, index1, descr1) is None
@@ -379,11 +386,24 @@
         assert h.getarrayitem(box4, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
             [None, None, box2, None, None]
         )
         assert h.getarrayitem(box4, index1, descr1) is None
 
+    def test_ll_arraycopy_differing_descrs(self):
+        h = HeapCache()
+        h.setarrayitem(box1, index1, box2, descr1)
+        assert h.getarrayitem(box1, index1, descr1) is box2
+        h.new_array(box2, lengthbox2)
+        h.invalidate_caches(
+            rop.CALL,
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr2]),
+            [None, None, box2, None, None]
+        )
+        assert h.getarrayitem(box1, index1, descr1) is box2
+
+
     def test_unescaped(self):
         h = HeapCache()
         assert not h.is_unescaped(box1)
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -1201,6 +1201,7 @@
         # ^^^ a fast path of write-barrier
         #
         if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
+            assert self.card_page_indices > 0
             #
             if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
                 # The source object may have random young pointers.
diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -121,13 +121,15 @@
                 cur = next
             free_non_gc_object(self)
 
-        def _length_estimate(self):
+        def length(self):
             chunk = self.chunk
+            result = 0
             count = self.used_in_last_chunk
             while chunk:
+                result += count
                 chunk = chunk.next
-                count += chunk_size
-            return count
+                count = chunk_size
+            return result
 
         def foreach(self, callback, arg):
             """Invoke 'callback(address, arg)' for all addresses in the stack.
@@ -144,7 +146,7 @@
         foreach._annspecialcase_ = 'specialize:arg(1)'
 
         def stack2dict(self):
-            result = AddressDict(self._length_estimate())
+            result = AddressDict(self.length())
             self.foreach(_add_in_dict, result)
             return result
 
diff --git a/rpython/memory/test/test_support.py b/rpython/memory/test/test_support.py
--- a/rpython/memory/test/test_support.py
+++ b/rpython/memory/test/test_support.py
@@ -94,6 +94,18 @@
             assert a == addrs[i]
         assert not ll.non_empty()
 
+    def test_length(self):
+        AddressStack = get_address_stack(10)
+        ll = AddressStack()
+        a = raw_malloc(llmemory.sizeof(lltype.Signed))
+        for i in range(42):
+            assert ll.length() == i
+            ll.append(a)
+        for i in range(42-1, -1, -1):
+            b = ll.pop()
+            assert b == a
+            assert ll.length() == i
+
 
 class TestAddressDeque:
     def test_big_access(self):
diff --git a/rpython/rlib/parsing/deterministic.py b/rpython/rlib/parsing/deterministic.py
--- a/rpython/rlib/parsing/deterministic.py
+++ b/rpython/rlib/parsing/deterministic.py
@@ -60,7 +60,8 @@
         self.args = (input, state, source_pos)
 
     def nice_error_message(self, filename="<unknown>"):
-        result = ["  File %s, line %s" % (filename, self.source_pos.lineno)]
+        # + 1 is because source_pos is 0-based and humans 1-based


More information about the pypy-commit mailing list