Skip to content

Commit

Permalink
PEP 670: rephrase conversion to regular functions (#2119)
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner authored Oct 20, 2021
1 parent ccb8ee3 commit 9afa9ee
Showing 1 changed file with 25 additions and 30 deletions.
55 changes: 25 additions & 30 deletions pep-0670.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
==============
Expand Down Expand Up @@ -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
Expand All @@ -99,28 +103,28 @@ 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
<https://github.com/python/cpython/commit/2aaf0c12041bcaadd7f2cc5a54450eefd7a6ff12>`__),
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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9afa9ee

Please sign in to comment.