PEP 670: rephrase conversion to regular functions (#2119)
This commit is contained in:
parent
ccb8ee3cc3
commit
9afa9ee0b6
55
pep-0670.rst
55
pep-0670.rst
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue