[pypy-commit] pypy jumbo: merge conflict

nanjekye pypy.commits at gmail.com
Mon Mar 13 12:30:53 EDT 2017


Author: Joannah Nanjekye <nanjekyejoannah at gmail.com>
Branch: jumbo
Changeset: r90657:1e6aa8fc49eb
Date: 2017-03-08 15:07 +0300
http://bitbucket.org/pypy/pypy/changeset/1e6aa8fc49eb/

Log:	merge conflict

diff --git a/lib-python/3/datetime.py b/lib-python/3/datetime.py
--- a/lib-python/3/datetime.py
+++ b/lib-python/3/datetime.py
@@ -1000,6 +1000,11 @@
         else:
             return (self.__class__, args, state)
 
+    # PyPy: added for compatibility with the _datetime module
+    # issue #2489
+    def __new__(cls, *args, **kwds):
+        return super(tzinfo, cls).__new__(cls)
+
 _tzinfo_class = tzinfo
 
 class time:
diff --git a/lib-python/3/test/test_functools.py b/lib-python/3/test/test_functools.py
--- a/lib-python/3/test/test_functools.py
+++ b/lib-python/3/test/test_functools.py
@@ -233,21 +233,21 @@
         f = self.partial(capture)
         f.__setstate__((f, (), {}, {}))
         try:
-            self.assertEqual(repr(f), '%s(%s(...))' % (name, name))
+            self.assertEqual(repr(f), '%s(...)' % (name))
         finally:
             f.__setstate__((capture, (), {}, {}))
 
         f = self.partial(capture)
         f.__setstate__((capture, (f,), {}, {}))
         try:
-            self.assertEqual(repr(f), '%s(%r, %s(...))' % (name, capture, name))
+            self.assertEqual(repr(f), '%s(%r, ...)' % (name, capture))
         finally:
             f.__setstate__((capture, (), {}, {}))
 
         f = self.partial(capture)
         f.__setstate__((capture, (), {'a': f}, {}))
         try:
-            self.assertEqual(repr(f), '%s(%r, a=%s(...))' % (name, capture, name))
+            self.assertEqual(repr(f), '%s(%r, a=...)' % (name, capture))
         finally:
             f.__setstate__((capture, (), {}, {}))
 
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -176,3 +176,20 @@
 .. branch: py3.5-text-utf8
 
 space.text_w now encodes to utf-8 not preserving surrogates.
+
+.. branch: fix-cpyext-releasebuffer
+
+Improve handling of the Py3-style buffer slots in cpyext: fix memoryviews
+keeping objects alive forever (missing decref), and make sure that
+bf_releasebuffer is called when it should, e.g. from PyBuffer_Release.
+
+.. branch: fix-global
+
+Fix bug (bad reported info) when asked to translate SyntaxWarning to
+SyntaxError.
+
+.. branch: optinfo-into-bridges-3
+
+Improve the optimization of branchy Python code by retaining more
+information across failing guards. This is done by appending some
+carefully encoded extra information into the resume code.
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -672,15 +672,17 @@
                          w_filename2=w_filename2,
                          eintr_retry=eintr_retry)
 
-def exception_from_saved_errno(space, w_type):
-    from rpython.rlib.rposix import get_saved_errno
-
-    errno = get_saved_errno()
+def exception_from_errno(space, w_type, errno):
     msg = strerror(errno)
     w_error = space.call_function(w_type, space.newint(errno),
                                   space.newunicode(msg))
     return OperationError(w_type, w_error)
 
+def exception_from_saved_errno(space, w_type):
+    from rpython.rlib.rposix import get_saved_errno
+    errno = get_saved_errno()
+    return exception_from_errno(space, w_type, errno)
+
 def new_exception_class(space, name, w_bases=None, w_dict=None):
     """Create a new exception type.
     @param name: the name of the type.
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -5,6 +5,8 @@
     TypeDef, GetSetProperty, generic_new_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from rpython.rlib.buffer import Buffer, SubBuffer
+from rpython.rlib.rgc import (
+    nonmoving_raw_ptr_for_resizable_list, resizable_list_supporting_raw_ptr)
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import r_longlong, intmask
 from rpython.rlib import rposix
@@ -13,7 +15,6 @@
     W_IOBase, DEFAULT_BUFFER_SIZE, convert_size, trap_eintr,
     check_readable_w, check_writable_w, check_seekable_w)
 from rpython.rlib import rthread
-from rpython.rlib.rgc import nonmoving_raw_ptr_for_resizable_list
 
 STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
 
@@ -159,7 +160,7 @@
 
     def __init__(self, n):
         self.length = n
-        self.buf = ['\0'] * n
+        self.buf = resizable_list_supporting_raw_ptr(['\0'] * n)
         self.readonly = False
 
     def getlength(self):
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -2,10 +2,13 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import (
     OperationError, oefmt, wrap_oserror, wrap_oserror2)
+from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rarithmetic import r_longlong
+from rpython.rlib.rposix import c_read, get_saved_errno
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib import rposix
 from rpython.rlib.rposix_stat import STAT_FIELD_TYPES
+from rpython.rtyper.lltypesystem import lltype, rffi
 from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_EXCL
 import sys, os, stat, errno
 from pypy.module._io.interp_iobase import (
@@ -126,6 +129,7 @@
             return currentsize + BIGCHUNK
     return currentsize + SMALLCHUNK
 
+
 class W_FileIO(W_RawIOBase):
     def __init__(self, space):
         W_RawIOBase.__init__(self, space)
@@ -447,18 +451,43 @@
         self._check_readable(space)
         rwbuffer = space.getarg_w('w*', w_buffer)
         length = rwbuffer.getlength()
-        while True:
+
+        target_address = lltype.nullptr(rffi.CCHARP.TO)
+        if length > 64:
             try:
-                buf = os.read(self.fd, length)
-                break
-            except OSError as e:
-                if e.errno == errno.EAGAIN:
-                    return space.w_None
-                wrap_oserror(space, e,
-                             exception_name='w_IOError',
-                             eintr_retry=True)
-        rwbuffer.setslice(0, buf)
-        return space.newint(len(buf))
+                target_address = rwbuffer.get_raw_address()
+            except ValueError:
+                pass
+
+        if not target_address:
+            # unoptimized case
+            while True:
+                try:
+                    buf = os.read(self.fd, length)
+                    break
+                except OSError as e:
+                    if e.errno == errno.EAGAIN:
+                        return space.w_None
+                    wrap_oserror(space, e, exception_name='w_IOError',
+                                 eintr_retry=True)
+            rwbuffer.setslice(0, buf)
+            return space.newint(len(buf))
+        else:
+            # optimized case: reading more than 64 bytes into a rwbuffer
+            # with a valid raw address
+            while True:
+                got = c_read(self.fd, target_address, length)
+                keepalive_until_here(rwbuffer)
+                got = rffi.cast(lltype.Signed, got)
+                if got >= 0:
+                    return space.newint(got)
+                else:
+                    err = get_saved_errno()
+                    if err == errno.EAGAIN:
+                        return space.w_None
+                    e = OSError(err, "read failed")
+                    wrap_oserror(space, e, exception_name='w_IOError',
+                                 eintr_retry=True)
 
     def readall_w(self, space):
         self._check_closed(space)
diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -12,6 +12,9 @@
         tmpfile = udir.join('tmpfile')
         tmpfile.write("a\nb\nc", mode='wb')
         cls.w_tmpfile = cls.space.wrap(str(tmpfile))
+        bigtmpfile = udir.join('bigtmpfile')
+        bigtmpfile.write("a\nb\nc" * 20, mode='wb')
+        cls.w_bigtmpfile = cls.space.wrap(str(bigtmpfile))
 
     def test_simple_read(self):
         import _io
@@ -287,7 +290,21 @@
         raises(_io.UnsupportedOperation, bufio.tell)
 
 class AppTestBufferedReaderWithThreads(AppTestBufferedReader):
-    spaceconfig = dict(usemodules=['_io', 'thread'])
+    spaceconfig = dict(usemodules=['_io', 'thread', 'time'])
+
+    def test_readinto_small_parts(self):
+        import _io, os, _thread, time
+        read_fd, write_fd = os.pipe()
+        raw = _io.FileIO(read_fd)
+        f = _io.BufferedReader(raw)
+        a = bytearray(b'x' * 10)
+        os.write(write_fd, b"abcde")
+        def write_more():
+            time.sleep(0.5)
+            os.write(write_fd, b"fghij")
+        _thread.start_new_thread(write_more, ())
+        assert f.readinto(a) == 10
+        assert a == b'abcdefghij'
 
 
 class AppTestBufferedWriter:
diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -1,4 +1,5 @@
 # encoding: utf-8
+from pypy.interpreter.gateway import interp2app
 from rpython.tool.udir import udir
 import os
 
@@ -6,14 +7,18 @@
 class AppTestFileIO:
     spaceconfig = dict(usemodules=['_io'] + (['fcntl'] if os.name != 'nt' else []))
 
-    def setup_class(cls):
+    def setup_method(self, meth):
         tmpfile = udir.join('tmpfile')
         tmpfile.write("a\nb\nc", mode='wb')
-        cls.w_tmpfile = cls.space.wrap(str(tmpfile))
-        cls.w_tmpdir = cls.space.wrap(str(udir))
-        cls.w_posix = cls.space.appexec([], """():
+        self.w_tmpfile = self.space.wrap(str(tmpfile))
+        self.w_tmpdir = self.space.wrap(str(udir))
+        self.w_posix = self.space.appexec([], """():
             import %s as m;
             return m""" % os.name)
+        if meth == self.test_readinto_optimized:
+            bigfile = udir.join('bigfile')
+            bigfile.write('a' * 1000, mode='wb')
+            self.w_bigfile = self.space.wrap(self.space.wrap(str(bigfile)))
 
     def test_constructor(self):
         import _io
@@ -151,13 +156,10 @@
         import _io
         a = bytearray(b'x' * 10)
         f = _io.FileIO(self.tmpfile, 'r+')
-        f.seek(5)
-        f.write(b'\x00' * 5)
-        f.seek(0)
-        assert f.readinto(a) == 10
+        assert f.readinto(a) == 5
         f.seek(0)
         m = memoryview(bytearray(b"helloworld"))
-        assert f.readinto(m) == 10
+        assert f.readinto(m) == 5
         #
         exc = raises(TypeError, f.readinto, u"hello")
         msg = str(exc.value)
@@ -170,7 +172,7 @@
         assert " read-write b" in msg and msg.endswith(", not memoryview")
         #
         f.close()
-        assert a == b'a\nb\nc\0\0\0\0\0'
+        assert a == b'a\nb\ncxxxxx'
         #
         a = bytearray(b'x' * 10)
         f = _io.FileIO(self.tmpfile, 'r+')
@@ -179,6 +181,13 @@
         f.close()
         assert a == b'a\nbxxxxxxx'
 
+    def test_readinto_optimized(self):
+        import _io
+        a = bytearray(b'x' * 1024)
+        f = _io.FileIO(self.bigfile, 'r+')
+        assert f.readinto(a) == 1000
+        assert a == b'a' * 1000 + b'x' * 24
+
     def test_nonblocking_read(self):
         try:
             import os, fcntl
@@ -194,6 +203,8 @@
         assert f.read(10) is None
         a = bytearray(b'x' * 10)
         assert f.readinto(a) is None
+        a2 = bytearray(b'x' * 1024)
+        assert f.readinto(a2) is None
 
     def test_repr(self):
         import _io
diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -565,6 +565,8 @@
             raise oefmt(space.w_ValueError, "negative buffersize in recv_into")
         if nbytes == 0:
             nbytes = lgt
+        if lgt < nbytes:
+            raise oefmt(space.w_ValueError, "buffer too small for requested bytes")
         while True:
             try:
                 nbytes_read = self.sock.recvinto(rwbuffer, nbytes, flags)
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
@@ -296,7 +296,8 @@
 
 
 class AppTestSocket:
-    spaceconfig = dict(usemodules=['_socket', '_weakref', 'struct', 'select'])
+    spaceconfig = dict(usemodules=['_socket', '_weakref', 'struct', 'select',
+                                   'unicodedata'])
 
     def setup_class(cls):
         cls.space = space
@@ -667,8 +668,6 @@
     def test_hostname_unicode(self):
         import _socket
         domain = u"испытание.pythontest.net"
-        # XXX figure out why the idna encoding is sometimes missing in
-        # tests, notably if we run all tests instead of just this one
         _socket.gethostbyname(domain)
         _socket.gethostbyname_ex(domain)
         _socket.getaddrinfo(domain, 0, _socket.AF_UNSPEC, _socket.SOCK_STREAM)
diff --git a/pypy/module/_warnings/interp_warnings.py b/pypy/module/_warnings/interp_warnings.py
--- a/pypy/module/_warnings/interp_warnings.py
+++ b/pypy/module/_warnings/interp_warnings.py
@@ -226,14 +226,16 @@
     return False
 
 def normalize_module(space, w_filename):
-    filename = space.text_w(w_filename)
+    # XXX: could be more efficient (doesn't necessarily need
+    # fsencoding/redecoding)
+    filename = space.fsencode_w(w_filename)
     if len(filename) == 0:
         return space.newtext("<unknown>")
     if filename.endswith(".py"):
         n = len(filename) - 3
         assert n >= 0
         filename = filename[:n]
-        return space.newtext(filename)
+        return space.newfilename(filename)
     return w_filename
 
 def show_warning(space, w_filename, lineno, w_text, w_category,
diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
--- a/pypy/module/cppyy/capi/loadable_capi.py
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -355,7 +355,7 @@
     return rffi.cast(rffi.UCHAR, space.c_uint_w(call_capi(space, 'call_b', args)))
 def c_call_c(space, cppmethod, cppobject, nargs, cargs):
     args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
-    return rffi.cast(rffi.CHAR, space.text_w(call_capi(space, 'call_c', args))[0])
+    return rffi.cast(rffi.CHAR, space.bytes_w(call_capi(space, 'call_c', args))[0])
 def c_call_h(space, cppmethod, cppobject, nargs, cargs):
     args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
     return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args)))
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -132,7 +132,11 @@
         if ccpresult == rffi.cast(rffi.CCHARP, 0):
             return space.newbytes("")
         result = rffi.charp2str(ccpresult)   # TODO: make it a choice to free
-        return space.newbytes(result)
+        # debatable whether this should be newtext or newbytes; they are bytes
+        # but will be more likely used as text after binding ... probably need
+        # to make this configurable on a per-function bases (same as the old
+        # char* v.s. byte* problem)
+        return space.newtext(result)
 
 
 class ConstructorExecutor(FunctionExecutor):
diff --git a/pypy/module/cppyy/ffitypes.py b/pypy/module/cppyy/ffitypes.py
--- a/pypy/module/cppyy/ffitypes.py
+++ b/pypy/module/cppyy/ffitypes.py
@@ -81,13 +81,15 @@
                 raise oefmt(space.w_ValueError, "char arg not in range(256)")
 
             value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
+        elif space.isinstance_w(w_value, space.w_text):
+            value = space.text_w(w_value)
         else:
             value = space.bytes_w(w_value)
 
         if len(value) != 1:  
             raise oefmt(space.w_ValueError,
                         "char expected, got string of size %d", len(value))
-        return value[0] # turn it into a "char" to the annotator
+        return rffi.cast(rffi.CHAR, value[0]) # help the annotator
 
     def cffi_type(self, space):
         state = space.fromcache(State)
diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py
--- a/pypy/module/cppyy/test/test_datatypes.py
+++ b/pypy/module/cppyy/test/test_datatypes.py
@@ -38,9 +38,9 @@
         assert not c.get_bool(); assert not c.get_bool_cr(); assert not c.get_bool_r()
 
         # reading char types
-        assert c.m_char  == 'a'
-        assert c.m_schar == 'b'
-        assert c.m_uchar == 'c'
+        assert c.m_char  == b'a'
+        assert c.m_schar == b'b'
+        assert c.m_uchar == b'c'
 
         # reading integer types
         assert c.m_short   == -11; assert c.get_short_cr()   == -11; assert c.get_short_r()   == -11
@@ -133,18 +133,20 @@
         raises(ValueError, 'c.set_bool(10)')
 
         # char types through functions
-        c.set_char('c');   assert c.get_char()  == 'c'
-        c.set_uchar('e');  assert c.get_uchar() == 'e'
+        c.set_char('c');   assert c.get_char()  == b'c'
+        c.set_char(b'b');  assert c.get_char()  == b'b'
+        c.set_uchar('e');  assert c.get_uchar() == b'e'
+        c.set_uchar(b'd'); assert c.get_uchar() == b'd'
 
         # char types through data members
-        c.m_char = 'b';    assert c.get_char()  ==     'b'
-        c.m_char = 40;     assert c.get_char()  == chr(40)
-        c.set_char('c');   assert c.m_char      ==     'c'
-        c.set_char(41);    assert c.m_char      == chr(41)
-        c.m_uchar = 'd';   assert c.get_uchar() ==     'd'
-        c.m_uchar = 42;    assert c.get_uchar() == chr(42)
-        c.set_uchar('e');  assert c.m_uchar     ==     'e'
-        c.set_uchar(43);   assert c.m_uchar     == chr(43)
+        c.m_char = 'b';    assert c.get_char()  == b'b'
+        c.m_char = 40;     assert c.get_char()  == str.encode(chr(40))
+        c.set_char('c');   assert c.m_char      == b'c'
+        c.set_char(41);    assert c.m_char      == str.encode(chr(41))
+        c.m_uchar = 'd';   assert c.get_uchar() == b'd'
+        c.m_uchar = 42;    assert c.get_uchar() == str.encode(chr(42))
+        c.set_uchar('e');  assert c.m_uchar     == b'e'
+        c.set_uchar(43);   assert c.m_uchar     == str.encode(chr(43))
 
         raises(ValueError, 'c.set_char("string")')
         raises(ValueError, 'c.set_char(500)')
@@ -246,10 +248,10 @@
         assert isinstance(c, CppyyTestData)
 
         # char types
-        assert CppyyTestData.s_char    == 'c'
-        assert c.s_char                == 'c'
-        assert c.s_uchar               == 'u'
-        assert CppyyTestData.s_uchar   == 'u'
+        assert CppyyTestData.s_char    == b'c'
+        assert c.s_char                == b'c'
+        assert c.s_uchar               == b'u'
+        assert CppyyTestData.s_uchar   == b'u'
 
         # integer types
         assert CppyyTestData.s_short    == -101
@@ -259,15 +261,15 @@
         assert CppyyTestData.s_int      == -202
         assert c.s_int                  == -202
         assert c.s_uint                 ==  202
-        assert CppyyTestData.s_uint   ==  202
-        assert CppyyTestData.s_long   == -303
+        assert CppyyTestData.s_uint     ==  202
+        assert CppyyTestData.s_long     == -303
         assert c.s_long                 == -303
         assert c.s_ulong                ==  303
-        assert CppyyTestData.s_ulong  ==  303
-        assert CppyyTestData.s_llong  == -404
+        assert CppyyTestData.s_ulong    ==  303
+        assert CppyyTestData.s_llong    == -404
         assert c.s_llong                == -404
-        assert c.s_ullong               ==  505
-        assert CppyyTestData.s_ullong ==  505
+        assert c.s_ullong               ==  404
+        assert CppyyTestData.s_ullong   ==  404
 
         # floating point types
         assert round(CppyyTestData.s_float  + 606., 5)   == 0
@@ -287,57 +289,57 @@
         assert isinstance(c, CppyyTestData)
 
         # char types
-        CppyyTestData.s_char          = 'a'
-        assert c.s_char                == 'a'
-        c.s_char                        = 'b'
-        assert CppyyTestData.s_char  == 'b'
-        CppyyTestData.s_uchar         = 'c'
-        assert c.s_uchar               == 'c'
-        c.s_uchar                       = 'd'
-        assert CppyyTestData.s_uchar == 'd'
+        CppyyTestData.s_char           =  'a'
+        assert c.s_char               == b'a'
+        c.s_char                       =  'b'
+        assert CppyyTestData.s_char   == b'b'
+        CppyyTestData.s_uchar          =  'c'
+        assert c.s_uchar              == b'c'
+        c.s_uchar                      =  'd'
+        assert CppyyTestData.s_uchar  == b'd'
         raises(ValueError, setattr, CppyyTestData, 's_uchar', -1)
-        raises(ValueError, setattr, c,               's_uchar', -1)
+        raises(ValueError, setattr, c,             's_uchar', -1)
 
         # integer types
         c.s_short                        = -102
-        assert CppyyTestData.s_short  == -102
-        CppyyTestData.s_short          = -203
+        assert CppyyTestData.s_short    == -102
+        CppyyTestData.s_short            = -203
         assert c.s_short                == -203
         c.s_ushort                       =  127
-        assert CppyyTestData.s_ushort ==  127
-        CppyyTestData.s_ushort         =  227
+        assert CppyyTestData.s_ushort   ==  127
+        CppyyTestData.s_ushort           =  227
         assert c.s_ushort               ==  227
-        CppyyTestData.s_int            = -234
+        CppyyTestData.s_int              = -234
         assert c.s_int                  == -234
         c.s_int                          = -321
-        assert CppyyTestData.s_int    == -321
-        CppyyTestData.s_uint           = 1234
+        assert CppyyTestData.s_int      == -321
+        CppyyTestData.s_uint             = 1234
         assert c.s_uint                 == 1234
         c.s_uint                         = 4321
-        assert CppyyTestData.s_uint   == 4321
+        assert CppyyTestData.s_uint     == 4321
         raises(ValueError, setattr, c,               's_uint', -1)
         raises(ValueError, setattr, CppyyTestData, 's_uint', -1)
-        CppyyTestData.s_long           = -87
+        CppyyTestData.s_long             = -87
         assert c.s_long                 == -87
         c.s_long                         = 876
-        assert CppyyTestData.s_long   == 876
-        CppyyTestData.s_ulong          = 876
+        assert CppyyTestData.s_long     == 876
+        CppyyTestData.s_ulong            = 876
         assert c.s_ulong                == 876
         c.s_ulong                        = 678
-        assert CppyyTestData.s_ulong  == 678
+        assert CppyyTestData.s_ulong    == 678
         raises(ValueError, setattr, CppyyTestData, 's_ulong', -1)
-        raises(ValueError, setattr, c,               's_ulong', -1)
+        raises(ValueError, setattr, c,             's_ulong', -1)
 
         # floating point types
         CppyyTestData.s_float                    = -3.1415
-        assert round(c.s_float, 5 )               == -3.1415
-        c.s_float                                  =  3.1415
+        assert round(c.s_float, 5 )             == -3.1415
+        c.s_float                                =  3.1415
         assert round(CppyyTestData.s_float, 5 ) ==  3.1415
         import math
-        c.s_double                                 = -math.pi
+        c.s_double                               = -math.pi
         assert CppyyTestData.s_double           == -math.pi
         CppyyTestData.s_double                   =  math.pi
-        assert c.s_double                         ==  math.pi
+        assert c.s_double                       ==  math.pi
 
         c.destruct()
 
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -579,7 +579,7 @@
     'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
     '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
 
-    'PyBuffer_Release',
+    'PyObject_GetBuffer', 'PyBuffer_Release',
 
     'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr',
     'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
@@ -597,6 +597,7 @@
     'PyImport_ImportModuleLevel',
 
     'PyOS_getsig', 'PyOS_setsig',
+    '_Py_RestoreSignals',
     'PyThread_get_thread_ident', 'PyThread_allocate_lock', 'PyThread_free_lock',
     'PyThread_acquire_lock', 'PyThread_release_lock',
     'PyThread_create_key', 'PyThread_delete_key', 'PyThread_set_key_value',
diff --git a/pypy/module/cpyext/include/abstract.h b/pypy/module/cpyext/include/abstract.h
--- a/pypy/module/cpyext/include/abstract.h
+++ b/pypy/module/cpyext/include/abstract.h
@@ -1,5 +1,8 @@
 #ifndef Py_ABSTRACTOBJECT_H
 #define Py_ABSTRACTOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
 
     /* new buffer API */
 
@@ -10,9 +13,22 @@
     /* Return 1 if the getbuffer function is available, otherwise
        return 0 */
 
+     PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view,
+                                        int flags);
+
+    /* This is a C-API version of the getbuffer function call.  It checks
+       to make sure object has the required function pointer and issues the
+       call.  Returns -1 and raises an error on failure and returns 0 on
+       success
+    */
+
      PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view);
 
     /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
     */
 
+
+#ifdef __cplusplus
+}
+#endif
 #endif /* Py_ABSTRACTOBJECT_H */
diff --git a/pypy/module/cpyext/include/pylifecycle.h b/pypy/module/cpyext/include/pylifecycle.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/pylifecycle.h
@@ -0,0 +1,17 @@
+#ifndef Py_PYLIFECYCLE_H
+#define Py_PYLIFECYCLE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_RestoreSignals(void);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_PYLIFECYCLE_H */
diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,9 +1,11 @@
+from rpython.rlib.objectmodel import keepalive_until_here
+from pypy.interpreter.error import oefmt
 from pypy.module.cpyext.api import (
     cpython_api, Py_buffer, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS,
     build_type_checkers, Py_ssize_tP, PyObjectFields, cpython_struct,
-    bootstrap_function, Py_bufferP, generic_cpy_call, slot_function)
+    bootstrap_function, Py_bufferP, slot_function, generic_cpy_call)
 from pypy.module.cpyext.pyobject import (
-    PyObject, make_ref, as_pyobj, incref, decref, from_ref, make_typedescr,
+    PyObject, make_ref, as_pyobj, decref, from_ref, make_typedescr,
     get_typedescr, track_reference)
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.rarithmetic import widen
@@ -94,30 +96,6 @@
     mem_obj.c_view.c_obj = rffi.cast(PyObject, 0)
     _dealloc(space, py_obj)
 
- at cpython_api([PyObject, Py_bufferP, rffi.INT_real],
-             rffi.INT_real, error=-1)
-def PyObject_GetBuffer(space, exporter, view, flags):
-    """Send a request to exporter to fill in view as specified by flags. If the
-    exporter cannot provide a buffer of the exact type, it MUST raise
-    PyExc_BufferError, set view->obj to NULL and return -1.
-
-    On success, fill in view, set view->obj to a new reference to exporter and
-    return 0. In the case of chained buffer providers that redirect requests
-    to a single object, view->obj MAY refer to this object instead of exporter.
-
-    Successful calls to PyObject_GetBuffer() must be paired with calls to
-    PyBuffer_Release(), similar to malloc() and free(). Thus, after the
-    consumer is done with the buffer, PyBuffer_Release() must be called exactly
-    once.
-    """
-    # XXX compare this implementation with PyPy2's XXX
-    pb = exporter.c_ob_type.c_tp_as_buffer
-    if not pb or not pb.c_bf_getbuffer:
-        w_exporter = from_ref(space, exporter)
-        raise oefmt(space.w_TypeError,
-            "a bytes-like object is required, not '%T'", w_exporter)
-    return generic_cpy_call(space, pb.c_bf_getbuffer, exporter, view, flags)
-
 def fill_Py_buffer(space, buf, view):
     # c_buf, c_obj have been filled in
     ndim = buf.getndim()
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -7,14 +7,14 @@
 from rpython.rlib import rgc # Force registration of gc.collect
 from pypy.module.cpyext.api import (
     slot_function, generic_cpy_call, PyObject, Py_ssize_t,
-    pypy_decl, Py_buffer, Py_bufferP, PyTypeObjectPtr)
+    pypy_decl, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts)
 from pypy.module.cpyext.typeobjectdefs import (
     unaryfunc, ternaryfunc, binaryfunc,
     getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
     cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
     getbufferproc, releasebufferproc, ssizessizeobjargproc)
-from pypy.module.cpyext.pyobject import make_ref, decref
+from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.memoryobject import fill_Py_buffer
 from pypy.module.cpyext.state import State
@@ -318,13 +318,14 @@
     _immutable_ = True
 
     def __init__(self, space, ptr, size, w_obj, format='B', shape=None,
-                strides=None, ndim=1, itemsize=1, readonly=True,
-                releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
+                 strides=None, ndim=1, itemsize=1, readonly=True,
+                 needs_decref=False,
+                 releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
         self.space = space
         self.ptr = ptr
         self.size = size
         self.w_obj = w_obj  # kept alive
-        self.pyobj = make_ref(space, w_obj)
+        self.pyobj = as_pyobj(space, w_obj)
         self.format = format
         self.ndim = ndim
         self.itemsize = itemsize
@@ -348,30 +349,33 @@
             # XXX: missing init_strides_from_shape
             self.strides = strides
         self.readonly = readonly
+        self.needs_decref = needs_decref
         self.releasebufferproc = releasebufferproc
 
     def releasebuffer(self):
         if self.pyobj:
-            decref(self.space, self.pyobj)
+            if self.needs_decref:
+                if self.releasebufferproc:
+                    func_target = rffi.cast(releasebufferproc, self.releasebufferproc)
+                    with lltype.scoped_alloc(Py_buffer) as pybuf:
+                        pybuf.c_buf = self.ptr
+                        pybuf.c_len = self.size
+                        pybuf.c_ndim = cts.cast('int', self.ndim)
+                        pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape)
+                        pybuf.c_strides = cts.cast('Py_ssize_t*', pybuf.c__strides)
+                        for i in range(self.ndim):
+                            pybuf.c_shape[i] = self.shape[i]
+                            pybuf.c_strides[i] = self.strides[i]
+                        if self.format:
+                            pybuf.c_format = rffi.str2charp(self.format)
+                        else:
+                            pybuf.c_format = rffi.str2charp("B")
+                        generic_cpy_call(self.space, func_target, self.pyobj, pybuf)
+                decref(self.space, self.pyobj)
             self.pyobj = lltype.nullptr(PyObject.TO)
         else:
             #do not call twice
             return
-        if self.releasebufferproc:
-            func_target = rffi.cast(releasebufferproc, self.releasebufferproc)
-            with lltype.scoped_alloc(Py_buffer) as pybuf:
-                pybuf.c_buf = self.ptr
-                pybuf.c_len = self.size
-                pybuf.c_ndim = rffi.cast(rffi.INT_real, self.ndim)
-                for i in range(self.ndim):
-                    pybuf.c_shape[i] = self.shape[i]
-                    pybuf.c_strides[i] = self.strides[i]
-                if self.format:
-                    pybuf.c_format = rffi.str2charp(self.format)
-                else:
-                    pybuf.c_format = rffi.str2charp("B")
-                generic_cpy_call(self.space, func_target, self.pyobj, pybuf)
-            self.releasebufferproc = rffi.cast(rffi.VOIDP, 0)
 
     def getlength(self):
         return self.size
@@ -467,22 +471,25 @@
         ptr = pybuf.c_buf
         size = pybuf.c_len
         ndim = widen(pybuf.c_ndim)
+        shape = None
         if pybuf.c_shape:
-            shape = [pybuf.c_shape[i] for i in range(ndim)]
-        else:
-            shape = None
+            shape = [pybuf.c_shape[i]   for i in range(ndim)]
+        strides = None
         if pybuf.c_strides:
             strides = [pybuf.c_strides[i] for i in range(ndim)]
-        else:
-            strides = [1]
         if pybuf.c_format:
             format = rffi.charp2str(pybuf.c_format)
         else:
             format = 'B'
+        # the CPython docs mandates that you do an incref whenever you call
+        # bf_getbuffer; so, we pass needs_decref=True to ensure that we don't
+        # leak we release the buffer:
+        # https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer
         buf = CPyBuffer(space, ptr, size, w_self, format=format,
                             ndim=ndim, shape=shape, strides=strides,
                             itemsize=pybuf.c_itemsize,
                             readonly=widen(pybuf.c_readonly),
+                            needs_decref=True,
                             releasebufferproc = rbp)
         fq.register_finalizer(buf)
         return space.newbuffer(buf, itemsize=buf.itemsize)
@@ -717,33 +724,12 @@
         slot_func = slot_tp_new
     elif name == 'tp_as_buffer.c_bf_getbuffer':
         buff_fn = w_type.getdictvalue(space, '__buffer__')
-        if buff_fn is None:
+        if buff_fn is not None:
+            buff_w = slot_from___buffer__(space, typedef, buff_fn)
+        elif typedef.buffer:
+            buff_w = slot_from_buffer_w(space, typedef, buff_fn)
+        else:
             return
-        @slot_function([PyObject, Py_bufferP, rffi.INT_real],
-                rffi.INT_real, error=-1)
-        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
-        def buff_w(space, w_self, view, flags):
-            args = Arguments(space, [space.newint(flags)])
-            w_obj = space.call_args(space.get(buff_fn, w_self), args)
-            if view:
-                #like PyObject_GetBuffer
-                flags = widen(flags)
-                buf = space.buffer_w(w_obj, flags)
-                try:
-                    view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
-                    view.c_obj = make_ref(space, w_obj)
-                except ValueError:
-                    s = buf.as_str()
-                    w_s = space.newbytes(s)
-                    view.c_obj = make_ref(space, w_s)
-                    view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(
-                                           s, track_allocation=False))
-                    rffi.setintfield(view, 'c_readonly', 1)
-                ret = fill_Py_buffer(space, buf, view)
-                return ret
-            return 0
-        # XXX remove this when it no longer crashes a translated PyPy
-        return
         slot_func = buff_w
     else:
         # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
@@ -753,6 +739,60 @@
 
     return slot_func
 
+
+def slot_from___buffer__(space, typedef, buff_fn):
+    name = 'bf_getbuffer'
+    @slot_function([PyObject, Py_bufferP, rffi.INT_real],
+            rffi.INT_real, error=-1)
+    @func_renamer("cpyext_%s_%s" % (name, typedef.name))
+    def buff_w(space, w_self, view, flags):
+        args = Arguments(space, [space.newint(flags)])
+        w_obj = space.call_args(space.get(buff_fn, w_self), args)
+        if view:
+            #like PyObject_GetBuffer
+            flags = widen(flags)
+            buf = space.buffer_w(w_obj, flags)
+            try:
+                view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
+                view.c_obj = make_ref(space, w_obj)
+            except ValueError:
+                s = buf.as_str()
+                w_s = space.newbytes(s)
+                view.c_obj = make_ref(space, w_s)
+                view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(
+                                        s, track_allocation=False))
+                rffi.setintfield(view, 'c_readonly', 1)
+            ret = fill_Py_buffer(space, buf, view)
+            return ret
+        return 0
+    return buff_w
+
+def slot_from_buffer_w(space, typedef, buff_fn):
+    name = 'bf_getbuffer'
+    @slot_function([PyObject, Py_bufferP, rffi.INT_real],
+            rffi.INT_real, error=-1)
+    @func_renamer("cpyext_%s_%s" % (name, typedef.name))
+    def buff_w(space, w_self, view, flags):
+        w_obj = w_self
+        if view:
+            #like PyObject_GetBuffer
+            flags = widen(flags)
+            buf = space.buffer_w(w_obj, flags)
+            try:
+                view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
+                view.c_obj = make_ref(space, w_obj)
+            except ValueError:
+                s = buf.as_str()
+                w_s = space.newbytes(s)
+                view.c_obj = make_ref(space, w_s)
+                view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(
+                                        s, track_allocation=False))
+                rffi.setintfield(view, 'c_readonly', 1)
+            ret = fill_Py_buffer(space, buf, view)
+            return ret
+        return 0
+    return buff_w
+
 PyWrapperFlag_KEYWORDS = 1
 
 class TypeSlot:
diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c
--- a/pypy/module/cpyext/src/abstract.c
+++ b/pypy/module/cpyext/src/abstract.c
@@ -98,6 +98,18 @@
 
 /* Buffer C-API for Python 3.0 */
 
+int
+PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
+{
+    if (!PyObject_CheckBuffer(obj)) {
+        PyErr_Format(PyExc_TypeError,
+                     "'%100s' does not have the buffer interface",
+                     Py_TYPE(obj)->tp_name);
+        return -1;
+    }
+    return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+}
+
 void
 PyBuffer_Release(Py_buffer *view)
 {
diff --git a/pypy/module/cpyext/src/pylifecycle.c b/pypy/module/cpyext/src/pylifecycle.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/src/pylifecycle.c
@@ -0,0 +1,15 @@
+#include "Python.h"
+
+void
+_Py_RestoreSignals(void)
+{
+#ifdef SIGPIPE
+    PyOS_setsig(SIGPIPE, SIG_DFL);
+#endif
+#ifdef SIGXFZ
+    PyOS_setsig(SIGXFZ, SIG_DFL);
+#endif
+#ifdef SIGXFSZ
+    PyOS_setsig(SIGXFSZ, SIG_DFL);
+#endif
+}
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2351,10 +2351,10 @@
     }
     else if(obj1->ob_type == &Arraytype)
         fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
-            ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name); 
+            ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name);
     else if(obj2->ob_type == &Arraytype)
         fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
-            ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name); 
+            ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name);
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
 }
@@ -2401,10 +2401,10 @@
     }
     else if(obj1->ob_type == &Arraytype)
         fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
-            ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name); 
+            ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name);
     else if(obj2->ob_type == &Arraytype)
         fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
-            ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name); 
+            ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name);
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
 }
@@ -2426,7 +2426,7 @@
 
 
 static int
-array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
+array_getbuffer(arrayobject *self, Py_buffer *view, int flags)
 {
     if (view==NULL) goto finish;
 
@@ -2463,10 +2463,19 @@
     return 0;
 }
 
+static long releasebuffer_cnt = 0;
+
+static PyObject *
+get_releasebuffer_cnt(void)
+{
+    return PyLong_FromLong(releasebuffer_cnt);
+}
+
 static void
-array_buffer_relbuf(arrayobject *self, Py_buffer *view)
+array_releasebuffer(arrayobject *self, Py_buffer *view)
 {
     self->ob_exports--;
+    releasebuffer_cnt++;
 }
 
 static PySequenceMethods array_as_sequence = {
@@ -2483,8 +2492,8 @@
 };
 
 static PyBufferProcs array_as_buffer = {
-    (getbufferproc)array_buffer_getbuf,
-    (releasebufferproc)array_buffer_relbuf
+    (getbufferproc)array_getbuffer,
+    (releasebufferproc)array_releasebuffer
 };
 
 static PyObject *
@@ -2872,6 +2881,16 @@
 }
 
 static PyObject *
+create_and_release_buffer(PyObject *self, PyObject *obj)
+{
+    Py_buffer view;
+    int res = PyObject_GetBuffer(obj, &view, 0);
+    if (res < 0)
+        return NULL;
+    PyBuffer_Release(&view);
+    Py_RETURN_NONE;
+}
+static PyObject *
 write_buffer_len(PyObject * self, PyObject * obj)
 {
     void* buf;
@@ -2890,6 +2909,8 @@
      PyDoc_STR("Internal. Used for pickling support.")},
     {"switch_multiply",   (PyCFunction)switch_multiply, METH_NOARGS, NULL},
     {"readbuffer_as_string",   (PyCFunction)readbuffer_as_string, METH_VARARGS, NULL},
+    {"get_releasebuffer_cnt",   (PyCFunction)get_releasebuffer_cnt, METH_NOARGS, NULL},
+    {"create_and_release_buffer",   (PyCFunction)create_and_release_buffer, METH_O, NULL},
     {"write_buffer_len", write_buffer_len, METH_O, NULL},
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -69,6 +69,23 @@
                                 b'\x03\0\0\0'
                                 b'\x04\0\0\0')
 
+    def test_releasebuffer(self):
+        module = self.import_module(name='array')
+        arr = module.array('i', [1,2,3,4])
+        assert module.get_releasebuffer_cnt() == 0
+        module.create_and_release_buffer(arr)
+        assert module.get_releasebuffer_cnt() == 1
+
+    def test_Py_buffer(self):
+        module = self.import_module(name='array')
+        arr = module.array('i', [1,2,3,4])
+        assert module.get_releasebuffer_cnt() == 0
+        m = memoryview(arr)
+        assert module.get_releasebuffer_cnt() == 0
+        del m
+        self.debug_collect()
+        assert module.get_releasebuffer_cnt() == 1
+
     def test_0d_view(self):
         module = self.import_module(name='array')
         arr = module.array('B', b'\0\0\0\x01')
diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -214,6 +214,15 @@
         print(module.fmt(b'd:%d', 10))
         assert module.fmt(b'd:%d', 10) == b'd:10'
 
+    def test_suboffsets(self):
+        module = self.import_extension('foo', [
+            ("check_suboffsets", "METH_O",
+             """
+                Py_buffer view;
+                PyObject_GetBuffer(args, &view, 0);
+                return PyLong_FromLong(view.suboffsets == NULL);
+             """)])
+        assert module.check_suboffsets(b'1234') == 1
 
 class TestBytes(BaseApiTest):
     def test_bytes_resize(self, space, api):
@@ -304,9 +313,3 @@
         assert api.PyBytes_FromObject(w_obj) is None
         api.PyErr_Clear()
 
-    def test_suboffsets(self, space, api):
-        w_bytes = space.newbytes('1234')
-        view = lltype.malloc(Py_buffer, flavor='raw', zero=True)
-        flags = rffi.cast(rffi.INT_real, 0)
-        api.PyObject_GetBuffer(w_bytes, view, flags)
-        assert not view.c_suboffsets
diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -10,15 +10,6 @@
 only_pypy ="config.option.runappdirect and '__pypy__' not in sys.builtin_module_names"
 
 class TestMemoryViewObject(BaseApiTest):
-    def test_fromobject(self, space, api):
-        w_hello = space.newbytes("hello")
-        #assert api.PyObject_CheckBuffer(w_hello)
-        w_view = from_ref(space, api.PyMemoryView_FromObject(w_hello))
-        w_byte = space.call_method(w_view, '__getitem__', space.wrap(0))
-        assert space.eq_w(w_byte, space.wrap(ord('h')))
-        w_bytes = space.call_method(w_view, "tobytes")
-        assert space.unwrap(w_bytes) == "hello"
-
     def test_frombuffer(self, space, api):
         w_buf = space.newbuffer(StringBuffer("hello"))
         c_memoryview = rffi.cast(
@@ -96,6 +87,19 @@
         assert result.tobytes() == b'hello, world.'
 
 class AppTestBufferProtocol(AppTestCpythonExtensionBase):
+    def test_fromobject(self):
+        foo = self.import_extension('foo', [
+            ("make_view", "METH_O",
+             """
+             if (!PyObject_CheckBuffer(args))
+                return Py_None;
+             return PyMemoryView_FromObject(args);
+             """)])
+        hello = b'hello'
+        mview = foo.make_view(hello)
+        assert mview[0] == hello[0]
+        assert mview.tobytes() == hello
+
     def test_buffer_protocol_app(self):
         module = self.import_module(name='buffer_test')
         arr = module.PyMyArray(10)
@@ -183,3 +187,75 @@
                           " on too long format string"
         finally:
             warnings.resetwarnings()
+
+    def test_releasebuffer(self):
+        if not self.runappdirect:
+            skip("Fails due to ll2ctypes nonsense")
+        module = self.import_extension('foo', [
+            ("create_test", "METH_NOARGS",
+             """
+                PyObject *obj;
+                obj = PyObject_New(PyObject, (PyTypeObject*)type);
+                return obj;
+             """),
+            ("get_cnt", "METH_NOARGS",
+             'return PyLong_FromLong(cnt);'),
+            ("get_dealloc_cnt", "METH_NOARGS",
+             'return PyLong_FromLong(dealloc_cnt);'),
+        ],
+        prologue="""
+                static float test_data = 42.f;
+                static int cnt=0;
+                static int dealloc_cnt=0;
+                static PyHeapTypeObject * type=NULL;
+
+                void dealloc(PyObject *self) {
+                    dealloc_cnt++;
+                }
+                int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
+
+                    cnt ++;
+                    memset(view, 0, sizeof(Py_buffer));
+                    view->obj = obj;
+                    /* see the CPython docs for why we need this incref:
+                       https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer */
+                    Py_INCREF(obj);
+                    view->ndim = 0;
+                    view->buf = (void *) &test_data;
+                    view->itemsize = sizeof(float);
+                    view->len = 1;
+                    view->strides = NULL;
+                    view->shape = NULL;
+                    view->format = "f";
+                    return 0;
+                }
+
+                void releasebuffer(PyObject *obj, Py_buffer *view) {
+                    cnt --;
+                }
+            """, more_init="""
+                type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
+
+                type->ht_type.tp_name = "Test";
+                type->ht_type.tp_basicsize = sizeof(PyObject);
+                type->ht_name = PyUnicode_FromString("Test");
+                type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+                                          Py_TPFLAGS_HEAPTYPE;
+                type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
+
+                type->ht_type.tp_dealloc = dealloc;
+                type->ht_type.tp_as_buffer = &type->as_buffer;
+                type->as_buffer.bf_getbuffer = getbuffer;
+                type->as_buffer.bf_releasebuffer = releasebuffer;
+
+                if (PyType_Ready(&type->ht_type) < 0) INITERROR;
+            """, )
+        import gc
+        assert module.get_cnt() == 0
+        a = memoryview(module.create_test())
+        assert module.get_cnt() == 1
+        assert module.get_dealloc_cnt() == 0
+        del a
+        self.debug_collect()
+        assert module.get_cnt() == 0
+        assert module.get_dealloc_cnt() == 1
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
@@ -235,6 +235,18 @@
              """)])
         assert module.test_macro_invocations() == u''
 
+    def test_AsUTF8AndSize(self):
+        module = self.import_extension('foo', [
+             ("utf8", "METH_O",
+             """
+                Py_ssize_t size;
+                char *utf8 = PyUnicode_AsUTF8AndSize(args, &size);
+                return PyBytes_FromStringAndSize(utf8, size);
+             """)])
+        assert module.utf8('xyz') == b'xyz'
+        assert module.utf8('café') == 'café'.encode('utf-8')
+
+
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space):
         encoding = rffi.charp2str(PyUnicode_GetDefaultEncoding(space, ))
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
@@ -103,17 +103,20 @@
     return py_obj.c_state
 
 def get_kind(py_obj):
-    return get_state(py_obj).c_kind
+    return rffi.getintfield(get_state(py_obj), 'c_kind')
 
 def set_kind(py_obj, value):
     get_state(py_obj).c_kind = cts.cast('unsigned int', value)
 
 def get_ascii(py_obj):
-    return get_state(py_obj).c_ascii
+    return rffi.getintfield(get_state(py_obj), 'c_ascii')
 
 def set_ascii(py_obj, value):
     get_state(py_obj).c_ascii = cts.cast('unsigned int', value)
 
+def get_ready(py_obj):
+    return rffi.getintfield(get_state(py_obj), 'c_ready')
+
 def set_ready(py_obj, value):
     get_state(py_obj).c_ready = cts.cast('unsigned int', value)
 
@@ -259,7 +262,7 @@
 def _PyUnicode_Ready(space, w_obj):
     assert isinstance(w_obj, unicodeobject.W_UnicodeObject)
     py_obj = as_pyobj(space, w_obj)
-    assert widen(get_kind(py_obj)) == WCHAR_KIND
+    assert get_kind(py_obj) == WCHAR_KIND
     maxchar = 0
     for c in w_obj._value:
         if ord(c) > maxchar:
@@ -303,8 +306,8 @@
     set_ready(py_obj, 1)
     return 0
 
- at cpython_api([PyObject], rffi.CWCHARP)
-def PyUnicode_AsUnicode(space, ref):
+ at cts.decl("Py_UNICODE * PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size)")
+def PyUnicode_AsUnicodeAndSize(space, ref, psize):
     """Return a read-only pointer to the Unicode object's internal Py_UNICODE
     buffer, NULL if unicode is not a Unicode object."""
     # Don't use PyUnicode_Check, it will realize the object :-(
@@ -316,10 +319,22 @@
         w_unicode = from_ref(space, rffi.cast(PyObject, ref))
         u = space.unicode_w(w_unicode)
         set_wbuffer(ref, rffi.unicode2wcharp(u))
+        set_wsize(ref, len(u))
+    if psize:
+        psize[0] = get_wsize(ref)
     return get_wbuffer(ref)
 
- at cts.decl("char * PyUnicode_AsUTF8(PyObject *unicode)")
-def PyUnicode_AsUTF8(space, ref):
+ at cts.decl("Py_UNICODE * PyUnicode_AsUnicode(PyObject *unicode)")
+def PyUnicode_AsUnicode(space, ref):
+    return PyUnicode_AsUnicodeAndSize(space, ref, cts.cast('Py_ssize_t *', 0))
+
+ at cts.decl("char * PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)")
+def PyUnicode_AsUTF8AndSize(space, ref, psize):
+    if not PyUnicode_Check(space, ref):
+        PyErr_BadArgument(space)
+    if not get_ready(ref):
+        res = _PyUnicode_Ready(space, ref)
+
     if not get_utf8(ref):
         # Copy unicode buffer
         w_unicode = from_ref(space, ref)
@@ -327,8 +342,15 @@
                                                 "strict")
         s = space.bytes_w(w_encoded)
         set_utf8(ref, rffi.str2charp(s))
+        set_utf8_len(ref, len(s))
+    if psize:
+        psize[0] = get_utf8_len(ref)
     return get_utf8(ref)
 
+ at cts.decl("char * PyUnicode_AsUTF8(PyObject *unicode)")
+def PyUnicode_AsUTF8(space, ref):
+    return PyUnicode_AsUTF8AndSize(space, ref, cts.cast('Py_ssize_t *', 0))
+
 @cpython_api([PyObject, rffi.CWCHARP, Py_ssize_t], Py_ssize_t, error=-1)
 def PyUnicode_AsWideChar(space, ref, buf, size):
     """Copy the Unicode object contents into the wchar_t buffer w.  At most
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
@@ -1513,7 +1513,7 @@
         return res
 """, filename=__file__).interphook('ptp')
 
-W_NDimArray.typedef = TypeDef("numpy.ndarray",
+W_NDimArray.typedef = TypeDef("numpy.ndarray", None, None, 'read-write',
     __new__ = interp2app(descr_new_array),
 
     __len__ = interp2app(W_NDimArray.descr_len),
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
@@ -1,3 +1,4 @@
+import sys
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rlib import rposix
 from rpython.rlib import rdynload
@@ -213,6 +214,9 @@
             assert getattr(rposix, _name) is not None, "missing %r" % (_name,)
             interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name)
 
+    if sys.platform.startswith('linux'): #hasattr(rposix, 'sendfile'):
+        interpleveldefs['sendfile'] = 'interp_posix.sendfile'
+
     if hasattr(rposix, 'pread'):
         interpleveldefs['pread'] = 'interp_posix.pread'
     if hasattr(rposix, 'pwrite'):
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
@@ -2371,3 +2371,28 @@
         rposix.set_status_flags(fd, flags)
     except OSError as e:
         raise wrap_oserror(space, e, eintr_retry=False)
+
+ at unwrap_spec(out=c_int, count=int)
+def sendfile(space, out, w_in, w_offset, count):
+    # why is an argument called "in"???  that doesn't make sense (it is
+    # a reserved word), but that's what CPython does
+    in_ = space.c_int_w(w_in)
+
+    # XXX only supports the common arguments for now (BSD takes more).
+    # Until that is fixed, we only expose sendfile() on linux.
+    if space.is_none(w_offset):     # linux only
+        while True:
+            try:
+                res = rposix.sendfile_no_offset(out, in_, count)
+                break
+            except OSError as e:
+                wrap_oserror(space, e, eintr_retry=True)
+    else:
+        offset = space.gateway_r_longlong_w(w_offset)
+        while True:
+            try:
+                res = rposix.sendfile(out, in_, offset, count)
+                break
+            except OSError as e:
+                wrap_oserror(space, e, eintr_retry=True)
+    return space.newint(res)
diff --git a/pypy/module/posix/interp_scandir.py b/pypy/module/posix/interp_scandir.py
--- a/pypy/module/posix/interp_scandir.py
+++ b/pypy/module/posix/interp_scandir.py
@@ -161,7 +161,7 @@
         if (self.flags & FLAG_LSTAT) == 0:
             # Unlike CPython, try to use fstatat() if possible
             dirfd = self.scandir_iterator.dirfd
-            if dirfd != -1:
+            if dirfd != -1 and rposix.HAVE_FSTATAT:
                 st = rposix_stat.fstatat(self.name, dirfd,
                                          follow_symlinks=False)
             else:
@@ -206,7 +206,7 @@
             if must_call_stat:
                 # Must call stat().  Try to use fstatat() if possible
                 dirfd = self.scandir_iterator.dirfd
-                if dirfd != -1:
+                if dirfd != -1 and rposix.HAVE_FSTATAT:
                     st = rposix_stat.fstatat(self.name, dirfd,
                                              follow_symlinks=True)
                 else:
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -14,7 +14,7 @@
 USEMODULES = ['binascii', 'posix', 'signal', 'struct', 'time']
 # py3k os.open uses subprocess, requiring the following per platform
 if os.name != 'nt':
-    USEMODULES += ['fcntl', 'select', '_posixsubprocess']
+    USEMODULES += ['fcntl', 'select', '_posixsubprocess', '_socket']
 else:
     USEMODULES += ['_rawffi', 'thread']
 
@@ -1213,6 +1213,36 @@
             raises(OSError, posix.get_blocking, 1234567)
             raises(OSError, posix.set_blocking, 1234567, True)
 
+    if sys.platform != 'win32':
+        def test_sendfile(self):
+            import _socket, posix
+            s1, s2 = _socket.socketpair()
+            fd = posix.open(self.path, posix.O_RDONLY)
+            res = posix.sendfile(s1.fileno(), fd, 3, 5)
+            assert res == 5
+            assert posix.lseek(fd, 0, 1) == 0
+            data = s2.recv(10)
+            expected = b'this is a test'[3:8]
+            assert data == expected
+            posix.close(fd)
+            s2.close()
+            s1.close()
+
+    if sys.platform.startswith('linux'):
+        def test_sendfile_no_offset(self):
+            import _socket, posix
+            s1, s2 = _socket.socketpair()
+            fd = posix.open(self.path, posix.O_RDONLY)
+            posix.lseek(fd, 3, 0)
+            res = posix.sendfile(s1.fileno(), fd, None, 5)
+            assert res == 5
+            assert posix.lseek(fd, 0, 1) == 8
+            data = s2.recv(10)
+            expected = b'this is a test'[3:8]
+            assert data == expected
+            posix.close(fd)
+            s2.close()
+            s1.close()
 
     def test_urandom(self):
         os = self.posix
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
@@ -1,8 +1,10 @@
+import errno
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import oefmt
 from pypy.interpreter.error import exception_from_saved_errno, wrap_oserror
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.typedef import TypeDef, generic_new_descr, GetSetProperty
+from pypy.interpreter import timeutils
 from rpython.rlib._rsocket_rffi import socketclose_no_errno
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib import rposix
@@ -50,6 +52,12 @@
     ("tv_nsec", rffi.LONG),
 ])
 
+def fill_timespec(time_float, timespec_ptr):
+    sec = int(time_float)
+    nsec = int(1e9 * (time_float - sec))
+    rffi.setintfield(timespec_ptr, 'c_tv_sec', sec)
+    rffi.setintfield(timespec_ptr, 'c_tv_nsec', nsec)
+
 
 symbol_map = {
     "KQ_FILTER_READ": "EVFILT_READ",
@@ -180,13 +188,11 @@
                             raise oefmt(space.w_ValueError,
                                         "Timeout must be None or >= 0, got %s",
                                         str(_timeout))
-                        XXX   # fix test_select_signal.py first, for PEP475!
-                        sec = int(_timeout)
-                        nsec = int(1e9 * (_timeout - sec))
-                        rffi.setintfield(timeout, 'c_tv_sec', sec)
-                        rffi.setintfield(timeout, 'c_tv_nsec', nsec)
+                        fill_timespec(_timeout, timeout)
+                        timeout_at = timeutils.monotonic(space) + _timeout
                         ptimeout = timeout
                     else:
+                        timeout_at = 0.0
                         ptimeout = lltype.nullptr(timespec)
 
                     if not space.is_w(w_changelist, space.w_None):
@@ -204,29 +210,40 @@
                     else:
                         pchangelist = lltype.nullptr(rffi.CArray(kevent))
 
-                    nfds = syscall_kevent(self.kqfd,
-                                          pchangelist,
-                                          changelist_len,
-                                          eventlist,
-                                          max_events,
-                                          ptimeout)
-                    if nfds < 0:
-                        raise exception_from_saved_errno(space, space.w_OSError)
-                    else:
-                        elist_w = [None] * nfds
-                        for i in xrange(nfds):
+                    while True:
+                        nfds = syscall_kevent(self.kqfd,
+                                              pchangelist,
+                                              changelist_len,
+                                              eventlist,
+                                              max_events,
+                                              ptimeout)
+                        if nfds >= 0:
+                            break
+                        if rposix.get_saved_errno() != errno.EINTR:
+                            raise exception_from_saved_errno(space,
+                                                             space.w_OSError)
+                        space.getexecutioncontext().checksignals()
+                        if ptimeout:
+                            _timeout = (timeout_at -
+                                        timeutils.monotonic(space))
+                            if _timeout < 0.0:
+                                _timeout = 0.0
+                            fill_timespec(_timeout, ptimeout)
 
-                            evt = eventlist[i]
+                    elist_w = [None] * nfds
+                    for i in xrange(nfds):
 
-                            w_event = W_Kevent(space)
-                            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
+                        evt = eventlist[i]
 
-                            elist_w[i] = w_event
+                        w_event = W_Kevent(space)
+                        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
 
                     return space.newlist(elist_w)
 
diff --git a/pypy/module/select/test/test_kqueue.py b/pypy/module/select/test/test_kqueue.py
--- a/pypy/module/select/test/test_kqueue.py
+++ b/pypy/module/select/test/test_kqueue.py
@@ -102,7 +102,10 @@
         except socket.error as e:
             assert e.args[0] == errno.EINPROGRESS
         else:
-            assert False, "EINPROGRESS not raised"
+            #assert False, "EINPROGRESS not raised"
+            pass # FreeBSD doesn't raise an exception here
+            # (the above commented-out code is just like CPython's
+            # test_kqueue)
         server, addr = server_socket.accept()
 
         if sys.platform.startswith("darwin"):
diff --git a/pypy/objspace/std/objectobject.py b/pypy/objspace/std/objectobject.py
--- a/pypy/objspace/std/objectobject.py
+++ b/pypy/objspace/std/objectobject.py
@@ -27,6 +27,9 @@
         # and raises a TypeError if the condition holds true, this is done
         # just before reduce_2 is called in pypy
         state = getattr(obj, "__dict__", None)
+        # CPython returns None if the dict is empty
+        if state is not None and len(state) == 0:
+            state = None
         names = slotnames(cls) # not checking for list
         if names is not None:
             slots = {}
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -89,6 +89,11 @@
         assert '__getnewargs__' not in seen
         assert '__getnewargs_ex__' not in seen
 
+    def test_reduce_state_empty_dict(self):
+        class X(object):
+            pass
+        assert X().__reduce_ex__(2)[2] is None
+
     def test_default_format(self):
         class x(object):
             def __str__(self):
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -35,7 +35,7 @@
         w_uni = space.wrap(u'abcd')
         assert space.text_w(w_uni) == 'abcd'
         w_uni = space.wrap(unichr(0xd921) + unichr(0xdddd))
-        raises(UnicodeEncodeError, space.text_w, w_uni)
+        space.raises_w(space.w_UnicodeEncodeError, space.text_w, w_uni)
 
 
 class AppTestUnicodeStringStdOnly:
@@ -500,6 +500,7 @@
         assert u'x\ty'.expandtabs(-42) == u'xy'
 
     def test_translate(self):
+        import sys
         assert 'bbbc' == 'abababc'.translate({ord('a'):None})
         assert 'iiic' == 'abababc'.translate({ord('a'):None, ord('b'):ord('i')})
         assert 'iiix' == 'abababc'.translate({ord('a'):None, ord('b'):ord('i'), ord('c'):'x'})
@@ -511,6 +512,7 @@
         assert 'abababc'.translate({ord('a'): ''}) == 'bbbc'
 
         raises(TypeError, 'hello'.translate)
+        raises(ValueError, "\xff".translate, {0xff: sys.maxunicode+1})
 
     def test_maketrans(self):
         assert 'abababc' == 'abababc'.translate({'b': '<i>'})
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -429,7 +429,7 @@
                 elif space.isinstance_w(w_newval, space.w_int):
                     newval = space.int_w(w_newval)
                     if newval < 0 or newval > maxunicode:
-                        raise oefmt(space.w_TypeError,
+                        raise oefmt(space.w_ValueError,
                                     "character mapping must be in range(%s)",
                                     hex(maxunicode + 1))
                     result.append(unichr(newval))
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -948,11 +948,11 @@
         # If this also contains args[0], this returns the current
         # location too.
         arglocs = [self.loc(args[i]) for i in range(2, len(args))]
-        gcmap = self.get_gcmap()
 
         if op.type == 'v':
             # a plain COND_CALL.  Calls the function when args[0] is
             # true.  Often used just after a comparison operation.
+            gcmap = self.get_gcmap()
             self.load_condition_into_cc(op.getarg(0))
             resloc = None
         else:
@@ -969,6 +969,22 @@
             resloc = self.rm.force_result_in_reg(op, args[0],
                                                  forbidden_vars=args[2:])
 
+            # Get the gcmap here, possibly including the spilled
+            # location, and always excluding the 'resloc' register.
+            # Some more details: the only interesting case is the case
+            # where we're doing the call (if we are not, the gcmap is
+            # not used); and in this case, the gcmap must include the
+            # spilled location (it contains a valid GC pointer to fix
+            # during the call if a GC occurs), and never 'resloc'
+            # (it will be overwritten with the result of the call, which
+            # is not computed yet if a GC occurs).
+            #
+            # (Note that the spilled value is always NULL at the moment
+            # if the call really occurs, but it's not worth the effort to
+            # not list it in the gcmap and get crashes if we tweak
+            # COND_CALL_VALUE_R in the future)
+            gcmap = self.get_gcmap([resloc])
+
             # Test the register for the result.
             self.assembler.test_location(resloc)
             self.assembler.guard_success_cc = rx86.Conditions['Z']
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -773,24 +773,33 @@
         from rpython.jit.metainterp.optimizeopt.intutils import ConstIntBound,\
                 IntLowerBound
 
-        if mode is None:
+        length = self.getstrlen1(mode)
+        if length < 0:
             # XXX we can do better if we know it's an array
             return IntLowerBound(0)
-        else:
-            return ConstIntBound(self.getstrlen1(mode))
+        return ConstIntBound(length)
 
     def getstrlen(self, op, string_optimizer, mode):
-        return ConstInt(self.getstrlen1(mode))
+        length = self.getstrlen1(mode)
+        if length < 0:
+            return None
+        return ConstInt(length)
 
     def getstrlen1(self, mode):
         from rpython.jit.metainterp.optimizeopt import vstring
-        
+
         if mode is vstring.mode_string:
             s = self._unpack_str(vstring.mode_string)
+            if s is None:
+                return -1
+            return len(s)
+        elif mode is vstring.mode_unicode:
+            s = self._unpack_str(vstring.mode_unicode)            
+            if s is None:
+                return -1
             return len(s)
         else:
-            s = self._unpack_str(vstring.mode_unicode)            
-            return len(s)
+            return -1
 
     def getstrhash(self, op, mode):
         from rpython.jit.metainterp.optimizeopt import vstring
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -2124,7 +2124,8 @@
     def _malloc_out_of_nursery(self, totalsize):
         """Allocate non-movable memory for an object of the given
         'totalsize' that lives so far in the nursery."""
-        if raw_malloc_usage(totalsize) <= self.small_request_threshold:
+        if (r_uint(raw_malloc_usage(totalsize)) <=
+            r_uint(self.small_request_threshold)):
             # most common path
             return self.ac.malloc(totalsize)
         else:
@@ -2133,6 +2134,9 @@
     _malloc_out_of_nursery._always_inline_ = True
 
     def _malloc_out_of_nursery_nonsmall(self, totalsize):
+        if r_uint(raw_malloc_usage(totalsize)) > r_uint(self.nursery_size):
+            out_of_memory("memory corruption: bad size for object in the "
+                          "nursery")
         # 'totalsize' should be aligned.
         ll_assert(raw_malloc_usage(totalsize) & (WORD-1) == 0,
                   "misaligned totalsize in _malloc_out_of_nursery_nonsmall")
diff --git a/rpython/rlib/debug.py b/rpython/rlib/debug.py
--- a/rpython/rlib/debug.py
+++ b/rpython/rlib/debug.py
@@ -524,7 +524,8 @@
     ll_attach = rffi.llexternal("AttachToVS", [], lltype.Void,
                                 compilation_info=make_vs_attach_eci())
     def impl_attach_gdb():
-        ll_attach()
+        #ll_attach()
+        print "AttachToVS is disabled at the moment (compilation failure)"
 
 register_external(attach_gdb, [], result=None,
                   export_name="impl_attach_gdb", llimpl=impl_attach_gdb)
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -2451,3 +2451,21 @@
     def set_status_flags(fd, flags):
         res = c_set_status_flags(fd, flags)
         handle_posix_error('set_status_flags', res)
+
+if not _WIN32:
+    sendfile_eci = ExternalCompilationInfo(includes=["sys/sendfile.h"])
+    _OFF_PTR_T = rffi.CArrayPtr(OFF_T)
+    c_sendfile = rffi.llexternal('sendfile',
+            [rffi.INT, rffi.INT, _OFF_PTR_T, rffi.SIZE_T],
+            rffi.SSIZE_T, compilation_info=sendfile_eci)
+
+    def sendfile(out_fd, in_fd, offset, count):
+        with lltype.scoped_alloc(_OFF_PTR_T.TO, 1) as p_offset:
+            p_offset[0] = rffi.cast(OFF_T, offset)
+            res = c_sendfile(out_fd, in_fd, p_offset, count)
+        return handle_posix_error('sendfile', res)
+
+    def sendfile_no_offset(out_fd, in_fd, count):
+        """Passes offset==NULL; not support on all OSes"""
+        res = c_sendfile(out_fd, in_fd, lltype.nullptr(_OFF_PTR_T.TO), count)
+        return handle_posix_error('sendfile', res)
diff --git a/rpython/translator/platform/linux.py b/rpython/translator/platform/linux.py
--- a/rpython/translator/platform/linux.py
+++ b/rpython/translator/platform/linux.py
@@ -14,7 +14,7 @@
     extra_libs = ('-lrt',)
     cflags = tuple(
              ['-O3', '-pthread', '-fomit-frame-pointer',
-              '-Wall', '-Wno-unused']
+              '-Wall', '-Wno-unused', '-Wno-address']
              + os.environ.get('CFLAGS', '').split())
     standalone_only = ()
     shared_only = ('-fPIC',)


More information about the pypy-commit mailing list