PEP 670: rephrase conversion to regular functions (#2119)

This commit is contained in:
Victor Stinner 2021-10-20 02:10:04 +02:00 committed by GitHub
parent ccb8ee3cc3
commit 9afa9ee0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 30 deletions

View File

@ -48,6 +48,10 @@ Converting macros to functions has multiple advantages:
* Add commas to execute multiple expressions.
* Use ``do { ... } while (0)`` to write multiple statements.
Converting macros and static inline functions to regular functions makes
these regular functions accessible to projects which use Python but
cannot use macros and static inline functions.
Macro Pitfalls
==============
@ -78,8 +82,8 @@ save/restore the register value on the stack and so increase the stack
memory usage or be less efficient.
Debug mode
----------
Debug build
-----------
When Python is built in debug mode, most compiler optimizations are
disabled. For example, Visual Studio disables inlining. Benchmarks must
@ -99,7 +103,7 @@ So far, previous attempts to use ``Py_ALWAYS_INLINE`` didn't show any
benefit and were abandoned. See for example: `bpo-45094
<https://bugs.python.org/issue45094>`_: "Consider using
``__forceinline`` and ``__attribute__((always_inline))`` on static
inline functions (``Py_INCREF``, ``Py_TYPE``) for debug builds".
inline functions (``Py_INCREF``, ``Py_TYPE``) for debug build".
When the ``Py_INCREF()`` macro was converted to a static inline
functions in 2018 (`commit
@ -107,20 +111,20 @@ functions in 2018 (`commit
it was decided not to force inlining. The machine code was analyzed with
multiple C compilers and compiler options: ``Py_INCREF()`` was always
inlined without having to force inlining. The only case where it was not
inlined was debug builds, but this is acceptable for a debug build. See
discussion in the `bpo-35059 <https://bugs.python.org/issue35059>`_:
"Convert Py_INCREF() and PyObject_INIT() to inlined functions".
inlined was the debug build. See discussion in the `bpo-35059
<https://bugs.python.org/issue35059>`_: "Convert ``Py_INCREF()`` and
``PyObject_INIT()`` to inlined functions".
Prevent inlining
Disable inlining
----------------
On the other side, the ``Py_NO_INLINE`` macro can be used to prevent
inlining. It is useful to reduce the stack memory usage, it is
especially useful on LTO+PGO builds which heavily inlines code: see
`bpo-33720 <https://bugs.python.org/issue33720>`_. This macro uses
``__attribute__ ((noinline))`` with GCC and Clang, and
``__declspec(noinline)`` with MSC.
On the other side, the ``Py_NO_INLINE`` macro can be used to disable
inlining. It is useful to reduce the stack memory usage. It is
especially useful on a LTO+PGO build which is more aggressive to inline
code: see `bpo-33720 <https://bugs.python.org/issue33720>`_. The
``Py_NO_INLINE`` macro uses ``__attribute__ ((noinline))`` with GCC and
Clang, and ``__declspec(noinline)`` with MSC.
Specification
@ -145,19 +149,10 @@ The following macros should not be converted:
Convert static inline functions to regular functions
----------------------------------------------------
There are projects embedding Python or using Python which cannot use
macros and static inline functions. For example, projects using
programming languages other than C and C++. There are also projects
written in C which make the deliberate choice of only getting
``libpython`` symbols (functions and variables).
Converting static inline functions to regular functions makes these
regular functions accessible to these projects.
The performance impact of such conversion should be measured with
benchmarks. If there is a significant slowdown, there should be a good
reason to do the conversion. One reason can be hiding implementation
details.
The performance impact of converting static inline functions to regular
functions should be measured with benchmarks. If there is a significant
slowdown, there should be a good reason to do the conversion. One reason
can be hiding implementation details.
Using static inline functions in the internal C API is fine: the
internal C API exposes implemenation details by design and should not be
@ -206,8 +201,8 @@ bugs in C extensions when the C API is misused.
Backwards Compatibility
=======================
Removing the return value of macros is an incompatible change made on
purpose: see the `Remove the return value`_ section.
Removing the return value of macros is an incompatible API change made
on purpose: see the `Remove the return value`_ section.
Rejected Ideas
@ -289,8 +284,8 @@ single long line. Inside the function, the *op* argument has a well
defined type: ``PyObject*``.
Discussions
===========
References
==========
* `bpo-45490 <https://bugs.python.org/issue45490>`_:
[meta][C API] Avoid C macro pitfalls and usage of static inline