Author: Matti Picus <[email protected]>
Branch: py3.7
Changeset: r98427:19ce9addfd08
Date: 2019-12-31 10:39 +0200
http://bitbucket.org/pypy/pypy/changeset/19ce9addfd08/

Log:    merge py3.6 into py3.7

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -61,3 +61,12 @@
 533398cfd64e5146a07c4824e90a1b629c8b6523 release-pypy3.6-v7.3.0rc1
 285307a0f5a77ffa46781b5c54c52eb1c385081d release-pypy2.7-v7.3.0rc2
 008914050baeedb6d3ca30fe26ef43b78bb63841 release-pypy3.6-v7.3.0rc2
+c124c11a5921bf12797b08a696753a12ae82595a release-pypy3.6-v7.2.0rc3
+e7e02dccbd8c14fa2d4880f6bd4c47362a8952f5 release-pypy3.6-v7.3.0rc3
+c124c11a5921bf12797b08a696753a12ae82595a release-pypy2.7-v7.3.0rc3
+c124c11a5921bf12797b08a696753a12ae82595a release-pypy3.6-v7.2.0rc3
+0000000000000000000000000000000000000000 release-pypy3.6-v7.2.0rc3
+1608da62bfc71e8ac775121dd0b21bb72e61c6ea release-pypy3.6-v7.3.0rc4
+724f1a7d62e8d8ac0fa20823f5c35497b29ad56f release-pypy2.7-v7.3.0rc4
+724f1a7d62e8d8ac0fa20823f5c35497b29ad56f release-pypy2.7-v7.3.0
+1608da62bfc71e8ac775121dd0b21bb72e61c6ea release-pypy3.6-v7.3.0
diff --git a/lib-python/3/importlib/_bootstrap.py 
b/lib-python/3/importlib/_bootstrap.py
--- a/lib-python/3/importlib/_bootstrap.py
+++ b/lib-python/3/importlib/_bootstrap.py
@@ -67,7 +67,7 @@
         # Deadlock avoidance for concurrent circular imports.
         me = _thread.get_ident()
         tid = self.owner
-        count = 0
+        seen = set()
         while True:
             lock = _blocking_on.get(tid)
             if lock is None:
@@ -75,14 +75,14 @@
             tid = lock.owner
             if tid == me:
                 return True
-            # workaround for https://bugs.python.org/issue38091:
-            # instead of looping here forever, eventually return False.
-            # Unsure if this will cause real deadlocks to go undetected,
-            # but at least it doesn't cause *this* logic here to
-            # deadlock when there is otherwise no deadlock!
-            count += 1
-            if count >= 100:
+            if tid in seen:
+                # bpo 38091: the chain of tid's we encounter here
+                # eventually leads to a fixpoint or a cycle, but
+                # does not reach 'me'.  This means we would not
+                # actually deadlock.  This can happen if other
+                # threads are at the beginning of acquire() below.
                 return False
+            seen.add(tid)
 
     def acquire(self):
         """
diff --git a/lib-python/3/pickle.py b/lib-python/3/pickle.py
--- a/lib-python/3/pickle.py
+++ b/lib-python/3/pickle.py
@@ -1644,6 +1644,15 @@
     import doctest
     return doctest.testmod()
 
+# ===== PyPy modification to support pickling cpyext methods =====
+try:
+    import cpyext
+except ImportError:
+    pass
+else:
+    Pickler.dispatch[cpyext.FunctionType] = Pickler.save_global
+# ================= end of PyPy modification ====================
+
 if __name__ == "__main__":
     import argparse
     parser = argparse.ArgumentParser(
diff --git a/lib-python/3/subprocess.py b/lib-python/3/subprocess.py
--- a/lib-python/3/subprocess.py
+++ b/lib-python/3/subprocess.py
@@ -1803,3 +1803,9 @@
             src_library = os.path.join(src_dir, libname)
             if os.path.exists(src_library):
                 caller.f_globals['copyfile'](src_library, dest_library)
+        src_lib = os.path.join(src_dir, '../lib')
+        if os.path.exists(src_lib):
+            # portable build
+            import shutil
+            shutil.copytree(src_lib, os.path.join(dest_dir, '../lib'))
+
diff --git a/lib-python/3/test/test_coroutines.py 
b/lib-python/3/test/test_coroutines.py
--- a/lib-python/3/test/test_coroutines.py
+++ b/lib-python/3/test/test_coroutines.py
@@ -931,11 +931,11 @@
 
     def test_corotype_1(self):
         ct = types.CoroutineType
-        self.assert_('into coroutine' in ct.send.__doc__ or
+        self.assertTrue('into coroutine' in ct.send.__doc__ or
                      'into generator/coroutine' in ct.send.__doc__)
-        self.assert_('inside coroutine' in ct.close.__doc__ or
+        self.assertTrue('inside coroutine' in ct.close.__doc__ or
                      'inside generator/coroutine' in ct.close.__doc__)
-        self.assert_('in coroutine' in ct.throw.__doc__ or
+        self.assertTrue('in coroutine' in ct.throw.__doc__ or
                      'in generator/coroutine' in ct.throw.__doc__)
         self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__)
         self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__)
@@ -1279,8 +1279,8 @@
 
         with self.assertRaisesRegex(
                 TypeError,
-                "'async with' received an object from __aenter__ "
-                "that does not implement __await__: int"):
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression"):
             # it's important that __aexit__ wasn't called
             run_async(foo())
 
@@ -1302,8 +1302,8 @@
         except TypeError as exc:
             self.assertRegex(
                 exc.args[0],
-                "'async with' received an object from __aexit__ "
-                "that does not implement __await__: int")
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression")
             self.assertTrue(exc.__context__ is not None)
             self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
         else:
@@ -1327,8 +1327,8 @@
                 CNT += 1
         with self.assertRaisesRegex(
                 TypeError,
-                "'async with' received an object from __aexit__ "
-                "that does not implement __await__: int"):
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression"):
             run_async(foo())
         self.assertEqual(CNT, 1)
 
@@ -1341,8 +1341,8 @@
                     break
         with self.assertRaisesRegex(
                 TypeError,
-                "'async with' received an object from __aexit__ "
-                "that does not implement __await__: int"):
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression"):
             run_async(foo())
         self.assertEqual(CNT, 2)
 
@@ -1355,8 +1355,8 @@
                     continue
         with self.assertRaisesRegex(
                 TypeError,
-                "'async with' received an object from __aexit__ "
-                "that does not implement __await__: int"):
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression"):
             run_async(foo())
         self.assertEqual(CNT, 3)
 
@@ -1368,8 +1368,8 @@
                 return
         with self.assertRaisesRegex(
                 TypeError,
-                "'async with' received an object from __aexit__ "
-                "that does not implement __await__: int"):
+                # XXX: PyPy change
+                "object int can't be used in 'await' expression"):
             run_async(foo())
         self.assertEqual(CNT, 4)
 
diff --git a/lib-python/3/venv/__init__.py b/lib-python/3/venv/__init__.py
--- a/lib-python/3/venv/__init__.py
+++ b/lib-python/3/venv/__init__.py
@@ -267,6 +267,16 @@
                     copier(src_library, dest_library)
                     if not os.path.islink(dest_library):
                         os.chmod(dest_library, 0o755)
+            libsrc = os.path.join(context.python_dir, '..', 'lib')
+            if os.path.exists(libsrc):
+                # PyPy: also copy lib/*.so* for portable builds
+                libdst = os.path.join(context.env_dir, 'lib')
+                if not os.path.exists(libdst):
+                    os.mkdir(libdst)
+                for f in os.listdir(libsrc):
+                    src = os.path.join(libsrc, f)
+                    dst = os.path.join(libdst, f)
+                    copier(src, dst)
             #
         else:
             if self.symlinks:
diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py
--- a/lib_pypy/_tkinter/app.py
+++ b/lib_pypy/_tkinter/app.py
@@ -35,6 +35,16 @@
 
 
 def Tcl_AppInit(app):
+    # For portable builds, try to load a local version of the libraries
+    from os.path import join, dirname, exists
+    lib_path = join(dirname(dirname(dirname(__file__))), 'lib')
+    tcl_path = join(lib_path, 'tcl')
+    tk_path = join(lib_path, 'tk')
+    if exists(tcl_path):
+        tklib.Tcl_Eval(app.interp, 'set tcl_library 
"{0}"'.format(tcl_path).encode('utf-8'))
+    if exists(tk_path):    
+        tklib.Tcl_Eval(app.interp, 'set tk_library 
"{0}"'.format(tk_path).encode('utf-8'))
+
     if tklib.Tcl_Init(app.interp) == tklib.TCL_ERROR:
         app.raiseTclError()
     skip_tk_init = tklib.Tcl_GetVar(
diff --git a/lib_pypy/pyrepl/completing_reader.py 
b/lib_pypy/pyrepl/completing_reader.py
--- a/lib_pypy/pyrepl/completing_reader.py
+++ b/lib_pypy/pyrepl/completing_reader.py
@@ -266,7 +266,7 @@
     reader.ps1 = "c**> "
     reader.ps2 = "c/*> "
     reader.ps3 = "c|*> "
-    reader.ps4 = "c\*> "
+    reader.ps4 = r"c\*> "
     while reader.readline():
         pass
 
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -648,7 +648,7 @@
     reader.ps1 = "**> "
     reader.ps2 = "/*> "
     reader.ps3 = "|*> "
-    reader.ps4 = "\*> "
+    reader.ps4 = r"\*> "
     while reader.readline():
         pass
 
diff --git a/lib_pypy/tools/__init__.py b/lib_pypy/tools/__init__.py
new file mode 100644
diff --git a/pypy/tool/build_cffi_imports.py 
b/lib_pypy/tools/build_cffi_imports.py
rename from pypy/tool/build_cffi_imports.py
rename to lib_pypy/tools/build_cffi_imports.py
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -226,7 +226,7 @@
 command::
 
    cd pypy/goal
-   PYTHONPATH=../.. ./pypy-c ../tool/build_cffi_imports.py
+   PYTHONPATH=../.. ./pypy-c ../../lib_pypy/tools/build_cffi_imports.py
 
 .. _`out-of-line API mode`: 
http://cffi.readthedocs.org/en/latest/overview.html#real-example-api-level-out-of-line
 
diff --git a/pypy/doc/release-v7.3.0.rst b/pypy/doc/release-v7.3.0.rst
--- a/pypy/doc/release-v7.3.0.rst
+++ b/pypy/doc/release-v7.3.0.rst
@@ -18,7 +18,7 @@
 building third party packages for python, so this release changes the ABI tag
 for PyPy.
 
-Based on the great work done in `portable-pypy`_, the linux downloads we
+Based on the great work done in `portable-pypy`_, the linux x86 downloads we
 provide are now built on top of the `manylinux2010`_ CentOS6 docker image. 
 The tarballs include the needed shared objects to run on any platform that
 supports manylinux2010 wheels, which should include all supported versions of
@@ -57,6 +57,11 @@
 previous release, we have accepted contributions from 3 new contributors,
 thanks for pitching in.
 
+If you are a python library maintainer and use c-extensions, please consider
+making a cffi / cppyy version of your library that would be performant on PyPy.
+If you are stuck with using the C-API, you can use `docker images`_ with PyPy
+built in or the `multibuild system`_ to build wheels.
+
 .. _`PyPy`: index.html
 .. _`RPython`: https://rpython.readthedocs.org
 .. _`help`: project-ideas.html
@@ -64,6 +69,8 @@
 .. _`cppyy`: https://cppyy.readthedocs.io
 .. _`available as wheels`: https://github.com/antocuni/pypy-wheels
 .. _`portable-pypy`: https://github.com/squeaky-pl/portable-pypy
+.. _`docker images`: https://github.com/pypy/manylinux
+.. _`multibuild system`: https://github.com/matthew-brett/multibuild
 .. _`manylinux2010`: https://github.com/pypa/manylinux
 
 What is PyPy?
@@ -116,7 +123,7 @@
 * Fix up LICENSE file
 * Turn all ``http`` links in the documentation to ``https``
 * Update the bndled pip and setuptools (used in ``pypy -mensurepip`` to version
-  that support `manylinux2010`_ wheels
+  that support manylinux2010 wheels
 * Link the ``DEFAULT_SOABI`` to the ``PYPY_VERSION``
 * Workaround for programs calling ``sys.setrecursionlimit(huge_value)`` (`issue
   3094`_)
@@ -138,6 +145,10 @@
 * Overflow in RPython when converting ``2<<32`` into a ``Signed`` on 32-bit
   platforms rather than automatically using a ``SignedLongLong``, require an
   explicit ``r_int64()`` call instead
+* Fix multithread contention when creating an object in cffi (PyPy only)
+* Copy lib/* shared objects in portable builds when creating virtual
+  environments with virtualenv and venv
+* Potential fix in rare-case JIT optimizer (`issue 3128`_)
 
 C-API (cpyext) and c-extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -145,7 +156,7 @@
 * Add ``_PySet_Next``, ``_PySet_NextEntry``
 * Correctly swallow exceptions happening inside ``PyDict_GetItem()`` (`issue
   3098`_)
-* Respect tp_dict on PyType_Ready (`issue XXX`_)
+* Respect tp_dict on PyType_Ready
 * Allow calling ``PyType_Ready`` on a subclass with a partially built
   ``tp_base`` (issue 3117`_)
 * Rename ``tuple_new`` to ``_PyPy_tuple_new`` to follow the naming convention 
of
@@ -193,7 +204,8 @@
 
 * Add ``PyObject_GenericGetDict``, ``PyObject_GenericSetDict``, ``_Py_strhex``,
   ``_Py_strhex_bytes``, ``PyUnicodeNew``, ``_PyFinalizing``,
-  ``PySlice_Unpack``, ``PySlice_AdjustIndices``, ``PyOS_FSPath``
+  ``PySlice_Unpack``, ``PySlice_AdjustIndices``, ``PyOS_FSPath``,
+  ``PyModule_AddFunctions``
 * Implement ``pystrhex.h`` (`issue 2687`_)
 * Make ``PyUnicodeObject`` slightly more compact
 * Fix memory leak when releasing a ``PyUnicodeObject``
@@ -226,6 +238,7 @@
 .. _`issue 3117`: https://bitbucket.com/pypy/pypy/issues/3117
 .. _`issue 3119`: https://bitbucket.com/pypy/pypy/issues/3119
 .. _`issue 3120`: https://bitbucket.com/pypy/pypy/issues/3120
+.. _`issue 3128`: https://bitbucket.com/pypy/pypy/issues/3120
 
 .. _13312: https://bugs.python.org/issue13312
 .. _13617: https://bugs.python.org/issue13617
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
@@ -3,5 +3,16 @@
 ============================
 
 .. this is a revision shortly after release-pypy-7.3.0
-.. startrev: 994c42529580 
+.. startrev: 994c42529580
 
+.. branch: cpyext-speedup-tests
+
+Make cpyext test faster, especially on py3.6
+
+.. branch: array-and-nan
+
+Handle ``NAN`` more correctly in ``array.array`` for ``__eq__`` and ``count``
+
+.. branch: bpo-16055
+
+Fixes incorrect error text for ``int('1', base=1000)``
diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst
--- a/pypy/doc/whatsnew-pypy3-head.rst
+++ b/pypy/doc/whatsnew-pypy3-head.rst
@@ -5,3 +5,6 @@
 .. this is the revision after release-pypy3.6-v7.3.0
 .. startrev: a56889d5df88
 
+.. branch: cpyext-speedup-tests-py36
+
+Make cpyext test faster, especially on py3.6
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -91,7 +91,8 @@
     set PYPY_GC_MAX_DELTA=200MB
     pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit 
targetpypystandalone
     set PYPY_GC_MAX_DELTA=
-    PYTHONPATH=../.. ./pypy-c ../tool/build_cffi_imports.py
+    # This is done as part of translation
+    PYTHONPATH=../.. ./pypy-c ../../lib_pypy/tools/build_cffi_imports.py
 
 .. _build instructions: http://pypy.org/download.html#building-from-source
 
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -368,7 +368,8 @@
         @taskdef([compile_goal], "Create cffi bindings for modules")
         def task_build_cffi_imports(self):
             ''' Use cffi to compile cffi interfaces to modules'''
-            filename = os.path.join(pypydir, 'tool', 'build_cffi_imports.py')
+            filename = os.path.join(pypydir, '..', 'lib_pypy', 'tools',
+                                   'build_cffi_imports.py')
             if sys.platform == 'darwin':
                 argv = [filename, '--embed-dependencies']
             else:
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -565,7 +565,7 @@
         # Copy values from the fastlocals to self.w_locals
         d = self.getorcreatedebug()
         if d.w_locals is None:
-            d.w_locals = self.space.newdict()
+            d.w_locals = self.space.newdict(module=True)
         varnames = self.getcode().getvarnames()
         for i in range(min(len(varnames), self.getcode().co_nlocals)):
             name = varnames[i]
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -1209,8 +1209,6 @@
             r, pos, rettype = errorhandler(errors, public_encoding_name,
                                   errmsg, s, pos, len(s))
             result.append(r)
-            if len(s) - pos < 2:
-                break
         elif 0xD800 <= ch <= 0xDBFF:
             ch2 = (ord(s[pos+ihi]) << 8) | ord(s[pos+ilo])
             pos += 2
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
@@ -610,19 +610,14 @@
 
     def test_recvmsg_issue2649(self):
         import _socket as socket
-        listener = socket.socket(family=socket.AF_INET6, 
type=socket.SOCK_DGRAM)
+        listener = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
         listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        listener.bind(('::1', 1234))
+        listener.bind(('127.0.0.1', 1234))
 
-        s = socket.socket(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
-        IPV6_RECVERR = 25
-        s.setsockopt(socket.IPPROTO_IPV6, IPV6_RECVERR, 1)
-
-        s.sendto(b'x', ('::1', 1234))
-        try:
+        s = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
+        s.sendto(b'x', ('127.0.0.1', 1234))
+        with raises(BlockingIOError):
             queue = s.recvmsg(1024, 1024, socket.MSG_ERRQUEUE)
-        except BlockingIOError as e:
-            assert True
 
     def test_buffer(self):
         # Test that send/sendall/sendto accept a buffer as arg
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
@@ -97,7 +97,7 @@
         w_elem1 = arr1.w_getitem(space, i, integer_instead_of_char=True)
         w_elem2 = arr2.w_getitem(space, i, integer_instead_of_char=True)
         if comp_op == EQ:
-            res = space.eq_w(w_elem1, w_elem2)
+            res = space.is_true(space.eq(w_elem1, w_elem2))
             if not res:
                 return space.w_False
         elif comp_op == NE:
@@ -111,7 +111,7 @@
                 res = space.is_true(space.gt(w_elem1, w_elem2))
             if res:
                 return space.w_True
-            elif not space.eq_w(w_elem1, w_elem2):
+            elif not space.is_true(space.eq(w_elem1, w_elem2)):
                 return space.w_False
         else:
             if comp_op == LE:
@@ -120,7 +120,7 @@
                 res = space.is_true(space.ge(w_elem1, w_elem2))
             if not res:
                 return space.w_False
-            elif not space.eq_w(w_elem1, w_elem2):
+            elif not space.is_true(space.eq(w_elem1, w_elem2)):
                 return space.w_True
     # we have some leftovers
     if comp_op == EQ:
@@ -153,7 +153,7 @@
             tp_item=tp_item, count=count,
             arrclass=arrclass)
         w_item = arr.w_getitem(space, i)
-        if space.eq_w(w_item, w_val):
+        if space.is_true(space.eq(w_item, w_val)):
             if count:
                 cnt += 1
             else:
diff --git a/pypy/module/array/test/test_array.py 
b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -114,6 +114,18 @@
             assert a[2] == 2.5
             assert len(a) == len(values)
 
+    def test_nan(self):
+        for tc in 'fd':
+            a = self.array(tc, [float('nan')])
+            b = self.array(tc, [float('nan')])
+            assert not a == b
+            assert a != b
+            assert not a > b
+            assert not a >= b
+            assert not a < b
+            assert not a <= b
+            assert a.count(float('nan')) == 0
+
     def test_itemsize(self):
         for t in 'bB':
             assert(self.array(t).itemsize >= 1)
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -232,3 +232,14 @@
         raise oefmt(space.w_SystemError, "PyModule_GetName(): not a module")
     from pypy.module.cpyext.unicodeobject import PyUnicode_AsUTF8
     return PyUnicode_AsUTF8(space, as_pyobj(space, w_mod.w_name))
+
+@cpython_api([PyObject, lltype.Ptr(PyMethodDef)], rffi.INT_real, error=-1)
+def PyModule_AddFunctions(space, w_mod, methods):
+    if not isinstance(w_mod, Module):
+        raise oefmt(space.w_SystemError, "PyModule_AddFuntions(): not a 
module")
+    name = space.utf8_w(w_mod.w_name)
+    dict_w = {}
+    convert_method_defs(space, dict_w, methods, None, w_mod, name=name)
+    for key, w_value in dict_w.items():
+        space.setattr(w_mod, space.newtext(key), w_value)
+    return 0
diff --git a/pypy/module/cpyext/moduledef.py b/pypy/module/cpyext/moduledef.py
--- a/pypy/module/cpyext/moduledef.py
+++ b/pypy/module/cpyext/moduledef.py
@@ -5,6 +5,7 @@
 class Module(MixedModule):
     interpleveldefs = {
         'is_cpyext_function': 'interp_cpyext.is_cpyext_function',
+        'FunctionType': 'methodobject.W_PyCFunctionObject',
     }
 
     appleveldefs = {
@@ -14,15 +15,6 @@
 
     def startup(self, space):
         space.fromcache(State).startup(space)
-        method = pypy.module.cpyext.typeobject.get_new_method_def(space)
-        # the w_self argument here is a dummy, the only thing done with w_obj
-        # is call type() on it
-        w_obj = pypy.module.cpyext.methodobject.W_PyCFunctionObject(space,
-                                                           method, 
space.w_None)
-        space.appexec([w_obj], """(meth):
-            from pickle import Pickler
-            Pickler.dispatch[type(meth)] = Pickler.save_global
-        """)
 
     def register_atexit(self, function):
         if len(self.atexit_funcs) >= 32:
diff --git a/pypy/module/cpyext/test/_widechar.c 
b/pypy/module/cpyext/test/_widechar.c
--- a/pypy/module/cpyext/test/_widechar.c
+++ b/pypy/module/cpyext/test/_widechar.c
@@ -36,11 +36,7 @@
     "_widechar",
     NULL,
     -1,
-    TestMethods,
     NULL,
-    NULL,
-    NULL,
-    NULL
 };
 
 PyMODINIT_FUNC
@@ -50,5 +46,6 @@
     m = PyModule_Create(&_testcapimodule);
     if (m == NULL)
         return NULL;
+    PyModule_AddFunctions(m, TestMethods);
     return m;
 }
diff --git a/pypy/module/cpyext/test/test_cpyext.py 
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -7,7 +7,7 @@
 from pypy.interpreter.error import OperationError
 from rpython.rtyper.lltypesystem import lltype
 from pypy.module.cpyext import api
-from pypy.module.cpyext.api import cts
+from pypy.module.cpyext.api import cts, create_extension_module
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.state import State
 from rpython.tool import leakfinder
@@ -43,13 +43,25 @@
         self.space = space
         SystemCompilationInfo.__init__(self, *args, **kwargs)
 
-    def load_module(self, mod, name):
+    def load_module(self, mod, name, use_imp=False):
         space = self.space
         w_path = space.newtext(mod)
         w_name = space.newtext(name)
-        return space.appexec([w_name, w_path], '''(name, path):
-            import imp
-            return imp.load_dynamic(name, path)''')
+        if use_imp:
+            # this is VERY slow and should be used only by tests which
+            # actually needs it
+            return space.appexec([w_name, w_path], '''(name, path):
+                import imp
+                return imp.load_dynamic(name, path)''')
+        else:
+            w_spec = space.appexec([w_name, w_path], '''(modname, path):
+                class FakeSpec:
+                    name = modname
+                    origin = path
+                return FakeSpec
+            ''')
+            w_mod = create_extension_module(space, w_spec)
+            return w_mod
 
 
 def get_cpyext_info(space):
@@ -84,23 +96,6 @@
 def freeze_refcnts(self):
     rawrefcount._dont_free_any_more()
 
-def preload(space, name):
-    from pypy.module.cpyext.pyobject import make_ref
-    if '.' not in name:
-        w_obj = space.builtin.getdictvalue(space, name)
-    else:
-        module, localname = name.rsplit('.', 1)
-        code = "(): import {module}; return {module}.{localname}"
-        code = code.format(**locals())
-        w_obj = space.appexec([], code)
-    make_ref(space, w_obj)
-
-def preload_expr(space, expr):
-    from pypy.module.cpyext.pyobject import make_ref
-    code = "(): return {}".format(expr)
-    w_obj = space.appexec([], code)
-    make_ref(space, w_obj)
-
 def is_interned_string(space, w_obj):
     try:
         u = space.utf8_w(w_obj)
@@ -151,13 +146,37 @@
         Eagerly create pyobjs for various builtins so they don't look like
         leaks.
         """
-        for name in [
-                'buffer', 'mmap.mmap',
-                'types.FunctionType', 'types.CodeType',
-                'types.TracebackType', 'types.FrameType']:
-            preload(space, name)
-        for expr in ['type(str.join)']:
-            preload_expr(space, expr)
+        from pypy.module.cpyext.pyobject import make_ref
+        w_to_preload = space.appexec([], """():
+            import sys
+            import mmap
+            #
+            # copied&pasted to avoid importing the whole types.py, which is
+            # expensive on py3k
+            # <types.py>
+            def _f(): pass
+            FunctionType = type(_f)
+            CodeType = type(_f.__code__)
+            try:
+                raise TypeError
+            except TypeError:
+                tb = sys.exc_info()[2]
+                TracebackType = type(tb)
+                FrameType = type(tb.tb_frame)
+                del tb
+            # </types.py>
+            return [
+                #buffer,   ## does not exist on py3k
+                mmap.mmap,
+                FunctionType,
+                CodeType,
+                TracebackType,
+                FrameType,
+                type(str.join),
+            ]
+        """)
+        for w_obj in space.unpackiterable(w_to_preload):
+            make_ref(space, w_obj)
 
     def cleanup(self):
         self.space.getexecutioncontext().cleanup_cpyext_state()
@@ -229,7 +248,7 @@
             cls.preload_builtins(space)
         else:
             def w_import_module(self, name, init=None, body='', filename=None,
-                    include_dirs=None, PY_SSIZE_T_CLEAN=False):
+                    include_dirs=None, PY_SSIZE_T_CLEAN=False, use_imp=False):
                 from extbuild import get_sys_info_app
                 sys_info = get_sys_info_app(self.udir)
                 return sys_info.import_module(
@@ -310,13 +329,15 @@
             return space.wrap(pydname)
 
         @unwrap_spec(name='text', init='text_or_none', body='text',
-                     filename='fsencode_or_none', PY_SSIZE_T_CLEAN=bool)
+                     filename='fsencode_or_none', PY_SSIZE_T_CLEAN=bool,
+                     use_imp=bool)
         def import_module(space, name, init=None, body='',
                           filename=None, w_include_dirs=None,
-                          PY_SSIZE_T_CLEAN=False):
+                          PY_SSIZE_T_CLEAN=False, use_imp=False):
             include_dirs = _unwrap_include_dirs(space, w_include_dirs)
             w_result = self.sys_info.import_module(
-                name, init, body, filename, include_dirs, PY_SSIZE_T_CLEAN)
+                name, init, body, filename, include_dirs, PY_SSIZE_T_CLEAN,
+                use_imp)
             self.record_imported_module(name)
             return w_result
 
@@ -445,7 +466,7 @@
             NULL,           /* m_methods */
         };
         """
-        foo = self.import_module(name='foo', body=body)
+        foo = self.import_module(name='foo', body=body, use_imp=True)
         assert 'foo' in sys.modules
         del sys.modules['foo']
         import imp
diff --git a/pypy/module/cpyext/test/test_module.py 
b/pypy/module/cpyext/test/test_module.py
--- a/pypy/module/cpyext/test/test_module.py
+++ b/pypy/module/cpyext/test/test_module.py
@@ -63,14 +63,14 @@
 class AppTestMultiPhase(AppTestCpythonExtensionBase):
     def test_basic(self):
         from types import ModuleType
-        module = self.import_module(name='multiphase')
+        module = self.import_module(name='multiphase', use_imp=True)
         assert isinstance(module, ModuleType)
         assert module.__name__ == 'multiphase'
         assert module.__doc__ == "example docstring"
 
     def test_getdef(self):
         from types import ModuleType
-        module = self.import_module(name='multiphase')
+        module = self.import_module(name='multiphase', use_imp=True)
         assert module.check_getdef_same()
 
     def test_slots(self):
@@ -113,7 +113,8 @@
         init = """
         return PyModuleDef_Init(&multiphase_def);
         """
-        module = self.import_module(name='multiphase', body=body, init=init)
+        module = self.import_module(name='multiphase', body=body, init=init,
+                                    use_imp=True)
         assert module.create_spec
         assert module.create_spec is module.__spec__
         assert module.create_def_eq
@@ -133,7 +134,7 @@
         return (PyObject *) &multiphase_def;
         """
         raises(SystemError, self.import_module, name='multiphase', body=body,
-               init=init)
+               init=init, use_imp=True)
 
 class AppTestMultiPhase2(AppTestCpythonExtensionBase):
     def setup_class(cls):
@@ -143,7 +144,7 @@
     def test_multiphase2(self):
         import sys
         from importlib import machinery, util
-        module = self.import_module(name=self.name)
+        module = self.import_module(name=self.name, use_imp=True)
         finder = machinery.FileFinder(None)
         spec = util.find_spec(self.name)
         assert spec
@@ -156,7 +157,7 @@
 
     def test_functionality(self):
         import types
-        module = self.import_module(name=self.name)
+        module = self.import_module(name=self.name, use_imp=True)
         assert isinstance(module, types.ModuleType)
         ex = module.Example()
         assert ex.demo('abcd') == 'abcd'
@@ -173,7 +174,7 @@
 
     def test_reload(self):
         import importlib
-        module = self.import_module(name=self.name)
+        module = self.import_module(name=self.name, use_imp=True)
         ex_class = module.Example
         # Simulate what importlib.reload() does, without recomputing the spec
         module.__spec__.loader.exec_module(module)
@@ -182,7 +183,7 @@
     def w_load_from_name(self, name, origin=None, use_prefix=True):
         from importlib import machinery, util
         if not origin:
-            module = self.import_module(name=self.name)
+            module = self.import_module(name=self.name, use_imp=True)
             origin = module.__loader__.path
         if use_prefix:
             name = '_testmultiphase_' + name
@@ -195,7 +196,7 @@
     def test_bad_modules(self):
         # XXX: not a very good test, since most internal issues in cpyext
         # cause SystemErrors.
-        module = self.import_module(name=self.name)
+        module = self.import_module(name=self.name, use_imp=True)
         origin = module.__loader__.path
         for name in [
                 'bad_slot_large',
@@ -237,7 +238,7 @@
         assert excinfo.value.name == '_testmultiphase_' + name
 
     def test_nonascii(self):
-        module = self.import_module(name=self.name)
+        module = self.import_module(name=self.name, use_imp=True)
         origin = module.__loader__.path
         cases = [
             ('_testmultiphase_zkou\u0161ka_na\u010dten\xed', 'Czech'),
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py 
b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -82,7 +82,6 @@
         assert entry_bridge.match_by_id('call', """
             dummy_get_utf8?
             p38 = 
call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #, 
descr=<Callr . i EF=1 OS=5>)
-            p99 = getfield_gc_r(p38, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_sys_exc_operror .*>)
             p39 = getfield_gc_r(p38, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
             i40 = force_token()
             p41 = getfield_gc_r(p38, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
@@ -444,7 +443,6 @@
             dummy_get_utf8?
             guard_not_invalidated(descr=...)
             p29 = 
call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #, 
descr=<Callr . i EF=1 OS=5>)
-            p99 = getfield_gc_r(p29, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_sys_exc_operror .*>)
             p30 = getfield_gc_r(p29, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
             p31 = force_token()
             p32 = getfield_gc_r(p29, descr=<FieldP 
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_capture_locals.py 
b/pypy/module/pypyjit/test_pypy_c/test_capture_locals.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_capture_locals.py
@@ -0,0 +1,41 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestCaptureLocals(BaseTestPyPyC):
+    def test_capture_locals(self):
+        def main(n):
+            num = 42
+            i = 0
+            acc = 0
+            src = '''
+while i < n:
+    acc += num
+    i += 1
+'''
+            exec(src)
+            return acc
+
+        log = self.run(main, [500])
+        print (log.result)
+        assert log.result == 0
+        loop, = log.loops_by_filename("<string>")
+        print (loop)
+        assert loop.match("""
+            i41 = instance_ptr_eq(ConstPtr(ptr18), p16)
+            guard_false(i41, descr=...)
+            guard_not_invalidated(descr=...)
+            i43 = int_lt(i35, 500)
+            guard_true(i43, descr=...)
+            i45 = getfield_gc_i(ConstPtr(ptr44), descr=...)
+            i47 = int_add_ovf(i45, 42)
+            guard_no_overflow(descr=...)
+            setfield_gc(ConstPtr(ptr48), i47, descr=...)
+            i50 = getfield_gc_i(ConstPtr(ptr49), descr=...)
+            i52 = int_add_ovf(i50, 1)
+            guard_no_overflow(descr=...)
+            i54 = getfield_raw_i(..., descr=...)
+            setfield_gc(ConstPtr(ptr55), i52, descr=...)
+            i57 = int_lt(i54, 0)
+            guard_false(i57, descr=...)
+            jump(..., descr=...)
+        """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py 
b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -428,7 +428,6 @@
         p156 = getfield_gc_r(p48, descr=...)
         i158 = getfield_raw_i(..., descr=...)
         setfield_gc(p48, p49, descr=...)
-        setfield_gc(p48, p50, descr=...)
         setfield_gc(p134, ConstPtr(null), descr=...)
         i159 = int_lt(i158, 0)
         guard_false(i159, descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py 
b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 import sys
+import pytest
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 
 # XXX review the <Call> descrs to replace some EF=5 with EF=4 (elidable)
@@ -66,26 +67,20 @@
             i97 = int_ge(i94, i53)
             guard_false(i97, descr=...)
             i98 = strgetitem(p52, i94)
-            p1 = force_token()
             p103 = newstr(1)
             strsetitem(p103, 0, i98)
-            setfield_gc(p0, p1, descr=<FieldP 
pypy.interpreter.pyframe.PyFrame.vable_token .>)
-            p296 = call_may_force_r(ConstClass(str_decode_utf8), p103, 
ConstPtr(null), 1, _, 0, descr=<Callr . rriii EF=7>)
-            guard_not_forced(descr=...)
+            i95 = call_i(ConstClass(_check_utf8), p103, 0, 0, -1, descr=<Calli 
8 riii EF=4>)
             guard_no_exception(descr=...)
-            p116 = getfield_gc_r(p296, descr=<FieldP tuple3.item0 .+ pure>)
-            i107 = getfield_gc_i(p296, descr=<FieldS tuple3.item1 .+ pure>)
-            i109 = int_lt(i107, 0)
-            guard_false(i109, descr=...)
-            guard_not_invalidated(descr=...)
+            i98 = int_ge(i95, 0)
+            guard_true(i98, descr=...)
             i99 = int_ge(i94, i46)
             guard_false(i99, descr=...)
             i115 = int_add(i94, 1)
             i116 = int_gt(i115, i71)
             guard_false(i116, descr=...)
-            i120 = strgetitem(p45, i94)
-            i122 = 
call_i(ConstClass(_ll_2_str_eq_checknull_char__rpy_stringPtr_Char), p116, i120, 
descr=<Calli . ri EF=0 OS=30>)
-            guard_true(i122, descr=...)
+
+            i104 = 
call_i(ConstClass(_ll_4_str_eq_slice_char__rpy_stringPtr_Signed_Signed_Char), 
p65, i94, 1, i98, descr=<Calli 8 riii EF=0 OS=27>)
+            guard_true(i104, descr=...)
             i124 = int_add(i83, 1)
             --TICK--
             jump(..., descr=...)
@@ -207,6 +202,7 @@
             ''')
         assert loop.match_by_id('calltwo', '')    # nothing
 
+    @pytest.mark.xfail
     def test_move_method_call_out_of_loop(self):
         # XXX this does not work: _lower_unicode() is found to be elidable,
         # but it can raise (because of 'raise StopIteration' in
@@ -273,7 +269,6 @@
         --TICK--
         jump(..., descr=...)
         """)
-        # XXX remove the guard_nonnull above?
 
     def test_unicode_indexing_makes_no_bridges(self):
         log = self.run(r"""
diff --git a/pypy/objspace/std/stringmethods.py 
b/pypy/objspace/std/stringmethods.py
--- a/pypy/objspace/std/stringmethods.py
+++ b/pypy/objspace/std/stringmethods.py
@@ -482,7 +482,7 @@
     def _lower_in_str(self, value, i):
         # overridden in unicodeobject.py
         return self._lower(value[i])
-        
+
     # This is not used for W_UnicodeObject.
     def descr_partition(self, space, w_sub):
         from pypy.objspace.std.bytearrayobject import W_BytearrayObject
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
@@ -813,6 +813,10 @@
         assert b'hello'.decode('ascii') == 'hello'
         raises(UnicodeDecodeError, b'he\x97lo'.decode, 'ascii')
 
+    def test_decode_surrogatepass_issue_3132(self):
+        with raises(UnicodeDecodeError):
+            b"\xd8=a".decode("utf-16-be", "surrogatepass")
+
     def test_encode(self):
         assert 'hello'.encode() == b'hello'
         assert type('hello'.encode()) is bytes
diff --git a/pypy/test_all.py b/pypy/test_all.py
--- a/pypy/test_all.py
+++ b/pypy/test_all.py
@@ -25,10 +25,6 @@
         print >> sys.stderr, __doc__
         sys.exit(2)
     toplevel = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-    # Always remove the cached files
-    # Before translation this is done via "py.path.local(CACHE_DIR).remove()"
-    print 'removing %s/rpython/_cache' % toplevel
-    shutil.rmtree('%s/rpython/_cache' % toplevel, ignore_errors=True)
     # Add toplevel repository dir to sys.path
     sys.path.insert(0, toplevel)
     import pytest
diff --git a/pypy/tool/cpyext/extbuild.py b/pypy/tool/cpyext/extbuild.py
--- a/pypy/tool/cpyext/extbuild.py
+++ b/pypy/tool/cpyext/extbuild.py
@@ -57,7 +57,7 @@
         return str(pydname)
 
     def import_module(self, name, init=None, body='', filename=None,
-            include_dirs=None, PY_SSIZE_T_CLEAN=False):
+                      include_dirs=None, PY_SSIZE_T_CLEAN=False, 
use_imp=False):
         """
         init specifies the overall template of the module.
 
@@ -81,7 +81,7 @@
             kwds = dict(source_files=[filename])
         mod = self.compile_extension_module(
             name, include_dirs=include_dirs, **kwds)
-        return self.load_module(mod, name)
+        return self.load_module(mod, name, use_imp)
 
     def import_extension(self, modname, functions, prologue="",
             include_dirs=None, more_init="", PY_SSIZE_T_CLEAN=False):
@@ -99,7 +99,8 @@
 
 class ExtensionCompiler(SystemCompilationInfo):
     """Extension compiler for appdirect mode"""
-    def load_module(space, mod, name):
+    def load_module(space, mod, name, use_imp=False):
+        # use_imp is ignored, it is useful only for non-appdirect mode
         import imp
         return imp.load_dynamic(name, mod)
 
diff --git a/pypy/tool/release/make_portable.py 
b/pypy/tool/release/make_portable.py
--- a/pypy/tool/release/make_portable.py
+++ b/pypy/tool/release/make_portable.py
@@ -1,11 +1,11 @@
 #!/usr/bin/env python
 
-bundle = ['sqlite3', 'ssl', 'crypto', 'ffi', 'expat', 'tcl', 'tk', 'gdbm',
+bundle = ['sqlite3', 'ssl', 'crypto', 'ffi', 'expat', 'tcl8', 'tk8', 'gdbm',
           'lzma', 'tinfo', 'tinfow', 'ncursesw', 'panelw', 'ncurses', 'panel', 
'panelw']
 
 import os
 from os.path import dirname, relpath, join, exists, basename, realpath
-from shutil import copy2
+from shutil import copy2, copytree
 import sys
 from glob import glob
 from subprocess import check_output, check_call
@@ -62,6 +62,7 @@
     rpaths = {}
 
     for binary in binaries:
+        check_call(['chmod', 'a+w', binary])
         rpath = join('$ORIGIN', relpath('lib', dirname(binary)))
         check_call(['patchelf', '--set-rpath', rpath, binary])
 
@@ -85,6 +86,9 @@
     for path, item in copied.items():
         print('Copied {0} to {1}'.format(path, item))
 
+    copytree('/usr/share/tcl8.5', 'lib/tcl')
+    copytree('/usr/share/tk8.5', 'lib/tk')
+
     binaries.extend(copied.values())
 
     rpaths = rpath_binaries(binaries)
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -29,7 +29,7 @@
 STDLIB_VER = "3"
 POSIX_EXE = 'pypy3'
 
-from pypy.tool.build_cffi_imports import (create_cffi_import_libraries,
+from lib_pypy.tools.build_cffi_imports import (create_cffi_import_libraries,
         MissingDependenciesError, cffi_build_scripts)
 
 def ignore_patterns(*patterns):
diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh
--- a/pypy/tool/release/repackage.sh
+++ b/pypy/tool/release/repackage.sh
@@ -3,7 +3,7 @@
 pmin=7  # python minor version
 maj=7
 min=3
-rev=0rc1
+rev=0
 
 case $pmaj in
     "2") exe=pypy;;
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py 
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -683,7 +683,14 @@
                 elif constvalue == 1:
                     opnum = rop.GUARD_TRUE
                 else:
-                    raise AssertionError("uh?")
+                    # Issue #3128: there might be rare cases where strange
+                    # code is produced.  That issue hits the assert from
+                    # OptUnroll.inline_short_preamble's send_extra_operation().
+                    # Better just disable this optimization than crash with
+                    # an AssertionError here.  Note also that such code might
+                    # trigger an InvalidLoop to be raised later---so we must
+                    # not crash here.
+                    return op
                 newop = self.replace_op_with(op, opnum, [op.getarg(0)], descr)
                 return newop
         return op
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -698,6 +698,15 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_guard_value_on_boolean_but_not_zero_or_one(self):
+        ops = """
+        [i]
+        i1 = int_lt(i, 3)
+        guard_value(i1, -1) [i]
+        jump(i)
+        """
+        py.test.raises(InvalidLoop, self.optimize_loop, ops, ops, ops)
+
     def test_int_is_true_of_bool(self):
         ops = """
         [i0, i1]
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -534,7 +534,7 @@
             else:
                 base = 10
         elif base < 2 or base > 36:
-            raise InvalidBaseError("%s() base must be >= 2 and <= 36" % fname)
+            raise InvalidBaseError("%s() base must be >= 2 and <= 36, or 0" % 
fname)
         self.base = base
 
         # Leading underscores are not allowed
diff --git a/rpython/translator/c/test/test_standalone.py 
b/rpython/translator/c/test/test_standalone.py
--- a/rpython/translator/c/test/test_standalone.py
+++ b/rpython/translator/c/test/test_standalone.py
@@ -1146,6 +1146,33 @@
         out = cbuilder.cmdexec('')
         assert out.strip() == 'ok'
 
+    def test_int_manipulation(self):
+        # Distilled from micronumpy.descriptor._compute_hash
+        # which, for some version of gcc8 compiler produced
+        # out1 == out2
+        from rpython.rlib.rarithmetic import intmask
+        
+        def entry_point(argv):
+            if len(argv) < 4:
+                print 'need 3 arguments, not %s' % str(argv)
+                return -1
+            flags = 0
+            x = 0x345678
+            y = 0x345678
+            s = str(argv[1])[0]
+            y = intmask((1000003 * y) ^ ord(s))
+            y = intmask((1000003 * y) ^ ord(str(argv[2])[0]))
+            y = (1000003 * y)
+            y = intmask(y ^ flags)
+            y = intmask((1000003 * y) ^ int(argv[3]))
+            print y
+            return 0
+
+        t, cbuilder = self.compile(entry_point)
+        out1 = cbuilder.cmdexec(args=['i', '>', '64'])
+        out2 = cbuilder.cmdexec(args=['f', '>', '64'])
+        assert out1 != out2
+
 
 class TestThread(object):
     gcrootfinder = 'shadowstack'
diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py
--- a/rpython/translator/driver.py
+++ b/rpython/translator/driver.py
@@ -479,11 +479,12 @@
             exename = self.c_entryp
             newexename = mkexename(self.compute_exe_name())
             shutil_copy(str(exename), str(newexename))
+            self.log.info("copied: %s to %s" % (exename, newexename,))
             if self.cbuilder.shared_library_name is not None:
                 soname = self.cbuilder.shared_library_name
                 newsoname = newexename.new(basename=soname.basename)
                 shutil_copy(str(soname), str(newsoname))
-                self.log.info("copied: %s" % (newsoname,))
+                self.log.info("copied: %s to %s" % (soname, newsoname,))
                 if sys.platform == 'win32':
                     # Copy pypyw.exe
                     newexename = mkexename(self.compute_exe_name(suffix='w'))
diff --git a/testrunner/lib_python_tests.py b/testrunner/lib_python_tests.py
--- a/testrunner/lib_python_tests.py
+++ b/testrunner/lib_python_tests.py
@@ -19,7 +19,7 @@
 popen = subprocess.Popen(
     [sys.executable, "pypy/test_all.py",
      pypyopt,
-     "--timeout=3600",
+     "--timeout=1324",   # make it easy to search for
      "-rs",
      "--duration=10",
      "--resultlog=cpython.log", "lib-python",
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to