Author: Matti Picus <matti.pi...@gmail.com>
Branch: release-pypy3.5-5.x
Changeset: r92567:d72f9800a42b
Date: 2017-10-03 13:53 +0300
http://bitbucket.org/pypy/pypy/changeset/d72f9800a42b/

Log:    merge py3.5 into release

diff too long, truncating to 2000 out of 2653 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -60,8 +60,8 @@
   Wim Lavrijsen
   Eric van Riet Paap
   Richard Emslie
+  Remi Meier
   Alexander Schremmer
-  Remi Meier
   Dan Villiom Podlaski Christiansen
   Lukas Diekmann
   Sven Hager
@@ -102,6 +102,7 @@
   Michael Foord
   Stephan Diehl
   Stefano Rivera
+  Jean-Paul Calderone
   Stefan Schwarzer
   Tomek Meka
   Valentino Volonghi
@@ -110,14 +111,13 @@
   Bob Ippolito
   Bruno Gola
   David Malcolm
-  Jean-Paul Calderone
   Squeaky
   Edd Barrett
   Timo Paulssen
   Marius Gedminas
+  Nicolas Truessel
   Alexandre Fayolle
   Simon Burton
-  Nicolas Truessel
   Martin Matusiak
   Laurence Tratt
   Wenzhu Man
@@ -156,6 +156,7 @@
   Stefan H. Muller
   Tim Felgentreff
   Eugene Oden
+  Dodan Mihai
   Jeff Terrace
   Henry Mason
   Vasily Kuznetsov
@@ -182,11 +183,13 @@
   Rocco Moretti
   Gintautas Miliauskas
   Lucian Branescu Mihaila
+  Mariano Anaya
   anatoly techtonik
-  Dodan Mihai
   Karl Bartel
+  Stefan Beyer
   Gabriel Lavoie
   Jared Grubb
+  Alecsandru Patrascu
   Olivier Dormond
   Wouter van Heyst
   Sebastian Pawlu&#347;
@@ -194,6 +197,7 @@
   Victor Stinner
   Andrews Medina
   Aaron Iles
+  p_ziesch...@yahoo.de
   Toby Watson
   Daniel Patrick
   Stuart Williams
@@ -204,6 +208,7 @@
   Michael Cheng
   Mikael Sch&#246;nenberg
   Stanislaw Halik
+  Mihnea Saracin
   Berkin Ilbeyi
   Gasper Zejn
   Faye Zhao
@@ -214,14 +219,12 @@
   Jonathan David Riehl
   Beatrice During
   Alex Perry
-  p_ziesch...@yahoo.de
   Robert Zaremba
   Alan McIntyre
   Alexander Sedov
   Vaibhav Sood
   Reuben Cummings
   Attila Gobi
-  Alecsandru Patrascu
   Christopher Pope
   Tristan Arthur
   Christian Tismer 
@@ -243,7 +246,6 @@
   Jacek Generowicz
   Sylvain Thenault
   Jakub Stasiak
-  Stefan Beyer
   Andrew Dalke
   Alejandro J. Cura
   Vladimir Kryachko
@@ -275,6 +277,7 @@
   Christoph Gerum
   Miguel de Val Borro
   Artur Lisiecki
+  afteryu
   Toni Mattis
   Laurens Van Houtven
   Bobby Impollonia
@@ -305,6 +308,7 @@
   Anna Katrina Dominguez
   Kim Jin Su
   Amber Brown
+  Anthony Sottile
   Nate Bragg
   Ben Darnell
   Juan Francisco Cantero Hurtado
@@ -325,12 +329,14 @@
   Mike Bayer
   Rodrigo Ara&#250;jo
   Daniil Yarancev
+  Min RK
   OlivierBlanvillain
   Jonas Pfannschmidt
   Zearin
   Andrey Churin
   Dan Crosta
   reub...@gmail.com
+  Stanis&#322;aw Halik
   Julien Phalip
   Roman Podoliaka
   Eli Stevens
diff --git a/lib-python/2.7/inspect.py b/lib-python/2.7/inspect.py
--- a/lib-python/2.7/inspect.py
+++ b/lib-python/2.7/inspect.py
@@ -203,7 +203,7 @@
         f_locals        local namespace seen by this frame
         f_restricted    0 or 1 if frame is in restricted execution mode
         f_trace         tracing function for this frame, or None"""
-    return isinstance(object, types.FrameType)
+    return isinstance(object, (types.FrameType, types.FakeFrameType))
 
 def iscode(object):
     """Return true if the object is a code object.
diff --git a/lib-python/2.7/types.py b/lib-python/2.7/types.py
--- a/lib-python/2.7/types.py
+++ b/lib-python/2.7/types.py
@@ -71,6 +71,12 @@
     FrameType = type(tb.tb_frame)
     del tb
 
+# PyPy extension
+try:
+    FakeFrameType = type(next(sys._current_frames().itervalues()))
+except (AttributeError, StopIteration):
+    FakeFrameType = FrameType
+
 SliceType = slice
 EllipsisType = type(Ellipsis)
 
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.11.0
+Version: 1.11.1
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 
-__version__ = "1.11.0"
-__version_info__ = (1, 11, 0)
+__version__ = "1.11.1"
+__version_info__ = (1, 11, 1)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -247,7 +247,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.11.0"
+                               "\ncompiled with cffi version: 1.11.1"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/pyrepl/historical_reader.py 
b/lib_pypy/pyrepl/historical_reader.py
--- a/lib_pypy/pyrepl/historical_reader.py
+++ b/lib_pypy/pyrepl/historical_reader.py
@@ -17,7 +17,7 @@
 # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-from pyrepl import reader, commands
+from pyrepl import reader, commands, input
 from pyrepl.reader import Reader as R
 
 isearch_keymap = tuple(
@@ -215,7 +215,6 @@
                   isearch_forwards, isearch_backwards, operate_and_get_next]:
             self.commands[c.__name__] = c
             self.commands[c.__name__.replace('_', '-')] = c
-        from pyrepl import input
         self.isearch_trans = input.KeymapTranslator(
             isearch_keymap, invalid_cls=isearch_end,
             character_cls=isearch_add_character)
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -27,8 +27,8 @@
   Wim Lavrijsen
   Eric van Riet Paap
   Richard Emslie
+  Remi Meier
   Alexander Schremmer
-  Remi Meier
   Dan Villiom Podlaski Christiansen
   Lukas Diekmann
   Sven Hager
@@ -69,6 +69,7 @@
   Michael Foord
   Stephan Diehl
   Stefano Rivera
+  Jean-Paul Calderone
   Stefan Schwarzer
   Tomek Meka
   Valentino Volonghi
@@ -77,14 +78,13 @@
   Bob Ippolito
   Bruno Gola
   David Malcolm
-  Jean-Paul Calderone
   Squeaky
   Edd Barrett
   Timo Paulssen
   Marius Gedminas
+  Nicolas Truessel
   Alexandre Fayolle
   Simon Burton
-  Nicolas Truessel
   Martin Matusiak
   Laurence Tratt
   Wenzhu Man
@@ -123,6 +123,7 @@
   Stefan H. Muller
   Tim Felgentreff
   Eugene Oden
+  Dodan Mihai
   Jeff Terrace
   Henry Mason
   Vasily Kuznetsov
@@ -149,11 +150,13 @@
   Rocco Moretti
   Gintautas Miliauskas
   Lucian Branescu Mihaila
+  Mariano Anaya
   anatoly techtonik
-  Dodan Mihai
   Karl Bartel
+  Stefan Beyer
   Gabriel Lavoie
   Jared Grubb
+  Alecsandru Patrascu
   Olivier Dormond
   Wouter van Heyst
   Sebastian Pawlu&#347;
@@ -161,6 +164,7 @@
   Victor Stinner
   Andrews Medina
   Aaron Iles
+  p_ziesch...@yahoo.de
   Toby Watson
   Daniel Patrick
   Stuart Williams
@@ -171,6 +175,7 @@
   Michael Cheng
   Mikael Sch&#246;nenberg
   Stanislaw Halik
+  Mihnea Saracin
   Berkin Ilbeyi
   Gasper Zejn
   Faye Zhao
@@ -181,14 +186,12 @@
   Jonathan David Riehl
   Beatrice During
   Alex Perry
-  p_ziesch...@yahoo.de
   Robert Zaremba
   Alan McIntyre
   Alexander Sedov
   Vaibhav Sood
   Reuben Cummings
   Attila Gobi
-  Alecsandru Patrascu
   Christopher Pope
   Tristan Arthur
   Christian Tismer 
@@ -210,7 +213,6 @@
   Jacek Generowicz
   Sylvain Thenault
   Jakub Stasiak
-  Stefan Beyer
   Andrew Dalke
   Alejandro J. Cura
   Vladimir Kryachko
@@ -242,6 +244,7 @@
   Christoph Gerum
   Miguel de Val Borro
   Artur Lisiecki
+  afteryu
   Toni Mattis
   Laurens Van Houtven
   Bobby Impollonia
@@ -272,6 +275,7 @@
   Anna Katrina Dominguez
   Kim Jin Su
   Amber Brown
+  Anthony Sottile
   Nate Bragg
   Ben Darnell
   Juan Francisco Cantero Hurtado
@@ -292,12 +296,14 @@
   Mike Bayer
   Rodrigo Ara&#250;jo
   Daniil Yarancev
+  Min RK
   OlivierBlanvillain
   Jonas Pfannschmidt
   Zearin
   Andrey Churin
   Dan Crosta
   reub...@gmail.com
+  Stanis&#322;aw Halik
   Julien Phalip
   Roman Podoliaka
   Eli Stevens
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
@@ -436,7 +436,8 @@
 
 * the ``__builtins__`` name is always referencing the ``__builtin__`` module,
   never a dictionary as it sometimes is in CPython. Assigning to
-  ``__builtins__`` has no effect.
+  ``__builtins__`` has no effect.  (For usages of tools like
+  RestrictedPython, see `issue #2653`_.)
 
 * directly calling the internal magic methods of a few built-in types
   with invalid arguments may have a slightly different result.  For
@@ -556,4 +557,4 @@
 .. _`is ignored in PyPy`: http://bugs.python.org/issue14621
 .. _`little point`: 
http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html
 .. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/
-
+.. _`issue #2653`: https://bitbucket.org/pypy/pypy/issues/2653/
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.9.0.rst
    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.9.0.rst
    whatsnew-pypy2-5.8.0.rst
    whatsnew-pypy2-5.7.0.rst
    whatsnew-pypy2-5.6.0.rst
@@ -36,6 +37,7 @@
 .. toctree::
 
    whatsnew-pypy3-head.rst
+   whatsnew-pypy3-5.9.0.rst
    whatsnew-pypy3-5.8.0.rst
    whatsnew-pypy3-5.7.0.rst
 
diff --git a/pypy/doc/release-v5.9.0.rst b/pypy/doc/release-v5.9.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v5.9.0.rst
@@ -0,0 +1,217 @@
+=====================================
+PyPy2.7 and PyPy3.5 v5.9 dual release
+=====================================
+
+The PyPy team is proud to release both PyPy2.7 v5.9 (an interpreter supporting
+Python 2.7 syntax), and a beta-quality PyPy3.5 v5.9 (an interpreter for Python
+3.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 includes the upstream stdlib version 3.5.3.
+
+NumPy and Pandas now work on PyPy2.7 (together with Cython 0.27.1). Issues
+that appeared as excessive memory
+use were cleared up and other incompatibilities were resolved. The C-API
+compatibility layer does slow down code which crosses the python-c interface
+often, we have ideas on how it could be improved, and still recommend
+using pure python on PyPy or interfacing via CFFI_. Many other modules
+based on C-API exentions now work on PyPy as well.
+
+Cython 0.27.1 (released very recently) supports more projects with PyPy, both
+on PyPy2.7 and PyPy3.5 beta. Note version **0.27.1** is now the minimum
+version that supports this version of PyPy, due to some interactions with
+updated C-API interface code.
+
+We optimized the JSON parser for recurring string keys, which should decrease
+memory use to 50% and increase parsing speed by up to 15% for large JSON files
+with many repeating dictionary keys (which is quite common).
+
+CFFI_, which is part of the PyPy release, has been updated to 1.11.1,
+improving an already great package for interfacing with C. CFFI now supports
+complex arguments in API mode, as well as ``char16_t`` and ``char32_t`` and has
+improved support for callbacks.
+
+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 sponsored by a Mozilla grant_ continues on PyPy3.5; numerous fixes from
+CPython were ported to PyPy. Of course the bug fixes and performance 
enhancements
+mentioned above are part of both PyPy2.7 and PyPy3.5 beta.
+
+As always, this release fixed many other issues and bugs raised by the
+growing community of PyPy users. We strongly recommend updating.
+
+You can download the v5.9 releases 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.
+
+.. _vmprof: http://vmprof.readthedocs.io
+.. _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
+
+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.8 released 
June, 2017)
+======================================================================================
+
+See also issues that were resolved_
+
+Note that these are also merged into PyPy 3.5
+
+* New features and cleanups
+
+  * Add support for ``PyFrozenSet_New``, ``PyObject_HashNotImplemented``,
+    ``PyObject_Print(NULL, ...)``, ``PyObject_RichCompareBool(a, a, ...)``,
+    ``PyType_IS_GC`` (does nothing), ``PyUnicode_FromFormat``
+  * ctypes ``char_p`` and ``unichar_p`` indexing now CPython compatible
+  * ``gcdump`` now reports largest object
+  * More complete support in the ``_curses`` CFFI module
+  * Add cPickle.Unpickler.find_global (issue 1853_)
+  * Fix ``PyErr_Fetch`` + ``PyErr_NormalizeException`` with no exception set
+  * Simplify ``gc.get_referrers()`` to return the opposite of 
``gc.get_referents()``
+  * Update RevDB to version pypy2.7-v5.6.2
+  * Previously, ``instance.method`` would return always the same bound method
+    object, when gotten from the same instance (as far as ``is`` and ``id()``
+    can tell).  CPython doesn't do that.  Now PyPy, like CPython, returns a 
+    different bound method object every time.  For ``type.method``, PyPy2 still
+    returns always the same *unbound* method object; CPython does it for 
built-in
+    types but not for user-defined types
+  * Link to disable PaX protection for the JIT when needed
+  * Update build instructions and an rarely used Makefile
+  * Recreate support for using leakfinder in cpyext tests which had suffered
+    bit-rot, disable due to many false positives
+  * Add more functionality to ``sysconfig``
+  * Added ``_swappedbytes_`` support for ``ctypes.Structure``
+  * Better support the ``inspect`` module on ``frames``
+
+* Bug Fixes 
+
+  * Fix issue 2592_ - cpyext ``PyListObject.pop``, ``pop_end`` must return a 
value
+  * Implement ``PyListOjbect.getstorage_copy``
+  * Fix for ``reversed(dictproxy)`` issue 2601_
+  * Fix for duplicate names in ctypes' ``_fields__``, issue 2621_
+  * Update built-in ``pyexpat`` module on win32 to use UTF-8 version not UTF-16
+  * ``gc.get_objects`` now handles objects with finalizers more consistently
+  * Fixed memory leak in ``SSLContext.getpeercert`` returning validated
+    certificates and ``SSLContext.get_ca_certs(binary_mode=True)``
+    (_get_crl_dp) `CPython issue 29738`_
+
+* Performance improvements:
+
+  * Improve performance of ``bytearray.extend`` by rewriting portions in 
app-level
+  * Optimize list accesses with constant indexes better by retaining more
+    information about them
+  * Add a jit driver for ``array.count`` and ``array.index``
+  * Improve information retained in a bridge wrt ``array``
+  * Move some dummy CAPI functions and ``Py*_Check`` functions from RPython 
into
+    pure C macros
+  * In the fast ``zip(intlist1, intlist2)`` implementation, don't wrap and 
unwrap
+    all the ints
+  * Cache string keys that occur in JSON dicts, as they are likely to repeat
+
+* RPython improvements
+
+  * Do not preallocate a RPython list if we only know an upper bound on its 
size
+  * Issue 2590_: fix the bounds in the GC when allocating a lot of objects 
with finalizers
+  * Replace magical NOT RPYTHON comment with a decorator
+  * Implement ``socket.sendmsg()``/``.recvmsg()`` for py3.5
+  * Add ``memory_pressure`` for ``_SSLSocket`` objects
+
+* Degredations
+
+  * Disable vmprof on win32, due to upstream changes that break the internal 
``_vmprof`` module
+
+.. _here: cpython_differences.html
+.. _1853: https://bitbucket.org/pypy/pypy/issues/1853
+.. _2592: https://bitbucket.org/pypy/pypy/issues/2592
+.. _2590: https://bitbucket.org/pypy/pypy/issues/2590
+.. _2621: https://bitbucket.org/pypy/pypy/issues/2621
+
+Highlights of the PyPy3.5 release (since 5.8 beta released June 2017)
+======================================================================
+
+* New features
+
+  * Add support for ``_PyNamespace_New``, ``PyMemoryView_FromMemory``, 
+    ``Py_EnterRecursiveCall`` raising RecursionError, ``PyObject_LengthHint``,
+    ``PyUnicode_FromKindAndData``, ``PyDict_SetDefault``, ``PyGenObject``,
+    ``PyGenObject``, ``PyUnicode_Substring``, ``PyLong_FromUnicodeObject``
+  * Implement ``PyType_FromSpec`` (PEP 384) and fix issues with PEP 489 support
+  * Support the new version of ``os.stat()`` on win32
+  * Use ``stat3()`` on Posix
+  * Accept buffer objects as filenames, except for `oslistdir``
+  * Make slices of array ``memoryview`` s usable as writable buffers if 
contiguous
+  * Better handling of ``'%s'`` formatting for byte strings which might be 
utf-8 encoded
+  * Update the macros ``Py_DECREF`` and similar to use the CPython 3.5 version
+  * Ensure that ``mappingproxy`` is recognised as a mapping, not a sequence
+  * Enable PGO for CLang
+  * Rework ``cppyy`` packaging and rename the backend to ``_cppyy``
+  * Support for libressl 2.5.4
+  * Mirror CPython ``classmethod __reduce__`` which fixes pickling test
+  * Use utf-8 for ``readline`` history file
+  * Allow assigning ``'__class__'`` between ``ModuleType`` and its subclasses
+  * Add async slot functions in cpyext
+
+* Bug Fixes
+
+  * Try to make ``openssl`` CFFI bindings more general and future-proof
+  * Better support ``importlib`` by only listing built-in modules in 
``sys.builtin``
+  * Add ``memory_pressure`` to large CFFI allocations in ``_lzma``, issue 2579_
+  * Fix for ``reversed(mapping object)`` issue 2601_
+  * Fixing regression with non-started generator receiving non-``None``, should
+    always raise ``TypeError``
+  * ``itertools.islice``: use same logic as CPython, fixes 2643_
+
+* Performance improvements:
+
+  * 
+
+* The following features of Python 3.5 are not implemented yet in PyPy:
+
+  * PEP 442: Safe object finalization
+
+.. _resolved: whatsnew-pypy2-5.9.0.html
+.. _2579: https://bitbucket.org/pypy/pypy/issues/2579
+.. _2601: https://bitbucket.org/pypy/pypy/issues/2601
+.. _2643: https://bitbucket.org/pypy/pypy/issues/2643
+.. _CPython issue 29738: https://bugs.python.org/issue29738
+
+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,87 +1,15 @@
-==========================
-What's new in PyPy2.7 5.9+
-==========================
-
-.. this is a revision shortly after release-pypy2.7-v5.8.0
-.. startrev: 558bd00b3dd8
-
-In previous versions of PyPy, ``instance.method`` would return always
-the same bound method object, when gotten out of the same instance (as
-far as ``is`` and ``id()`` can tell).  CPython doesn't do that.  Now
-PyPy, like CPython, returns a different bound method object every time.
-For ``type.method``, PyPy2 still returns always the same *unbound*
-method object; CPython does it for built-in types but not for
-user-defined types.
-
-.. branch: cffi-complex
-.. branch: cffi-char16-char32
-
-The two ``cffi-*`` branches are part of the upgrade to cffi 1.11.
-
-.. branch: ctypes_char_indexing
-
-Indexing into char* behaves differently than CPython
-
-.. branch: vmprof-0.4.8
-
-Improve and fix issues with vmprof
-
-.. branch: issue-2592
-
-CPyext PyListObject.pop must return the value
-
-.. branch: cpyext-hash_notimpl
-
-If ``tp_hash`` is ``PyObject_HashNotImplemented``, set 
``obj.__dict__['__hash__']`` to None
-
-.. branch: cppyy-packaging
-
-Renaming of ``cppyy`` to ``_cppyy``.
-The former is now an external package installable with ``pip install cppyy``.
-
-.. branch: Enable_PGO_for_clang
-
-.. branch: nopax
-
-At the end of translation, run ``attr -q -s pax.flags -V m`` on
-PAX-enabled systems on the produced binary.  This seems necessary
-because PyPy uses a JIT.
-
-.. branch: pypy_bytearray
-
-Improve ``bytearray`` performance (backported from py3.5)
-
-.. branch: gc-del-limit-growth
-
-Fix the bounds in the GC when allocating a lot of objects with finalizers,
-fixes issue #2590
-
-.. branch: arrays-force-less
-
-Small improvement to optimize list accesses with constant indexes better by
-throwing away information about them less eagerly.
-
-
-.. branch: getarrayitem-into-bridges
-
-More information is retained into a bridge: knowledge about the content of
-arrays (at fixed indices) is stored in guards (and thus available at the
-beginning of bridges). Also, some better feeding of information about known
-fields of constant objects into bridges.
-
-.. branch: cpyext-leakchecking
-
-Add support for leakfinder in cpyext tests (disabled for now, due to too many
-failures).
-
-.. branch: pypy_swappedbytes
-
-Added ``_swappedbytes_`` support for ``ctypes.Structure``
-
-.. branch: pycheck-macros
-
-Convert many Py*_Check cpyext functions into macros, like CPython.
-
-.. branch: py_ssize_t
-
-Explicitly use Py_ssize_t as the Signed type in pypy c-api
+===========================
+What's new in PyPy2.7 5.10+
+===========================
+
+.. this is a revision shortly after release-pypy2.7-v5.9.0
+.. startrev:899e5245de1e
+
+.. branch: cpyext-jit
+
+Differentiate the code to call METH_NOARGS, METH_O and METH_VARARGS in cpyext:
+this allows to write specialized code which is much faster than previous
+completely generic version. Moreover, let the JIT to look inside the cpyext
+module: the net result is that cpyext calls are up to 7x faster. However, this
+is true only for very simple situations: in all real life code, we are still
+much slower than CPython (more optimizations to come)
diff --git a/pypy/doc/whatsnew-pypy2-5.9.0.rst 
b/pypy/doc/whatsnew-pypy2-5.9.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.9.0.rst
@@ -0,0 +1,87 @@
+=========================
+What's new in PyPy2.7 5.9
+=========================
+
+.. this is a revision shortly after release-pypy2.7-v5.8.0
+.. startrev: 558bd00b3dd8
+
+In previous versions of PyPy, ``instance.method`` would return always
+the same bound method object, when gotten out of the same instance (as
+far as ``is`` and ``id()`` can tell).  CPython doesn't do that.  Now
+PyPy, like CPython, returns a different bound method object every time.
+For ``type.method``, PyPy2 still returns always the same *unbound*
+method object; CPython does it for built-in types but not for
+user-defined types.
+
+.. branch: cffi-complex
+.. branch: cffi-char16-char32
+
+The two ``cffi-*`` branches are part of the upgrade to cffi 1.11.
+
+.. branch: ctypes_char_indexing
+
+Indexing into char* behaves differently than CPython
+
+.. branch: vmprof-0.4.8
+
+Improve and fix issues with vmprof
+
+.. branch: issue-2592
+
+CPyext PyListObject.pop must return the value
+
+.. branch: cpyext-hash_notimpl
+
+If ``tp_hash`` is ``PyObject_HashNotImplemented``, set 
``obj.__dict__['__hash__']`` to None
+
+.. branch: cppyy-packaging
+
+Renaming of ``cppyy`` to ``_cppyy``.
+The former is now an external package installable with ``pip install cppyy``.
+
+.. branch: Enable_PGO_for_clang
+
+.. branch: nopax
+
+At the end of translation, run ``attr -q -s pax.flags -V m`` on
+PAX-enabled systems on the produced binary.  This seems necessary
+because PyPy uses a JIT.
+
+.. branch: pypy_bytearray
+
+Improve ``bytearray`` performance (backported from py3.5)
+
+.. branch: gc-del-limit-growth
+
+Fix the bounds in the GC when allocating a lot of objects with finalizers,
+fixes issue #2590
+
+.. branch: arrays-force-less
+
+Small improvement to optimize list accesses with constant indexes better by
+throwing away information about them less eagerly.
+
+
+.. branch: getarrayitem-into-bridges
+
+More information is retained into a bridge: knowledge about the content of
+arrays (at fixed indices) is stored in guards (and thus available at the
+beginning of bridges). Also, some better feeding of information about known
+fields of constant objects into bridges.
+
+.. branch: cpyext-leakchecking
+
+Add support for leakfinder in cpyext tests (disabled for now, due to too many
+failures).
+
+.. branch: pypy_swappedbytes
+
+Added ``_swappedbytes_`` support for ``ctypes.Structure``
+
+.. branch: pycheck-macros
+
+Convert many Py*_Check cpyext functions into macros, like CPython.
+
+.. branch: py_ssize_t
+
+Explicitly use Py_ssize_t as the Signed type in pypy c-api
diff --git a/pypy/doc/whatsnew-pypy3-5.9.0.rst 
b/pypy/doc/whatsnew-pypy3-5.9.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-5.9.0.rst
@@ -0,0 +1,7 @@
+=======================
+What's new in PyPy3 5.9
+=======================
+
+.. this is the revision after release-pypy3.5-5.8
+.. startrev: afbf09453369
+
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
@@ -1,9 +1,9 @@
 =========================
-What's new in PyPy3 5.8+
+What's new in PyPy3 5.9+
 =========================
 
-.. this is the revision after release-pypy3.3-5.8.x was branched
-.. startrev: c173df164527
+.. this is the revision after release-pypy3.5-5.9
+.. startrev: be41e3ac0a29
 
 .. branch: multiphase
 
diff --git a/pypy/interpreter/test/test_app_main.py 
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -1162,9 +1162,13 @@
         import os
         old_sys_path = sys.path[:]
         sys.path.append(self.goal_dir)
+        if sys.platform == 'win32':
+            exename = 'pypy3-c.exe'
+        else:
+            exename = 'pypy3-c'
         try:
             import app_main
-            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy3-c')
+            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', exename)
             app_main.setup_bootstrap_path(pypy_c)
             newpath = sys.path[:]
             # we get at least lib_pypy
@@ -1180,9 +1184,13 @@
         import os
         old_sys_path = sys.path[:]
         sys.path.append(self.goal_dir)
+        if sys.platform == 'win32':
+            exename = 'pypy3-c.exe'
+        else:
+            exename = 'pypy3-c'
         try:
             import app_main
-            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy3-c')
+            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', exename)
             app_main.entry_point(pypy_c, [self.foo_py])
             # assert it did not crash
         finally:
diff --git a/pypy/module/__builtin__/test/test_descriptor.py 
b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -258,6 +258,17 @@
         raises(TypeError, "super(D).__get__(12)")
         raises(TypeError, "super(D).__get__(C())")
 
+    def test_super_incomplete(self):
+        """
+        class M(type):
+            def mro(cls):
+                if cls.__mro__ is None:
+                    raises(AttributeError, lambda: super(cls, cls).xxx)
+                return type.mro(cls)
+        class A(metaclass=M):
+            pass
+        """
+
     def test_classmethods_various(self):
         class C(object):
             def foo(*a): return a
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.11.0"
+VERSION = "1.11.1"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/cffi1_module.py 
b/pypy/module/_cffi_backend/cffi1_module.py
--- a/pypy/module/_cffi_backend/cffi1_module.py
+++ b/pypy/module/_cffi_backend/cffi1_module.py
@@ -1,4 +1,5 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib import jit
 
 from pypy.interpreter.error import oefmt
 from pypy.interpreter.module import Module
@@ -15,7 +16,7 @@
 
 INITFUNCPTR = lltype.Ptr(lltype.FuncType([rffi.VOIDPP], lltype.Void))
 
-
+@jit.dont_look_inside
 def load_cffi1_module(space, name, path, initptr):
     # This is called from pypy.module.cpyext.api.load_extension_module()
     from pypy.module._cffi_backend.call_python import get_ll_cffi_call_python
diff --git a/pypy/module/_cffi_backend/ctypeptr.py 
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -158,10 +158,11 @@
 
 class W_CTypePtrBase(W_CTypePtrOrArray):
     # base class for both pointers and pointers-to-functions
-    _attrs_ = ['is_void_ptr', 'is_voidchar_ptr']
-    _immutable_fields_ = ['is_void_ptr', 'is_voidchar_ptr']
+    _attrs_ = ['is_void_ptr', 'is_voidchar_ptr', 'is_onebyte_ptr']
+    _immutable_fields_ = ['is_void_ptr', 'is_voidchar_ptr', 'is_onebyte_ptr']
     is_void_ptr = False
     is_voidchar_ptr = False
+    is_onebyte_ptr = False
 
     def convert_to_object(self, cdata):
         ptrdata = rffi.cast(rffi.CCHARPP, cdata)[0]
@@ -181,12 +182,20 @@
             if self.is_void_ptr or other.is_void_ptr:
                 pass     # cast from or to 'void *'
             elif self.is_voidchar_ptr or other.is_voidchar_ptr:
-                space = self.space
-                msg = ("implicit cast from '%s' to '%s' "
-                    "will be forbidden in the future (check that the types "
-                    "are as you expect; use an explicit ffi.cast() if they "
-                    "are correct)" % (other.name, self.name))
-                space.warn(space.newtext(msg), space.w_UserWarning)
+                # for backward compatibility, accept "char *" as either
+                # source of target.  This is not what C does, though,
+                # so emit a warning that will eventually turn into an
+                # error.  The warning is turned off if both types are
+                # pointers to single bytes.
+                if self.is_onebyte_ptr and other.is_onebyte_ptr:
+                    pass   # no warning
+                else:
+                    space = self.space
+                    msg = ("implicit cast from '%s' to '%s' "
+                        "will be forbidden in the future (check that the types 
"
+                        "are as you expect; use an explicit ffi.cast() if they 
"
+                        "are correct)" % (other.name, self.name))
+                    space.warn(space.newtext(msg), space.w_UserWarning)
             else:
                 raise self._convert_error("compatible pointer", w_ob)
 
@@ -216,6 +225,7 @@
         self.is_void_ptr = isinstance(ctitem, ctypevoid.W_CTypeVoid)
         self.is_voidchar_ptr = (self.is_void_ptr or
                            isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar))
+        self.is_onebyte_ptr = (ctitem.size == 1)
         W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
 
     def newp(self, w_init, allocator):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.11.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.11.1", ("This test_c.py file is for testing a version"
                                  " of cffi that differs from the one that we"
                                  " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
@@ -2099,7 +2099,8 @@
     if sys.platform.startswith("linux"):
         BWChar = new_primitive_type("wchar_t")
         assert sizeof(BWChar) == 4
-        assert int(cast(BWChar, -1)) == -1        # signed, on linux
+        # wchar_t is often signed on Linux, but not always (e.g. on ARM)
+        assert int(cast(BWChar, -1)) in (-1, 4294967295)
 
 def test_char16():
     BChar16 = new_primitive_type("char16_t")
@@ -3903,9 +3904,11 @@
     BCharP = new_pointer_type(new_primitive_type("char"))
     BIntP = new_pointer_type(new_primitive_type("int"))
     BVoidP = new_pointer_type(new_void_type())
+    BUCharP = new_pointer_type(new_primitive_type("unsigned char"))
     z1 = cast(BCharP, 0)
     z2 = cast(BIntP, 0)
     z3 = cast(BVoidP, 0)
+    z4 = cast(BUCharP, 0)
     with warnings.catch_warnings(record=True) as w:
         newp(new_pointer_type(BIntP), z1)    # warn
         assert len(w) == 1
@@ -3919,6 +3922,12 @@
         assert len(w) == 2
         newp(new_pointer_type(BIntP), z3)    # fine
         assert len(w) == 2
+        newp(new_pointer_type(BCharP), z4)   # fine (ignore signedness here)
+        assert len(w) == 2
+        newp(new_pointer_type(BUCharP), z1)  # fine (ignore signedness here)
+        assert len(w) == 2
+        newp(new_pointer_type(BUCharP), z3)  # fine
+        assert len(w) == 2
     # check that the warnings are associated with lines in this file
     assert w[1].lineno == w[0].lineno + 4
 
diff --git a/pypy/module/_pypyjson/interp_decoder.py 
b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -1,6 +1,6 @@
 import sys
 from rpython.rlib.rstring import StringBuilder
-from rpython.rlib.objectmodel import specialize, always_inline
+from rpython.rlib.objectmodel import specialize, always_inline, r_dict
 from rpython.rlib import rfloat, runicode
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.interpreter.error import oefmt, OperationError
@@ -42,6 +42,22 @@
         ll_res.chars[i] = cast_primitive(UniChar, ch)
     return hlunicode(ll_res)
 
+def slice_eq(a, b):
+    (ll_chars1, start1, length1, _) = a
+    (ll_chars2, start2, length2, _) = b
+    if length1 != length2:
+        return False
+    j = start2
+    for i in range(start1, start1 + length1):
+        if ll_chars1[i] != ll_chars2[j]:
+            return False
+        j += 1
+    return True
+
+def slice_hash(a):
+    (ll_chars, start, length, h) = a
+    return h
+
 class DecoderError(Exception):
     def __init__(self, msg, pos):
         self.msg = msg
@@ -60,8 +76,7 @@
         self.ll_chars = rffi.str2charp(s)
         self.end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
         self.pos = 0
-        self.last_type = TYPE_UNKNOWN
-        self.memo = {}
+        self.cache = r_dict(slice_eq, slice_hash)
 
     def close(self):
         rffi.free_charp(self.ll_chars)
@@ -249,21 +264,16 @@
 
     def decode_object(self, i):
         start = i
-        w_dict = self.space.newdict()
-        #
+
         i = self.skip_whitespace(i)
         if self.ll_chars[i] == '}':
             self.pos = i+1
-            return w_dict
-        #
+            return self.space.newdict()
+
+        d = {}
         while True:
             # parse a key: value
-            self.last_type = TYPE_UNKNOWN
-            w_name = self.decode_any(i)
-            if self.last_type != TYPE_STRING:
-                raise DecoderError("Key name must be string for object 
starting at", start)
-            w_name = self.memo.setdefault(self.space.unicode_w(w_name), w_name)
-
+            name = self.decode_key(i)
             i = self.skip_whitespace(self.pos)
             ch = self.ll_chars[i]
             if ch != ':':
@@ -272,13 +282,13 @@
             i = self.skip_whitespace(i)
             #
             w_value = self.decode_any(i)
-            self.space.setitem(w_dict, w_name, w_value)
+            d[name] = w_value
             i = self.skip_whitespace(self.pos)
             ch = self.ll_chars[i]
             i += 1
             if ch == '}':
                 self.pos = i
-                return w_dict
+                return self._create_dict(d)
             elif ch == ',':
                 pass
             elif ch == '\0':
@@ -287,6 +297,9 @@
                 raise DecoderError("Unexpected '%s' when decoding object" % ch,
                                    i-1)
 
+    def _create_dict(self, d):
+        from pypy.objspace.std.dictmultiobject import from_unicode_key_dict
+        return from_unicode_key_dict(self.space, d)
 
     def decode_string(self, i):
         start = i
@@ -298,22 +311,23 @@
             i += 1
             bits |= ord(ch)
             if ch == '"':
-                if bits & 0x80:
-                    # the 8th bit is set, it's an utf8 strnig
-                    content_utf8 = self.getslice(start, i-1)
-                    content_unicode = unicodehelper.decode_utf8(self.space, 
content_utf8)
-                else:
-                    # ascii only, fast path (ascii is a strict subset of
-                    # latin1, and we already checked that all the chars are <
-                    # 128)
-                    content_unicode = strslice2unicode_latin1(self.s, start, 
i-1)
-                self.last_type = TYPE_STRING
                 self.pos = i
-                return self.space.newunicode(content_unicode)
+                return self.space.newunicode(
+                        self._create_string(start, i - 1, bits))
             elif ch == '\\' or ch < '\x20':
                 self.pos = i-1
                 return self.decode_string_escaped(start)
 
+    def _create_string(self, start, end, bits):
+        if bits & 0x80:
+            # the 8th bit is set, it's an utf8 string
+            content_utf8 = self.getslice(start, end)
+            return unicodehelper.decode_utf8(self.space, content_utf8)
+        else:
+            # ascii only, fast path (ascii is a strict subset of
+            # latin1, and we already checked that all the chars are <
+            # 128)
+            return strslice2unicode_latin1(self.s, start, end)
 
     def decode_string_escaped(self, start):
         i = self.pos
@@ -326,9 +340,7 @@
             i += 1
             if ch == '"':
                 content_utf8 = builder.build()
-                content_unicode = unicodehelper.decode_utf8(
-                    self.space, content_utf8, allow_surrogates=True)
-                self.last_type = TYPE_STRING
+                content_unicode = unicodehelper.decode_utf8(self.space, 
content_utf8, allow_surrogates=True)
                 self.pos = i
                 return self.space.newunicode(content_unicode)
             elif ch == '\\':
@@ -390,6 +402,47 @@
         lowsurr = int(hexdigits, 16) # the possible ValueError is caugth by 
the caller
         return 0x10000 + (((highsurr - 0xd800) << 10) | (lowsurr - 0xdc00))
 
+    def decode_key(self, i):
+        """ returns an unwrapped unicode """
+        from rpython.rlib.rarithmetic import intmask
+
+        i = self.skip_whitespace(i)
+        ll_chars = self.ll_chars
+        ch = ll_chars[i]
+        if ch != '"':
+            raise DecoderError("Key name must be string at char", i)
+        i += 1
+
+        start = i
+        bits = 0
+        strhash = ord(ll_chars[i]) << 7
+        while True:
+            ch = ll_chars[i]
+            i += 1
+            if ch == '"':
+                break
+            elif ch == '\\' or ch < '\x20':
+                self.pos = i-1
+                return self.space.unicode_w(self.decode_string_escaped(start))
+            strhash = intmask((1000003 * strhash) ^ ord(ll_chars[i]))
+            bits |= ord(ch)
+        length = i - start - 1
+        if length == 0:
+            strhash = -1
+        else:
+            strhash ^= length
+            strhash = intmask(strhash)
+        self.pos = i
+        # check cache first:
+        key = (ll_chars, start, length, strhash)
+        try:
+            return self.cache[key]
+        except KeyError:
+            pass
+        res = self._create_string(start, i - 1, bits)
+        self.cache[key] = res
+        return res
+
 def loads(space, w_s, w_errorcls=None):
     s = space.text_w(w_s)
     decoder = JSONDecoder(space, s)
diff --git a/pypy/module/_pypyjson/targetjson.py 
b/pypy/module/_pypyjson/targetjson.py
--- a/pypy/module/_pypyjson/targetjson.py
+++ b/pypy/module/_pypyjson/targetjson.py
@@ -5,9 +5,15 @@
 
 import time
 from pypy.interpreter.error import OperationError
-from pypy.module._pypyjson.interp_decoder import loads
+from pypy.module._pypyjson.interp_decoder import loads, JSONDecoder
 from rpython.rlib.objectmodel import specialize, dont_inline
 
+def _create_dict(self, d):
+    w_res = W_Dict()
+    w_res.dictval = d
+    return w_res
+
+JSONDecoder._create_dict = _create_dict
 
 ## MSG = open('msg.json').read()
 
@@ -65,10 +71,14 @@
     def isinstance_w(self, w_x, w_type):
         return isinstance(w_x, w_type)
 
-    def str_w(self, w_x):
+    def bytes_w(self, w_x):
         assert isinstance(w_x, W_String)
         return w_x.strval
 
+    def unicode_w(self, w_x):
+        assert isinstance(w_x, W_Unicode)
+        return w_x.unival
+
     @dont_inline
     def call_method(self, obj, name, arg):
         assert name == 'append'
@@ -83,13 +93,17 @@
         assert isinstance(key, W_Unicode)
         d.dictval[key.unival] = value
 
-    def wrapunicode(self, x):
+    def newunicode(self, x):
         return W_Unicode(x)
 
-    def wrapint(self, x):
+    def newtext(self, x):
+        return W_String(x)
+    newbytes = newtext
+
+    def newint(self, x):
         return W_Int(x)
 
-    def wrapfloat(self, x):
+    def newfloat(self, x):
         return W_Float(x)
 
     @specialize.argtype(1)
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py 
b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -10,7 +10,18 @@
     assert dec.skip_whitespace(8) == len(s)
     dec.close()
 
-
+def test_decode_key():
+    s1 = "123" * 100
+    s = ' "%s"   "%s" ' % (s1, s1)
+    dec = JSONDecoder('fake space', s)
+    assert dec.pos == 0
+    x = dec.decode_key(0)
+    assert x == s1
+    # check caching
+    y = dec.decode_key(dec.pos)
+    assert y == s1
+    assert y is x
+    dec.close()
 
 class AppTest(object):
     spaceconfig = {"usemodules": ['_pypyjson']}
@@ -189,6 +200,12 @@
         res = _pypyjson.loads(json)
         assert res == {u'a': u'\ud83d'}
 
+    def test_cache_keys(self):
+        import _pypyjson
+        json = '[{"a": 1}, {"a": 2}]'
+        res = _pypyjson.loads(json)
+        assert res == [{u'a': 1}, {u'a': 2}]
+
     def test_tab_in_string_should_fail(self):
         import _pypyjson
         # http://json.org/JSON_checker/test/fail25.json
@@ -226,7 +243,7 @@
             ('{"spam":[42}', "Unexpected '}' when decoding array", 11),
             ('["]', 'Unterminated string starting at', 1),
             ('["spam":', "Unexpected ':' when decoding array", 7),
-            ('[{]', "Unexpected ']' at", 2),
+            ('[{]', "Key name must be string at char", 2),
         ]
         for inputtext, errmsg, errpos in test_cases:
             exc = raises(ValueError, _pypyjson.loads, inputtext)
diff --git a/pypy/module/_vmprof/test/test__vmprof.py 
b/pypy/module/_vmprof/test/test__vmprof.py
--- a/pypy/module/_vmprof/test/test__vmprof.py
+++ b/pypy/module/_vmprof/test/test__vmprof.py
@@ -45,10 +45,10 @@
                     _, size = struct.unpack("ll", s[i:i + 2 * WORD])
                     count += 1
                     i += 2 * WORD + size
-                elif s[i] == '\x06':
+                elif s[i] == 6:
                     print(s[i:i+24])
                     i += 1+8+8+8
-                elif s[i] == '\x07':
+                elif s[i] == 7:
                     i += 1
                     # skip string
                     size, = struct.unpack("l", s[i:i + WORD])
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -14,6 +14,7 @@
 from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite,
         c_fdopen, c_fileno,
         c_fopen)# for tests
+from rpython.rlib import jit
 from rpython.translator import cdir
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.gensupp import NameManager
@@ -453,6 +454,11 @@
         if func.__name__ in FUNCTIONS_BY_HEADER[header]:
             raise ValueError("%s already registered" % func.__name__)
         func._always_inline_ = 'try'
+        #
+        # XXX: should we @jit.dont_look_inside all the @cpython_api functions,
+        # or we should only disable some of them?
+        func._jit_look_inside_ = False
+        #
         api_function = ApiFunction(
             argtypes, restype, func,
             error=_compute_error(error, restype), gil=gil,
@@ -562,6 +568,7 @@
     '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
 
     'PyObject_GetBuffer', 'PyBuffer_Release',
+    '_Py_setfilesystemdefaultencoding',
 
     'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 
'PyCObject_AsVoidPtr',
     'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
@@ -668,7 +675,11 @@
         'PySlice_Type': 'space.gettypeobject(W_SliceObject.typedef)',
         'PyStaticMethod_Type': 'space.gettypeobject(StaticMethod.typedef)',
         'PyCFunction_Type': 
'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
-        'PyWrapperDescr_Type': 
'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)',
+        'PyClassMethodDescr_Type': 
'space.gettypeobject(cpyext.methodobject.W_PyCClassMethodObject.typedef)',
+        'PyGetSetDescr_Type': 
'space.gettypeobject(cpyext.typeobject.W_GetSetPropertyEx.typedef)',
+        'PyMemberDescr_Type': 
'space.gettypeobject(cpyext.typeobject.W_MemberDescr.typedef)',
+        'PyMethodDescr_Type': 
'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)',
+        'PyWrapperDescr_Type': 
'space.gettypeobject(cpyext.methodobject.W_PyCWrapperObject.typedef)',
         'PyInstanceMethod_Type': 
'space.gettypeobject(cpyext.classobject.InstanceMethod.typedef)',
         }.items():
         register_global(cpyname, 'PyTypeObject*', pypyexpr, header=pypy_decl)
@@ -1058,10 +1069,16 @@
     get_capsule_type = rffi.llexternal('_%s_get_capsule_type' % prefix,
                                        [], PyTypeObjectPtr,
                                        compilation_info=eci, _nowrapper=True)
+    setdefenc = rffi.llexternal('_%s_setfilesystemdefaultencoding' % prefix,
+                                [rffi.CCHARP], lltype.Void,
+                                compilation_info=eci, _nowrapper=True)
     def init_types(space):
         from pypy.module.cpyext.typeobject import py_type_ready
+        from pypy.module.sys.interp_encoding import getfilesystemencoding
         py_type_ready(space, get_cobject_type())
         py_type_ready(space, get_capsule_type())
+        s = space.text_w(getfilesystemencoding(space))
+        setdefenc(rffi.str2charp(s, track_allocation=False))  # "leaks"
     INIT_FUNCTIONS.append(init_types)
     from pypy.module.posix.interp_posix import add_fork_hook
     global py_fatalerror
@@ -1330,6 +1347,21 @@
     decls = defaultdict(list)
     for decl in FORWARD_DECLS:
         decls[pypy_decl].append("%s;" % (decl,))
+    decls[pypy_decl].append("""
+/* hack for https://bugs.python.org/issue29943 */
+
+PyAPI_FUNC(int) %s(PyObject *arg0,
+                    Signed arg1, Signed *arg2,
+                    Signed *arg3, Signed *arg4, Signed *arg5);
+#ifdef __GNUC__
+__attribute__((__unused__))
+#endif
+static int PySlice_GetIndicesEx(PyObject *arg0, Py_ssize_t arg1,
+        Py_ssize_t *arg2, Py_ssize_t *arg3, Py_ssize_t *arg4,
+        Py_ssize_t *arg5) {
+    return %s(arg0, arg1, arg2, arg3,
+                arg4, arg5);
+}""" % ((mangle_name(prefix, 'PySlice_GetIndicesEx'),)*2))
 
     for header_name, header_functions in FUNCTIONS_BY_HEADER.iteritems():
         header = decls[header_name]
@@ -1638,6 +1670,7 @@
     state.fixup_extension(w_mod, name, path)
     return w_mod
 
+@jit.dont_look_inside
 def exec_extension_module(space, w_mod):
     from pypy.module.cpyext.modsupport import exec_def
     if not space.config.objspace.usemodules.cpyext:
diff --git a/pypy/module/cpyext/include/descrobject.h 
b/pypy/module/cpyext/include/descrobject.h
--- a/pypy/module/cpyext/include/descrobject.h
+++ b/pypy/module/cpyext/include/descrobject.h
@@ -1,34 +1,6 @@
 #ifndef Py_DESCROBJECT_H
 #define Py_DESCROBJECT_H
 
-#define PyDescr_COMMON \
-    PyObject_HEAD \
-    PyTypeObject *d_type; \
-    PyObject *d_name
-
-typedef struct {
-    PyDescr_COMMON;
-} PyDescrObject;
-
-typedef struct {
-    PyDescr_COMMON;
-    PyMethodDef *d_method;
-} PyMethodDescrObject;
-
-typedef struct {
-    PyDescr_COMMON;
-    struct PyMemberDef *d_member;
-} PyMemberDescrObject;
-
-typedef struct {
-    PyDescr_COMMON;
-    PyGetSetDef *d_getset;
-} PyGetSetDescrObject;
-
-typedef struct {
-    PyDescr_COMMON;
-    struct wrapperbase *d_base;
-    void *d_wrapped; /* This can be any function pointer */
-} PyWrapperDescrObject;
+#include "cpyext_descrobject.h"
 
 #endif
diff --git a/pypy/module/cpyext/include/fileobject.h 
b/pypy/module/cpyext/include/fileobject.h
--- a/pypy/module/cpyext/include/fileobject.h
+++ b/pypy/module/cpyext/include/fileobject.h
@@ -1,1 +1,2 @@
-#define Py_FileSystemDefaultEncoding   NULL
+PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding;
+PyAPI_FUNC(void) _Py_setfilesystemdefaultencoding(const char *);
diff --git a/pypy/module/cpyext/methodobject.py 
b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -1,4 +1,5 @@
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib import jit
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
@@ -10,8 +11,8 @@
 from pypy.module.cpyext.api import (
     CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O,
     METH_STATIC, METH_VARARGS, PyObject, bootstrap_function,
-    cpython_api, generic_cpy_call, CANNOT_FAIL,
-    PyTypeObjectPtr, slot_function, cts)
+    cpython_api, generic_cpy_call, CANNOT_FAIL, slot_function, cts,
+    build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr)
 
@@ -42,8 +43,8 @@
     from pypy.module.cpyext.object import _dealloc
     _dealloc(space, py_obj)
 
-
 class W_PyCFunctionObject(W_Root):
+    # TODO create a slightly different class depending on the c_ml_flags
     def __init__(self, space, ml, w_self, w_module=None):
         self.ml = ml
         self.name = rffi.charp2str(rffi.cast(rffi.CCHARP, self.ml.c_ml_name))
@@ -56,7 +57,7 @@
             w_self = self.w_self
         flags = rffi.cast(lltype.Signed, self.ml.c_ml_flags)
         flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST)
-        if space.is_true(w_kw) and not flags & METH_KEYWORDS:
+        if not flags & METH_KEYWORDS and space.is_true(w_kw):
             raise oefmt(space.w_TypeError,
                         "%s() takes no keyword arguments", self.name)
 
@@ -89,6 +90,20 @@
         else:
             return space.w_None
 
+class W_PyCFunctionObjectNoArgs(W_PyCFunctionObject):
+    def call(self, space, w_self, w_args, w_kw):
+        # Call the C function
+        if w_self is None:
+            w_self = self.w_self
+        func = self.ml.c_ml_meth
+        return generic_cpy_call(space, func, w_self, None)
+
+class W_PyCFunctionObjectSingleObject(W_PyCFunctionObject):
+    def call(self, space, w_self, w_o, w_kw):
+        if w_self is None:
+            w_self = self.w_self
+        func = self.ml.c_ml_meth
+        return generic_cpy_call(space, func, w_self, w_o)
 
 class W_PyCMethodObject(W_PyCFunctionObject):
     w_self = None
@@ -102,7 +117,7 @@
         return self.space.unwrap(self.descr_method_repr())
 
     def descr_method_repr(self):
-        w_objclass = self.w_objclass 
+        w_objclass = self.w_objclass
         assert isinstance(w_objclass, W_TypeObject)
         return self.space.newtext("<method '%s' of '%s' objects>" % (
             self.name, w_objclass.name))
@@ -110,7 +125,7 @@
     def descr_call(self, space, __args__):
         args_w, kw_w = __args__.unpack()
         if len(args_w) < 1:
-            w_objclass = self.w_objclass 
+            w_objclass = self.w_objclass
             assert isinstance(w_objclass, W_TypeObject)
             raise oefmt(space.w_TypeError,
                 "descriptor '%8' of '%s' object needs an argument",
@@ -118,7 +133,7 @@
         w_instance = args_w[0]
         # XXX: needs a stricter test
         if not space.isinstance_w(w_instance, self.w_objclass):
-            w_objclass = self.w_objclass 
+            w_objclass = self.w_objclass
             assert isinstance(w_objclass, W_TypeObject)
             raise oefmt(space.w_TypeError,
                 "descriptor '%8' requires a '%s' object but received a '%T'",
@@ -130,6 +145,10 @@
         ret = self.call(space, w_instance, w_args, w_kw)
         return ret
 
+# PyPy addition, for Cython
+_, _ = build_type_checkers("MethodDescr", W_PyCMethodObject)
+
+
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyCFunction_Check(space, w_obj):
     from pypy.interpreter.function import BuiltinFunction
@@ -156,6 +175,7 @@
             (self.name.decode('utf-8'), self.w_objclass.getname(self.space)))
 
 
+
 class W_PyCWrapperObject(W_Root):
     def __init__(self, space, pto, method_name, wrapper_func,
                  wrapper_func_kwds, doc, func, offset=None):
@@ -203,6 +223,7 @@
                                   (self.method_name,
                                    self.w_objclass.name))
 
+@jit.dont_look_inside
 def cwrapper_descr_call(space, w_self, __args__):
     self = space.interp_w(W_PyCWrapperObject, w_self)
     args_w, kw_w = __args__.unpack()
@@ -213,10 +234,22 @@
         space.setitem(w_kw, space.newtext(key), w_obj)
     return self.call(space, w_self, w_args, w_kw)
 
+def cfunction_descr_call_noargs(space, w_self):
+    # special case for calling with flags METH_NOARGS
+    self = space.interp_w(W_PyCFunctionObjectNoArgs, w_self)
+    return self.call(space, None, None, None)
 
+def cfunction_descr_call_single_object(space, w_self, w_o):
+    # special case for calling with flags METH_O
+    self = space.interp_w(W_PyCFunctionObjectSingleObject, w_self)
+    return self.call(space, None, w_o, None)
+
+@jit.dont_look_inside
 def cfunction_descr_call(space, w_self, __args__):
+    # specialize depending on the W_PyCFunctionObject
     self = space.interp_w(W_PyCFunctionObject, w_self)
     args_w, kw_w = __args__.unpack()
+    # XXX __args__.unpack is slow
     w_args = space.newtuple(args_w)
     w_kw = space.newdict()
     for key, w_obj in kw_w.items():
@@ -224,6 +257,7 @@
     ret = self.call(space, None, w_args, w_kw)
     return ret
 
+@jit.dont_look_inside
 def cclassmethod_descr_call(space, w_self, __args__):
     self = space.interp_w(W_PyCFunctionObject, w_self)
     args_w, kw_w = __args__.unpack()
@@ -261,6 +295,26 @@
     )
 W_PyCFunctionObject.typedef.acceptable_as_base_class = False
 
+W_PyCFunctionObjectNoArgs.typedef = TypeDef(
+    'builtin_function_or_method', W_PyCFunctionObject.typedef,
+    __call__ = interp2app(cfunction_descr_call_noargs),
+    __doc__ = GetSetProperty(W_PyCFunctionObjectNoArgs.get_doc),
+    __module__ = interp_attrproperty_w('w_module', 
cls=W_PyCFunctionObjectNoArgs),
+    __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectNoArgs,
+        wrapfn="newtext_or_none"),
+    )
+W_PyCFunctionObjectNoArgs.typedef.acceptable_as_base_class = False
+
+W_PyCFunctionObjectSingleObject.typedef = TypeDef(
+    'builtin_function_or_method', W_PyCFunctionObject.typedef,
+    __call__ = interp2app(cfunction_descr_call_single_object),
+    __doc__ = GetSetProperty(W_PyCFunctionObjectSingleObject.get_doc),
+    __module__ = interp_attrproperty_w('w_module', 
cls=W_PyCFunctionObjectSingleObject),
+    __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectSingleObject,
+        wrapfn="newtext_or_none"),
+    )
+W_PyCFunctionObjectSingleObject.typedef.acceptable_as_base_class = False
+
 W_PyCMethodObject.typedef = TypeDef(
     'method_descriptor',
     __get__ = interp2app(cmethod_descr_get),
@@ -323,11 +377,15 @@
 def PyClassMethod_New(space, w_func):
     return ClassMethod(w_func)
 
-@cpython_api([PyTypeObjectPtr, lltype.Ptr(PyMethodDef)], PyObject)
+@cts.decl("""
+    PyObject *
+    PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)""")
 def PyDescr_NewMethod(space, w_type, method):
     return W_PyCMethodObject(space, method, w_type)
 
-@cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
+@cts.decl("""
+    PyObject *
+    PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)""")
 def PyDescr_NewClassMethod(space, w_type, method):
     return W_PyCClassMethodObject(space, method, w_type)
 
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
@@ -1,13 +1,15 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
     cpython_api, METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, cts,
+    METH_NOARGS, METH_O,
     parse_dir, bootstrap_function, generic_cpy_call,
     generic_cpy_call_dont_convert_result, slot_function)
 from pypy.module.cpyext.pyobject import PyObject, as_pyobj, make_typedescr
 from pypy.interpreter.module import Module
 from pypy.module.cpyext.methodobject import (
     W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod,
-    PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New)
+    PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New,
+    W_PyCFunctionObjectNoArgs, W_PyCFunctionObjectSingleObject)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import oefmt
@@ -165,6 +167,13 @@
                                 "exception", w_mod.w_name)
         cur_slot = rffi.ptradd(cur_slot, 1)
 
+def _create_pyc_function_object(space, method, w_self, w_name, flags):
+    flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST)
+    if flags == METH_NOARGS:
+        return W_PyCFunctionObjectNoArgs(space, method, w_self, w_name)
+    if flags == METH_O:
+        return W_PyCFunctionObjectSingleObject(space, method, w_self, w_name)
+    return W_PyCFunctionObject(space, method, w_self, w_name)
 
 def convert_method_defs(space, dict_w, methods, w_type, w_self=None, 
name=None):
     w_name = space.newtext_or_none(name)
@@ -184,7 +193,8 @@
                     raise oefmt(space.w_ValueError,
                             "module functions cannot set METH_CLASS or "
                             "METH_STATIC")
-                w_obj = W_PyCFunctionObject(space, method, w_self, w_name)
+                w_obj = _create_pyc_function_object(space, method, w_self,
+                                                    w_name, flags)
             else:
                 if methodname in dict_w and not (flags & METH_COEXIST):
                     continue
diff --git a/pypy/module/cpyext/parse/cpyext_descrobject.h 
b/pypy/module/cpyext/parse/cpyext_descrobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/parse/cpyext_descrobject.h
@@ -0,0 +1,29 @@
+typedef struct {
+    PyObject_HEAD
+    PyTypeObject *d_type;
+    PyObject *d_name;
+    PyObject *d_qualname;
+} PyDescrObject;
+
+#define PyDescr_COMMON PyDescrObject d_common
+
+typedef struct {
+    PyDescr_COMMON;
+    PyMethodDef *d_method;
+} PyMethodDescrObject;
+
+typedef struct {
+    PyDescr_COMMON;
+    struct PyMemberDef *d_member;
+} PyMemberDescrObject;
+
+typedef struct {
+    PyDescr_COMMON;
+    PyGetSetDef *d_getset;
+} PyGetSetDescrObject;
+
+typedef struct {
+    PyDescr_COMMON;
+    struct wrapperbase *d_base;
+    void *d_wrapped; /* This can be any function pointer */
+} PyWrapperDescrObject;
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -14,7 +14,7 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.annlowlevel import llhelper
-from rpython.rlib import rawrefcount
+from rpython.rlib import rawrefcount, jit
 from rpython.rlib.debug import fatalerror
 
 
@@ -151,6 +151,7 @@
 class InvalidPointerException(Exception):
     pass
 
+@jit.dont_look_inside
 def create_ref(space, w_obj, w_userdata=None, immortal=False):
     """
     Allocates a PyObject, and fills its fields with info from the given
@@ -190,6 +191,7 @@
 
 w_marker_deallocating = W_Root()
 
+@jit.dont_look_inside
 def from_ref(space, ref):
     """
     Finds the interpreter object corresponding to the given reference.  If the
@@ -227,6 +229,7 @@
     assert isinstance(w_type, W_TypeObject)
     return get_typedescr(w_type.layout.typedef).realize(space, ref)
 
+@jit.dont_look_inside
 def as_pyobj(space, w_obj, w_userdata=None, immortal=False):
     """
     Returns a 'PyObject *' representing the given intepreter object.
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -420,23 +420,6 @@
 
 from rpython.rlib.nonconst import NonConstant
 
-SLOTS = {}
-
-@specialize.memo()
-def get_slot_tp_function(space, typedef, name):
-    """Return a description of the slot C function to use for the built-in
-    type for 'typedef'.  The 'name' is the slot name.  This is a memo
-    function that, after translation, returns one of a built-in finite set.
-    """
-    key = (typedef, name)
-    try:
-        return SLOTS[key]
-    except KeyError:
-        slot_func = build_slot_tp_function(space, typedef, name)
-        api_func = slot_func.api_func if slot_func else None
-        SLOTS[key] = api_func
-        return api_func
-
 def build_slot_tp_function(space, typedef, name):
     w_type = space.gettypeobject(typedef)
 
@@ -785,7 +768,7 @@
     def __init__(self, method_name, slot_name, function, wrapper1, wrapper2, 
doc):
         self.method_name = method_name
         self.slot_name = slot_name
-        self.slot_names = ("c_" + slot_name).split(".")
+        self.slot_names = tuple(("c_" + slot_name).split("."))
         self.slot_func = function
         self.wrapper_func = wrapper1
         self.wrapper_func_kwds = wrapper2
diff --git a/pypy/module/cpyext/src/missing.c b/pypy/module/cpyext/src/missing.c
--- a/pypy/module/cpyext/src/missing.c
+++ b/pypy/module/cpyext/src/missing.c
@@ -27,3 +27,7 @@
 int Py_Py3kWarningFlag = 0;
 int Py_HashRandomizationFlag = 0;
 
+const char *Py_FileSystemDefaultEncoding;  /* filled when cpyext is imported */
+void _Py_setfilesystemdefaultencoding(const char *enc) {
+    Py_FileSystemDefaultEncoding = enc;
+}
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -83,6 +83,35 @@
     return cls;
 }
 
+// for CPython
+#ifndef PyMethodDescr_Check
+int PyMethodDescr_Check(PyObject* method)
+{
+    PyObject *meth = PyObject_GetAttrString((PyObject*)&PyList_Type, "append");
+    if (!meth) return 0;
+    int res = PyObject_TypeCheck(method, meth->ob_type);
+    Py_DECREF(meth);
+    return res;
+}
+#endif
+
+PyObject* make_classmethod(PyObject* method)
+{
+    // adapted from __Pyx_Method_ClassMethod
+    if (PyMethodDescr_Check(method)) {
+        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
+        PyTypeObject *d_type = descr->d_common.d_type;
+        return PyDescr_NewClassMethod(d_type, descr->d_method);
+    }
+    else if (PyMethod_Check(method)) {
+        return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
+    }
+    else {
+        PyErr_SetString(PyExc_TypeError, "unknown method kind");
+        return NULL;
+    }
+}
+
 static PyObject *
 foo_unset(fooobject *self)
 {
@@ -95,6 +124,7 @@
     {"copy",      (PyCFunction)foo_copy,      METH_NOARGS,  NULL},
     {"create",    (PyCFunction)foo_create,    METH_NOARGS|METH_STATIC,  NULL},
     {"classmeth", (PyCFunction)foo_classmeth, METH_NOARGS|METH_CLASS,  NULL},
+    {"fake_classmeth", (PyCFunction)foo_classmeth, METH_NOARGS,  NULL},
     {"unset_string_member", (PyCFunction)foo_unset, METH_NOARGS, NULL},
     {NULL, NULL}                 /* sentinel */
 };
@@ -167,19 +197,19 @@
     /* copied from numpy scalartypes.c for inherited classes */
     if (t->tp_bases && (PyTuple_GET_SIZE(t->tp_bases) > 1))
     {
-        PyTypeObject *sup; 
-        /* We are inheriting from a Python type as well so 
+        PyTypeObject *sup;
+        /* We are inheriting from a Python type as well so
            give it first dibs on conversion */
         sup = (PyTypeObject *)PyTuple_GET_ITEM(t->tp_bases, 1);
-        /* Prevent recursion */ 
-        if (new_fooType != sup->tp_new) 
+        /* Prevent recursion */
+        if (new_fooType != sup->tp_new)
         {
             o = sup->tp_new(t, args, kwds);
             return o;
         }
     }
     o = t->tp_alloc(t, 0);
-    return o;   
+    return o;
 };
 
 static PyMemberDef foo_members[] = {
@@ -717,7 +747,7 @@
     "foo",
     "Module Doc",
     -1,
-    foo_functions, 
+    foo_functions,
     NULL,
     NULL,
     NULL,
@@ -751,6 +781,7 @@
 #endif
 {
     PyObject *d;
+    PyObject *fake_classmeth, *classmeth;
 #if PY_MAJOR_VERSION >= 3
     PyObject *module = PyModule_Create(&moduledef);
 #else
@@ -808,6 +839,12 @@
         INITERROR;
     gettype2 = PyObject_New(PyObject, &GetType2);
 
+    fake_classmeth = PyDict_GetItemString((PyObject *)fooType.tp_dict, 
"fake_classmeth");
+    classmeth = make_classmethod(fake_classmeth);
+    if (classmeth == NULL)
+        INITERROR;
+    if (PyDict_SetItemString((PyObject *)fooType.tp_dict, "fake_classmeth", 
classmeth) < 0)
+        INITERROR;
 
     d = PyModule_GetDict(module);
     if (d == NULL)
diff --git a/pypy/module/cpyext/test/test_fileobject.py 
b/pypy/module/cpyext/test/test_fileobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_fileobject.py
@@ -0,0 +1,13 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestFileObject(AppTestCpythonExtensionBase):
+    def test_defaultencoding(self):
+        import sys
+        module = self.import_extension('foo', [
+            ("defenc", "METH_NOARGS",
+             """
+                return PyUnicode_FromString(Py_FileSystemDefaultEncoding);
+             """),
+            ])
+        assert module.defenc() == sys.getfilesystemencoding()
diff --git a/pypy/module/cpyext/test/test_memoryobject.py 
b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -72,7 +72,7 @@
              """
              /* Create an approximation of the buffer for a 0d ndarray */
              Py_buffer buf;
-             PyObject *str = PyBytes_FromString("hello, world.");
+             PyObject *ret, *str = PyBytes_FromString("hello, world.");
              buf.buf = PyBytes_AsString(str);
              buf.obj = str;
              buf.readonly = 1;
@@ -80,7 +80,7 @@
              buf.itemsize = 13;
              buf.ndim = 0;
              buf.shape = NULL;
-             PyObject* ret = PyMemoryView_FromBuffer(&buf);
+             ret = PyMemoryView_FromBuffer(&buf);
              return ret;
             """)])
         result = module.create_view()
diff --git a/pypy/module/cpyext/test/test_typeobject.py 
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -135,6 +135,12 @@
             "<method 'copy' of 'foo' objects>")
         raises(TypeError, descr, None)
 
+    def test_cython_fake_classmethod(self):
+        module = self.import_module(name='foo')
+        print(module.fooType.fake_classmeth)
+        print(type(module.fooType.fake_classmeth))
+        assert module.fooType.fake_classmeth() is module.fooType
+
     def test_new(self):
         # XXX cpython segfaults but if run singly (with -k test_new) this 
passes
         module = self.import_module(name='foo')
@@ -1315,6 +1321,52 @@
         assert Asize == Bsize
         assert Asize > basesize
 
+    def test_multiple_inheritance_bug1(self):
+        module = self.import_extension('foo', [
+           ("get_type", "METH_NOARGS",
+            '''
+                Py_INCREF(&Foo_Type);
+                return (PyObject *)&Foo_Type;
+            '''
+            ), ("forty_two", "METH_O",
+            '''
+                return PyLong_FromLong(42);
+            '''
+            )], prologue='''
+            static PyTypeObject Foo_Type = {
+                PyVarObject_HEAD_INIT(NULL, 0)
+                "foo.foo",
+            };
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to