Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-1286 : Document how to add a bytecode specialization #1522

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions development-tools/clinic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2213,3 +2213,90 @@ and update your unit tests to reflect the new behaviour.
If you forget to update your input block during the alpha and beta phases,
the compiler warning will turn into a compiler error when the
release candidate phase begins.

How to add a new bytecode specialization
----------------------------------------

Bytecode specialization is a performance optimization technique in CPython.
It involves dynamically replacing general-purpose bytecode instructions with
specialized versions tailored to specific runtime contexts. This guide explains
how to add a new bytecode specialization, using ``CONTAINS_OP`` as an example.

Steps:

1. Update ``Python/bytecodes.c``

- Convert ``CONTAINS_OP`` to a micro-operation (uop) by renaming
it to ``_CONTAINS_OP`` and changing the instruction definition
from ``inst`` to ``op``.

.. code-block:: c

// Before
inst(CONTAINS_OP, ...);

// After
op(_CONTAINS_OP, ...);

- Add a uop that calls the specializing function
``_SPECIALIZE_CONTAINS_OP``.

.. code-block:: c

specializing op(_SPECIALIZE_CONTAINS_OP, (counter/1, left, right -- left, right)) {
#if ENABLE_SPECIALIZATION
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
next_instr = this_instr;
_Py_Specialize_ContainsOp(right, next_instr);
DISPATCH_SAME_OPARG();
}
STAT_INC(CONTAINS_OP, deferred);
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
#endif /* ENABLE_SPECIALIZATION */
}

- The original ``CONTAINS_OP`` is now a new macro consisting of
``_SPECIALIZE_CONTAINS_OP`` and ``_CONTAINS_OP``.

2. Define the cache structure

- In ``Include/internal/pycore_code.h``, define a cache structure with
at least a 16-bit counter.

.. code-block:: c

typedef struct {
uint16_t counter;
} _PyContainsOpCache;

3. Write the specializing function

- Implement the specializing function in ``Python/specialize.c``.
Refer to existing functions in the file for the standard format.
- Update operation stats by calling ``add_stat_dict`` in
``Python/specialize.c``.

4. Add the cache layout to ``Lib/opcode.py``

- Define the cache layout in ``Lib/opcode.py`` so that Python's ``dis``
module correctly represents the specialization.

5. Bump the magic number

- Update ``Include/internal/pycore_magic_number.h`` to bump the magic
number so the interpreter recognizes the new bytecode format.

6. Regenerate build artifacts

- Run the appropriate build regeneration commands:

- *Unix/macOS:*
``make regen-all``
- *Windows:*
``build.bat --regen``


Additional Resources:

- :pep:`659`
- `Reference PR for CONTAINS_OP <https://github.com/python/cpython/pull/116385/files>`_
Loading