[pypy-commit] pypy release-pypy2.7-5.x: merge default into release branch

mattip pypy.commits at gmail.com
Tue May 30 09:53:30 EDT 2017


Author: Matti Picus <matti.picus at gmail.com>
Branch: release-pypy2.7-5.x
Changeset: r91458:4a11c013124d
Date: 2017-05-30 16:45 +0300
http://bitbucket.org/pypy/pypy/changeset/4a11c013124d/

Log:	merge default into release branch

diff --git a/lib-python/2.7/ctypes/test/test_unaligned_structures.py b/lib-python/2.7/ctypes/test/test_unaligned_structures.py
--- a/lib-python/2.7/ctypes/test/test_unaligned_structures.py
+++ b/lib-python/2.7/ctypes/test/test_unaligned_structures.py
@@ -37,7 +37,10 @@
         for typ in byteswapped_structures:
 ##            print >> sys.stderr, typ.value
             self.assertEqual(typ.value.offset, 1)
-            o = typ()
+            try:
+                o = typ()
+            except NotImplementedError as e:
+                self.skipTest(str(e))    # for PyPy
             o.value = 4
             self.assertEqual(o.value, 4)
 
diff --git a/lib-python/2.7/zipfile.py b/lib-python/2.7/zipfile.py
--- a/lib-python/2.7/zipfile.py
+++ b/lib-python/2.7/zipfile.py
@@ -622,19 +622,23 @@
         """Read and return up to n bytes.
         If the argument is omitted, None, or negative, data is read and returned until EOF is reached..
         """
-        buf = ''
+        # PyPy modification: don't do repeated string concatenation
+        buf = []
+        lenbuf = 0
         if n is None:
             n = -1
         while True:
             if n < 0:
                 data = self.read1(n)
-            elif n > len(buf):
-                data = self.read1(n - len(buf))
+            elif n > lenbuf:
+                data = self.read1(n - lenbuf)
             else:
-                return buf
+                break
             if len(data) == 0:
-                return buf
-            buf += data
+                break
+            lenbuf += len(data)
+            buf.append(data)
+        return "".join(buf)
 
     def _update_crc(self, newdata, eof):
         # Update the CRC using the given data.
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -357,6 +357,26 @@
 
 .. __: https://bitbucket.org/pypy/pypy/issue/1974/different-behaviour-for-collections-of
 
+C-API Differences
+-----------------
+
+The external C-API has been reimplemented in PyPy as an internal cpyext module.
+We support most of the documented C-API, but sometimes internal C-abstractions
+leak out on CPython and are abused, perhaps even unknowingly. For instance,
+assignment to a ``PyTupleObject`` is not supported after the tuple is
+used internally, even by another C-API function call. On CPython this will
+succeed as long as the refcount is 1.  On PyPy this will always raise a
+``SystemError('PyTuple_SetItem called on tuple after  use of tuple")``
+exception (explicitly listed here for search engines).
+
+Another similar problem is assignment of a new function pointer to any of the
+``tp_as_*`` structures after calling ``PyType_Ready``. For instance, overriding
+``tp_as_number.nb_int`` with a different function after calling ``PyType_Ready``
+on CPython will result in the old function being called for ``x.__int__()``
+(via class ``__dict__`` lookup) and the new function being called for ``int(x)``
+(via slot lookup). On PyPy we will always call the __new__ function, not the
+old, this quirky behaviour is unfortunately necessary to fully support NumPy.
+
 Performance Differences
 -------------------------
 
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-v5.8.0.rst
    release-v5.7.1.rst
    release-v5.7.0.rst
    release-pypy2.7-v5.6.0.rst
@@ -60,6 +61,7 @@
 
 .. toctree::
 
+   release-v5.8.0.rst
    release-v5.7.1.rst
    release-v5.7.0.rst
 
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-pypy2-5.8.0.rst
    whatsnew-pypy2-5.7.0.rst
    whatsnew-pypy2-5.6.0.rst
    whatsnew-pypy2-5.4.0.rst
diff --git a/pypy/doc/release-v5.8.0.rst b/pypy/doc/release-v5.8.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v5.8.0.rst
@@ -0,0 +1,131 @@
+=====================================
+PyPy2.7 and PyPy3.5 v5.8 dual release
+=====================================
+
+The PyPy team is proud to release both PyPy2.7 v5.8 (an interpreter supporting
+Python v2.7 syntax), and a beta-quality PyPy3.5 v5.8 (an interpreter for Python
+v3.5 syntax). The two releases are both based on much the same codebase, thus
+the dual release.  Note that PyPy3.5 supports Linux 64bit only for now. 
+
+This new PyPy2.7 release includes the upstream stdlib version 2.7.13, and
+PyPy3.5 (our first in the 3.5 series) includes the upstream stdlib version
+3.5.3.
+
+We continue to make incremental improvements to our C-API
+compatibility layer (cpyext). PyPy2 can now import and run many C-extension
+packages, among the most notable are Numpy, Cython, and Pandas. Performance may
+be slower than CPython, especially for frequently-called short C functions.
+Please let us know if your use case is slow, we have ideas how to make things
+faster but need real-world examples (not micro-benchmarks) of problematic code.
+
+Work proceeds at a good pace on the PyPy3.5
+version due to a grant_ from the Mozilla Foundation, hence our first 3.5.3 beta
+release. Thanks Mozilla !!! While we do not pass all tests yet, asyncio works and
+as `these benchmarks show`_ it already gives a nice speed bump.
+We also backported the ``f""`` formatting from 3.6 (as an exception; otherwise
+"PyPy3.5" supports the Python 3.5 language).
+
+CFFI_ has been updated to 1.10, improving an already great package for
+interfacing with C.
+
+As always, this release fixed many issues and bugs raised by the
+growing community of PyPy users. We strongly recommend updating.
+
+You can download the v5.8 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _CFFI: https://cffi.readthedocs.io/en/latest/whatsnew.html
+.. _grant: https://morepypy.blogspot.com/2016/08/pypy-gets-funding-from-mozilla-for.html
+.. _`PyPy`: index.html
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: project-ideas.html
+.. _`these benchmarks show`: https://morepypy.blogspot.com/2017/03/async-http-benchmarks-on-pypy3.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7 and CPython 3.5. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+The PyPy 2.7 release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
+
+Highlights of the PyPy2.7, cpyext, and RPython changes (since 5.7 released March, 2017)
+=======================================================================================
+
+See also issues that were resolved_
+
+* New features and cleanups
+
+  * 
+  * 
+
+* Bug Fixes
+
+  * 
+  * 
+
+* Performance improvements:
+
+  * 
+  * 
+
+* RPython improvements
+
+  * 
+  * 
+
+
+Highlights of the PyPy3.5 release (since 5.7 beta released March 2017)
+======================================================================
+
+* New features
+
+  * 
+  * 
+
+* Bug Fixes
+
+  * 
+  * 
+
+* Performance improvements:
+
+  * 
+
+* The following features of Python 3.5 are not implemented yet in PyPy:
+
+  * PEP 442: Safe object finalization
+  * PEP 489: Multi-phase extension module initialization
+
+.. _resolved: whatsnew-pypy2-5.8.0.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
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
@@ -1,70 +1,8 @@
 ==========================
-What's new in PyPy2.7 5.8+
+What's new in PyPy2.7 5.9+
 ==========================
 
-.. this is a revision shortly after release-pypy2.7-v5.7.0
-.. startrev: 44f31f6dd39f
+.. this is a revision shortly after release-pypy2.7-v5.8.0
+.. startrev: 0c91b5f4f275
 
-Add cpyext interfaces for ``PyModule_New``
 
-Correctly handle `dict.pop`` where the ``pop``
-key is not the same type as the ``dict``'s and ``pop``
-is called with a default (will be part of release 5.7.1)
-
-.. branch: issue2522
-
-Fix missing tp_new on w_object called through multiple inheritance
-(will be part of release 5.7.1)
-
-.. branch: lstrip_to_empty_string
-
-.. branch: vmprof-native
-
-PyPy support to profile native frames in vmprof.
-
-.. branch: reusing-r11
-.. branch: branch-prediction
-
-Performance tweaks in the x86 JIT-generated machine code: rarely taken
-blocks are moved off-line.  Also, the temporary register used to contain
-large constants is reused across instructions.
-
-.. branch: vmprof-0.4.4
-
-.. branch: controller-refactor
-
-Refactor rpython.rtyper.controllerentry.
-
-.. branch: PyBuffer-backport
-
-Internal refactoring of buffers and memoryviews. Memoryviews will now be
-accepted in a few more places, e.g. in compile().
-
-.. branch: sthalik/fix-signed-integer-sizes-1494493539409
-
-.. branch: cpyext-obj-stealing
-
-Redo much of the refcount semantics in PyList_{SG}etItem to closer match
-CPython and ensure the same PyObject stored in the list can be later
-retrieved
-
-.. branch: cpyext-recursionlimit
-
-Implement Py_EnterRecursiveCall and associated functions
-
-.. branch: pypy_ctypes_nosegfault_nofastpath
-
-Remove faulty fastpath from ctypes
-
-.. branch: sockopt_zero
-
-Passing a buffersize of 0 to socket.getsockopt
-
-.. branch: better-test-whatsnew
-
-.. branch: faster-rstruct-2
-
-Improve the performance of struct.pack and struct.pack_into by using raw_store
-or gc_store_indexed whenever possible. Moreover, enable the existing
-struct.unpack fast path to all the existing buffer types, whereas previously
-it was enabled only for strings
diff --git a/pypy/doc/whatsnew-pypy2-5.8.0.rst b/pypy/doc/whatsnew-pypy2-5.8.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.8.0.rst
@@ -0,0 +1,77 @@
+==========================
+What's new in PyPy2.7 5.8+
+==========================
+
+.. this is a revision shortly after release-pypy2.7-v5.7.0
+.. startrev: 44f31f6dd39f
+
+Add cpyext interfaces for ``PyModule_New``
+
+Correctly handle `dict.pop`` where the ``pop``
+key is not the same type as the ``dict``'s and ``pop``
+is called with a default (will be part of release 5.7.1)
+
+.. branch: issue2522
+
+Fix missing tp_new on w_object called through multiple inheritance
+(will be part of release 5.7.1)
+
+.. branch: lstrip_to_empty_string
+
+.. branch: vmprof-native
+
+PyPy support to profile native frames in vmprof.
+
+.. branch: reusing-r11
+.. branch: branch-prediction
+
+Performance tweaks in the x86 JIT-generated machine code: rarely taken
+blocks are moved off-line.  Also, the temporary register used to contain
+large constants is reused across instructions.
+
+.. branch: vmprof-0.4.4
+
+.. branch: controller-refactor
+
+Refactor rpython.rtyper.controllerentry.
+
+.. branch: PyBuffer-backport
+
+Internal refactoring of buffers and memoryviews. Memoryviews will now be
+accepted in a few more places, e.g. in compile().
+
+.. branch: sthalik/fix-signed-integer-sizes-1494493539409
+
+.. branch: cpyext-obj-stealing
+
+Redo much of the refcount semantics in PyList_{SG}etItem to closer match
+CPython and ensure the same PyObject stored in the list can be later
+retrieved
+
+.. branch: cpyext-recursionlimit
+
+Implement Py_EnterRecursiveCall and associated functions
+
+.. branch: pypy_ctypes_nosegfault_nofastpath
+
+Remove faulty fastpath from ctypes
+
+.. branch: sockopt_zero
+
+Passing a buffersize of 0 to socket.getsockopt
+
+.. branch: better-test-whatsnew
+
+.. branch: faster-rstruct-2
+
+Improve the performance of struct.pack and struct.pack_into by using raw_store
+or gc_store_indexed whenever possible. Moreover, enable the existing
+struct.unpack fast path to all the existing buffer types, whereas previously
+it was enabled only for strings
+
+.. branch: Kounavi/fix-typo-depricate-to-deprecate-p-1495624547235
+
+.. branch: PyPy_profopt_enabled
+
+Add profile-based optimization option ``profopt``, and specify training data
+via ``profoptpath``
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -798,8 +798,8 @@
                               '"license" for more information.')
 
 STDLIB_WARNING = """\
-debug: WARNING: Library path not found, using compiled-in sys.path.
-debug: WARNING: 'sys.prefix' will not be set.
+debug: WARNING: Library path not found, using compiled-in sys.path, with
+debug: WARNING: sys.prefix = %r
 debug: WARNING: Make sure the pypy binary is kept inside its tree of files.
 debug: WARNING: It is ok to create a symlink to it from somewhere else."""
 
@@ -818,12 +818,8 @@
     executable = sys.pypy_find_executable(executable)
     stdlib_path = sys.pypy_find_stdlib(executable)
     if stdlib_path is None:
-        for lib_path in sys.path:
-            stdlib_path = sys.pypy_find_stdlib(lib_path)
-            if stdlib_path is not None:
-                break
-    if stdlib_path is None:
-        print >> sys.stderr, STDLIB_WARNING
+        print >> sys.stderr, STDLIB_WARNING % (
+            getattr(sys, 'prefix', '<missing>'),)
     else:
         sys.path[:] = stdlib_path
     # from this point on, we are free to use all the unicode stuff we want,
diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py
--- a/pypy/module/__builtin__/operation.py
+++ b/pypy/module/__builtin__/operation.py
@@ -6,7 +6,7 @@
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
 from rpython.rlib.runicode import UNICHR
-from rpython.rlib.rfloat import isnan, isinf, round_double
+from rpython.rlib.rfloat import isfinite, isinf, round_double, round_away
 from rpython.rlib import rfloat
 import __builtin__
 
@@ -134,23 +134,26 @@
     ndigits = space.getindex_w(w_ndigits, None)
 
     # nans, infinities and zeros round to themselves
-    if number == 0 or isinf(number) or isnan(number):
-        return space.newfloat(number)
-
-    # Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x
-    # always rounds to itself.  For ndigits < NDIGITS_MIN, x always
-    # rounds to +-0.0.
-    if ndigits > NDIGITS_MAX:
-        return space.newfloat(number)
-    elif ndigits < NDIGITS_MIN:
-        # return 0.0, but with sign of x
-        return space.newfloat(0.0 * number)
-
-    # finite x, and ndigits is not unreasonably large
-    z = round_double(number, ndigits)
-    if isinf(z):
-        raise oefmt(space.w_OverflowError,
-                    "rounded value too large to represent")
+    if not isfinite(number):
+        z = number
+    elif ndigits == 0:    # common case
+        z = round_away(number)
+        # no need to check for an infinite 'z' here
+    else:
+        # Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x
+        # always rounds to itself.  For ndigits < NDIGITS_MIN, x always
+        # rounds to +-0.0.
+        if ndigits > NDIGITS_MAX:
+            z = number
+        elif ndigits < NDIGITS_MIN:
+            # return 0.0, but with sign of x
+            z = 0.0 * number
+        else:
+            # finite x, and ndigits is not unreasonably large
+            z = round_double(number, ndigits)
+            if isinf(z):
+                raise oefmt(space.w_OverflowError,
+                            "rounded value too large to represent")
     return space.newfloat(z)
 
 # ____________________________________________________________
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
@@ -625,6 +625,9 @@
         assert round(5e15) == 5e15
         assert round(-(5e15-1)) == -(5e15-1)
         assert round(-5e15) == -5e15
+        assert round(5e15/2) == 5e15/2
+        assert round((5e15+1)/2) == 5e15/2+1
+        assert round((5e15-1)/2) == 5e15/2
         #
         inf = 1e200 * 1e200
         assert round(inf) == inf
@@ -636,6 +639,12 @@
         #
         assert round(562949953421312.5, 1) == 562949953421312.5
         assert round(56294995342131.5, 3) == 56294995342131.5
+        #
+        for i in range(-10, 10):
+            expected = i if i < 0 else i + 1
+            assert round(i + 0.5) == round(i + 0.5, 0) == expected
+            x = i * 10 + 5
+            assert round(x, -1) == round(float(x), -1) == expected * 10
 
     def test_vars_obscure_case(self):
         class C_get_vars(object):
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
@@ -310,6 +310,8 @@
                 return space.newint(self.sock.getsockopt_int(level, optname))
             except SocketError as e:
                 raise converted_error(space, e)
+        if buflen < 0 or buflen > 1024:
+            raise explicit_socket_error(space, "getsockopt buflen out of range")
         return space.newbytes(self.sock.getsockopt(level, optname, buflen))
 
     def gettimeout_w(self, space):
@@ -696,6 +698,12 @@
         w_exception = space.call_function(w_exception_class, space.newtext(message))
     return OperationError(w_exception_class, w_exception)
 
+def explicit_socket_error(space, msg):
+    w_exception_class = space.fromcache(SocketAPI).w_error
+    w_exception = space.call_function(w_exception_class, space.newtext(msg))
+    return OperationError(w_exception_class, w_exception)
+
+
 # ____________________________________________________________
 
 socketmethodnames = """
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
@@ -595,6 +595,16 @@
         s.setsockopt(_socket.IPPROTO_TCP, _socket.TCP_NODELAY, 1)
         assert s.getsockopt(_socket.IPPROTO_TCP, _socket.TCP_NODELAY, 0) == 1
 
+    def test_getsockopt_bad_length(self):
+        import _socket
+        s = _socket.socket()
+        buf = s.getsockopt(_socket.IPPROTO_TCP, _socket.TCP_NODELAY, 1024)
+        assert buf == b'\x00' * 4
+        raises(_socket.error, s.getsockopt,
+               _socket.IPPROTO_TCP, _socket.TCP_NODELAY, 1025)
+        raises(_socket.error, s.getsockopt,
+               _socket.IPPROTO_TCP, _socket.TCP_NODELAY, -1)
+
     def test_socket_ioctl(self):
         import _socket, sys
         if sys.platform != 'win32':
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -799,51 +799,39 @@
 class ArrayBuffer(RawBuffer):
     _immutable_ = True
 
-    def __init__(self, array, readonly):
-        self.array = array
+    def __init__(self, w_array, readonly):
+        self.w_array = w_array
         self.readonly = readonly
 
     def getlength(self):
-        return self.array.len * self.array.itemsize
-
-    def getformat(self):
-        return self.array.typecode
-
-    def getitemsize(self):
-        return self.array.itemsize
-
-    def getndim(self):
-        return 1
-
-    def getstrides(self):
-        return [self.getitemsize()]
+        return self.w_array.len * self.w_array.itemsize
 
     def getitem(self, index):
-        array = self.array
-        data = array._charbuf_start()
+        w_array = self.w_array
+        data = w_array._charbuf_start()
         char = data[index]
-        array._charbuf_stop()
+        w_array._charbuf_stop()
         return char
 
     def setitem(self, index, char):
-        array = self.array
-        data = array._charbuf_start()
+        w_array = self.w_array
+        data = w_array._charbuf_start()
         data[index] = char
-        array._charbuf_stop()
+        w_array._charbuf_stop()
 
     def getslice(self, start, stop, step, size):
         if size == 0:
             return ''
         if step == 1:
-            data = self.array._charbuf_start()
+            data = self.w_array._charbuf_start()
             try:
                 return rffi.charpsize2str(rffi.ptradd(data, start), size)
             finally:
-                self.array._charbuf_stop()
+                self.w_array._charbuf_stop()
         return RawBuffer.getslice(self, start, stop, step, size)
 
     def get_raw_address(self):
-        return self.array._charbuf_start()
+        return self.w_array._charbuf_start()
 
 
 unpack_driver = jit.JitDriver(name='unpack_array',
diff --git a/pypy/module/cpyext/bufferobject.py b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -56,9 +56,9 @@
         py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(buf.value))
         py_buf.c_b_size = buf.getlength()
     elif isinstance(buf, ArrayBuffer):
-        w_base = buf.array
+        w_base = buf.w_array
         py_buf.c_b_base = make_ref(space, w_base)
-        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, buf.array._charbuf_start())
+        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, buf.w_array._charbuf_start())
         py_buf.c_b_size = buf.getlength()
     else:
         raise oefmt(space.w_NotImplementedError, "buffer flavor not supported")
diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -161,3 +161,47 @@
         assert list(a) == range(100, 400, 100)
         assert list(a) == range(100, 400, 100)
         assert list(a) == range(100, 400, 100)
+
+    def test_setitem(self):
+        module = self.import_extension('foo', [
+            ("set_after_use", "METH_O",
+             """
+                PyObject *t2, *tuple = PyTuple_New(1);
+                PyObject * one = PyLong_FromLong(1);
+                int res;
+                Py_INCREF(one);
+                res = PyTuple_SetItem(tuple, 0, one);
+                if (res != 0)
+                {
+                    Py_DECREF(tuple);
+                    return NULL;
+                }
+                Py_INCREF(args);
+                res = PyTuple_SetItem(tuple, 0, args);
+                if (res != 0)
+                {
+                    Py_DECREF(tuple);
+                    return NULL;
+                }
+                /* Do something that uses the tuple, but does not incref */
+                t2 = PyTuple_GetSlice(tuple, 0, 1);
+                Py_DECREF(t2);
+                Py_INCREF(one);
+                res = PyTuple_SetItem(tuple, 0, one);
+                Py_DECREF(tuple);
+                if (res != 0)
+                {
+                    Py_DECREF(one);
+                    return NULL;
+                }
+                Py_INCREF(Py_None);
+                return Py_None;
+             """),
+            ])
+        import sys
+        s = 'abc'
+        if '__pypy__' in sys.builtin_module_names:
+            raises(SystemError, module.set_after_use, s)
+        else:
+            module.set_after_use(s)
+
diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -6,7 +6,7 @@
     PyVarObjectFields, cpython_struct, bootstrap_function, slot_function)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, make_ref, from_ref, decref, incref,
-    track_reference, make_typedescr, get_typedescr)
+    track_reference, make_typedescr, get_typedescr, pyobj_has_w_obj)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.objspace.std.tupleobject import W_TupleObject
 
@@ -132,19 +132,20 @@
 
 @cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
 def PyTuple_SetItem(space, ref, index, py_obj):
-    # XXX this will not complain when changing tuples that have
-    # already been realized as a W_TupleObject, but won't update the
-    # W_TupleObject
     if not tuple_check_ref(space, ref):
         decref(space, py_obj)
         PyErr_BadInternalCall(space)
-    ref = rffi.cast(PyTupleObject, ref)
-    size = ref.c_ob_size
+    tupleobj = rffi.cast(PyTupleObject, ref)
+    size = tupleobj.c_ob_size
     if index < 0 or index >= size:
         decref(space, py_obj)
         raise oefmt(space.w_IndexError, "tuple assignment index out of range")
-    old_ref = ref.c_ob_item[index]
-    ref.c_ob_item[index] = py_obj    # consumes a reference
+    old_ref = tupleobj.c_ob_item[index]
+    if pyobj_has_w_obj(ref):
+        # similar but not quite equal to ref.c_ob_refcnt != 1 on CPython
+        raise oefmt(space.w_SystemError, "PyTuple_SetItem called on tuple after"
+                                        " use of tuple")
+    tupleobj.c_ob_item[index] = py_obj    # consumes a reference
     if old_ref:
         decref(space, old_ref)
     return 0
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -39,8 +39,8 @@
         'stderr'                : 'state.getio(space).w_stderr',
         '__stderr__'            : 'state.getio(space).w_stderr',
         'pypy_objspaceclass'    : 'space.newtext(repr(space))',
-        #'prefix'               : # added by pypy_initial_path() when it
-        #'exec_prefix'          : # succeeds, pointing to trunk or /usr
+        'prefix'                : 'state.get(space).w_initial_prefix',
+        'exec_prefix'           : 'state.get(space).w_initial_prefix',
         'path'                  : 'state.get(space).w_path',
         'modules'               : 'state.get(space).w_modules',
         'argv'                  : 'state.get(space).w_argv',
diff --git a/pypy/module/sys/state.py b/pypy/module/sys/state.py
--- a/pypy/module/sys/state.py
+++ b/pypy/module/sys/state.py
@@ -19,8 +19,11 @@
 
     def setinitialpath(self, space):
         from pypy.module.sys.initpath import compute_stdlib_path
+        # This initial value for sys.prefix is normally overwritten
+        # at runtime by initpath.py
+        srcdir = os.path.dirname(pypydir)
+        self.w_initial_prefix = space.newtext(srcdir)
         # Initialize the default path
-        srcdir = os.path.dirname(pypydir)
         path = compute_stdlib_path(self, srcdir)
         self.w_path = space.newlist([space.newtext(p) for p in path])
 
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -648,7 +648,7 @@
         if space.isinstance_w(w_other, space.w_unicode):
             self_as_unicode = unicode_from_encoded_object(space, self, None,
                                                           None)
-            return space.add(self_as_unicode, w_other)
+            return self_as_unicode.descr_add(space, w_other)
         elif space.isinstance_w(w_other, space.w_bytearray):
             # XXX: eliminate double-copy
             from .bytearrayobject import W_BytearrayObject, _make_data
diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -846,3 +846,7 @@
                 return 42
         x = Foo()
         assert "hello" + x == 42
+
+    def test_add(self):
+        assert 'abc' + 'abc' == 'abcabc'
+        assert isinstance('abc' + u'\u03a3', unicode)
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -463,6 +463,21 @@
     def get_root_stack_top_addr(self):
         return rffi.cast(lltype.Signed, self.stack_addr)
 
+    def getlength(self):
+        top = self.stack_addr[0]
+        base = rffi.cast(lltype.Signed, self.stack)
+        n = (top - base) // WORD
+        assert 0 <= n < 10
+        return n
+
+    def curtop(self):
+        n = self.getlength()
+        return self.stack[n - 1]
+
+    def settop(self, newvalue):
+        n = self.getlength()
+        self.stack[n - 1] = newvalue
+
 class WriteBarrierDescr(AbstractDescr):
     jit_wb_cards_set = 0
     jit_wb_if_flag_singlebyte = 1
@@ -645,7 +660,7 @@
         frames = []
 
         def check(i):
-            assert cpu.gc_ll_descr.gcrootmap.stack[0] == i
+            assert cpu.gc_ll_descr.gcrootmap.curtop() == i
             frame = rffi.cast(JITFRAMEPTR, i)
             assert len(frame.jf_frame) == self.cpu.JITFRAME_FIXED_SIZE + 4
             # we "collect"
@@ -665,14 +680,14 @@
                 assert gcmap == [22, 23, 24]
             for item, s in zip(gcmap, new_items):
                 new_frame.jf_frame[item] = rffi.cast(lltype.Signed, s)
-            assert cpu.gc_ll_descr.gcrootmap.stack[0] == rffi.cast(lltype.Signed, frame)
-            cpu.gc_ll_descr.gcrootmap.stack[0] = rffi.cast(lltype.Signed, new_frame)
+            assert cpu.gc_ll_descr.gcrootmap.curtop() == rffi.cast(lltype.Signed, frame)
+            cpu.gc_ll_descr.gcrootmap.settop(rffi.cast(lltype.Signed, new_frame))
             print '"Collecting" moved the frame from %d to %d' % (
-                i, cpu.gc_ll_descr.gcrootmap.stack[0])
+                i, cpu.gc_ll_descr.gcrootmap.curtop())
             frames.append(new_frame)
 
         def check2(i):
-            assert cpu.gc_ll_descr.gcrootmap.stack[0] == i
+            assert cpu.gc_ll_descr.gcrootmap.curtop() == i
             frame = rffi.cast(JITFRAMEPTR, i)
             assert frame == frames[1]
             assert frame != frames[0]
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1052,17 +1052,19 @@
 
     def _call_header_shadowstack(self, gcrootmap):
         rst = self._load_shadowstack_top_in_ebx(self.mc, gcrootmap)
-        self.mc.MOV_mr((ebx.value, 0), ebp.value)      # MOV [ebx], ebp
-        self.mc.ADD_ri(ebx.value, WORD)
+        # the '1' is to benefit from the shadowstack 'is_minor' optimization
+        self.mc.MOV_mi((ebx.value, 0), 1)               # MOV [ebx], 1
+        self.mc.MOV_mr((ebx.value, WORD), ebp.value)    # MOV [ebx + WORD], ebp
+        self.mc.ADD_ri(ebx.value, WORD * 2)
         self.mc.MOV(heap(rst), ebx)                   # MOV [rootstacktop], ebx
 
     def _call_footer_shadowstack(self, gcrootmap):
         rst = gcrootmap.get_root_stack_top_addr()
         if rx86.fits_in_32bits(rst):
-            self.mc.SUB_ji8(rst, WORD)       # SUB [rootstacktop], WORD
+            self.mc.SUB_ji8(rst, WORD * 2)       # SUB [rootstacktop], WORD * 2
         else:
             self.mc.MOV_ri(ebx.value, rst)           # MOV ebx, rootstacktop
-            self.mc.SUB_mi8((ebx.value, 0), WORD)  # SUB [ebx], WORD
+            self.mc.SUB_mi8((ebx.value, 0), WORD * 2)  # SUB [ebx], WORD * 2
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         # some minimal sanity checking
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -925,6 +925,10 @@
     def gct_gc_adr_of_root_stack_top(self, hop):
         self._gc_adr_of_gcdata_attr(hop, 'root_stack_top')
 
+    def gct_gc_modified_shadowstack(self, hop):
+        # for stacklet
+        hop.genop("direct_call", [self.root_walker.gc_modified_shadowstack_ptr])
+
     def gct_gc_detach_callback_pieces(self, hop):
         op = hop.spaceop
         assert len(op.args) == 0
diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -245,6 +245,13 @@
         from rpython.rlib import _stacklet_shadowstack
         _stacklet_shadowstack.complete_destrptr(gctransformer)
 
+        gcdata = self.gcdata
+        def gc_modified_shadowstack():
+            gcdata.can_look_at_partial_stack = False
+
+        self.gc_modified_shadowstack_ptr = getfn(gc_modified_shadowstack,
+                                                 [], annmodel.s_None)
+
     def postprocess_graph(self, gct, graph, any_inlining):
         from rpython.memory.gctransform import shadowcolor
         if any_inlining:
diff --git a/rpython/rlib/_stacklet_shadowstack.py b/rpython/rlib/_stacklet_shadowstack.py
--- a/rpython/rlib/_stacklet_shadowstack.py
+++ b/rpython/rlib/_stacklet_shadowstack.py
@@ -77,6 +77,7 @@
     llmemory.raw_memcopy(sscopy + SIZEADDR, base, length_bytes)
     llop.gc_adr_of_root_stack_top(llmemory.Address).address[0] = (
         base + length_bytes)
+    llop.gc_modified_shadowstack(lltype.Void)
     llmemory.raw_free(sscopy)
 
 def alloc_stacklet():
diff --git a/rpython/rlib/rfloat.py b/rpython/rlib/rfloat.py
--- a/rpython/rlib/rfloat.py
+++ b/rpython/rlib/rfloat.py
@@ -96,7 +96,20 @@
     """Round a float half away from zero.
 
     Specify half_even=True to round half even instead.
+    The argument 'value' must be a finite number.  This
+    function may return an infinite number in case of
+    overflow (only if ndigits is a very negative integer).
     """
+    if ndigits == 0:
+        # fast path for this common case
+        if half_even:
+            return round_half_even(value)
+        else:
+            return round_away(value)
+
+    if value == 0.0:
+        return 0.0
+
     # The basic idea is very simple: convert and round the double to
     # a decimal string using _Py_dg_dtoa, then convert that decimal
     # string back to a double with _Py_dg_strtod.  There's one minor
@@ -217,11 +230,34 @@
 
 def round_away(x):
     # round() from libm, which is not available on all platforms!
+    # This version rounds away from zero.
     absx = abs(x)
-    if absx - math.floor(absx) >= .5:
-        r = math.ceil(absx)
+    r = math.floor(absx + 0.5)
+    if r - absx < 1.0:
+        return copysign(r, x)
     else:
-        r = math.floor(absx)
+        # 'absx' is just in the wrong range: its exponent is precisely
+        # the one for which all integers are representable but not any
+        # half-integer.  It means that 'absx + 0.5' computes equal to
+        # 'absx + 1.0', which is not equal to 'absx'.  So 'r - absx'
+        # computes equal to 1.0.  In this situation, we can't return
+        # 'r' because 'absx' was already an integer but 'r' is the next
+        # integer!  But just returning the original 'x' is fine.
+        return x
+
+def round_half_even(x):
+    absx = abs(x)
+    r = math.floor(absx + 0.5)
+    frac = r - absx
+    if frac >= 0.5:
+        # two rare cases: either 'absx' is precisely half-way between
+        # two integers (frac == 0.5); or we're in the same situation as
+        # described in round_away above (frac == 1.0).
+        if frac >= 1.0:
+            return x
+        # absx == n + 0.5  for a non-negative integer 'n'
+        # absx * 0.5 == n//2 + 0.25 or 0.75, which we round to nearest
+        r = math.floor(absx * 0.5 + 0.5) * 2.0
     return copysign(r, x)
 
 @not_rpython
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -235,6 +235,7 @@
     includes = ['unistd.h',  'sys/types.h', 'sys/wait.h',
                 'utime.h', 'sys/time.h', 'sys/times.h',
                 'sys/resource.h',
+                'sched.h',
                 'grp.h', 'dirent.h', 'sys/stat.h', 'fcntl.h',
                 'signal.h', 'sys/utsname.h', _ptyh]
     if sys.platform.startswith('linux'):
@@ -255,6 +256,10 @@
     PRIO_PROCESS = rffi_platform.DefinedConstantInteger('PRIO_PROCESS')
     PRIO_PGRP = rffi_platform.DefinedConstantInteger('PRIO_PGRP')
     PRIO_USER = rffi_platform.DefinedConstantInteger('PRIO_USER')
+    SCHED_FIFO = rffi_platform.DefinedConstantInteger('SCHED_FIFO')
+    SCHED_RR = rffi_platform.DefinedConstantInteger('SCHED_RR')
+    SCHED_OTHER = rffi_platform.DefinedConstantInteger('SCHED_OTHER')
+    SCHED_BATCH = rffi_platform.DefinedConstantInteger('SCHED_BATCH')
     O_NONBLOCK = rffi_platform.DefinedConstantInteger('O_NONBLOCK')
     OFF_T = rffi_platform.SimpleType('off_t')
     OFF_T_SIZE = rffi_platform.SizeOf('off_t')
@@ -1818,6 +1823,21 @@
     def setpriority(which, who, prio):
         handle_posix_error('setpriority', c_setpriority(which, who, prio))
 
+    c_sched_get_priority_max = external('sched_get_priority_max', [rffi.INT],
+                              rffi.INT, save_err=rffi.RFFI_FULL_ERRNO_ZERO)
+    c_sched_get_priority_min = external('sched_get_priority_min', [rffi.INT],
+                             rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
+
+    @enforceargs(int)
+    def sched_get_priority_max(policy):
+        return handle_posix_error('sched_get_priority_max', c_sched_get_priority_max(policy))
+
+    @enforceargs(int)
+    def sched_get_priority_min(policy):
+        return handle_posix_error('sched_get_priority_min', c_sched_get_priority_min(policy))
+
+
+
 
 #___________________________________________________________________
 
diff --git a/rpython/rlib/test/test_rfloat.py b/rpython/rlib/test/test_rfloat.py
--- a/rpython/rlib/test/test_rfloat.py
+++ b/rpython/rlib/test/test_rfloat.py
@@ -28,7 +28,7 @@
 
 def test_round_double():
     def almost_equal(x, y):
-        assert round(abs(x-y), 7) == 0
+        assert abs(x-y) < 1e-7
 
     almost_equal(round_double(0.125, 2), 0.13)
     almost_equal(round_double(0.375, 2), 0.38)
@@ -44,35 +44,35 @@
     almost_equal(round_double(-0.25, 1), -0.3)
     almost_equal(round_double(-0.75, 1), -0.8)
 
-    round_double(-6.5, 0) == -7.0
-    round_double(-5.5, 0) == -6.0
-    round_double(-1.5, 0) == -2.0
-    round_double(-0.5, 0) == -1.0
-    round_double(0.5, 0) == 1.0
-    round_double(1.5, 0) == 2.0
-    round_double(2.5, 0) == 3.0
-    round_double(3.5, 0) == 4.0
-    round_double(4.5, 0) == 5.0
-    round_double(5.5, 0) == 6.0
-    round_double(6.5, 0) == 7.0
+    assert round_double(-6.5, 0) == -7.0
+    assert round_double(-5.5, 0) == -6.0
+    assert round_double(-1.5, 0) == -2.0
+    assert round_double(-0.5, 0) == -1.0
+    assert round_double(0.5, 0) == 1.0
+    assert round_double(1.5, 0) == 2.0
+    assert round_double(2.5, 0) == 3.0
+    assert round_double(3.5, 0) == 4.0
+    assert round_double(4.5, 0) == 5.0
+    assert round_double(5.5, 0) == 6.0
+    assert round_double(6.5, 0) == 7.0
 
-    round_double(-25.0, -1) == -30.0
-    round_double(-15.0, -1) == -20.0
-    round_double(-5.0, -1) == -10.0
-    round_double(5.0, -1) == 10.0
-    round_double(15.0, -1) == 20.0
-    round_double(25.0, -1) == 30.0
-    round_double(35.0, -1) == 40.0
-    round_double(45.0, -1) == 50.0
-    round_double(55.0, -1) == 60.0
-    round_double(65.0, -1) == 70.0
-    round_double(75.0, -1) == 80.0
-    round_double(85.0, -1) == 90.0
-    round_double(95.0, -1) == 100.0
-    round_double(12325.0, -1) == 12330.0
+    assert round_double(-25.0, -1) == -30.0
+    assert round_double(-15.0, -1) == -20.0
+    assert round_double(-5.0, -1) == -10.0
+    assert round_double(5.0, -1) == 10.0
+    assert round_double(15.0, -1) == 20.0
+    assert round_double(25.0, -1) == 30.0
+    assert round_double(35.0, -1) == 40.0
+    assert round_double(45.0, -1) == 50.0
+    assert round_double(55.0, -1) == 60.0
+    assert round_double(65.0, -1) == 70.0
+    assert round_double(75.0, -1) == 80.0
+    assert round_double(85.0, -1) == 90.0
+    assert round_double(95.0, -1) == 100.0
+    assert round_double(12325.0, -1) == 12330.0
 
-    round_double(350.0, -2) == 400.0
-    round_double(450.0, -2) == 500.0
+    assert round_double(350.0, -2) == 400.0
+    assert round_double(450.0, -2) == 500.0
 
     almost_equal(round_double(0.5e21, -21), 1e21)
     almost_equal(round_double(1.5e21, -21), 2e21)
@@ -85,6 +85,13 @@
     almost_equal(round_double(0.5e22, -22), 1e22)
     almost_equal(round_double(1.5e22, -22), 2e22)
 
+    exact_integral = 5e15 + 1
+    assert round_double(exact_integral, 0) == exact_integral
+    assert round_double(exact_integral/2.0, 0) == 5e15/2.0 + 1.0
+    exact_integral = 5e15 - 1
+    assert round_double(exact_integral, 0) == exact_integral
+    assert round_double(exact_integral/2.0, 0) == 5e15/2.0
+
 def test_round_half_even():
     from rpython.rlib import rfloat
     func = rfloat.round_double
@@ -92,6 +99,15 @@
     assert func(2.5, 0, False) == 3.0
     # 3.x behavior
     assert func(2.5, 0, True) == 2.0
+    for i in range(-10, 10):
+        assert func(i + 0.5, 0, True) == i + (i & 1)
+        assert func(i * 10 + 5, -1, True) == (i + (i & 1)) * 10
+    exact_integral = 5e15 + 1
+    assert round_double(exact_integral, 0, True) == exact_integral
+    assert round_double(exact_integral/2.0, 0, True) == 5e15/2.0
+    exact_integral = 5e15 - 1
+    assert round_double(exact_integral, 0, True) == exact_integral
+    assert round_double(exact_integral/2.0, 0, True) == 5e15/2.0
 
 def test_float_as_rbigint_ratio():
     for f, ratio in [
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -781,3 +781,27 @@
             raise
     finally:
         os.close(fd)
+
+ at rposix_requires('sched_get_priority_max')
+def test_sched_get_priority_max():
+    assert rposix.sched_get_priority_max(rposix.SCHED_FIFO) != -1
+    assert rposix.sched_get_priority_max(rposix.SCHED_RR) != -1
+    assert rposix.sched_get_priority_max(rposix.SCHED_OTHER) != -1
+    assert rposix.sched_get_priority_max(rposix.SCHED_BATCH) != -1
+    
+ at rposix_requires('sched_get_priority_min')
+def test_sched_get_priority_min():
+    assert rposix.sched_get_priority_min(rposix.SCHED_FIFO) != -1
+    assert rposix.sched_get_priority_min(rposix.SCHED_RR) != -1
+    assert rposix.sched_get_priority_min(rposix.SCHED_OTHER) != -1
+    assert rposix.sched_get_priority_min(rposix.SCHED_BATCH) != -1
+    
+ at rposix_requires('sched_get_priority_min')
+def test_os_sched_priority_max_greater_than_min():
+    policy = rposix.SCHED_RR
+    low = rposix.sched_get_priority_min(policy)
+    high = rposix.sched_get_priority_max(policy)
+    assert isinstance(low, int) == True
+    assert isinstance(high, int) == True
+    assert  high > low
+
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -862,6 +862,9 @@
     def op_gc_adr_of_root_stack_top(self):
         raise NotImplementedError
 
+    def op_gc_modified_shadowstack(self):
+        raise NotImplementedError
+
     def op_gc_call_rtti_destructor(self, rtti, addr):
         if hasattr(rtti._obj, 'destructor_funcptr'):
             d = rtti._obj.destructor_funcptr
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -515,6 +515,7 @@
     'gc_adr_of_root_stack_base': LLOp(),
     'gc_adr_of_root_stack_top': LLOp(),
     # returns the address of gcdata.root_stack_base/top (for shadowstack only)
+    'gc_modified_shadowstack': LLOp(),
 
     # for asmgcroot support to get the address of various static structures
     # see translator/c/src/mem.h for the valid indices
diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py
--- a/rpython/translator/platform/__init__.py
+++ b/rpython/translator/platform/__init__.py
@@ -102,7 +102,7 @@
 
     def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                      shared=False, headers_to_precompile=[],
-                     no_precompile_cfiles = [], config=None):
+                     no_precompile_cfiles = [], profopt=False, config=None):
         raise NotImplementedError("Pure abstract baseclass")
 
     def __repr__(self):
diff --git a/rpython/translator/platform/darwin.py b/rpython/translator/platform/darwin.py
--- a/rpython/translator/platform/darwin.py
+++ b/rpython/translator/platform/darwin.py
@@ -96,7 +96,7 @@
 
     def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                      shared=False, headers_to_precompile=[],
-                     no_precompile_cfiles = [], config=None):
+                     no_precompile_cfiles = [], profopt=False, config=None):
         # ensure frameworks are passed in the Makefile
         fs = self._frameworks(eci.frameworks)
         if len(fs) > 0:
@@ -106,7 +106,7 @@
                                 shared=shared,
                                 headers_to_precompile=headers_to_precompile,
                                 no_precompile_cfiles = no_precompile_cfiles,
-                                config=config)
+                                profopt=profopt, config=config)
         return mk
 
 class Darwin_PowerPC(Darwin):#xxx fixme, mwp
diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -299,7 +299,7 @@
 
     def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                      shared=False, headers_to_precompile=[],
-                     no_precompile_cfiles = [], config=None):
+                     no_precompile_cfiles = [], profopt=False, config=None):
         cfiles = self._all_cfiles(cfiles, eci)
 
         if path is None:


More information about the pypy-commit mailing list