diff --git a/.gitattributes b/.gitattributes index 767ec620fbabc3..e88d6ea13e2a5e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -83,8 +83,10 @@ Include/opcode.h generated Include/opcode_ids.h generated Include/token.h generated Lib/_opcode_metadata.py generated -Lib/keyword.py generated Lib/idlelib/help.html generated +Lib/keyword.py generated +Lib/pydoc_data/topics.py generated +Lib/pydoc_data/module_docs.py generated Lib/test/certdata/*.pem generated Lib/test/certdata/*.0 generated Lib/test/levenshtein_examples.json generated diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index e99e317182eaa6..1bc1bf20de0e06 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -79,26 +79,25 @@ jobs: with: python-version: '3.11' - - name: Native Windows (debug) + - name: Native Windows MSVC (release) if: runner.os == 'Windows' && matrix.architecture != 'ARM64' - shell: cmd + shell: pwsh run: | - choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0 - set PlatformToolset=clangcl - set LLVMToolsVersion=${{ matrix.llvm }}.1.0 - set LLVMInstallDir=C:\Program Files\LLVM - call ./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }} - call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + choco install visualstudio2026buildtools --no-progress -y --force --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --locale en-US --passive" + $env:PATH = "C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\MSBuild\Current\bin;$env:PATH" + $env:PlatformToolset = "v145" + ./PCbuild/build.bat --tail-call-interp -c Release -p ${{ matrix.architecture }} + ./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 # No tests (yet): - - name: Emulated Windows (release) + - name: Emulated Windows Clang (release) if: runner.os == 'Windows' && matrix.architecture == 'ARM64' - shell: cmd + shell: pwsh run: | choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0 - set PlatformToolset=clangcl - set LLVMToolsVersion=${{ matrix.llvm }}.1.0 - set LLVMInstallDir=C:\Program Files\LLVM + $env:PlatformToolset = "clangcl" + $env:LLVMToolsVersion = "${{ matrix.llvm }}.1.0" + $env:LLVMInstallDir = "C:\Program Files\LLVM" ./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }} - name: Native macOS (release) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c5767ee841eb0d..ed88e9ca81b49c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.2 + rev: v0.14.10 hooks: - id: ruff-check name: Run Ruff (lint) on Apple/ @@ -40,19 +40,19 @@ repos: files: ^Apple - id: ruff-format name: Run Ruff (format) on Doc/ - args: [--check] + args: [--exit-non-zero-on-fix] files: ^Doc/ - id: ruff-format name: Run Ruff (format) on Tools/build/check_warnings.py - args: [--check, --config=Tools/build/.ruff.toml] + args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] files: ^Tools/build/check_warnings.py - id: ruff-format name: Run Ruff (format) on Tools/wasm/ - args: [--check, --config=Tools/wasm/.ruff.toml] + args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml] files: ^Tools/wasm/ - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.9.0 + rev: 25.12.0 hooks: - id: black name: Run Black on Tools/jit/ @@ -83,24 +83,24 @@ repos: files: '^\.github/CODEOWNERS|\.(gram)$' - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.34.0 + rev: 0.36.0 hooks: - id: check-dependabot - id: check-github-workflows - id: check-readthedocs - repo: https://github.com/rhysd/actionlint - rev: v1.7.7 + rev: v1.7.9 hooks: - id: actionlint - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.14.1 + rev: v1.19.0 hooks: - id: zizmor - repo: https://github.com/sphinx-contrib/sphinx-lint - rev: v1.0.0 + rev: v1.0.2 hooks: - id: sphinx-lint args: [--enable=default-role] diff --git a/Doc/Makefile b/Doc/Makefile index f16d9cacb1b6fb..4d605980a62904 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -140,7 +140,8 @@ doctest: pydoc-topics: BUILDER = pydoc-topics pydoc-topics: build @echo "Building finished; now run this:" \ - "cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py" + "cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py" \ + "&& cp build/pydoc-topics/module_docs.py ../Lib/pydoc_data/module_docs.py" .PHONY: gettext gettext: BUILDER = gettext diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index bb94bcb86a7899..5e90d9b7bc91ed 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -107,6 +107,46 @@ header files properly declare the entry points to be ``extern "C"``. As a result there is no need to do anything special to use the API from C++. +.. _capi-system-includes: + +System includes +--------------- + + :file:`Python.h` includes several standard header files. + C extensions should include the standard headers that they use, + and should not rely on these implicit includes. + The implicit includes are: + + * ```` + * ```` (on Windows) + * ```` + * ```` + * ```` + * ```` + * ```` + * ```` (if present) + + The following are included for backwards compatibility, unless using + :ref:`Limited API ` 3.13 or newer: + + * ```` + * ```` (on POSIX) + + The following are included for backwards compatibility, unless using + :ref:`Limited API ` 3.11 or newer: + + * ```` + * ```` + * ```` + * ```` + +.. note:: + + Since Python may define some pre-processor definitions which affect the standard + headers on some systems, you *must* include :file:`Python.h` before any standard + headers are included. + + Useful macros ============= diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 22f8b1309aa38b..37c92aeb6dcb38 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -571,7 +571,7 @@ A module's token -- and the *your_token* value to use in the above code -- is: of that slot; - For modules created from an ``PyModExport_*`` :ref:`export hook `: the slots array that the export - hook returned (unless overriden with :c:macro:`Py_mod_token`). + hook returned (unless overridden with :c:macro:`Py_mod_token`). .. c:macro:: Py_mod_token diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index 3b9cf892fe913d..00266b1725c8a1 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -33,16 +33,6 @@ Pending removal in Python 3.15 * ``load_module()`` method: use ``exec_module()`` instead. -* :class:`locale`: - - * The :func:`~locale.getdefaultlocale` function - has been deprecated since Python 3.11. - Its removal was originally planned for Python 3.13 (:gh:`90817`), - but has been postponed to Python 3.15. - Use :func:`~locale.getlocale`, :func:`~locale.setlocale`, - and :func:`~locale.getencoding` instead. - (Contributed by Hugo van Kemenade in :gh:`111187`.) - * :mod:`pathlib`: * :meth:`!.PurePath.is_reserved` diff --git a/Doc/deprecations/pending-removal-in-3.20.rst b/Doc/deprecations/pending-removal-in-3.20.rst index 185f20fbc6d125..4e4b2e1d5f8fff 100644 --- a/Doc/deprecations/pending-removal-in-3.20.rst +++ b/Doc/deprecations/pending-removal-in-3.20.rst @@ -1,9 +1,9 @@ Pending removal in Python 3.20 ------------------------------ -* The ``__version__`` attribute has been deprecated in these standard library - modules and will be removed in Python 3.20. - Use :py:data:`sys.version_info` instead. +* The ``__version__``, ``version`` and ``VERSION`` attributes have been + deprecated in these standard library modules and will be removed in + Python 3.20. Use :py:data:`sys.version_info` instead. - :mod:`argparse` - :mod:`csv` @@ -24,6 +24,9 @@ Pending removal in Python 3.20 - :mod:`tkinter.font` - :mod:`tkinter.ttk` - :mod:`wsgiref.simple_server` + - :mod:`xml.etree.ElementTree` + - :mod:`!xml.sax.expatreader` + - :mod:`xml.sax.handler` - :mod:`zlib` (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index f9b65643dfe888..c0066d315d092b 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -3,154 +3,20 @@ .. _extending-intro: -****************************** -Extending Python with C or C++ -****************************** +******************************** +Using the C API: Assorted topics +******************************** -It is quite easy to add new built-in modules to Python, if you know how to -program in C. Such :dfn:`extension modules` can do two things that can't be -done directly in Python: they can implement new built-in object types, and they -can call C library functions and system calls. - -To support extensions, the Python API (Application Programmers Interface) -defines a set of functions, macros and variables that provide access to most -aspects of the Python run-time system. The Python API is incorporated in a C -source file by including the header ``"Python.h"``. - -The compilation of an extension module depends on its intended use as well as on -your system setup; details are given in later chapters. - -.. note:: - - The C extension interface is specific to CPython, and extension modules do - not work on other Python implementations. In many cases, it is possible to - avoid writing C extensions and preserve portability to other implementations. - For example, if your use case is calling C library functions or system calls, - you should consider using the :mod:`ctypes` module or the `cffi - `_ library rather than writing - custom C code. - These modules let you write Python code to interface with C code and are more - portable between implementations of Python than writing and compiling a C - extension module. - - -.. _extending-simpleexample: - -A Simple Example -================ - -Let's create an extension module called ``spam`` (the favorite food of Monty -Python fans...) and let's say we want to create a Python interface to the C -library function :c:func:`system` [#]_. This function takes a null-terminated -character string as argument and returns an integer. We want this function to -be callable from Python as follows: - -.. code-block:: pycon - - >>> import spam - >>> status = spam.system("ls -l") - -Begin by creating a file :file:`spammodule.c`. (Historically, if a module is -called ``spam``, the C file containing its implementation is called -:file:`spammodule.c`; if the module name is very long, like ``spammify``, the -module name can be just :file:`spammify.c`.) - -The first two lines of our file can be:: - - #define PY_SSIZE_T_CLEAN - #include - -which pulls in the Python API (you can add a comment describing the purpose of -the module and a copyright notice if you like). - -.. note:: - - Since Python may define some pre-processor definitions which affect the standard - headers on some systems, you *must* include :file:`Python.h` before any standard - headers are included. - - ``#define PY_SSIZE_T_CLEAN`` was used to indicate that ``Py_ssize_t`` should be - used in some APIs instead of ``int``. - It is not necessary since Python 3.13, but we keep it here for backward compatibility. - See :ref:`arg-parsing-string-and-buffers` for a description of this macro. - -All user-visible symbols defined by :file:`Python.h` have a prefix of ``Py`` or -``PY``, except those defined in standard header files. - -.. tip:: - - For backward compatibility, :file:`Python.h` includes several standard header files. - C extensions should include the standard headers that they use, - and should not rely on these implicit includes. - If using the limited C API version 3.13 or newer, the implicit includes are: - - * ```` - * ```` (on Windows) - * ```` - * ```` - * ```` - * ```` - * ```` - * ```` (if present) - - If :c:macro:`Py_LIMITED_API` is not defined, or is set to version 3.12 or older, - the headers below are also included: - - * ```` - * ```` (on POSIX) - - If :c:macro:`Py_LIMITED_API` is not defined, or is set to version 3.10 or older, - the headers below are also included: - - * ```` - * ```` - * ```` - * ```` - -The next thing we add to our module file is the C function that will be called -when the Python expression ``spam.system(string)`` is evaluated (we'll see -shortly how it ends up being called):: - - static PyObject * - spam_system(PyObject *self, PyObject *args) - { - const char *command; - int sts; - - if (!PyArg_ParseTuple(args, "s", &command)) - return NULL; - sts = system(command); - return PyLong_FromLong(sts); - } - -There is a straightforward translation from the argument list in Python (for -example, the single expression ``"ls -l"``) to the arguments passed to the C -function. The C function always has two arguments, conventionally named *self* -and *args*. - -The *self* argument points to the module object for module-level functions; -for a method it would point to the object instance. - -The *args* argument will be a pointer to a Python tuple object containing the -arguments. Each item of the tuple corresponds to an argument in the call's -argument list. The arguments are Python objects --- in order to do anything -with them in our C function we have to convert them to C values. The function -:c:func:`PyArg_ParseTuple` in the Python API checks the argument types and -converts them to C values. It uses a template string to determine the required -types of the arguments as well as the types of the C variables into which to -store the converted values. More about this later. - -:c:func:`PyArg_ParseTuple` returns true (nonzero) if all arguments have the right -type and its components have been stored in the variables whose addresses are -passed. It returns false (zero) if an invalid argument list was passed. In the -latter case it also raises an appropriate exception so the calling function can -return ``NULL`` immediately (as we saw in the example). +The :ref:`tutorial ` walked you through +creating a C API extension module, but left many areas unexplained. +This document looks at several concepts that you'll need to learn +in order to write more complex extensions. .. _extending-errors: -Intermezzo: Errors and Exceptions -================================= +Errors and Exceptions +===================== An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value @@ -321,194 +187,14 @@ call to :c:func:`PyErr_SetString` as shown below:: } -.. _backtoexample: - -Back to the Example -=================== - -Going back to our example function, you should now be able to understand this -statement:: - - if (!PyArg_ParseTuple(args, "s", &command)) - return NULL; - -It returns ``NULL`` (the error indicator for functions returning object pointers) -if an error is detected in the argument list, relying on the exception set by -:c:func:`PyArg_ParseTuple`. Otherwise the string value of the argument has been -copied to the local variable :c:data:`!command`. This is a pointer assignment and -you are not supposed to modify the string to which it points (so in Standard C, -the variable :c:data:`!command` should properly be declared as ``const char -*command``). - -The next statement is a call to the Unix function :c:func:`system`, passing it -the string we just got from :c:func:`PyArg_ParseTuple`:: - - sts = system(command); - -Our :func:`!spam.system` function must return the value of :c:data:`!sts` as a -Python object. This is done using the function :c:func:`PyLong_FromLong`. :: - - return PyLong_FromLong(sts); - -In this case, it will return an integer object. (Yes, even integers are objects -on the heap in Python!) - -If you have a C function that returns no useful argument (a function returning -:c:expr:`void`), the corresponding Python function must return ``None``. You -need this idiom to do so (which is implemented by the :c:macro:`Py_RETURN_NONE` -macro):: - - Py_INCREF(Py_None); - return Py_None; - -:c:data:`Py_None` is the C name for the special Python object ``None``. It is a -genuine Python object rather than a ``NULL`` pointer, which means "error" in most -contexts, as we have seen. - - -.. _methodtable: - -The Module's Method Table and Initialization Function -===================================================== - -I promised to show how :c:func:`!spam_system` is called from Python programs. -First, we need to list its name and address in a "method table":: - - static PyMethodDef spam_methods[] = { - ... - {"system", spam_system, METH_VARARGS, - "Execute a shell command."}, - ... - {NULL, NULL, 0, NULL} /* Sentinel */ - }; - -Note the third entry (``METH_VARARGS``). This is a flag telling the interpreter -the calling convention to be used for the C function. It should normally always -be ``METH_VARARGS`` or ``METH_VARARGS | METH_KEYWORDS``; a value of ``0`` means -that an obsolete variant of :c:func:`PyArg_ParseTuple` is used. - -When using only ``METH_VARARGS``, the function should expect the Python-level -parameters to be passed in as a tuple acceptable for parsing via -:c:func:`PyArg_ParseTuple`; more information on this function is provided below. - -The :c:macro:`METH_KEYWORDS` bit may be set in the third field if keyword -arguments should be passed to the function. In this case, the C function should -accept a third ``PyObject *`` parameter which will be a dictionary of keywords. -Use :c:func:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a -function. - -The method table must be referenced in the module definition structure:: - - static struct PyModuleDef spam_module = { - ... - .m_methods = spam_methods, - ... - }; - -This structure, in turn, must be passed to the interpreter in the module's -initialization function. The initialization function must be named -:c:func:`!PyInit_name`, where *name* is the name of the module, and should be the -only non-\ ``static`` item defined in the module file:: - - PyMODINIT_FUNC - PyInit_spam(void) - { - return PyModuleDef_Init(&spam_module); - } - -Note that :c:macro:`PyMODINIT_FUNC` declares the function as ``PyObject *`` return type, -declares any special linkage declarations required by the platform, and for C++ -declares the function as ``extern "C"``. - -:c:func:`!PyInit_spam` is called when each interpreter imports its module -:mod:`!spam` for the first time. (See below for comments about embedding Python.) -A pointer to the module definition must be returned via :c:func:`PyModuleDef_Init`, -so that the import machinery can create the module and store it in ``sys.modules``. - -When embedding Python, the :c:func:`!PyInit_spam` function is not called -automatically unless there's an entry in the :c:data:`PyImport_Inittab` table. -To add the module to the initialization table, use :c:func:`PyImport_AppendInittab`, -optionally followed by an import of the module:: - - #define PY_SSIZE_T_CLEAN - #include - - int - main(int argc, char *argv[]) - { - PyStatus status; - PyConfig config; - PyConfig_InitPythonConfig(&config); - - /* Add a built-in module, before Py_Initialize */ - if (PyImport_AppendInittab("spam", PyInit_spam) == -1) { - fprintf(stderr, "Error: could not extend in-built modules table\n"); - exit(1); - } - - /* Pass argv[0] to the Python interpreter */ - status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]); - if (PyStatus_Exception(status)) { - goto exception; - } - - /* Initialize the Python interpreter. Required. - If this step fails, it will be a fatal error. */ - status = Py_InitializeFromConfig(&config); - if (PyStatus_Exception(status)) { - goto exception; - } - PyConfig_Clear(&config); - - /* Optionally import the module; alternatively, - import can be deferred until the embedded script - imports it. */ - PyObject *pmodule = PyImport_ImportModule("spam"); - if (!pmodule) { - PyErr_Print(); - fprintf(stderr, "Error: could not import module 'spam'\n"); - } - - // ... use Python C API here ... - - return 0; - - exception: - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } - -.. note:: - - If you declare a global variable or a local static one, the module may - experience unintended side-effects on re-initialisation, for example when - removing entries from ``sys.modules`` or importing compiled modules into - multiple interpreters within a process - (or following a :c:func:`fork` without an intervening :c:func:`exec`). - If module state is not yet fully :ref:`isolated `, - authors should consider marking the module as having no support for subinterpreters - (via :c:macro:`Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED`). - -A more substantial example module is included in the Python source distribution -as :file:`Modules/xxlimited.c`. This file may be used as a template or simply -read as an example. - - .. _compilation: -Compilation and Linkage -======================= +Embedding an extension +====================== -There are two more things to do before you can use your new extension: compiling -and linking it with the Python system. If you use dynamic loading, the details -may depend on the style of dynamic loading your system uses; see the chapters -about building extension modules (chapter :ref:`building`) and additional -information that pertains only to building on Windows (chapter -:ref:`building-on-windows`) for more information about this. - -If you can't use dynamic loading, or if you want to make your module a permanent +If you want to make your module a permanent part of the Python interpreter, you will have to change the configuration setup -and rebuild the interpreter. Luckily, this is very simple on Unix: just place +and rebuild the interpreter. On Unix, place your file (:file:`spammodule.c` for example) in the :file:`Modules/` directory of an unpacked source distribution, add a line to the file :file:`Modules/Setup.local` describing your file: @@ -536,7 +222,7 @@ on the line in the configuration file as well, for instance: Calling Python Functions from C =============================== -So far we have concentrated on making C functions callable from Python. The +The tutorial concentrated on making C functions callable from Python. The reverse is also useful: calling Python functions from C. This is especially the case for libraries that support so-called "callback" functions. If a C interface makes use of callbacks, the equivalent Python often needs to provide a @@ -581,7 +267,7 @@ be part of a module definition:: } This function must be registered with the interpreter using the -:c:macro:`METH_VARARGS` flag; this is described in section :ref:`methodtable`. The +:c:macro:`METH_VARARGS` flag in :c:type:`PyMethodDef.ml_flags`. The :c:func:`PyArg_ParseTuple` function and its arguments are documented in section :ref:`parsetuple`. @@ -676,14 +362,21 @@ the above example, we use :c:func:`Py_BuildValue` to construct the dictionary. : Py_DECREF(result); +.. index:: single: PyArg_ParseTuple (C function) + .. _parsetuple: Extracting Parameters in Extension Functions ============================================ -.. index:: single: PyArg_ParseTuple (C function) +The :ref:`tutorial ` uses a ":c:data:`METH_O`" +function, which is limited to a single Python argument. +If you want more, you can use :c:data:`METH_VARARGS` instead. +With this flag, the C function will receive a :py:class:`tuple` of arguments +instead of a single object. -The :c:func:`PyArg_ParseTuple` function is declared as follows:: +For unpacking the tuple, CPython provides the :c:func:`PyArg_ParseTuple` +function, declared as follows:: int PyArg_ParseTuple(PyObject *arg, const char *format, ...); @@ -693,6 +386,19 @@ whose syntax is explained in :ref:`arg-parsing` in the Python/C API Reference Manual. The remaining arguments must be addresses of variables whose type is determined by the format string. +For example, to receive a single Python :py:class:`str` object and turn it +into a C buffer, you would use ``"s"`` as the format string:: + + const char *command; + if (!PyArg_ParseTuple(args, "s", &command)) { + return NULL; + } + +If an error is detected in the argument list, :c:func:`!PyArg_ParseTuple` +returns ``NULL`` (the error indicator for functions returning object pointers); +your function may return ``NULL``, relying on the exception set by +:c:func:`PyArg_ParseTuple`. + Note that while :c:func:`PyArg_ParseTuple` checks that the Python arguments have the required types, it cannot check the validity of the addresses of C variables passed to the call: if you make mistakes there, your code will probably crash or @@ -703,7 +409,6 @@ Note that any Python object references which are provided to the caller are Some example calls:: - #define PY_SSIZE_T_CLEAN #include :: @@ -773,6 +478,17 @@ Some example calls:: Keyword Parameters for Extension Functions ========================================== +If you also want your function to accept +:term:`keyword arguments `, use the :c:data:`METH_KEYWORDS` +flag in combination with :c:data:`METH_VARARGS`. +(:c:data:`!METH_KEYWORDS` can also be used with other flags; see its +documentation for the allowed combinations.) + +In this case, the C function should accept a third ``PyObject *`` parameter +which will be a dictionary of keywords. +Use :c:func:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a +function. + .. index:: single: PyArg_ParseTupleAndKeywords (C function) The :c:func:`PyArg_ParseTupleAndKeywords` function is declared as follows:: @@ -833,19 +549,6 @@ Philbrick (philbrick@hks.com):: {NULL, NULL, 0, NULL} /* sentinel */ }; - static struct PyModuleDef keywdarg_module = { - .m_base = PyModuleDef_HEAD_INIT, - .m_name = "keywdarg", - .m_size = 0, - .m_methods = keywdarg_methods, - }; - - PyMODINIT_FUNC - PyInit_keywdarg(void) - { - return PyModuleDef_Init(&keywdarg_module); - } - .. _buildvalue: @@ -986,11 +689,11 @@ needed. Ownership of a reference can be transferred. There are three ways to dispose of an owned reference: pass it on, store it, or call :c:func:`Py_DECREF`. Forgetting to dispose of an owned reference creates a memory leak. -It is also possible to :dfn:`borrow` [#]_ a reference to an object. The +It is also possible to :dfn:`borrow` [#borrow]_ a reference to an object. The borrower of a reference should not call :c:func:`Py_DECREF`. The borrower must not hold on to the object longer than the owner from which it was borrowed. Using a borrowed reference after the owner has disposed of it risks using freed -memory and should be avoided completely [#]_. +memory and should be avoided completely [#dont-check-refcount]_. The advantage of borrowing over owning a reference is that you don't need to take care of disposing of the reference on all possible paths through the code @@ -1169,7 +872,7 @@ checking. The C function calling mechanism guarantees that the argument list passed to C functions (``args`` in the examples) is never ``NULL`` --- in fact it guarantees -that it is always a tuple [#]_. +that it is always a tuple [#old-calling-convention]_. It is a severe error to ever let a ``NULL`` pointer "escape" to the Python user. @@ -1226,8 +929,8 @@ the module whose functions one wishes to call might not have been loaded yet! Portability therefore requires not to make any assumptions about symbol visibility. This means that all symbols in extension modules should be declared ``static``, except for the module's initialization function, in order to -avoid name clashes with other extension modules (as discussed in section -:ref:`methodtable`). And it means that symbols that *should* be accessible from +avoid name clashes with other extension modules. And it means that symbols +that *should* be accessible from other extension modules must be exported in a different way. Python provides a special mechanism to pass C-level information (pointers) from @@ -1269,8 +972,9 @@ file corresponding to the module provides a macro that takes care of importing the module and retrieving its C API pointers; client modules only have to call this macro before accessing the C API. -The exporting module is a modification of the :mod:`!spam` module from section -:ref:`extending-simpleexample`. The function :func:`!spam.system` does not call +The exporting module is a modification of the :mod:`!spam` module from the +:ref:`tutorial `. +The function :func:`!spam.system` does not call the C library function :c:func:`system` directly, but a function :c:func:`!PySpam_System`, which would of course do something more complicated in reality (such as adding "spam" to every command). This function @@ -1412,15 +1116,14 @@ code distribution). .. rubric:: Footnotes -.. [#] An interface for this function already exists in the standard module :mod:`os` - --- it was chosen as a simple and straightforward example. - -.. [#] The metaphor of "borrowing" a reference is not completely correct: the owner - still has a copy of the reference. +.. [#borrow] The metaphor of "borrowing" a reference is not completely correct: + the owner still has a copy of the reference. -.. [#] Checking that the reference count is at least 1 **does not work** --- the +.. [#dont-check-refcount] Checking that the reference count is at least 1 + **does not work** --- the reference count itself could be in freed memory and may thus be reused for another object! -.. [#] These guarantees don't hold when you use the "old" style calling convention --- +.. [#old-calling-convention] These guarantees don't hold when you use the + "old" style calling convention --- this is still found in much existing code. diff --git a/Doc/extending/first-extension-module.rst b/Doc/extending/first-extension-module.rst new file mode 100644 index 00000000000000..5bde785c49e81e --- /dev/null +++ b/Doc/extending/first-extension-module.rst @@ -0,0 +1,667 @@ +.. highlight:: c + + +.. _extending-simpleexample: +.. _first-extension-module: + +********************************* +Your first C API extension module +********************************* + +This tutorial will take you through creating a simple +Python extension module written in C or C++. + +We will use the low-level Python C API directly. +For easier ways to create extension modules, see +the :ref:`recommended third party tools `. + +The tutorial assumes basic knowledge about Python: you should be able to +define functions in Python code before starting to write them in C. +See :ref:`tutorial-index` for an introduction to Python itself. + +The tutorial should be approachable for anyone who can write a basic C library. +While we will mention several concepts that a C beginner would not be expected +to know, like ``static`` functions or linkage declarations, understanding these +is not necessary for success. + +We will focus on giving you a "feel" of what Python's C API is like. +It will not teach you important concepts, like error handling +and reference counting, which are covered in later chapters. + +We will assume that you use a Unix-like system (including macOS and +Linux), or Windows. +On other systems, you might need to adjust some details -- for example, +a system command name. + +You need to have a suitable C compiler and Python development headers installed. +On Linux, headers are often in a package like ``python3-dev`` +or ``python3-devel``. + +You need to be able to install Python packages. +This tutorial uses `pip `__ (``pip install``), but you +can substitute any tool that can build and install ``pyproject.toml``-based +projects, like `uv `_ (``uv pip install``). +Preferably, have a :ref:`virtual environment ` activated. + + +.. note:: + + This tutorial uses APIs that were added in CPython 3.15. + To create an extension that's compatible with earlier versions of CPython, + please follow an earlier version of this documentation. + + This tutorial uses C syntax added in C11 and C++20. + If your extension needs to be compatible with earlier standards, + please follow tutorials in documentation for Python 3.14 or below. + + +What we'll do +============= + +Let's create an extension module called ``spam`` [#why-spam]_, +which will include a Python interface to the C +standard library function :c:func:`system`. +This function is defined in ``stdlib.h``. +It takes a C string as argument, runs the argument as a system +command, and returns a result value as an integer. +A manual page for :c:func:`system` might summarize it this way:: + + #include + int system(const char *command); + +Note that like many functions in the C standard library, +this function is already exposed in Python. +In production, use :py:func:`os.system` or :py:func:`subprocess.run` +rather than the module you'll write here. + +We want this function to be callable from Python as follows: + +.. code-block:: pycon + + >>> import spam + >>> status = spam.system("whoami") + User Name + >>> status + 0 + +.. note:: + + The system command ``whoami`` prints out your username. + It's useful in tutorials like this one because it has the same name on + both Unix and Windows. + + +Start with the headers +====================== + +Begin by creating a directory for this tutorial, and switching to it +on the command line. +Then, create a file named :file:`spammodule.c` in your directory. +[#why-spammodule]_ + +In this file, we'll include two headers: :file:`Python.h` to pull in +all declarations of the Python C API, and :file:`stdlib.h` for the +:c:func:`system` function. [#stdlib-h]_ + +Add the following lines to :file:`spammodule.c`: + +.. literalinclude:: ../includes/capi-extension/spammodule-01.c + :start-at: + :end-at: + +Be sure to put :file:`stdlib.h`, and any other standard library includes, +*after* :file:`Python.h`. +On some systems, Python may define some pre-processor definitions +that affect the standard headers. + + +Running your build tool +======================= + +With only the includes in place, your extension won't do anything. +Still, it's a good time to compile it and try to import it. +This will ensure that your build tool works, so that you can make +and test incremental changes as you follow the rest of the text. + +CPython itself does not come with a tool to build extension modules; +it is recommended to use a third-party project for this. +In this tutorial, we'll use `meson-python`_. +(If you want to use another one, see :ref:`first-extension-other-tools`.) + +.. at the time of writing, meson-python has the least overhead for a + simple extension using PyModExport. + Change this if another tool makes things easier. + +``meson-python`` requires defining a "project" using two extra files. + +First, add ``pyproject.toml`` with these contents: + +.. code-block:: toml + + [build-system] + build-backend = 'mesonpy' + requires = ['meson-python'] + + [project] + # Placeholder project information + # (change this before distributing the module) + name = 'sampleproject' + version = '0' + +Then, create ``meson.build`` containing the following: + +.. code-block:: meson + + project('sampleproject', 'c') + + py = import('python').find_installation(pure: false) + + py.extension_module( + 'spam', # name of the importable Python module + 'spammodule.c', # the C source file + install: true, + ) + +.. note:: + + See `meson-python documentation `_ for details on + configuration. + +Now, build install the *project in the current directory* (``.``) via ``pip``: + +.. code-block:: sh + + python -m pip install . + +.. tip:: + + If you don't have ``pip`` installed, run ``python -m ensurepip``, + preferably in a :ref:`virtual environment `. + (Or, if you prefer another tool that can build and install + ``pyproject.toml``-based projects, use that.) + +.. _meson-python: https://mesonbuild.com/meson-python/ +.. _virtual environment: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments + +Note that you will need to run this command again every time you change your +extension. +Unlike Python, C has an explicit compilation step. + +When your extension is compiled and installed, start Python and try to +import it. +This should fail with the following exception: + +.. code-block:: pycon + + >>> import spam + Traceback (most recent call last): + ... + ImportError: dynamic module does not define module export function (PyModExport_spam or PyInit_spam) + + +Module export hook +================== + +The exception you got when you tried to import the module told you that Python +is looking for a "module export function", also known as a +:ref:`module export hook `. +Let's define one. + +First, add a prototype below the ``#include`` lines: + +.. literalinclude:: ../includes/capi-extension/spammodule-01.c + :start-after: /// Export hook prototype + :end-before: /// + +.. tip:: + The prototype is not strictly necessary, but some modern compilers emit + warnings without it. + It's generally better to add the prototype than to disable the warning. + +The :c:macro:`PyMODEXPORT_FUNC` macro declares the function's +return type, and adds any special linkage declarations needed +to make the function visible and usable when CPython loads it. + +After the prototype, add the function itself. +For now, make it return ``NULL``: + +.. code-block:: c + + PyMODEXPORT_FUNC + PyModExport_spam(void) + { + return NULL; + } + +Compile and load the module again. +You should get a different error this time. + +.. code-block:: pycon + + >>> import spam + Traceback (most recent call last): + ... + SystemError: module export hook for module 'spam' failed without setting an exception + +Simply returning ``NULL`` is *not* correct behavior for an export hook, +and CPython complains about it. +That's good -- it means that CPython found the function! +Let's now make it do something useful. + + +The slot table +============== + +Rather than ``NULL``, the export hook should return the information needed to +create a module. +Let's start with the basics: the name and docstring. + +The information should be defined in a ``static`` array of +:c:type:`PyModuleDef_Slot` entries, which are essentially key-value pairs. +Define this array just before your export hook: + +.. code-block:: c + + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_name, "spam"}, + {Py_mod_doc, "A wonderful module with an example function"}, + {0, NULL} + }; + +For both :c:data:`Py_mod_name` and :c:data:`Py_mod_doc`, the values are C +strings -- that is, NUL-terminated, UTF-8 encoded byte arrays. + +Note the zero-filled sentinel entry at the end. +If you forget it, you'll trigger undefined behavior. + +The array is defined as ``static`` -- that is, not visible outside this ``.c`` file. +This will be a common theme. +CPython only needs to access the export hook; all global variables +and all other functions should generally be ``static``, so that they don't +clash with other extensions. + +Return this array from your export hook instead of ``NULL``: + +.. code-block:: c + :emphasize-lines: 4 + + PyMODEXPORT_FUNC + PyModExport_spam(void) + { + return spam_slots; + } + +Now, recompile and try it out: + +.. code-block:: pycon + + >>> import spam + >>> print(spam) + + +You have an extension module! +Try ``help(spam)`` to see the docstring. + +The next step will be adding a function. + + +.. _backtoexample: + +Exposing a function +=================== + +To expose the :c:func:`system` C function directly to Python, +we'll need to write a layer of glue code to convert arguments from Python +objects to C values, and the C return value back to Python. + +One of the simplest ways to write glue code is a ":c:data:`METH_O`" function, +which takes two Python objects and returns one. +All Python objects -- regardless of the Python type -- are represented in C +as pointers to the :c:type:`PyObject` structure. + +Add such a function above the slots array:: + + static PyObject * + spam_system(PyObject *self, PyObject *arg) + { + Py_RETURN_NONE; + } + +For now, we ignore the arguments, and use the :c:macro:`Py_RETURN_NONE` +macro, which expands to a ``return`` statement that properly returns +a Python :py:data:`None` object. + +Recompile your extension to make sure you don't have syntax errors. +We haven't yet added ``spam_system`` to the module, so you might get a +warning that ``spam_system`` is unused. + +.. _methodtable: + +Method definitions +------------------ + +To expose the C function to Python, you will need to provide several pieces of +information in a structure called +:c:type:`PyMethodDef` [#why-pymethoddef]_: + +* ``ml_name``: the name of the Python function; +* ``ml_doc``: a docstring; +* ``ml_meth``: the C function to be called; and +* ``ml_flags``: a set of flags describing details like how Python arguments are + passed to the C function. + We'll use :c:data:`METH_O` here -- the flag that matches our + ``spam_system`` function's signature. + +Because modules typically create several functions, these definitions +need to be collected in an array, with a zero-filled sentinel at the end. +Add this array just below the ``spam_system`` function: + +.. literalinclude:: ../includes/capi-extension/spammodule-01.c + :start-after: /// Module method table + :end-before: /// + +As with module slots, a zero-filled sentinel marks the end of the array. + +Next, we'll add the method to the module. +Add a :c:data:`Py_mod_methods` slot to your :c:type:`PyMethodDef` array: + +.. literalinclude:: ../includes/capi-extension/spammodule-01.c + :start-after: /// Module slot table + :end-before: /// + :emphasize-lines: 5 + +Recompile your extension again, and test it. +Be sure to restart the Python interpreter, so that ``import spam`` picks +up the new version of the module. + +You should now be able to call the function: + +.. code-block:: pycon + + >>> import spam + >>> print(spam.system) + + >>> print(spam.system('whoami')) + None + +Note that our ``spam.system`` does not yet run the ``whoami`` command; +it only returns ``None``. + +Check that the function accepts exactly one argument, as specified by +the :c:data:`METH_O` flag: + +.. code-block:: pycon + + >>> print(spam.system('too', 'many', 'arguments')) + Traceback (most recent call last): + ... + TypeError: spam.system() takes exactly one argument (3 given) + + +Returning an integer +==================== + +Now, let's take a look at the return value. +Instead of ``None``, we'll want ``spam.system`` to return a number -- that is, +a Python :py:type:`int` object. +Eventually this will be the exit code of a system command, +but let's start with a fixed value, say, ``3``. + +The Python C API provides a function to create a Python :py:type:`int` object +from a C ``int`` value: :c:func:`PyLong_FromLong`. [#why-pylongfromlong]_ + +To call it, replace the ``Py_RETURN_NONE`` with the following 3 lines: + +.. this could be a one-liner, but we want to show the data types here + +.. code-block:: c + :emphasize-lines: 4-6 + + static PyObject * + spam_system(PyObject *self, PyObject *arg) + { + int status = 3; + PyObject *result = PyLong_FromLong(status); + return result; + } + + +Recompile, restart the Python interpreter again, +and check that the function now returns 3: + +.. code-block:: pycon + + >>> import spam + >>> spam.system('whoami') + 3 + + +Accepting a string +================== + +Finally, let's handle the function argument. + +Our C function, :c:func:`!spam_system`, takes two arguments. +The first one, ``PyObject *self``, will be set to the ``spam`` module +object. +This isn't useful in our case, so we'll ignore it. + +The other one, ``PyObject *arg``, will be set to the object that the user +passed from Python. +We expect that it should be a Python string. +In order to use the information in it, we will need +to convert it to a C value -- in this case, a C string (``const char *``). + +There's a slight type mismatch here: Python's :py:class:`str` objects store +Unicode text, but C strings are arrays of bytes. +So, we'll need to *encode* the data, and we'll use the UTF-8 encoding for it. +(UTF-8 might not always be correct for system commands, but it's what +:py:meth:`str.encode` uses by default, +and the C API has special support for it.) + +The function to encode a Python string into a UTF-8 buffer is named +:c:func:`PyUnicode_AsUTF8` [#why-pyunicodeasutf8]_. +Call it like this: + +.. code-block:: c + :emphasize-lines: 4 + + static PyObject * + spam_system(PyObject *self, PyObject *arg) + { + const char *command = PyUnicode_AsUTF8(arg); + int status = 3; + PyObject *result = PyLong_FromLong(status); + return result; + } + +If :c:func:`PyUnicode_AsUTF8` is successful, *command* will point to the +resulting array of bytes. +This buffer is managed by the *arg* object, which means we don't need to free +it, but we must follow some rules: + +* We should only use the buffer inside the ``spam_system`` function. + When ``spam_system`` returns, *arg* and the buffer it manages might be + garbage-collected. +* We must not modify it. This is why we use ``const``. + +If :c:func:`PyUnicode_AsUTF8` was *not* successful, it returns a ``NULL`` +pointer. +When calling *any* Python C API, we always need to handle such error cases. +The way to do this in general is left for later chapters of this documentation. +For now, be assured that we are already handling errors from +:c:func:`PyLong_FromLong` correctly. + +For the :c:func:`PyUnicode_AsUTF8` call, the correct way to handle errors is +returning ``NULL`` from ``spam_system``. +Add an ``if`` block for this: + + +.. code-block:: c + :emphasize-lines: 5-7 + + static PyObject * + spam_system(PyObject *self, PyObject *arg) + { + const char *command = PyUnicode_AsUTF8(arg); + if (command == NULL) { + return NULL; + } + int status = 3; + PyObject *result = PyLong_FromLong(status); + return result; + } + +That's it for the setup. +Now, all that is left is calling the C library function :c:func:`system` with +the ``char *`` buffer, and using its result instead of the ``3``: + +.. code-block:: c + :emphasize-lines: 8 + + static PyObject * + spam_system(PyObject *self, PyObject *arg) + { + const char *command = PyUnicode_AsUTF8(arg); + if (command == NULL) { + return NULL; + } + int status = system(command); + PyObject *result = PyLong_FromLong(status); + return result; + } + +Compile your module, restart Python, and test. +This time, you should see your username -- the output of the ``whoami`` +system command: + +.. code-block:: pycon + + >>> import spam + >>> result = spam.system('whoami') + User Name + >>> result + 0 + +You might also want to test error cases: + +.. code-block:: pycon + + >>> import spam + >>> result = spam.system('nonexistent-command') + sh: line 1: nonexistent-command: command not found + >>> result + 32512 + + >>> spam.system(3) + Traceback (most recent call last): + ... + TypeError: bad argument type for built-in operation + + +The result +========== + + +Congratulations! +You have written a complete Python C API extension module, +and completed this tutorial! + +Here is the entire source file, for your convenience: + +.. _extending-spammodule-source: + +.. literalinclude:: ../includes/capi-extension/spammodule-01.c + :start-at: /// + + +.. _first-extension-other-tools: + +Appendix: Other build tools +=========================== + +You should be able to follow this tutorial -- except the +*Running your build tool* section itself -- with a build tool other +than ``meson-python``. + +The Python Packaging User Guide has a `list of recommended tools `_; +be sure to choose one for the C language. + + +Workaround for missing PyInit function +-------------------------------------- + +If your build tool output complains about missing ``PyInit_spam``, +add the following function to your module for now: + +.. code-block:: c + + // A workaround + void *PyInit_spam(void) { return NULL; } + +This is a shim for an old-style :ref:`initialization function `, +which was required in extension modules for CPython 3.14 and below. +Current CPython does not need it, but some build tools may still assume that +all extension modules need to define it. + +If you use this workaround, you will get the exception +``SystemError: initialization of spam failed without raising an exception`` +instead of +``ImportError: dynamic module does not define module export function``. + + +Compiling directly +------------------ + +Using a third-party build tool is heavily recommended, +as it will take care of various details of your platform and Python +installation, of naming the resulting extension, and, later, of distributing +your work. + +If you are building an extension for as *specific* system, or for yourself +only, you might instead want to run your compiler directly. +The way to do this is system-specific; be prepared for issues you will need +to solve yourself. + +Linux +^^^^^ + +On Linux, the Python development package may include a ``python3-config`` +command that prints out the required compiler flags. +If you use it, check that it corresponds to the CPython interpreter you'll use +to load the module. +Then, start with the following command: + +.. code-block:: sh + + gcc --shared $(python3-config --cflags --ldflags) spammodule.c -o spam.so + +This should generate a ``spam.so`` file that you need to put in a directory +on :py:attr:`sys.path`. + + +.. rubric:: Footnotes + +.. [#why-spam] ``spam`` is the favorite food of Monty Python fans... +.. [#why-spammodule] The source file name is entirely up to you, + though some tools can be picky about the ``.c`` extension. + This tutorial uses the traditional ``*module.c`` suffix. + Some people would just use :file:`spam.c` to implement a module + named ``spam``, + projects where Python isn't the primary language might use ``py_spam.c``, + and so on. +.. [#stdlib-h] Including :file:`stdlib.h` is technically not necessary, + since :file:`Python.h` includes it and + :ref:`several other standard headers ` for its own use + or for backwards compatibility. + However, it is good practice to explicitly include what you need. +.. [#why-pymethoddef] The :c:type:`!PyMethodDef` structure is also used + to create methods of classes, so there's no separate + ":c:type:`!PyFunctionDef`". +.. [#why-pylongfromlong] The name :c:func:`PyLong_FromLong` + might not seem obvious. + ``PyLong`` refers to a the Python :py:class:`int`, which was originally + called ``long``; the ``FromLong`` refers to the C ``long`` (or ``long int``) + type. +.. [#why-pyunicodeasutf8] Here, ``PyUnicode`` refers to the original name of + the Python :py:class:`str` class: ``unicode``. diff --git a/Doc/extending/index.rst b/Doc/extending/index.rst index 4cc2c96d8d5b47..c0c494c3059d99 100644 --- a/Doc/extending/index.rst +++ b/Doc/extending/index.rst @@ -5,15 +5,17 @@ ################################################## This document describes how to write modules in C or C++ to extend the Python -interpreter with new modules. Those modules can not only define new functions -but also new object types and their methods. The document also describes how +interpreter with new modules. Those modules can do what Python code does -- +define functions, object types and methods -- but also interact with native +libraries or achieve better performance by avoiding the overhead of an +interpreter. The document also describes how to embed the Python interpreter in another application, for use as an extension language. Finally, it shows how to compile and link extension modules so that they can be loaded dynamically (at run time) into the interpreter, if the underlying operating system supports this feature. -This document assumes basic knowledge about Python. For an informal -introduction to the language, see :ref:`tutorial-index`. :ref:`reference-index` +This document assumes basic knowledge about C and Python. For an informal +introduction to Python, see :ref:`tutorial-index`. :ref:`reference-index` gives a more formal definition of the language. :ref:`library-index` documents the existing object types, functions and modules (both built-in and written in Python) that give the language its wide application range. @@ -21,37 +23,75 @@ Python) that give the language its wide application range. For a detailed description of the whole Python/C API, see the separate :ref:`c-api-index`. +To support extensions, Python's C API (Application Programmers Interface) +defines a set of functions, macros and variables that provide access to most +aspects of the Python run-time system. The Python API is incorporated in a C +source file by including the header ``"Python.h"``. + +.. note:: + + The C extension interface is specific to CPython, and extension modules do + not work on other Python implementations. In many cases, it is possible to + avoid writing C extensions and preserve portability to other implementations. + For example, if your use case is calling C library functions or system calls, + you should consider using the :mod:`ctypes` module or the `cffi + `_ library rather than writing + custom C code. + These modules let you write Python code to interface with C code and are more + portable between implementations of Python than writing and compiling a C + extension module. + + +.. toctree:: + :hidden: + + first-extension-module.rst + extending.rst + newtypes_tutorial.rst + newtypes.rst + building.rst + windows.rst + embedding.rst + Recommended third party tools ============================= -This guide only covers the basic tools for creating extensions provided +This document only covers the basic tools for creating extensions provided as part of this version of CPython. Some :ref:`third party tools ` offer both simpler and more sophisticated approaches to creating C and C++ extensions for Python. +While this document is aimed at extension authors, it should also be helpful to +the authors of such tools. +For example, the tutorial module can serve as a simple test case for a build +tool or sample expected output of a code generator. + + +C API Tutorial +============== + +This tutorial describes how to write a simple module in C or C++, +using the Python C API -- that is, using the basic tools provided +as part of this version of CPython. -Creating extensions without third party tools -============================================= + +#. :ref:`first-extension-module` + + +Guides for intermediate topics +============================== This section of the guide covers creating C and C++ extensions without assistance from third party tools. It is intended primarily for creators of those tools, rather than being a recommended way to create your own C extensions. -.. seealso:: - - :pep:`489` -- Multi-phase extension module initialization - -.. toctree:: - :maxdepth: 2 - :numbered: - - extending.rst - newtypes_tutorial.rst - newtypes.rst - building.rst - windows.rst +* :ref:`extending-intro` +* :ref:`defining-new-types` +* :ref:`new-types-topics` +* :ref:`building` +* :ref:`building-on-windows` Embedding the CPython runtime in a larger application ===================================================== @@ -61,8 +101,4 @@ interpreter as the main application, it is desirable to instead embed the CPython runtime inside a larger application. This section covers some of the details involved in doing that successfully. -.. toctree:: - :maxdepth: 2 - :numbered: - - embedding.rst +* :ref:`embedding` diff --git a/Doc/includes/capi-extension/spammodule-01.c b/Doc/includes/capi-extension/spammodule-01.c new file mode 100644 index 00000000000000..86c9840359d9c7 --- /dev/null +++ b/Doc/includes/capi-extension/spammodule-01.c @@ -0,0 +1,55 @@ +/* This file needs to be kept in sync with the tutorial + * at Doc/extending/first-extension-module.rst + */ + +/// Includes + +#include +#include // for system() + +/// Implementation of spam.system + +static PyObject * +spam_system(PyObject *self, PyObject *arg) +{ + const char *command = PyUnicode_AsUTF8(arg); + if (command == NULL) { + return NULL; + } + int status = system(command); + PyObject *result = PyLong_FromLong(status); + return result; +} + +/// Module method table + +static PyMethodDef spam_methods[] = { + { + .ml_name="system", + .ml_meth=spam_system, + .ml_flags=METH_O, + .ml_doc="Execute a shell command.", + }, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +/// Module slot table + +static PyModuleDef_Slot spam_slots[] = { + {Py_mod_name, "spam"}, + {Py_mod_doc, "A wonderful module with an example function"}, + {Py_mod_methods, spam_methods}, + {0, NULL} +}; + +/// Export hook prototype + +PyMODEXPORT_FUNC PyModExport_spam(void); + +/// Module export hook + +PyMODEXPORT_FUNC +PyModExport_spam(void) +{ + return spam_slots; +} diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 2e7d0dbc26e5bc..bf37540e5faf42 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -139,12 +139,13 @@ Node classes The :meth:`~object.__repr__` output of :class:`~ast.AST` nodes includes the values of the node fields. -.. deprecated:: 3.8 +.. deprecated-removed:: 3.8 3.14 - Old classes :class:`!ast.Num`, :class:`!ast.Str`, :class:`!ast.Bytes`, - :class:`!ast.NameConstant` and :class:`!ast.Ellipsis` are still available, - but they will be removed in future Python releases. In the meantime, - instantiating them will return an instance of a different class. + Previous versions of Python provided the AST classes :class:`!ast.Num`, + :class:`!ast.Str`, :class:`!ast.Bytes`, :class:`!ast.NameConstant` and + :class:`!ast.Ellipsis`, which were deprecated in Python 3.8. These classes + were removed in Python 3.14, and their functionality has been replaced with + :class:`ast.Constant`. .. deprecated:: 3.9 @@ -2419,12 +2420,12 @@ and classes for traversing abstract syntax trees: during traversal. For this a special visitor exists (:class:`NodeTransformer`) that allows modifications. - .. deprecated:: 3.8 + .. deprecated-removed:: 3.8 3.14 Methods :meth:`!visit_Num`, :meth:`!visit_Str`, :meth:`!visit_Bytes`, - :meth:`!visit_NameConstant` and :meth:`!visit_Ellipsis` are deprecated - now and will not be called in future Python versions. Add the - :meth:`visit_Constant` method to handle all constant nodes. + :meth:`!visit_NameConstant` and :meth:`!visit_Ellipsis` will not be called + in Python 3.14+. Add the :meth:`visit_Constant` method instead to handle + all constant nodes. .. class:: NodeTransformer() diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 529a7242443820..2d901824335145 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -267,14 +267,20 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 -.. function:: z85encode(s) +.. function:: z85encode(s, pad=False) Encode the :term:`bytes-like object` *s* using Z85 (as used in ZeroMQ) and return the encoded :class:`bytes`. See `Z85 specification `_ for more information. + If *pad* is true, the input is padded with ``b'\0'`` so its length is a + multiple of 4 bytes before encoding. + .. versionadded:: 3.13 + .. versionchanged:: next + The *pad* parameter was added. + .. function:: z85decode(s) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 8ae1c1fb9e46bb..48e7080da6c525 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2651,9 +2651,42 @@ Broadly speaking, ``d.strftime(fmt)`` acts like the :mod:`time` module's ``time.strftime(fmt, d.timetuple())`` although not all objects support a :meth:`~date.timetuple` method. -For the :meth:`.datetime.strptime` class method, the default value is -``1900-01-01T00:00:00.000``: any components not specified in the format string -will be pulled from the default value. [#]_ +For the :meth:`.datetime.strptime` and :meth:`.date.strptime` class methods, +the default value is ``1900-01-01T00:00:00.000``: any components not specified +in the format string will be pulled from the default value. + +.. note:: + When used to parse partial dates lacking a year, :meth:`.datetime.strptime` + and :meth:`.date.strptime` will raise when encountering February 29 because + the default year of 1900 is *not* a leap year. Always add a default leap + year to partial date strings before parsing. + + +.. testsetup:: + + # doctest seems to turn the warning into an error which makes it + # show up and require matching and prevents the actual interesting + # exception from being raised. + # Manually apply the catch_warnings context manager + import warnings + catch_warnings = warnings.catch_warnings() + catch_warnings.__enter__() + warnings.simplefilter("ignore") + +.. testcleanup:: + + catch_warnings.__exit__() + +.. doctest:: + + >>> from datetime import datetime + >>> value = "2/29" + >>> datetime.strptime(value, "%m/%d") + Traceback (most recent call last): + ... + ValueError: day 29 must be in range 1..28 for month 2 in year 1900 + >>> datetime.strptime(f"1904 {value}", "%Y %m/%d") + datetime.datetime(1904, 2, 29, 0, 0) Using ``datetime.strptime(date_string, format)`` is equivalent to:: @@ -2790,7 +2823,7 @@ Notes: include a year in the format. If the value you need to parse lacks a year, append an explicit dummy leap year. Otherwise your code will raise an exception when it encounters leap day because the default year used by the - parser is not a leap year. Users run into this bug every four years... + parser (1900) is not a leap year. Users run into that bug every leap year. .. doctest:: @@ -2817,5 +2850,3 @@ Notes: .. [#] See R. H. van Gent's `guide to the mathematics of the ISO 8601 calendar `_ for a good explanation. - -.. [#] Passing ``datetime.strptime('Feb 29', '%b %d')`` will fail since 1900 is not a leap year. diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index a8a7e671aadca2..0da27ba8e78284 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -947,12 +947,13 @@ Utilities and Decorators the member's name. Care must be taken if mixing *auto()* with manually specified values. - *auto* instances are only resolved when at the top level of an assignment: + *auto* instances are only resolved when at the top level of an assignment, either by + itself or as part of a tuple: * ``FIRST = auto()`` will work (auto() is replaced with ``1``); * ``SECOND = auto(), -2`` will work (auto is replaced with ``2``, so ``2, -2`` is used to create the ``SECOND`` enum member; - * ``THREE = [auto(), -3]`` will *not* work (``, -3`` is used to + * ``THREE = [auto(), -3]`` will *not* work (``[, -3]`` is used to create the ``THREE`` enum member) .. versionchanged:: 3.11.1 diff --git a/Doc/library/linecache.rst b/Doc/library/linecache.rst index e766a9280946d3..07305a2a39b252 100644 --- a/Doc/library/linecache.rst +++ b/Doc/library/linecache.rst @@ -31,7 +31,7 @@ The :mod:`linecache` module defines the following functions: .. index:: triple: module; search; path If *filename* indicates a frozen module (starting with ``'` available + on the system. + + On Windows, the *flags* parameter is ignored. + ``None`` is returned to indicate success. An exception is raised when the call failed. @@ -235,6 +241,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length specified alone, and the flush operation will extend from *offset* to the end of the mmap. + .. versionchanged:: next + Added *flags* parameter to control synchronization behavior. + .. method:: madvise(option[, start[, length]]) @@ -328,6 +337,17 @@ To map anonymous memory, -1 should be passed as the fileno along with the length .. versionadded:: 3.13 + .. method:: set_name(name, /) + + Annotate the memory mapping with the given *name* for easier identification + in ``/proc//maps`` if the kernel supports the feature and :option:`-X dev <-X>` is passed + to Python or if Python is built in :ref:`debug mode `. + The length of *name* must not exceed 67 bytes including the ``'\0'`` terminator. + + .. availability:: Linux >= 5.17 (kernel built with ``CONFIG_ANON_VMA_NAME`` option) + + .. versionadded:: next + .. method:: size() Return the length of the file, which can be larger than the size of the @@ -450,3 +470,22 @@ MAP_* Constants :data:`MAP_TPRO`, :data:`MAP_TRANSLATED_ALLOW_EXECUTE`, and :data:`MAP_UNIX03` constants. +.. _ms-constants: + +MS_* Constants +++++++++++++++ + +.. data:: MS_SYNC + MS_ASYNC + MS_INVALIDATE + + These flags control the synchronization behavior for :meth:`mmap.flush`: + + * :data:`MS_SYNC` - Synchronous flush: writes are scheduled and the call + blocks until they are physically written to storage. + * :data:`MS_ASYNC` - Asynchronous flush: writes are scheduled but the call + returns immediately without waiting for completion. + * :data:`MS_INVALIDATE` - Invalidate cached data: invalidates other mappings + of the same file so they can see the changes. + + .. versionadded:: next diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 671270d6112212..f75ad4e67a66d7 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -5993,7 +5993,7 @@ Miscellaneous System Information .. versionchanged:: 3.13 If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, - :func:`cpu_count` returns the overridden value *n*. + :func:`cpu_count` returns the override value *n*. .. function:: getloadavg() @@ -6015,7 +6015,7 @@ Miscellaneous System Information in the **system**. If :option:`-X cpu_count <-X>` is given or :envvar:`PYTHON_CPU_COUNT` is set, - :func:`process_cpu_count` returns the overridden value *n*. + :func:`process_cpu_count` returns the override value *n*. See also the :func:`sched_getaffinity` function. diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 0bbdc42535290a..8ab3e7ec9ef9d2 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -520,7 +520,8 @@ can be overridden by the local file. To remove all commands from a breakpoint, type ``commands`` and follow it immediately with ``end``; that is, give no commands. - With no *bpnumber* argument, ``commands`` refers to the last breakpoint set. + With no *bpnumber* argument, ``commands`` refers to the most recently set + breakpoint that still exists. You can use breakpoint commands to start your program up again. Simply use the :pdbcmd:`continue` command, or :pdbcmd:`step`, diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index 1f60e2cb578c4d..dae67cca66d9b4 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -53,7 +53,7 @@ counts**, not direct measurements. Tachyon counts how many times each function appears in the collected samples, then multiplies by the sampling interval to estimate time. -For example, with a 100 microsecond sampling interval over a 10-second profile, +For example, with a 10 kHz sampling rate over a 10-second profile, Tachyon collects approximately 100,000 samples. If a function appears in 5,000 samples (5% of total), Tachyon estimates it consumed 5% of the 10-second duration, or about 500 milliseconds. This is a statistical estimate, not a @@ -142,7 +142,7 @@ Use live mode for real-time monitoring (press ``q`` to quit):: Profile for 60 seconds with a faster sampling rate:: - python -m profiling.sampling run -d 60 -i 50 script.py + python -m profiling.sampling run -d 60 -r 20khz script.py Generate a line-by-line heatmap:: @@ -200,6 +200,36 @@ On most systems, attaching to another process requires appropriate permissions. See :ref:`profiling-permissions` for platform-specific requirements. +.. _replay-command: + +The ``replay`` command +---------------------- + +The ``replay`` command converts binary profile files to other output formats:: + + python -m profiling.sampling replay profile.bin + python -m profiling.sampling replay --flamegraph -o profile.html profile.bin + +This command is useful when you have captured profiling data in binary format +and want to analyze it later or convert it to a visualization format. Binary +profiles can be replayed multiple times to different formats without +re-profiling. + +:: + + # Convert binary to pstats (default, prints to stdout) + python -m profiling.sampling replay profile.bin + + # Convert binary to flame graph + python -m profiling.sampling replay --flamegraph -o output.html profile.bin + + # Convert binary to gecko format for Firefox Profiler + python -m profiling.sampling replay --gecko -o profile.json profile.bin + + # Convert binary to heatmap + python -m profiling.sampling replay --heatmap -o my_heatmap profile.bin + + Profiling in production ----------------------- @@ -211,8 +241,8 @@ is unaware it is being profiled. When profiling production systems, keep these guidelines in mind: Start with shorter durations (10-30 seconds) to get quick results, then extend -if you need more statistical accuracy. The default 10-second duration is usually -sufficient to identify major hotspots. +if you need more statistical accuracy. By default, profiling runs until the +target process completes, which is usually sufficient to identify major hotspots. If possible, profile during representative load rather than peak traffic. Profiles collected during normal operation are easier to interpret than those @@ -296,10 +326,10 @@ The default configuration works well for most use cases: * - Option - Default - * - Default for ``--interval`` / ``-i`` - - 100 µs between samples (~10,000 samples/sec) + * - Default for ``--sampling-rate`` / ``-r`` + - 1 kHz * - Default for ``--duration`` / ``-d`` - - 10 seconds + - Run to completion * - Default for ``--all-threads`` / ``-a`` - Main thread only * - Default for ``--native`` @@ -312,35 +342,35 @@ The default configuration works well for most use cases: - Disabled * - Default for ``--subprocesses`` - Disabled + * - Default for ``--blocking`` + - Disabled (non-blocking sampling) -Sampling interval and duration ------------------------------- +Sampling rate and duration +-------------------------- -The two most fundamental parameters are the sampling interval and duration. +The two most fundamental parameters are the sampling rate and duration. Together, these determine how many samples will be collected during a profiling session. -The :option:`--interval` option (:option:`-i`) sets the time between samples in -microseconds. The default is 100 microseconds, which produces approximately -10,000 samples per second:: +The :option:`--sampling-rate` option (:option:`-r`) sets how frequently samples +are collected. The default is 1 kHz (10,000 samples per second):: - python -m profiling.sampling run -i 50 script.py + python -m profiling.sampling run -r 20khz script.py -Lower intervals capture more samples and provide finer-grained data at the -cost of slightly higher profiler CPU usage. Higher intervals reduce profiler +Higher rates capture more samples and provide finer-grained data at the +cost of slightly higher profiler CPU usage. Lower rates reduce profiler overhead but may miss short-lived functions. For most applications, the -default interval provides a good balance between accuracy and overhead. +default rate provides a good balance between accuracy and overhead. -The :option:`--duration` option (:option:`-d`) sets how long to profile in seconds. The -default is 10 seconds:: +The :option:`--duration` option (:option:`-d`) sets how long to profile in seconds. By +default, profiling continues until the target process exits or is interrupted:: python -m profiling.sampling run -d 60 script.py -Longer durations collect more samples and produce more statistically reliable -results, especially for code paths that execute infrequently. When profiling -a program that runs for a fixed time, you may want to set the duration to -match or exceed the expected runtime. +Specifying a duration is useful when attaching to long-running processes or when +you want to limit profiling to a specific time window. When profiling a script, +the default behavior of running to completion is usually what you want. Thread selection @@ -362,6 +392,50 @@ This option is particularly useful when investigating concurrency issues or when work is distributed across a thread pool. +.. _blocking-mode: + +Blocking mode +------------- + +By default, Tachyon reads the target process's memory without stopping it. +This non-blocking approach is ideal for most profiling scenarios because it +imposes virtually zero overhead on the target application: the profiled +program runs at full speed and is unaware it is being observed. + +However, non-blocking sampling can occasionally produce incomplete or +inconsistent stack traces in applications with many generators or coroutines +that rapidly switch between yield points, or in programs with very fast-changing +call stacks where functions enter and exit between the start and end of a single +stack read, resulting in reconstructed stacks that mix frames from different +execution states or that never actually existed. + +For these cases, the :option:`--blocking` option stops the target process during +each sample:: + + python -m profiling.sampling run --blocking script.py + python -m profiling.sampling attach --blocking 12345 + +When blocking mode is enabled, the profiler suspends the target process, +reads its stack, then resumes it. This guarantees that each captured stack +represents a real, consistent snapshot of what the process was doing at that +instant. The trade-off is that the target process runs slower because it is +repeatedly paused. + +.. warning:: + + Do not use very high sample rates (low ``--interval`` values) with blocking + mode. Suspending and resuming a process takes time, and if the sampling + interval is too short, the target will spend more time stopped than running. + For blocking mode, intervals of 1000 microseconds (1 millisecond) or higher + are recommended. The default 100 microsecond interval may cause noticeable + slowdown in the target application. + +Use blocking mode only when you observe inconsistent stacks in your profiles, +particularly with generator-heavy or coroutine-heavy code. For most +applications, the default non-blocking mode provides accurate results with +zero impact on the target process. + + Special frames -------------- @@ -497,9 +571,9 @@ appended: - For pstats format (which defaults to stdout), subprocesses produce files like ``profile_12345.pstats`` -The subprocess profilers inherit most sampling options from the parent (interval, -duration, thread selection, native frames, GC frames, async-aware mode, and -output format). All Python descendant processes are profiled recursively, +The subprocess profilers inherit most sampling options from the parent (sampling +rate, duration, thread selection, native frames, GC frames, async-aware mode, +and output format). All Python descendant processes are profiled recursively, including grandchildren and further descendants. Subprocess detection works by periodically scanning for new descendants of @@ -1041,6 +1115,59 @@ intuitive view that shows exactly where time is spent without requiring interpretation of hierarchical visualizations. +Binary format +------------- + +Binary format (:option:`--binary`) produces a compact binary file for efficient +storage of profiling data:: + + python -m profiling.sampling run --binary -o profile.bin script.py + python -m profiling.sampling attach --binary -o profile.bin 12345 + +The :option:`--compression` option controls data compression: + +- ``auto`` (default): Use zstd compression if available, otherwise no + compression +- ``zstd``: Force zstd compression (requires :mod:`compression.zstd` support) +- ``none``: Disable compression + +:: + + python -m profiling.sampling run --binary --compression=zstd -o profile.bin script.py + +To analyze binary profiles, use the :ref:`replay-command` to convert them to +other formats like flame graphs or pstats output. + + +Record and replay workflow +========================== + +The binary format combined with the replay command enables a record-and-replay +workflow that separates data capture from analysis. Rather than generating +visualizations during profiling, you capture raw data to a compact binary file +and convert it to different formats later. + +This approach has three main benefits: + +- Sampling runs faster because the work of building data structures for + visualization is deferred until replay. +- A single binary capture can be converted to multiple output formats + without re-profiling: pstats for a quick overview, flame graph for visual + exploration, heatmap for line-level detail. +- Binary files are compact and easy to share with colleagues who can convert + them to their preferred format. + +A typical workflow:: + + # Capture profile in production or during tests + python -m profiling.sampling attach --binary -o profile.bin 12345 + + # Later, analyze with different formats + python -m profiling.sampling replay profile.bin + python -m profiling.sampling replay --flamegraph -o profile.html profile.bin + python -m profiling.sampling replay --heatmap -o heatmap profile.bin + + Live mode ========= @@ -1252,17 +1379,21 @@ Global options Attach to and profile a running process by PID. +.. option:: replay + + Convert a binary profile file to another output format. + Sampling options ---------------- -.. option:: -i , --interval +.. option:: -r , --sampling-rate - Sampling interval in microseconds. Default: 100. + Sampling rate (for example, ``10000``, ``10khz``, ``10k``). Default: ``1khz``. .. option:: -d , --duration - Profiling duration in seconds. Default: 10. + Profiling duration in seconds. Default: run to completion. .. option:: -a, --all-threads @@ -1296,6 +1427,13 @@ Sampling options Also profile subprocesses. Each subprocess gets its own profiler instance and output file. Incompatible with ``--live``. +.. option:: --blocking + + Pause the target process during each sample. This ensures consistent + stack traces at the cost of slowing down the target. Use with longer + intervals (1000 µs or higher) to minimize impact. See :ref:`blocking-mode` + for details. + Mode options ------------ @@ -1335,12 +1473,22 @@ Output options Generate HTML heatmap with line-level sample counts. +.. option:: --binary + + Generate high-performance binary format for later conversion with the + ``replay`` command. + +.. option:: --compression + + Compression for binary format: ``auto`` (use zstd if available, default), + ``zstd``, or ``none``. + .. option:: -o , --output Output file or directory path. Default behavior varies by format: - ``--pstats`` writes to stdout, ``--flamegraph`` and ``--gecko`` generate - files like ``flamegraph.PID.html``, and ``--heatmap`` creates a directory - named ``heatmap_PID``. + :option:`--pstats` writes to stdout, while other formats generate a file + named ``_.`` (for example, ``flamegraph_12345.html``). + :option:`--heatmap` creates a directory named ``heatmap_``. pstats display options diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 4e55e301b89095..6bddf575a809a1 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -78,7 +78,7 @@ Bookkeeping functions instead of the system time (see the :func:`os.urandom` function for details on availability). - If *a* is an int, it is used directly. + If *a* is an int, its absolute value is used directly. With version 2 (the default), a :class:`str`, :class:`bytes`, or :class:`bytearray` object gets converted to an :class:`int` and all of its bits are used. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index f33b73238ec8b3..7eaa9f48ab5bc4 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -46,8 +46,10 @@ Any object can be tested for truth value, for use in an :keyword:`if` or By default, an object is considered true unless its class defines either a :meth:`~object.__bool__` method that returns ``False`` or a :meth:`~object.__len__` method that -returns zero, when called with the object. [1]_ Here are most of the built-in -objects considered false: +returns zero, when called with the object. [1]_ If one of the methods raises an +exception when called, the exception is propagated and the object does +not have a truth value (for example, :data:`NotImplemented`). +Here are most of the built-in objects considered false: .. index:: single: None (Built-in object) diff --git a/Doc/tools/check-warnings.py b/Doc/tools/check-warnings.py index 2f2bb9e2dcb7ef..859bc1e2d5f5b5 100644 --- a/Doc/tools/check-warnings.py +++ b/Doc/tools/check-warnings.py @@ -311,8 +311,11 @@ def main(argv: list[str] | None = None) -> int: if not Path("Doc").exists() or not Path("Doc").is_dir(): raise RuntimeError(wrong_directory_msg) - with Path("Doc/sphinx-warnings.txt").open(encoding="UTF-8") as f: - warnings = f.read().splitlines() + warnings = ( + Path("Doc/sphinx-warnings.txt") + .read_text(encoding="UTF-8") + .splitlines() + ) cwd = str(Path.cwd()) + os.path.sep files_with_nits = { diff --git a/Doc/tools/extensions/grammar_snippet.py b/Doc/tools/extensions/grammar_snippet.py index 1e059f111e4091..8078b7ebeb8076 100644 --- a/Doc/tools/extensions/grammar_snippet.py +++ b/Doc/tools/extensions/grammar_snippet.py @@ -191,7 +191,7 @@ class GrammarSnippetDirective(GrammarSnippetBase): into something similar to Sphinx productionlist, but better suited for our needs: - Instead of `::=`, use a colon, as in `Grammar/python.gram` - - Show the listing almost as is, with no auto-aligment. + - Show the listing almost as is, with no auto-alignment. The only special character is the backtick, which marks tokens. Unlike Sphinx's productionlist, this directive supports options. diff --git a/Doc/tools/extensions/pydoc_topics.py b/Doc/tools/extensions/pydoc_topics.py index 01efbba628324f..a65d77433b255b 100644 --- a/Doc/tools/extensions/pydoc_topics.py +++ b/Doc/tools/extensions/pydoc_topics.py @@ -109,6 +109,7 @@ class PydocTopicsBuilder(TextBuilder): def init(self) -> None: super().init() self.topics: dict[str, str] = {} + self.module_docs: dict[str, str] = {} def get_outdated_docs(self) -> str: # Return a string describing what an update build will build. @@ -130,6 +131,15 @@ def write_documents(self, _docnames: Set[str]) -> None: continue doc_labels.setdefault(docname, []).append((topic_label, label_id)) + py_domain = env.domains['py'] + for module_name, module_info in py_domain.data['modules'].items(): + docname = module_info[0] + if docname.startswith('library/'): + doc_file = docname.replace('library/', '') + self.module_docs[module_name] = ( + f"{doc_file}#module-{module_name}" + ) + for docname, label_ids in status_iterator( doc_labels.items(), "building topics... ", @@ -161,6 +171,22 @@ def finish(self) -> None: """ self.outdir.joinpath("topics.py").write_text(topics, encoding="utf-8") + module_docs_repr = "\n".join( + f" '{module}': '{doc_file}'," + for module, doc_file in sorted(self.module_docs.items()) + ) + module_docs = f"""\ +# Autogenerated by Sphinx on {asctime()} +# as part of the release process. + +module_docs = {{ +{module_docs_repr} +}} +""" + self.outdir.joinpath("module_docs.py").write_text( + module_docs, encoding="utf-8" + ) + def _display_labels(item: tuple[str, Sequence[tuple[str, str]]]) -> str: _docname, label_ids = item diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 7e032fe5df2fdf..0d35eed38f303d 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -562,6 +562,9 @@ locale but included in the language code. (Contributed by Serhiy Storchaka in :gh:`137729`.) +* Undeprecate the :func:`locale.getdefaultlocale` function. + (Contributed by Victor Stinner in :gh:`130796`.) + math ---- @@ -592,6 +595,11 @@ mmap not be duplicated. (Contributed by Serhiy Storchaka in :gh:`78502`.) +* Added the :meth:`mmap.mmap.set_name` method + to annotate an anonymous memory mapping + if Linux kernel supports :manpage:`PR_SET_VMA_ANON_NAME ` (Linux 5.17 or newer). + (Contributed by Donghee Na in :gh:`142419`.) + os -- @@ -844,6 +852,16 @@ zlib Optimizations ============= +* Builds using Visual Studio 2026 (MSVC 18) may now use the new + :ref:`tail-calling interpreter `. + Results on an early experimental MSVC compiler reported roughly 15% speedup + on the geometric mean of pyperformance on Windows x86-64 over + the switch-case interpreter. We have + observed speedups ranging from 15% for large pure-Python libraries + to 40% for long-running small pure-Python scripts on Windows. + (Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`. + Special thanks to the MSVC team including Hulon Jenkins.) + csv --- @@ -920,8 +938,8 @@ code results in constants, the code can be simplified by the JIT. The JIT avoids :term:`reference count`\ s where possible. This generally reduces the cost of most operations in Python. -(Contributed by Ken Jin, Donghee Na, Zheao Li, Savannah Ostrowski, -Noam Cohen, Tomas Roun, PuQing in :gh:`134584`.) +(Contributed by Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, +Noam Cohen, Tomas Roun, and PuQing in :gh:`134584`.) .. rubric:: Better machine code generation @@ -1104,9 +1122,9 @@ New deprecations * ``__version__`` - * The ``__version__`` attribute has been deprecated in these standard library - modules and will be removed in Python 3.20. - Use :py:data:`sys.version_info` instead. + * The ``__version__``, ``version`` and ``VERSION`` attributes have been + deprecated in these standard library modules and will be removed in + Python 3.20. Use :py:data:`sys.version_info` instead. - :mod:`argparse` - :mod:`csv` @@ -1127,6 +1145,9 @@ New deprecations - :mod:`tkinter.font` - :mod:`tkinter.ttk` - :mod:`wsgiref.simple_server` + - :mod:`xml.etree.ElementTree` + - :mod:`!xml.sax.expatreader` + - :mod:`xml.sax.handler` - :mod:`zlib` (Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.) diff --git a/Include/cpython/pyatomic.h b/Include/cpython/pyatomic.h index 790640309f1e03..ce907fd6a4c453 100644 --- a/Include/cpython/pyatomic.h +++ b/Include/cpython/pyatomic.h @@ -523,6 +523,9 @@ _Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value); static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value); +static inline void +_Py_atomic_store_int8_release(int8_t *obj, int8_t value); + static inline void _Py_atomic_store_int_release(int *obj, int value); diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h index 1566b83b9f6a1b..c045213c898a03 100644 --- a/Include/cpython/pyatomic_gcc.h +++ b/Include/cpython/pyatomic_gcc.h @@ -572,6 +572,10 @@ static inline void _Py_atomic_store_int_release(int *obj, int value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } +static inline void +_Py_atomic_store_int8_release(int8_t *obj, int8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); } + static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index d155955df0cddf..8b9dd3eb0f8e16 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -1066,6 +1066,19 @@ _Py_atomic_store_int_release(int *obj, int value) #endif } +static inline void +_Py_atomic_store_int8_release(int8_t *obj, int8_t value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(int8_t volatile *)obj = value; +#elif defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(unsigned __int8); + __stlr8((unsigned __int8 volatile *)obj, (unsigned __int8)value); +#else +# error "no implementation of _Py_atomic_store_int8_release" +#endif +} + static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) { diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h index 7176f667a4082c..cfc8dbefc63d09 100644 --- a/Include/cpython/pyatomic_std.h +++ b/Include/cpython/pyatomic_std.h @@ -1023,6 +1023,14 @@ _Py_atomic_store_int_release(int *obj, int value) memory_order_release); } +static inline void +_Py_atomic_store_int8_release(int8_t *obj, int8_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(int8_t)*)obj, value, + memory_order_release); +} + static inline void _Py_atomic_store_uint_release(unsigned int *obj, unsigned int value) { diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index af53f2e7d6f73e..c6c82038d7c85f 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -123,7 +123,7 @@ _PyEval_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwfl #ifdef _Py_TIER2 #ifdef _Py_JIT -_Py_CODEUNIT *_Py_LazyJitTrampoline( +_Py_CODEUNIT *_Py_LazyJitShim( struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate ); @@ -415,6 +415,17 @@ _Py_VectorCall_StackRefSteal( int total_args, _PyStackRef kwnames); +PyAPI_FUNC(PyObject*) +_Py_VectorCallInstrumentation_StackRefSteal( + _PyStackRef callable, + _PyStackRef* arguments, + int total_args, + _PyStackRef kwnames, + bool call_instrumentation, + _PyInterpreterFrame* frame, + _Py_CODEUNIT* this_instr, + PyThreadState* tstate); + PyAPI_FUNC(PyObject *) _Py_BuiltinCallFast_StackRefSteal( _PyStackRef callable, @@ -464,6 +475,11 @@ _Py_assert_within_stack_bounds( _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, const char *filename, int lineno); +// Like PyMapping_GetOptionalItem, but returns the PyObject* instead of taking +// it as an out parameter. This helps MSVC's escape analysis when used with +// tail calling. +PyAPI_FUNC(PyObject*) _PyMapping_GetOptionalItem2(PyObject* obj, PyObject* key, int* err); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 1193f496da132d..a7005a3b8e2fab 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -272,8 +272,7 @@ _PyDict_SendEvent(int watcher_bits, PyObject *value); static inline void -_PyDict_NotifyEvent(PyInterpreterState *interp, - PyDict_WatchEvent event, +_PyDict_NotifyEvent(PyDict_WatchEvent event, PyDictObject *mp, PyObject *key, PyObject *value) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 56bc003ac3e246..e625bf2fef1912 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1653,9 +1653,11 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(co_varnames)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(code)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(col_offset)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(collector)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(command)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(comment_factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compression)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(config)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(consts)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(context)); @@ -1718,7 +1720,9 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(event)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eventmask)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_tb)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_type)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_val)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exception)); @@ -1974,6 +1978,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(print_file_and_line)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress_callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress_routine)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(proto)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(protocol)); @@ -2014,6 +2019,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reversed)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(rounding)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(salt)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sample_interval_us)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sched_priority)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(scheduler)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(script)); @@ -2053,8 +2059,10 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(spam)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(src)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(src_dir_fd)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stack_frames)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stacklevel)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(start)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(start_time_us)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(statement)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stats)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(status)); @@ -2095,6 +2103,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(times)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timespec)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timestamp)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timestamp_us)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timetuple)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeunit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(top)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 8be948b92ec8f9..771f0f8cb4ad87 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -376,9 +376,11 @@ struct _Py_global_strings { STRUCT_FOR_ID(co_varnames) STRUCT_FOR_ID(code) STRUCT_FOR_ID(col_offset) + STRUCT_FOR_ID(collector) STRUCT_FOR_ID(command) STRUCT_FOR_ID(comment_factory) STRUCT_FOR_ID(compile_mode) + STRUCT_FOR_ID(compression) STRUCT_FOR_ID(config) STRUCT_FOR_ID(consts) STRUCT_FOR_ID(context) @@ -441,7 +443,9 @@ struct _Py_global_strings { STRUCT_FOR_ID(event) STRUCT_FOR_ID(eventmask) STRUCT_FOR_ID(exc) + STRUCT_FOR_ID(exc_tb) STRUCT_FOR_ID(exc_type) + STRUCT_FOR_ID(exc_val) STRUCT_FOR_ID(exc_value) STRUCT_FOR_ID(excepthook) STRUCT_FOR_ID(exception) @@ -697,6 +701,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(print_file_and_line) STRUCT_FOR_ID(priority) STRUCT_FOR_ID(progress) + STRUCT_FOR_ID(progress_callback) STRUCT_FOR_ID(progress_routine) STRUCT_FOR_ID(proto) STRUCT_FOR_ID(protocol) @@ -737,6 +742,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(reversed) STRUCT_FOR_ID(rounding) STRUCT_FOR_ID(salt) + STRUCT_FOR_ID(sample_interval_us) STRUCT_FOR_ID(sched_priority) STRUCT_FOR_ID(scheduler) STRUCT_FOR_ID(script) @@ -776,8 +782,10 @@ struct _Py_global_strings { STRUCT_FOR_ID(spam) STRUCT_FOR_ID(src) STRUCT_FOR_ID(src_dir_fd) + STRUCT_FOR_ID(stack_frames) STRUCT_FOR_ID(stacklevel) STRUCT_FOR_ID(start) + STRUCT_FOR_ID(start_time_us) STRUCT_FOR_ID(statement) STRUCT_FOR_ID(stats) STRUCT_FOR_ID(status) @@ -818,6 +826,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(times) STRUCT_FOR_ID(timespec) STRUCT_FOR_ID(timestamp) + STRUCT_FOR_ID(timestamp_us) STRUCT_FOR_ID(timetuple) STRUCT_FOR_ID(timeunit) STRUCT_FOR_ID(top) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 6b3d5711b92971..818c4f159591fe 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -947,7 +947,6 @@ struct _is { struct _PyExecutorObject *executor_deletion_list_head; struct _PyExecutorObject *cold_executor; struct _PyExecutorObject *cold_dynamic_executor; - int executor_deletion_list_remaining_capacity; size_t executor_creation_counter; _rare_events rare_events; PyDict_WatchCallback builtins_dict_watcher; diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index 8949d6cc2fc4bb..2e9fbd39b276b1 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -27,7 +27,7 @@ static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) { // Similar to _PyFrame_GetCode(), but return NULL if the frame is invalid or // freed. Used by dump_frame() in Python/traceback.c. The function uses // heuristics to detect freed memory, it's not 100% reliable. -static inline PyCodeObject* +static inline PyCodeObject* _Py_NO_SANITIZE_THREAD _PyFrame_SafeGetCode(_PyInterpreterFrame *f) { // globals and builtins may be NULL on a legit frame, but it's unlikely. @@ -70,7 +70,7 @@ _PyFrame_GetBytecode(_PyInterpreterFrame *f) // Similar to PyUnstable_InterpreterFrame_GetLasti(), but return NULL if the // frame is invalid or freed. Used by dump_frame() in Python/traceback.c. The // function uses heuristics to detect freed memory, it's not 100% reliable. -static inline int +static inline int _Py_NO_SANITIZE_THREAD _PyFrame_SafeGetLasti(struct _PyInterpreterFrame *f) { // Code based on _PyFrame_GetBytecode() but replace _PyFrame_GetCode() diff --git a/Include/internal/pycore_jit.h b/Include/internal/pycore_jit.h index a7041ef8d4b000..89d5bb53643930 100644 --- a/Include/internal/pycore_jit.h +++ b/Include/internal/pycore_jit.h @@ -19,12 +19,13 @@ extern "C" { #ifdef _Py_JIT typedef _Py_CODEUNIT *(*jit_func)( - _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, + _PyExecutorObject *executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _PyStackRef _tos_cache0, _PyStackRef _tos_cache1, _PyStackRef _tos_cache2 ); int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length); void _PyJIT_Free(_PyExecutorObject *executor); +void _PyJIT_Fini(void); #endif // _Py_JIT diff --git a/Include/internal/pycore_mmap.h b/Include/internal/pycore_mmap.h index 214fd4362a55fe..897816db01077f 100644 --- a/Include/internal/pycore_mmap.h +++ b/Include/internal/pycore_mmap.h @@ -17,25 +17,27 @@ extern "C" { #endif #if defined(HAVE_PR_SET_VMA_ANON_NAME) && defined(__linux__) -static inline void +static inline int _PyAnnotateMemoryMap(void *addr, size_t size, const char *name) { #ifndef Py_DEBUG if (!_Py_GetConfig()->dev_mode) { - return; + return 0; } #endif + // The name length cannot exceed 80 (including the '\0'). assert(strlen(name) < 80); - int old_errno = errno; - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)addr, size, name); - /* Ignore errno from prctl */ - /* See: https://bugzilla.redhat.com/show_bug.cgi?id=2302746 */ - errno = old_errno; + int res = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)addr, size, name); + if (res < 0) { + return -1; + } + return 0; } #else -static inline void +static inline int _PyAnnotateMemoryMap(void *Py_UNUSED(addr), size_t Py_UNUSED(size), const char *Py_UNUSED(name)) { + return 0; } #endif diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 6b91e4334b169e..d14cee6af66103 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -252,25 +252,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) } } -static inline void -_Py_DECREF_NO_DEALLOC(PyObject *op) -{ - if (_Py_IsImmortal(op)) { - _Py_DECREF_IMMORTAL_STAT_INC(); - return; - } - _Py_DECREF_STAT_INC(); -#ifdef Py_REF_DEBUG - _Py_DEC_REFTOTAL(PyInterpreterState_Get()); -#endif - op->ob_refcnt--; -#ifdef Py_DEBUG - if (op->ob_refcnt <= 0) { - _Py_FatalRefcountError("Expected a positive remaining refcount"); - } -#endif -} - #else // TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build static inline void @@ -279,12 +260,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) Py_DECREF(op); } -static inline void -_Py_DECREF_NO_DEALLOC(PyObject *op) -{ - Py_DECREF(op); -} - static inline int _Py_REF_IS_MERGED(Py_ssize_t ob_ref_shared) { diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index a4f1f50e96d6d1..cd2475cd2374e8 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -534,7 +534,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case BINARY_OP_EXTEND: return 1; case BINARY_OP_INPLACE_ADD_UNICODE: - return 0; + return 1; case BINARY_OP_MULTIPLY_FLOAT: return 1; case BINARY_OP_MULTIPLY_INT: @@ -610,7 +610,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case CALL_LEN: return 1; case CALL_LIST_APPEND: - return 0; + return 1; case CALL_METHOD_DESCRIPTOR_FAST: return 1; case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: @@ -1081,7 +1081,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, - [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, @@ -1331,17 +1331,17 @@ _PyOpcode_macro_expansion[256] = { [BINARY_OP] = { .nuops = 1, .uops = { { _BINARY_OP, OPARG_SIMPLE, 4 } } }, [BINARY_OP_ADD_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_ADD_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_ADD_UNICODE] = { .nuops = 3, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_UNICODE, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_ADD_UNICODE] = { .nuops = 5, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 } } }, [BINARY_OP_EXTEND] = { .nuops = 2, .uops = { { _GUARD_BINARY_OP_EXTEND, 4, 1 }, { _BINARY_OP_EXTEND, 4, 1 } } }, [BINARY_OP_INPLACE_ADD_UNICODE] = { .nuops = 3, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_INPLACE_ADD_UNICODE, OPARG_SIMPLE, 5 } } }, [BINARY_OP_MULTIPLY_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_MULTIPLY_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_MULTIPLY_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_MULTIPLY_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_DICT] = { .nuops = 2, .uops = { { _GUARD_NOS_DICT, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_DICT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_GETITEM] = { .nuops = 4, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_CHECK_FUNC, OPARG_SIMPLE, 5 }, { _BINARY_OP_SUBSCR_INIT_CALL, OPARG_SIMPLE, 5 }, { _PUSH_FRAME, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_LIST_INT] = { .nuops = 3, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_INT, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_LIST_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBSCR_LIST_SLICE] = { .nuops = 3, .uops = { { _GUARD_TOS_SLICE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_LIST_SLICE, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_STR_INT] = { .nuops = 3, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_STR_INT, OPARG_SIMPLE, 5 } } }, - [BINARY_OP_SUBSCR_TUPLE_INT] = { .nuops = 3, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_TUPLE, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_TUPLE_INT, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_STR_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_STR_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, + [BINARY_OP_SUBSCR_TUPLE_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_TUPLE, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBSCR_TUPLE_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBTRACT_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBTRACT_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } }, [BINARY_OP_SUBTRACT_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_SUBTRACT_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } }, [BINARY_SLICE] = { .nuops = 1, .uops = { { _BINARY_SLICE, OPARG_SIMPLE, 0 } } }, @@ -1377,13 +1377,13 @@ _PyOpcode_macro_expansion[256] = { [CALL_PY_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_STR_1] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_STR_1, OPARG_SIMPLE, 3 }, { _CALL_STR_1, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_TUPLE_1] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TUPLE_1, OPARG_SIMPLE, 3 }, { _CALL_TUPLE_1, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_TYPE_1] = { .nuops = 3, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TYPE_1, OPARG_SIMPLE, 3 }, { _CALL_TYPE_1, OPARG_SIMPLE, 3 } } }, + [CALL_TYPE_1] = { .nuops = 4, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_TYPE_1, OPARG_SIMPLE, 3 }, { _CALL_TYPE_1, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { _CHECK_EG_MATCH, OPARG_SIMPLE, 0 } } }, [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { _CHECK_EXC_MATCH, OPARG_SIMPLE, 0 } } }, [COMPARE_OP] = { .nuops = 1, .uops = { { _COMPARE_OP, OPARG_SIMPLE, 0 } } }, - [COMPARE_OP_FLOAT] = { .nuops = 3, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _COMPARE_OP_FLOAT, OPARG_SIMPLE, 1 } } }, + [COMPARE_OP_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _COMPARE_OP_FLOAT, OPARG_SIMPLE, 1 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 1 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 1 } } }, [COMPARE_OP_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _COMPARE_OP_INT, OPARG_SIMPLE, 1 }, { _POP_TOP_INT, OPARG_SIMPLE, 1 }, { _POP_TOP_INT, OPARG_SIMPLE, 1 } } }, - [COMPARE_OP_STR] = { .nuops = 3, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _COMPARE_OP_STR, OPARG_SIMPLE, 1 } } }, + [COMPARE_OP_STR] = { .nuops = 5, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _COMPARE_OP_STR, OPARG_SIMPLE, 1 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 1 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 1 } } }, [CONTAINS_OP] = { .nuops = 1, .uops = { { _CONTAINS_OP, OPARG_SIMPLE, 0 } } }, [CONTAINS_OP_DICT] = { .nuops = 2, .uops = { { _GUARD_TOS_DICT, OPARG_SIMPLE, 0 }, { _CONTAINS_OP_DICT, OPARG_SIMPLE, 1 } } }, [CONTAINS_OP_SET] = { .nuops = 2, .uops = { { _GUARD_TOS_ANY_SET, OPARG_SIMPLE, 0 }, { _CONTAINS_OP_SET, OPARG_SIMPLE, 1 } } }, @@ -1416,7 +1416,7 @@ _PyOpcode_macro_expansion[256] = { [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { _GET_YIELD_FROM_ITER, OPARG_SIMPLE, 0 } } }, [IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } }, [IMPORT_NAME] = { .nuops = 1, .uops = { { _IMPORT_NAME, OPARG_SIMPLE, 0 } } }, - [IS_OP] = { .nuops = 1, .uops = { { _IS_OP, OPARG_SIMPLE, 0 } } }, + [IS_OP] = { .nuops = 3, .uops = { { _IS_OP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [JUMP_BACKWARD] = { .nuops = 2, .uops = { { _CHECK_PERIODIC, OPARG_SIMPLE, 1 }, { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 1 } } }, [JUMP_BACKWARD_NO_INTERRUPT] = { .nuops = 1, .uops = { { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 0 } } }, [JUMP_BACKWARD_NO_JIT] = { .nuops = 2, .uops = { { _CHECK_PERIODIC, OPARG_SIMPLE, 1 }, { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 1 } } }, @@ -1434,7 +1434,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, [LOAD_ATTR_PROPERTY] = { .nuops = 5, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_PROPERTY_FRAME, 4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_SLOT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, - [LOAD_ATTR_WITH_HINT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_WITH_HINT, 1, 3 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_WITH_HINT] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { _LOAD_BUILD_CLASS, OPARG_SIMPLE, 0 } } }, [LOAD_COMMON_CONSTANT] = { .nuops = 1, .uops = { { _LOAD_COMMON_CONSTANT, OPARG_SIMPLE, 0 } } }, [LOAD_CONST] = { .nuops = 1, .uops = { { _LOAD_CONST, OPARG_SIMPLE, 0 } } }, diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 295d4909e14735..6a0fc1a59e7965 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -25,9 +25,9 @@ typedef struct { uint8_t opcode; uint8_t oparg; uint8_t valid; - uint8_t linked; uint8_t chain_depth; // Must be big enough for MAX_CHAIN_DEPTH - 1. bool warm; + uint8_t pending_deletion; int32_t index; // Index of ENTER_EXECUTOR (if code isn't NULL, below). _PyBloomFilter bloom; _PyExecutorLinkListNode links; @@ -55,11 +55,6 @@ typedef struct _PyExecutorObject { _PyExitData exits[1]; } _PyExecutorObject; -/* If pending deletion list gets large enough, then scan, - * and free any executors that aren't executing - * i.e. any that aren't a thread's current_executor. */ -#define EXECUTOR_DELETE_LIST_MAX 100 - // Export for '_opcode' shared extension (JIT compiler). PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset); @@ -80,7 +75,6 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp); #else # define _Py_Executors_InvalidateDependency(A, B, C) ((void)0) # define _Py_Executors_InvalidateAll(A, B) ((void)0) -# define _Py_Executors_InvalidateCold(A) ((void)0) #endif diff --git a/Include/internal/pycore_parser.h b/Include/internal/pycore_parser.h index 2c46f59ab7da9f..b89d02035db71f 100644 --- a/Include/internal/pycore_parser.h +++ b/Include/internal/pycore_parser.h @@ -14,10 +14,8 @@ extern "C" { #include "pycore_pyarena.h" // PyArena _Py_DECLARE_STR(empty, "") -#if defined(Py_DEBUG) && defined(Py_GIL_DISABLED) #define _parser_runtime_state_INIT \ { \ - .mutex = {0}, \ .dummy_name = { \ .kind = Name_kind, \ .v.Name.id = &_Py_STR(empty), \ @@ -28,20 +26,6 @@ _Py_DECLARE_STR(empty, "") .end_col_offset = 0, \ }, \ } -#else -#define _parser_runtime_state_INIT \ - { \ - .dummy_name = { \ - .kind = Name_kind, \ - .v.Name.id = &_Py_STR(empty), \ - .v.Name.ctx = Load, \ - .lineno = 1, \ - .col_offset = 0, \ - .end_lineno = 1, \ - .end_col_offset = 0, \ - }, \ - } -#endif extern struct _mod* _PyParser_ASTFromString( const char *str, diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index 1a6d5075361f3c..70a32db663b293 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -41,6 +41,8 @@ extern "C" { _Py_atomic_load_uint8(&value) #define FT_ATOMIC_STORE_UINT8(value, new_value) \ _Py_atomic_store_uint8(&value, new_value) +#define FT_ATOMIC_LOAD_INT8_RELAXED(value) \ + _Py_atomic_load_int8_relaxed(&value) #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) \ _Py_atomic_load_uint8_relaxed(&value) #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) \ @@ -55,6 +57,10 @@ extern "C" { _Py_atomic_store_ptr_release(&value, new_value) #define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) \ _Py_atomic_store_uintptr_release(&value, new_value) +#define FT_ATOMIC_STORE_INT8_RELAXED(value, new_value) \ + _Py_atomic_store_int8_relaxed(&value, new_value) +#define FT_ATOMIC_STORE_INT8_RELEASE(value, new_value) \ + _Py_atomic_store_int8_release(&value, new_value) #define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) \ _Py_atomic_store_ssize_relaxed(&value, new_value) #define FT_ATOMIC_STORE_SSIZE_RELEASE(value, new_value) \ @@ -134,6 +140,7 @@ extern "C" { #define FT_ATOMIC_LOAD_PTR_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT8(value) value #define FT_ATOMIC_STORE_UINT8(value, new_value) value = new_value +#define FT_ATOMIC_LOAD_INT8_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value @@ -141,6 +148,8 @@ extern "C" { #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value +#define FT_ATOMIC_STORE_INT8_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_STORE_INT8_RELEASE(value, new_value) value = new_value #define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_SSIZE_RELEASE(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index d381fb9d2d42a3..499a2569b9a06c 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1651,9 +1651,11 @@ extern "C" { INIT_ID(co_varnames), \ INIT_ID(code), \ INIT_ID(col_offset), \ + INIT_ID(collector), \ INIT_ID(command), \ INIT_ID(comment_factory), \ INIT_ID(compile_mode), \ + INIT_ID(compression), \ INIT_ID(config), \ INIT_ID(consts), \ INIT_ID(context), \ @@ -1716,7 +1718,9 @@ extern "C" { INIT_ID(event), \ INIT_ID(eventmask), \ INIT_ID(exc), \ + INIT_ID(exc_tb), \ INIT_ID(exc_type), \ + INIT_ID(exc_val), \ INIT_ID(exc_value), \ INIT_ID(excepthook), \ INIT_ID(exception), \ @@ -1972,6 +1976,7 @@ extern "C" { INIT_ID(print_file_and_line), \ INIT_ID(priority), \ INIT_ID(progress), \ + INIT_ID(progress_callback), \ INIT_ID(progress_routine), \ INIT_ID(proto), \ INIT_ID(protocol), \ @@ -2012,6 +2017,7 @@ extern "C" { INIT_ID(reversed), \ INIT_ID(rounding), \ INIT_ID(salt), \ + INIT_ID(sample_interval_us), \ INIT_ID(sched_priority), \ INIT_ID(scheduler), \ INIT_ID(script), \ @@ -2051,8 +2057,10 @@ extern "C" { INIT_ID(spam), \ INIT_ID(src), \ INIT_ID(src_dir_fd), \ + INIT_ID(stack_frames), \ INIT_ID(stacklevel), \ INIT_ID(start), \ + INIT_ID(start_time_us), \ INIT_ID(statement), \ INIT_ID(stats), \ INIT_ID(status), \ @@ -2093,6 +2101,7 @@ extern "C" { INIT_ID(times), \ INIT_ID(timespec), \ INIT_ID(timestamp), \ + INIT_ID(timestamp_us), \ INIT_ID(timetuple), \ INIT_ID(timeunit), \ INIT_ID(top), \ diff --git a/Include/internal/pycore_runtime_structs.h b/Include/internal/pycore_runtime_structs.h index 995f49e78dcda3..92387031ad7465 100644 --- a/Include/internal/pycore_runtime_structs.h +++ b/Include/internal/pycore_runtime_structs.h @@ -77,9 +77,7 @@ struct _fileutils_state { struct _parser_runtime_state { #ifdef Py_DEBUG long memo_statistics[_PYPEGEN_NSTATISTICS]; -#ifdef Py_GIL_DISABLED PyMutex mutex; -#endif #else int _not_used; #endif diff --git a/Include/internal/pycore_tracemalloc.h b/Include/internal/pycore_tracemalloc.h index 693385f9a46d12..9974ea3c4143fa 100644 --- a/Include/internal/pycore_tracemalloc.h +++ b/Include/internal/pycore_tracemalloc.h @@ -21,7 +21,10 @@ struct _PyTraceMalloc_Config { } initialized; /* Is tracemalloc tracing memory allocations? - Variable protected by the TABLES_LOCK(). */ + Variable protected by the TABLES_LOCK() and stored atomically. + Atomic store is used so that it can read without locking for the + general case of checking if tracemalloc is enabled. + */ int tracing; /* limit of the number of frames in a traceback, 1 by default. diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index c4f723ac8abbbe..1a7ebb01403208 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -37,7 +37,6 @@ typedef struct _PyJitTracerInitialState { typedef struct _PyJitTracerPreviousState { bool dependencies_still_valid; - bool instr_is_super; int code_max_size; int code_curr_size; int instr_oparg; @@ -82,6 +81,13 @@ typedef struct _PyThreadStateImpl { PyObject *asyncio_running_loop; // Strong reference PyObject *asyncio_running_task; // Strong reference + // Distinguishes between yield and return from PyEval_EvalFrame(). + // See gen_send_ex2() in Objects/genobject.c + enum { + GENERATOR_RETURN = 0, + GENERATOR_YIELD = 1, + } generator_return_kind; + /* Head of circular linked-list of all tasks which are instances of `asyncio.Task` or subclasses of it used in `asyncio.all_tasks`. */ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 24e50828935106..1375f46018f943 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1284,6 +1284,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(collector); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(command); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1296,6 +1300,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(compression); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(config); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1544,10 +1552,18 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(exc_tb); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(exc_type); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(exc_val); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(exc_value); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2568,6 +2584,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(progress_callback); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(progress_routine); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2728,6 +2748,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(sample_interval_us); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(sched_priority); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2884,6 +2908,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(stack_frames); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(stacklevel); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2892,6 +2920,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(start_time_us); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(statement); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -3052,6 +3084,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(timestamp_us); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(timetuple); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 8678ccf5e1b823..b146c4ea39b4a9 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -189,914 +189,929 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE #define _IS_NONE 435 -#define _IS_OP IS_OP -#define _ITER_CHECK_LIST 436 -#define _ITER_CHECK_RANGE 437 -#define _ITER_CHECK_TUPLE 438 -#define _ITER_JUMP_LIST 439 -#define _ITER_JUMP_RANGE 440 -#define _ITER_JUMP_TUPLE 441 -#define _ITER_NEXT_LIST 442 -#define _ITER_NEXT_LIST_TIER_TWO 443 -#define _ITER_NEXT_RANGE 444 -#define _ITER_NEXT_TUPLE 445 +#define _IS_OP 436 +#define _ITER_CHECK_LIST 437 +#define _ITER_CHECK_RANGE 438 +#define _ITER_CHECK_TUPLE 439 +#define _ITER_JUMP_LIST 440 +#define _ITER_JUMP_RANGE 441 +#define _ITER_JUMP_TUPLE 442 +#define _ITER_NEXT_LIST 443 +#define _ITER_NEXT_LIST_TIER_TWO 444 +#define _ITER_NEXT_RANGE 445 +#define _ITER_NEXT_TUPLE 446 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 446 +#define _JUMP_TO_TOP 447 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 447 -#define _LOAD_ATTR_CLASS 448 +#define _LOAD_ATTR 448 +#define _LOAD_ATTR_CLASS 449 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 449 -#define _LOAD_ATTR_METHOD_LAZY_DICT 450 -#define _LOAD_ATTR_METHOD_NO_DICT 451 -#define _LOAD_ATTR_METHOD_WITH_VALUES 452 -#define _LOAD_ATTR_MODULE 453 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 454 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 455 -#define _LOAD_ATTR_PROPERTY_FRAME 456 -#define _LOAD_ATTR_SLOT 457 -#define _LOAD_ATTR_WITH_HINT 458 +#define _LOAD_ATTR_INSTANCE_VALUE 450 +#define _LOAD_ATTR_METHOD_LAZY_DICT 451 +#define _LOAD_ATTR_METHOD_NO_DICT 452 +#define _LOAD_ATTR_METHOD_WITH_VALUES 453 +#define _LOAD_ATTR_MODULE 454 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 455 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 456 +#define _LOAD_ATTR_PROPERTY_FRAME 457 +#define _LOAD_ATTR_SLOT 458 +#define _LOAD_ATTR_WITH_HINT 459 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 459 +#define _LOAD_BYTECODE 460 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 460 -#define _LOAD_CONST_INLINE_BORROW 461 -#define _LOAD_CONST_UNDER_INLINE 462 -#define _LOAD_CONST_UNDER_INLINE_BORROW 463 +#define _LOAD_CONST_INLINE 461 +#define _LOAD_CONST_INLINE_BORROW 462 +#define _LOAD_CONST_UNDER_INLINE 463 +#define _LOAD_CONST_UNDER_INLINE_BORROW 464 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 464 -#define _LOAD_FAST_0 465 -#define _LOAD_FAST_1 466 -#define _LOAD_FAST_2 467 -#define _LOAD_FAST_3 468 -#define _LOAD_FAST_4 469 -#define _LOAD_FAST_5 470 -#define _LOAD_FAST_6 471 -#define _LOAD_FAST_7 472 +#define _LOAD_FAST 465 +#define _LOAD_FAST_0 466 +#define _LOAD_FAST_1 467 +#define _LOAD_FAST_2 468 +#define _LOAD_FAST_3 469 +#define _LOAD_FAST_4 470 +#define _LOAD_FAST_5 471 +#define _LOAD_FAST_6 472 +#define _LOAD_FAST_7 473 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 473 -#define _LOAD_FAST_BORROW_0 474 -#define _LOAD_FAST_BORROW_1 475 -#define _LOAD_FAST_BORROW_2 476 -#define _LOAD_FAST_BORROW_3 477 -#define _LOAD_FAST_BORROW_4 478 -#define _LOAD_FAST_BORROW_5 479 -#define _LOAD_FAST_BORROW_6 480 -#define _LOAD_FAST_BORROW_7 481 +#define _LOAD_FAST_BORROW 474 +#define _LOAD_FAST_BORROW_0 475 +#define _LOAD_FAST_BORROW_1 476 +#define _LOAD_FAST_BORROW_2 477 +#define _LOAD_FAST_BORROW_3 478 +#define _LOAD_FAST_BORROW_4 479 +#define _LOAD_FAST_BORROW_5 480 +#define _LOAD_FAST_BORROW_6 481 +#define _LOAD_FAST_BORROW_7 482 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 482 -#define _LOAD_GLOBAL_BUILTINS 483 -#define _LOAD_GLOBAL_MODULE 484 +#define _LOAD_GLOBAL 483 +#define _LOAD_GLOBAL_BUILTINS 484 +#define _LOAD_GLOBAL_MODULE 485 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 485 -#define _LOAD_SMALL_INT_0 486 -#define _LOAD_SMALL_INT_1 487 -#define _LOAD_SMALL_INT_2 488 -#define _LOAD_SMALL_INT_3 489 -#define _LOAD_SPECIAL 490 +#define _LOAD_SMALL_INT 486 +#define _LOAD_SMALL_INT_0 487 +#define _LOAD_SMALL_INT_1 488 +#define _LOAD_SMALL_INT_2 489 +#define _LOAD_SMALL_INT_3 490 +#define _LOAD_SPECIAL 491 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 491 +#define _MAKE_CALLARGS_A_TUPLE 492 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 492 +#define _MAKE_WARM 493 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 493 -#define _MAYBE_EXPAND_METHOD_KW 494 -#define _MONITOR_CALL 495 -#define _MONITOR_CALL_KW 496 -#define _MONITOR_JUMP_BACKWARD 497 -#define _MONITOR_RESUME 498 +#define _MAYBE_EXPAND_METHOD 494 +#define _MAYBE_EXPAND_METHOD_KW 495 +#define _MONITOR_CALL 496 +#define _MONITOR_CALL_KW 497 +#define _MONITOR_JUMP_BACKWARD 498 +#define _MONITOR_RESUME 499 #define _NOP NOP -#define _POP_CALL 499 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 500 -#define _POP_CALL_ONE 501 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 502 -#define _POP_CALL_TWO 503 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 504 +#define _POP_CALL 500 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 501 +#define _POP_CALL_ONE 502 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 503 +#define _POP_CALL_TWO 504 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 505 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 505 -#define _POP_JUMP_IF_TRUE 506 +#define _POP_JUMP_IF_FALSE 506 +#define _POP_JUMP_IF_TRUE 507 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 507 -#define _POP_TOP_INT 508 -#define _POP_TOP_LOAD_CONST_INLINE 509 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 510 -#define _POP_TOP_NOP 511 -#define _POP_TOP_UNICODE 512 -#define _POP_TWO 513 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 514 +#define _POP_TOP_FLOAT 508 +#define _POP_TOP_INT 509 +#define _POP_TOP_LOAD_CONST_INLINE 510 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 511 +#define _POP_TOP_NOP 512 +#define _POP_TOP_UNICODE 513 +#define _POP_TWO 514 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 515 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 515 +#define _PUSH_FRAME 516 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 516 -#define _PY_FRAME_GENERAL 517 -#define _PY_FRAME_KW 518 -#define _QUICKEN_RESUME 519 -#define _REPLACE_WITH_TRUE 520 +#define _PUSH_NULL_CONDITIONAL 517 +#define _PY_FRAME_GENERAL 518 +#define _PY_FRAME_KW 519 +#define _QUICKEN_RESUME 520 +#define _REPLACE_WITH_TRUE 521 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 521 -#define _SEND 522 -#define _SEND_GEN_FRAME 523 +#define _SAVE_RETURN_OFFSET 522 +#define _SEND 523 +#define _SEND_GEN_FRAME 524 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SPILL_OR_RELOAD 524 -#define _START_EXECUTOR 525 -#define _STORE_ATTR 526 -#define _STORE_ATTR_INSTANCE_VALUE 527 -#define _STORE_ATTR_SLOT 528 -#define _STORE_ATTR_WITH_HINT 529 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 525 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 526 +#define _SPILL_OR_RELOAD 527 +#define _START_EXECUTOR 528 +#define _STORE_ATTR 529 +#define _STORE_ATTR_INSTANCE_VALUE 530 +#define _STORE_ATTR_SLOT 531 +#define _STORE_ATTR_WITH_HINT 532 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 530 -#define _STORE_FAST_0 531 -#define _STORE_FAST_1 532 -#define _STORE_FAST_2 533 -#define _STORE_FAST_3 534 -#define _STORE_FAST_4 535 -#define _STORE_FAST_5 536 -#define _STORE_FAST_6 537 -#define _STORE_FAST_7 538 +#define _STORE_FAST 533 +#define _STORE_FAST_0 534 +#define _STORE_FAST_1 535 +#define _STORE_FAST_2 536 +#define _STORE_FAST_3 537 +#define _STORE_FAST_4 538 +#define _STORE_FAST_5 539 +#define _STORE_FAST_6 540 +#define _STORE_FAST_7 541 #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 539 -#define _STORE_SUBSCR 540 -#define _STORE_SUBSCR_DICT 541 -#define _STORE_SUBSCR_LIST_INT 542 -#define _SWAP 543 -#define _SWAP_2 544 -#define _SWAP_3 545 -#define _TIER2_RESUME_CHECK 546 -#define _TO_BOOL 547 +#define _STORE_SLICE 542 +#define _STORE_SUBSCR 543 +#define _STORE_SUBSCR_DICT 544 +#define _STORE_SUBSCR_LIST_INT 545 +#define _SWAP 546 +#define _SWAP_2 547 +#define _SWAP_3 548 +#define _TIER2_RESUME_CHECK 549 +#define _TO_BOOL 550 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 548 +#define _TO_BOOL_LIST 551 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 549 +#define _TO_BOOL_STR 552 #define _TRACE_RECORD TRACE_RECORD #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 550 -#define _UNPACK_SEQUENCE_LIST 551 -#define _UNPACK_SEQUENCE_TUPLE 552 -#define _UNPACK_SEQUENCE_TWO_TUPLE 553 +#define _UNPACK_SEQUENCE 553 +#define _UNPACK_SEQUENCE_LIST 554 +#define _UNPACK_SEQUENCE_TUPLE 555 +#define _UNPACK_SEQUENCE_TWO_TUPLE 556 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 553 -#define _BINARY_OP_r21 554 -#define _BINARY_OP_ADD_FLOAT_r03 555 -#define _BINARY_OP_ADD_FLOAT_r13 556 -#define _BINARY_OP_ADD_FLOAT_r23 557 -#define _BINARY_OP_ADD_INT_r03 558 -#define _BINARY_OP_ADD_INT_r13 559 -#define _BINARY_OP_ADD_INT_r23 560 -#define _BINARY_OP_ADD_UNICODE_r01 561 -#define _BINARY_OP_ADD_UNICODE_r11 562 -#define _BINARY_OP_ADD_UNICODE_r21 563 -#define _BINARY_OP_ADD_UNICODE_r32 564 -#define _BINARY_OP_EXTEND_r21 565 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r20 566 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 567 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 568 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 569 -#define _BINARY_OP_MULTIPLY_INT_r03 570 -#define _BINARY_OP_MULTIPLY_INT_r13 571 -#define _BINARY_OP_MULTIPLY_INT_r23 572 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 573 -#define _BINARY_OP_SUBSCR_DICT_r21 574 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 575 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 576 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 577 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 578 -#define _BINARY_OP_SUBSCR_LIST_INT_r21 579 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r21 580 -#define _BINARY_OP_SUBSCR_STR_INT_r21 581 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r21 582 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 583 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 584 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 585 -#define _BINARY_OP_SUBTRACT_INT_r03 586 -#define _BINARY_OP_SUBTRACT_INT_r13 587 -#define _BINARY_OP_SUBTRACT_INT_r23 588 -#define _BINARY_SLICE_r31 589 -#define _BUILD_INTERPOLATION_r01 590 -#define _BUILD_LIST_r01 591 -#define _BUILD_MAP_r01 592 -#define _BUILD_SET_r01 593 -#define _BUILD_SLICE_r01 594 -#define _BUILD_STRING_r01 595 -#define _BUILD_TEMPLATE_r21 596 -#define _BUILD_TUPLE_r01 597 -#define _CALL_BUILTIN_CLASS_r01 598 -#define _CALL_BUILTIN_FAST_r01 599 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 600 -#define _CALL_BUILTIN_O_r03 601 -#define _CALL_INTRINSIC_1_r11 602 -#define _CALL_INTRINSIC_2_r21 603 -#define _CALL_ISINSTANCE_r31 604 -#define _CALL_KW_NON_PY_r11 605 -#define _CALL_LEN_r33 606 -#define _CALL_LIST_APPEND_r02 607 -#define _CALL_LIST_APPEND_r12 608 -#define _CALL_LIST_APPEND_r22 609 -#define _CALL_LIST_APPEND_r32 610 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 611 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 612 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 613 -#define _CALL_METHOD_DESCRIPTOR_O_r01 614 -#define _CALL_NON_PY_GENERAL_r01 615 -#define _CALL_STR_1_r32 616 -#define _CALL_TUPLE_1_r32 617 -#define _CALL_TYPE_1_r31 618 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 619 -#define _CHECK_ATTR_CLASS_r01 620 -#define _CHECK_ATTR_CLASS_r11 621 -#define _CHECK_ATTR_CLASS_r22 622 -#define _CHECK_ATTR_CLASS_r33 623 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 624 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 625 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 626 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 627 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 628 -#define _CHECK_EG_MATCH_r22 629 -#define _CHECK_EXC_MATCH_r22 630 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 631 -#define _CHECK_FUNCTION_VERSION_r00 632 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 633 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 634 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 635 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 636 -#define _CHECK_FUNCTION_VERSION_KW_r11 637 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 638 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 639 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 640 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 641 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 642 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 643 -#define _CHECK_METHOD_VERSION_r00 644 -#define _CHECK_METHOD_VERSION_KW_r11 645 -#define _CHECK_PEP_523_r00 646 -#define _CHECK_PEP_523_r11 647 -#define _CHECK_PEP_523_r22 648 -#define _CHECK_PEP_523_r33 649 -#define _CHECK_PERIODIC_r00 650 -#define _CHECK_PERIODIC_AT_END_r00 651 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 652 -#define _CHECK_RECURSION_REMAINING_r00 653 -#define _CHECK_RECURSION_REMAINING_r11 654 -#define _CHECK_RECURSION_REMAINING_r22 655 -#define _CHECK_RECURSION_REMAINING_r33 656 -#define _CHECK_STACK_SPACE_r00 657 -#define _CHECK_STACK_SPACE_OPERAND_r00 658 -#define _CHECK_STACK_SPACE_OPERAND_r11 659 -#define _CHECK_STACK_SPACE_OPERAND_r22 660 -#define _CHECK_STACK_SPACE_OPERAND_r33 661 -#define _CHECK_VALIDITY_r00 662 -#define _CHECK_VALIDITY_r11 663 -#define _CHECK_VALIDITY_r22 664 -#define _CHECK_VALIDITY_r33 665 -#define _COLD_DYNAMIC_EXIT_r00 666 -#define _COLD_EXIT_r00 667 -#define _COMPARE_OP_r21 668 -#define _COMPARE_OP_FLOAT_r01 669 -#define _COMPARE_OP_FLOAT_r11 670 -#define _COMPARE_OP_FLOAT_r21 671 -#define _COMPARE_OP_FLOAT_r32 672 -#define _COMPARE_OP_INT_r23 673 -#define _COMPARE_OP_STR_r21 674 -#define _CONTAINS_OP_r21 675 -#define _CONTAINS_OP_DICT_r21 676 -#define _CONTAINS_OP_SET_r21 677 -#define _CONVERT_VALUE_r11 678 -#define _COPY_r01 679 -#define _COPY_1_r02 680 -#define _COPY_1_r12 681 -#define _COPY_1_r23 682 -#define _COPY_2_r03 683 -#define _COPY_2_r13 684 -#define _COPY_2_r23 685 -#define _COPY_3_r03 686 -#define _COPY_3_r13 687 -#define _COPY_3_r23 688 -#define _COPY_3_r33 689 -#define _COPY_FREE_VARS_r00 690 -#define _COPY_FREE_VARS_r11 691 -#define _COPY_FREE_VARS_r22 692 -#define _COPY_FREE_VARS_r33 693 -#define _CREATE_INIT_FRAME_r01 694 -#define _DELETE_ATTR_r10 695 -#define _DELETE_DEREF_r00 696 -#define _DELETE_FAST_r00 697 -#define _DELETE_GLOBAL_r00 698 -#define _DELETE_NAME_r00 699 -#define _DELETE_SUBSCR_r20 700 -#define _DEOPT_r00 701 -#define _DEOPT_r10 702 -#define _DEOPT_r20 703 -#define _DEOPT_r30 704 -#define _DICT_MERGE_r10 705 -#define _DICT_UPDATE_r10 706 -#define _DO_CALL_r01 707 -#define _DO_CALL_FUNCTION_EX_r31 708 -#define _DO_CALL_KW_r11 709 -#define _DYNAMIC_EXIT_r00 710 -#define _DYNAMIC_EXIT_r10 711 -#define _DYNAMIC_EXIT_r20 712 -#define _DYNAMIC_EXIT_r30 713 -#define _END_FOR_r10 714 -#define _END_SEND_r21 715 -#define _ERROR_POP_N_r00 716 -#define _EXIT_INIT_CHECK_r10 717 -#define _EXIT_TRACE_r00 718 -#define _EXIT_TRACE_r10 719 -#define _EXIT_TRACE_r20 720 -#define _EXIT_TRACE_r30 721 -#define _EXPAND_METHOD_r00 722 -#define _EXPAND_METHOD_KW_r11 723 -#define _FATAL_ERROR_r00 724 -#define _FATAL_ERROR_r11 725 -#define _FATAL_ERROR_r22 726 -#define _FATAL_ERROR_r33 727 -#define _FORMAT_SIMPLE_r11 728 -#define _FORMAT_WITH_SPEC_r21 729 -#define _FOR_ITER_r23 730 -#define _FOR_ITER_GEN_FRAME_r23 731 -#define _FOR_ITER_TIER_TWO_r23 732 -#define _GET_AITER_r11 733 -#define _GET_ANEXT_r12 734 -#define _GET_AWAITABLE_r11 735 -#define _GET_ITER_r12 736 -#define _GET_LEN_r12 737 -#define _GET_YIELD_FROM_ITER_r11 738 -#define _GUARD_BINARY_OP_EXTEND_r22 739 -#define _GUARD_CALLABLE_ISINSTANCE_r03 740 -#define _GUARD_CALLABLE_ISINSTANCE_r13 741 -#define _GUARD_CALLABLE_ISINSTANCE_r23 742 -#define _GUARD_CALLABLE_ISINSTANCE_r33 743 -#define _GUARD_CALLABLE_LEN_r03 744 -#define _GUARD_CALLABLE_LEN_r13 745 -#define _GUARD_CALLABLE_LEN_r23 746 -#define _GUARD_CALLABLE_LEN_r33 747 -#define _GUARD_CALLABLE_LIST_APPEND_r03 748 -#define _GUARD_CALLABLE_LIST_APPEND_r13 749 -#define _GUARD_CALLABLE_LIST_APPEND_r23 750 -#define _GUARD_CALLABLE_LIST_APPEND_r33 751 -#define _GUARD_CALLABLE_STR_1_r03 752 -#define _GUARD_CALLABLE_STR_1_r13 753 -#define _GUARD_CALLABLE_STR_1_r23 754 -#define _GUARD_CALLABLE_STR_1_r33 755 -#define _GUARD_CALLABLE_TUPLE_1_r03 756 -#define _GUARD_CALLABLE_TUPLE_1_r13 757 -#define _GUARD_CALLABLE_TUPLE_1_r23 758 -#define _GUARD_CALLABLE_TUPLE_1_r33 759 -#define _GUARD_CALLABLE_TYPE_1_r03 760 -#define _GUARD_CALLABLE_TYPE_1_r13 761 -#define _GUARD_CALLABLE_TYPE_1_r23 762 -#define _GUARD_CALLABLE_TYPE_1_r33 763 -#define _GUARD_DORV_NO_DICT_r01 764 -#define _GUARD_DORV_NO_DICT_r11 765 -#define _GUARD_DORV_NO_DICT_r22 766 -#define _GUARD_DORV_NO_DICT_r33 767 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 768 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 769 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 770 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 771 -#define _GUARD_GLOBALS_VERSION_r00 772 -#define _GUARD_GLOBALS_VERSION_r11 773 -#define _GUARD_GLOBALS_VERSION_r22 774 -#define _GUARD_GLOBALS_VERSION_r33 775 -#define _GUARD_IP_RETURN_GENERATOR_r00 776 -#define _GUARD_IP_RETURN_GENERATOR_r11 777 -#define _GUARD_IP_RETURN_GENERATOR_r22 778 -#define _GUARD_IP_RETURN_GENERATOR_r33 779 -#define _GUARD_IP_RETURN_VALUE_r00 780 -#define _GUARD_IP_RETURN_VALUE_r11 781 -#define _GUARD_IP_RETURN_VALUE_r22 782 -#define _GUARD_IP_RETURN_VALUE_r33 783 -#define _GUARD_IP_YIELD_VALUE_r00 784 -#define _GUARD_IP_YIELD_VALUE_r11 785 -#define _GUARD_IP_YIELD_VALUE_r22 786 -#define _GUARD_IP_YIELD_VALUE_r33 787 -#define _GUARD_IP__PUSH_FRAME_r00 788 -#define _GUARD_IP__PUSH_FRAME_r11 789 -#define _GUARD_IP__PUSH_FRAME_r22 790 -#define _GUARD_IP__PUSH_FRAME_r33 791 -#define _GUARD_IS_FALSE_POP_r00 792 -#define _GUARD_IS_FALSE_POP_r10 793 -#define _GUARD_IS_FALSE_POP_r21 794 -#define _GUARD_IS_FALSE_POP_r32 795 -#define _GUARD_IS_NONE_POP_r00 796 -#define _GUARD_IS_NONE_POP_r10 797 -#define _GUARD_IS_NONE_POP_r21 798 -#define _GUARD_IS_NONE_POP_r32 799 -#define _GUARD_IS_NOT_NONE_POP_r10 800 -#define _GUARD_IS_TRUE_POP_r00 801 -#define _GUARD_IS_TRUE_POP_r10 802 -#define _GUARD_IS_TRUE_POP_r21 803 -#define _GUARD_IS_TRUE_POP_r32 804 -#define _GUARD_KEYS_VERSION_r01 805 -#define _GUARD_KEYS_VERSION_r11 806 -#define _GUARD_KEYS_VERSION_r22 807 -#define _GUARD_KEYS_VERSION_r33 808 -#define _GUARD_NOS_DICT_r02 809 -#define _GUARD_NOS_DICT_r12 810 -#define _GUARD_NOS_DICT_r22 811 -#define _GUARD_NOS_DICT_r33 812 -#define _GUARD_NOS_FLOAT_r02 813 -#define _GUARD_NOS_FLOAT_r12 814 -#define _GUARD_NOS_FLOAT_r22 815 -#define _GUARD_NOS_FLOAT_r33 816 -#define _GUARD_NOS_INT_r02 817 -#define _GUARD_NOS_INT_r12 818 -#define _GUARD_NOS_INT_r22 819 -#define _GUARD_NOS_INT_r33 820 -#define _GUARD_NOS_LIST_r02 821 -#define _GUARD_NOS_LIST_r12 822 -#define _GUARD_NOS_LIST_r22 823 -#define _GUARD_NOS_LIST_r33 824 -#define _GUARD_NOS_NOT_NULL_r02 825 -#define _GUARD_NOS_NOT_NULL_r12 826 -#define _GUARD_NOS_NOT_NULL_r22 827 -#define _GUARD_NOS_NOT_NULL_r33 828 -#define _GUARD_NOS_NULL_r02 829 -#define _GUARD_NOS_NULL_r12 830 -#define _GUARD_NOS_NULL_r22 831 -#define _GUARD_NOS_NULL_r33 832 -#define _GUARD_NOS_OVERFLOWED_r02 833 -#define _GUARD_NOS_OVERFLOWED_r12 834 -#define _GUARD_NOS_OVERFLOWED_r22 835 -#define _GUARD_NOS_OVERFLOWED_r33 836 -#define _GUARD_NOS_TUPLE_r02 837 -#define _GUARD_NOS_TUPLE_r12 838 -#define _GUARD_NOS_TUPLE_r22 839 -#define _GUARD_NOS_TUPLE_r33 840 -#define _GUARD_NOS_UNICODE_r02 841 -#define _GUARD_NOS_UNICODE_r12 842 -#define _GUARD_NOS_UNICODE_r22 843 -#define _GUARD_NOS_UNICODE_r33 844 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 845 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 846 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 847 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 848 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 849 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 850 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 851 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 852 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 853 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 854 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 855 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 856 -#define _GUARD_THIRD_NULL_r03 857 -#define _GUARD_THIRD_NULL_r13 858 -#define _GUARD_THIRD_NULL_r23 859 -#define _GUARD_THIRD_NULL_r33 860 -#define _GUARD_TOS_ANY_SET_r01 861 -#define _GUARD_TOS_ANY_SET_r11 862 -#define _GUARD_TOS_ANY_SET_r22 863 -#define _GUARD_TOS_ANY_SET_r33 864 -#define _GUARD_TOS_DICT_r01 865 -#define _GUARD_TOS_DICT_r11 866 -#define _GUARD_TOS_DICT_r22 867 -#define _GUARD_TOS_DICT_r33 868 -#define _GUARD_TOS_FLOAT_r01 869 -#define _GUARD_TOS_FLOAT_r11 870 -#define _GUARD_TOS_FLOAT_r22 871 -#define _GUARD_TOS_FLOAT_r33 872 -#define _GUARD_TOS_INT_r01 873 -#define _GUARD_TOS_INT_r11 874 -#define _GUARD_TOS_INT_r22 875 -#define _GUARD_TOS_INT_r33 876 -#define _GUARD_TOS_LIST_r01 877 -#define _GUARD_TOS_LIST_r11 878 -#define _GUARD_TOS_LIST_r22 879 -#define _GUARD_TOS_LIST_r33 880 -#define _GUARD_TOS_OVERFLOWED_r01 881 -#define _GUARD_TOS_OVERFLOWED_r11 882 -#define _GUARD_TOS_OVERFLOWED_r22 883 -#define _GUARD_TOS_OVERFLOWED_r33 884 -#define _GUARD_TOS_SLICE_r01 885 -#define _GUARD_TOS_SLICE_r11 886 -#define _GUARD_TOS_SLICE_r22 887 -#define _GUARD_TOS_SLICE_r33 888 -#define _GUARD_TOS_TUPLE_r01 889 -#define _GUARD_TOS_TUPLE_r11 890 -#define _GUARD_TOS_TUPLE_r22 891 -#define _GUARD_TOS_TUPLE_r33 892 -#define _GUARD_TOS_UNICODE_r01 893 -#define _GUARD_TOS_UNICODE_r11 894 -#define _GUARD_TOS_UNICODE_r22 895 -#define _GUARD_TOS_UNICODE_r33 896 -#define _GUARD_TYPE_VERSION_r01 897 -#define _GUARD_TYPE_VERSION_r11 898 -#define _GUARD_TYPE_VERSION_r22 899 -#define _GUARD_TYPE_VERSION_r33 900 -#define _GUARD_TYPE_VERSION_AND_LOCK_r01 901 -#define _GUARD_TYPE_VERSION_AND_LOCK_r11 902 -#define _GUARD_TYPE_VERSION_AND_LOCK_r22 903 -#define _GUARD_TYPE_VERSION_AND_LOCK_r33 904 -#define _HANDLE_PENDING_AND_DEOPT_r00 905 -#define _HANDLE_PENDING_AND_DEOPT_r10 906 -#define _HANDLE_PENDING_AND_DEOPT_r20 907 -#define _HANDLE_PENDING_AND_DEOPT_r30 908 -#define _IMPORT_FROM_r12 909 -#define _IMPORT_NAME_r21 910 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 911 -#define _INIT_CALL_PY_EXACT_ARGS_r01 912 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 913 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 914 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 915 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 916 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 917 -#define _INSERT_NULL_r10 918 -#define _INSTRUMENTED_FOR_ITER_r23 919 -#define _INSTRUMENTED_INSTRUCTION_r00 920 -#define _INSTRUMENTED_JUMP_FORWARD_r00 921 -#define _INSTRUMENTED_JUMP_FORWARD_r11 922 -#define _INSTRUMENTED_JUMP_FORWARD_r22 923 -#define _INSTRUMENTED_JUMP_FORWARD_r33 924 -#define _INSTRUMENTED_LINE_r00 925 -#define _INSTRUMENTED_NOT_TAKEN_r00 926 -#define _INSTRUMENTED_NOT_TAKEN_r11 927 -#define _INSTRUMENTED_NOT_TAKEN_r22 928 -#define _INSTRUMENTED_NOT_TAKEN_r33 929 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 930 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 931 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 932 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 933 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 934 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 935 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 936 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 937 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 938 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 939 -#define _IS_NONE_r11 940 -#define _IS_OP_r21 941 -#define _ITER_CHECK_LIST_r02 942 -#define _ITER_CHECK_LIST_r12 943 -#define _ITER_CHECK_LIST_r22 944 -#define _ITER_CHECK_LIST_r33 945 -#define _ITER_CHECK_RANGE_r02 946 -#define _ITER_CHECK_RANGE_r12 947 -#define _ITER_CHECK_RANGE_r22 948 -#define _ITER_CHECK_RANGE_r33 949 -#define _ITER_CHECK_TUPLE_r02 950 -#define _ITER_CHECK_TUPLE_r12 951 -#define _ITER_CHECK_TUPLE_r22 952 -#define _ITER_CHECK_TUPLE_r33 953 -#define _ITER_JUMP_LIST_r02 954 -#define _ITER_JUMP_LIST_r12 955 -#define _ITER_JUMP_LIST_r22 956 -#define _ITER_JUMP_LIST_r33 957 -#define _ITER_JUMP_RANGE_r02 958 -#define _ITER_JUMP_RANGE_r12 959 -#define _ITER_JUMP_RANGE_r22 960 -#define _ITER_JUMP_RANGE_r33 961 -#define _ITER_JUMP_TUPLE_r02 962 -#define _ITER_JUMP_TUPLE_r12 963 -#define _ITER_JUMP_TUPLE_r22 964 -#define _ITER_JUMP_TUPLE_r33 965 -#define _ITER_NEXT_LIST_r23 966 -#define _ITER_NEXT_LIST_TIER_TWO_r23 967 -#define _ITER_NEXT_RANGE_r03 968 -#define _ITER_NEXT_RANGE_r13 969 -#define _ITER_NEXT_RANGE_r23 970 -#define _ITER_NEXT_TUPLE_r03 971 -#define _ITER_NEXT_TUPLE_r13 972 -#define _ITER_NEXT_TUPLE_r23 973 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 974 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 975 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 976 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 977 -#define _JUMP_TO_TOP_r00 978 -#define _LIST_APPEND_r10 979 -#define _LIST_EXTEND_r10 980 -#define _LOAD_ATTR_r10 981 -#define _LOAD_ATTR_CLASS_r11 982 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 983 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 984 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 985 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 986 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 987 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 988 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 989 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 990 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 991 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 992 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 993 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 994 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 995 -#define _LOAD_ATTR_MODULE_r11 996 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 997 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 998 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 999 -#define _LOAD_ATTR_SLOT_r11 1000 -#define _LOAD_ATTR_WITH_HINT_r11 1001 -#define _LOAD_BUILD_CLASS_r01 1002 -#define _LOAD_BYTECODE_r00 1003 -#define _LOAD_COMMON_CONSTANT_r01 1004 -#define _LOAD_COMMON_CONSTANT_r12 1005 -#define _LOAD_COMMON_CONSTANT_r23 1006 -#define _LOAD_CONST_r01 1007 -#define _LOAD_CONST_r12 1008 -#define _LOAD_CONST_r23 1009 -#define _LOAD_CONST_INLINE_r01 1010 -#define _LOAD_CONST_INLINE_r12 1011 -#define _LOAD_CONST_INLINE_r23 1012 -#define _LOAD_CONST_INLINE_BORROW_r01 1013 -#define _LOAD_CONST_INLINE_BORROW_r12 1014 -#define _LOAD_CONST_INLINE_BORROW_r23 1015 -#define _LOAD_CONST_UNDER_INLINE_r02 1016 -#define _LOAD_CONST_UNDER_INLINE_r12 1017 -#define _LOAD_CONST_UNDER_INLINE_r23 1018 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1019 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1020 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1021 -#define _LOAD_DEREF_r01 1022 -#define _LOAD_FAST_r01 1023 -#define _LOAD_FAST_r12 1024 -#define _LOAD_FAST_r23 1025 -#define _LOAD_FAST_0_r01 1026 -#define _LOAD_FAST_0_r12 1027 -#define _LOAD_FAST_0_r23 1028 -#define _LOAD_FAST_1_r01 1029 -#define _LOAD_FAST_1_r12 1030 -#define _LOAD_FAST_1_r23 1031 -#define _LOAD_FAST_2_r01 1032 -#define _LOAD_FAST_2_r12 1033 -#define _LOAD_FAST_2_r23 1034 -#define _LOAD_FAST_3_r01 1035 -#define _LOAD_FAST_3_r12 1036 -#define _LOAD_FAST_3_r23 1037 -#define _LOAD_FAST_4_r01 1038 -#define _LOAD_FAST_4_r12 1039 -#define _LOAD_FAST_4_r23 1040 -#define _LOAD_FAST_5_r01 1041 -#define _LOAD_FAST_5_r12 1042 -#define _LOAD_FAST_5_r23 1043 -#define _LOAD_FAST_6_r01 1044 -#define _LOAD_FAST_6_r12 1045 -#define _LOAD_FAST_6_r23 1046 -#define _LOAD_FAST_7_r01 1047 -#define _LOAD_FAST_7_r12 1048 -#define _LOAD_FAST_7_r23 1049 -#define _LOAD_FAST_AND_CLEAR_r01 1050 -#define _LOAD_FAST_AND_CLEAR_r12 1051 -#define _LOAD_FAST_AND_CLEAR_r23 1052 -#define _LOAD_FAST_BORROW_r01 1053 -#define _LOAD_FAST_BORROW_r12 1054 -#define _LOAD_FAST_BORROW_r23 1055 -#define _LOAD_FAST_BORROW_0_r01 1056 -#define _LOAD_FAST_BORROW_0_r12 1057 -#define _LOAD_FAST_BORROW_0_r23 1058 -#define _LOAD_FAST_BORROW_1_r01 1059 -#define _LOAD_FAST_BORROW_1_r12 1060 -#define _LOAD_FAST_BORROW_1_r23 1061 -#define _LOAD_FAST_BORROW_2_r01 1062 -#define _LOAD_FAST_BORROW_2_r12 1063 -#define _LOAD_FAST_BORROW_2_r23 1064 -#define _LOAD_FAST_BORROW_3_r01 1065 -#define _LOAD_FAST_BORROW_3_r12 1066 -#define _LOAD_FAST_BORROW_3_r23 1067 -#define _LOAD_FAST_BORROW_4_r01 1068 -#define _LOAD_FAST_BORROW_4_r12 1069 -#define _LOAD_FAST_BORROW_4_r23 1070 -#define _LOAD_FAST_BORROW_5_r01 1071 -#define _LOAD_FAST_BORROW_5_r12 1072 -#define _LOAD_FAST_BORROW_5_r23 1073 -#define _LOAD_FAST_BORROW_6_r01 1074 -#define _LOAD_FAST_BORROW_6_r12 1075 -#define _LOAD_FAST_BORROW_6_r23 1076 -#define _LOAD_FAST_BORROW_7_r01 1077 -#define _LOAD_FAST_BORROW_7_r12 1078 -#define _LOAD_FAST_BORROW_7_r23 1079 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1080 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1081 -#define _LOAD_FAST_CHECK_r01 1082 -#define _LOAD_FAST_CHECK_r12 1083 -#define _LOAD_FAST_CHECK_r23 1084 -#define _LOAD_FAST_LOAD_FAST_r02 1085 -#define _LOAD_FAST_LOAD_FAST_r13 1086 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1087 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1088 -#define _LOAD_GLOBAL_r00 1089 -#define _LOAD_GLOBAL_BUILTINS_r01 1090 -#define _LOAD_GLOBAL_MODULE_r01 1091 -#define _LOAD_LOCALS_r01 1092 -#define _LOAD_LOCALS_r12 1093 -#define _LOAD_LOCALS_r23 1094 -#define _LOAD_NAME_r01 1095 -#define _LOAD_SMALL_INT_r01 1096 -#define _LOAD_SMALL_INT_r12 1097 -#define _LOAD_SMALL_INT_r23 1098 -#define _LOAD_SMALL_INT_0_r01 1099 -#define _LOAD_SMALL_INT_0_r12 1100 -#define _LOAD_SMALL_INT_0_r23 1101 -#define _LOAD_SMALL_INT_1_r01 1102 -#define _LOAD_SMALL_INT_1_r12 1103 -#define _LOAD_SMALL_INT_1_r23 1104 -#define _LOAD_SMALL_INT_2_r01 1105 -#define _LOAD_SMALL_INT_2_r12 1106 -#define _LOAD_SMALL_INT_2_r23 1107 -#define _LOAD_SMALL_INT_3_r01 1108 -#define _LOAD_SMALL_INT_3_r12 1109 -#define _LOAD_SMALL_INT_3_r23 1110 -#define _LOAD_SPECIAL_r00 1111 -#define _LOAD_SUPER_ATTR_ATTR_r31 1112 -#define _LOAD_SUPER_ATTR_METHOD_r32 1113 -#define _MAKE_CALLARGS_A_TUPLE_r33 1114 -#define _MAKE_CELL_r00 1115 -#define _MAKE_FUNCTION_r11 1116 -#define _MAKE_WARM_r00 1117 -#define _MAKE_WARM_r11 1118 -#define _MAKE_WARM_r22 1119 -#define _MAKE_WARM_r33 1120 -#define _MAP_ADD_r20 1121 -#define _MATCH_CLASS_r31 1122 -#define _MATCH_KEYS_r23 1123 -#define _MATCH_MAPPING_r02 1124 -#define _MATCH_MAPPING_r12 1125 -#define _MATCH_MAPPING_r23 1126 -#define _MATCH_SEQUENCE_r02 1127 -#define _MATCH_SEQUENCE_r12 1128 -#define _MATCH_SEQUENCE_r23 1129 -#define _MAYBE_EXPAND_METHOD_r00 1130 -#define _MAYBE_EXPAND_METHOD_KW_r11 1131 -#define _MONITOR_CALL_r00 1132 -#define _MONITOR_CALL_KW_r11 1133 -#define _MONITOR_JUMP_BACKWARD_r00 1134 -#define _MONITOR_JUMP_BACKWARD_r11 1135 -#define _MONITOR_JUMP_BACKWARD_r22 1136 -#define _MONITOR_JUMP_BACKWARD_r33 1137 -#define _MONITOR_RESUME_r00 1138 -#define _NOP_r00 1139 -#define _NOP_r11 1140 -#define _NOP_r22 1141 -#define _NOP_r33 1142 -#define _POP_CALL_r20 1143 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1144 -#define _POP_CALL_ONE_r30 1145 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1146 -#define _POP_CALL_TWO_r30 1147 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1148 -#define _POP_EXCEPT_r10 1149 -#define _POP_ITER_r20 1150 -#define _POP_JUMP_IF_FALSE_r00 1151 -#define _POP_JUMP_IF_FALSE_r10 1152 -#define _POP_JUMP_IF_FALSE_r21 1153 -#define _POP_JUMP_IF_FALSE_r32 1154 -#define _POP_JUMP_IF_TRUE_r00 1155 -#define _POP_JUMP_IF_TRUE_r10 1156 -#define _POP_JUMP_IF_TRUE_r21 1157 -#define _POP_JUMP_IF_TRUE_r32 1158 -#define _POP_TOP_r10 1159 -#define _POP_TOP_FLOAT_r00 1160 -#define _POP_TOP_FLOAT_r10 1161 -#define _POP_TOP_FLOAT_r21 1162 -#define _POP_TOP_FLOAT_r32 1163 -#define _POP_TOP_INT_r00 1164 -#define _POP_TOP_INT_r10 1165 -#define _POP_TOP_INT_r21 1166 -#define _POP_TOP_INT_r32 1167 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1168 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1169 -#define _POP_TOP_NOP_r00 1170 -#define _POP_TOP_NOP_r10 1171 -#define _POP_TOP_NOP_r21 1172 -#define _POP_TOP_NOP_r32 1173 -#define _POP_TOP_UNICODE_r00 1174 -#define _POP_TOP_UNICODE_r10 1175 -#define _POP_TOP_UNICODE_r21 1176 -#define _POP_TOP_UNICODE_r32 1177 -#define _POP_TWO_r20 1178 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1179 -#define _PUSH_EXC_INFO_r02 1180 -#define _PUSH_EXC_INFO_r12 1181 -#define _PUSH_EXC_INFO_r23 1182 -#define _PUSH_FRAME_r10 1183 -#define _PUSH_NULL_r01 1184 -#define _PUSH_NULL_r12 1185 -#define _PUSH_NULL_r23 1186 -#define _PUSH_NULL_CONDITIONAL_r00 1187 -#define _PY_FRAME_GENERAL_r01 1188 -#define _PY_FRAME_KW_r11 1189 -#define _QUICKEN_RESUME_r00 1190 -#define _QUICKEN_RESUME_r11 1191 -#define _QUICKEN_RESUME_r22 1192 -#define _QUICKEN_RESUME_r33 1193 -#define _REPLACE_WITH_TRUE_r11 1194 -#define _RESUME_CHECK_r00 1195 -#define _RESUME_CHECK_r11 1196 -#define _RESUME_CHECK_r22 1197 -#define _RESUME_CHECK_r33 1198 -#define _RETURN_GENERATOR_r01 1199 -#define _RETURN_VALUE_r11 1200 -#define _SAVE_RETURN_OFFSET_r00 1201 -#define _SAVE_RETURN_OFFSET_r11 1202 -#define _SAVE_RETURN_OFFSET_r22 1203 -#define _SAVE_RETURN_OFFSET_r33 1204 -#define _SEND_r22 1205 -#define _SEND_GEN_FRAME_r22 1206 -#define _SETUP_ANNOTATIONS_r00 1207 -#define _SET_ADD_r10 1208 -#define _SET_FUNCTION_ATTRIBUTE_r01 1209 -#define _SET_FUNCTION_ATTRIBUTE_r11 1210 -#define _SET_FUNCTION_ATTRIBUTE_r21 1211 -#define _SET_FUNCTION_ATTRIBUTE_r32 1212 -#define _SET_IP_r00 1213 -#define _SET_IP_r11 1214 -#define _SET_IP_r22 1215 -#define _SET_IP_r33 1216 -#define _SET_UPDATE_r10 1217 -#define _SPILL_OR_RELOAD_r01 1218 -#define _SPILL_OR_RELOAD_r02 1219 -#define _SPILL_OR_RELOAD_r03 1220 -#define _SPILL_OR_RELOAD_r10 1221 -#define _SPILL_OR_RELOAD_r12 1222 -#define _SPILL_OR_RELOAD_r13 1223 -#define _SPILL_OR_RELOAD_r20 1224 -#define _SPILL_OR_RELOAD_r21 1225 -#define _SPILL_OR_RELOAD_r23 1226 -#define _SPILL_OR_RELOAD_r30 1227 -#define _SPILL_OR_RELOAD_r31 1228 -#define _SPILL_OR_RELOAD_r32 1229 -#define _START_EXECUTOR_r00 1230 -#define _STORE_ATTR_r20 1231 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1232 -#define _STORE_ATTR_SLOT_r21 1233 -#define _STORE_ATTR_WITH_HINT_r21 1234 -#define _STORE_DEREF_r10 1235 -#define _STORE_FAST_r10 1236 -#define _STORE_FAST_0_r10 1237 -#define _STORE_FAST_1_r10 1238 -#define _STORE_FAST_2_r10 1239 -#define _STORE_FAST_3_r10 1240 -#define _STORE_FAST_4_r10 1241 -#define _STORE_FAST_5_r10 1242 -#define _STORE_FAST_6_r10 1243 -#define _STORE_FAST_7_r10 1244 -#define _STORE_FAST_LOAD_FAST_r11 1245 -#define _STORE_FAST_STORE_FAST_r20 1246 -#define _STORE_GLOBAL_r10 1247 -#define _STORE_NAME_r10 1248 -#define _STORE_SLICE_r30 1249 -#define _STORE_SUBSCR_r30 1250 -#define _STORE_SUBSCR_DICT_r31 1251 -#define _STORE_SUBSCR_LIST_INT_r32 1252 -#define _SWAP_r11 1253 -#define _SWAP_2_r02 1254 -#define _SWAP_2_r12 1255 -#define _SWAP_2_r22 1256 -#define _SWAP_2_r33 1257 -#define _SWAP_3_r03 1258 -#define _SWAP_3_r13 1259 -#define _SWAP_3_r23 1260 -#define _SWAP_3_r33 1261 -#define _TIER2_RESUME_CHECK_r00 1262 -#define _TIER2_RESUME_CHECK_r11 1263 -#define _TIER2_RESUME_CHECK_r22 1264 -#define _TIER2_RESUME_CHECK_r33 1265 -#define _TO_BOOL_r11 1266 -#define _TO_BOOL_BOOL_r01 1267 -#define _TO_BOOL_BOOL_r11 1268 -#define _TO_BOOL_BOOL_r22 1269 -#define _TO_BOOL_BOOL_r33 1270 -#define _TO_BOOL_INT_r11 1271 -#define _TO_BOOL_LIST_r11 1272 -#define _TO_BOOL_NONE_r01 1273 -#define _TO_BOOL_NONE_r11 1274 -#define _TO_BOOL_NONE_r22 1275 -#define _TO_BOOL_NONE_r33 1276 -#define _TO_BOOL_STR_r11 1277 -#define _TRACE_RECORD_r00 1278 -#define _UNARY_INVERT_r11 1279 -#define _UNARY_NEGATIVE_r11 1280 -#define _UNARY_NOT_r01 1281 -#define _UNARY_NOT_r11 1282 -#define _UNARY_NOT_r22 1283 -#define _UNARY_NOT_r33 1284 -#define _UNPACK_EX_r10 1285 -#define _UNPACK_SEQUENCE_r10 1286 -#define _UNPACK_SEQUENCE_LIST_r10 1287 -#define _UNPACK_SEQUENCE_TUPLE_r10 1288 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1289 -#define _WITH_EXCEPT_START_r33 1290 -#define _YIELD_VALUE_r11 1291 -#define MAX_UOP_REGS_ID 1291 +#define MAX_UOP_ID 556 +#define _BINARY_OP_r21 557 +#define _BINARY_OP_ADD_FLOAT_r03 558 +#define _BINARY_OP_ADD_FLOAT_r13 559 +#define _BINARY_OP_ADD_FLOAT_r23 560 +#define _BINARY_OP_ADD_INT_r03 561 +#define _BINARY_OP_ADD_INT_r13 562 +#define _BINARY_OP_ADD_INT_r23 563 +#define _BINARY_OP_ADD_UNICODE_r03 564 +#define _BINARY_OP_ADD_UNICODE_r13 565 +#define _BINARY_OP_ADD_UNICODE_r23 566 +#define _BINARY_OP_EXTEND_r21 567 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 568 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 569 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 570 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 571 +#define _BINARY_OP_MULTIPLY_INT_r03 572 +#define _BINARY_OP_MULTIPLY_INT_r13 573 +#define _BINARY_OP_MULTIPLY_INT_r23 574 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 575 +#define _BINARY_OP_SUBSCR_DICT_r21 576 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 577 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 578 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 579 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 580 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 581 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r21 582 +#define _BINARY_OP_SUBSCR_STR_INT_r23 583 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 584 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 585 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 586 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 587 +#define _BINARY_OP_SUBTRACT_INT_r03 588 +#define _BINARY_OP_SUBTRACT_INT_r13 589 +#define _BINARY_OP_SUBTRACT_INT_r23 590 +#define _BINARY_SLICE_r31 591 +#define _BUILD_INTERPOLATION_r01 592 +#define _BUILD_LIST_r01 593 +#define _BUILD_MAP_r01 594 +#define _BUILD_SET_r01 595 +#define _BUILD_SLICE_r01 596 +#define _BUILD_STRING_r01 597 +#define _BUILD_TEMPLATE_r21 598 +#define _BUILD_TUPLE_r01 599 +#define _CALL_BUILTIN_CLASS_r01 600 +#define _CALL_BUILTIN_FAST_r01 601 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 602 +#define _CALL_BUILTIN_O_r03 603 +#define _CALL_INTRINSIC_1_r11 604 +#define _CALL_INTRINSIC_2_r21 605 +#define _CALL_ISINSTANCE_r31 606 +#define _CALL_KW_NON_PY_r11 607 +#define _CALL_LEN_r33 608 +#define _CALL_LIST_APPEND_r03 609 +#define _CALL_LIST_APPEND_r13 610 +#define _CALL_LIST_APPEND_r23 611 +#define _CALL_LIST_APPEND_r33 612 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 613 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 614 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 615 +#define _CALL_METHOD_DESCRIPTOR_O_r01 616 +#define _CALL_NON_PY_GENERAL_r01 617 +#define _CALL_STR_1_r32 618 +#define _CALL_TUPLE_1_r32 619 +#define _CALL_TYPE_1_r02 620 +#define _CALL_TYPE_1_r12 621 +#define _CALL_TYPE_1_r22 622 +#define _CALL_TYPE_1_r32 623 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 624 +#define _CHECK_ATTR_CLASS_r01 625 +#define _CHECK_ATTR_CLASS_r11 626 +#define _CHECK_ATTR_CLASS_r22 627 +#define _CHECK_ATTR_CLASS_r33 628 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 629 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 630 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 631 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 632 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 633 +#define _CHECK_EG_MATCH_r22 634 +#define _CHECK_EXC_MATCH_r22 635 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 636 +#define _CHECK_FUNCTION_VERSION_r00 637 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 638 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 639 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 640 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 641 +#define _CHECK_FUNCTION_VERSION_KW_r11 642 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 643 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 644 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 645 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 646 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 647 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 648 +#define _CHECK_METHOD_VERSION_r00 649 +#define _CHECK_METHOD_VERSION_KW_r11 650 +#define _CHECK_PEP_523_r00 651 +#define _CHECK_PEP_523_r11 652 +#define _CHECK_PEP_523_r22 653 +#define _CHECK_PEP_523_r33 654 +#define _CHECK_PERIODIC_r00 655 +#define _CHECK_PERIODIC_AT_END_r00 656 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 657 +#define _CHECK_RECURSION_REMAINING_r00 658 +#define _CHECK_RECURSION_REMAINING_r11 659 +#define _CHECK_RECURSION_REMAINING_r22 660 +#define _CHECK_RECURSION_REMAINING_r33 661 +#define _CHECK_STACK_SPACE_r00 662 +#define _CHECK_STACK_SPACE_OPERAND_r00 663 +#define _CHECK_STACK_SPACE_OPERAND_r11 664 +#define _CHECK_STACK_SPACE_OPERAND_r22 665 +#define _CHECK_STACK_SPACE_OPERAND_r33 666 +#define _CHECK_VALIDITY_r00 667 +#define _CHECK_VALIDITY_r11 668 +#define _CHECK_VALIDITY_r22 669 +#define _CHECK_VALIDITY_r33 670 +#define _COLD_DYNAMIC_EXIT_r00 671 +#define _COLD_EXIT_r00 672 +#define _COMPARE_OP_r21 673 +#define _COMPARE_OP_FLOAT_r03 674 +#define _COMPARE_OP_FLOAT_r13 675 +#define _COMPARE_OP_FLOAT_r23 676 +#define _COMPARE_OP_INT_r23 677 +#define _COMPARE_OP_STR_r23 678 +#define _CONTAINS_OP_r21 679 +#define _CONTAINS_OP_DICT_r21 680 +#define _CONTAINS_OP_SET_r21 681 +#define _CONVERT_VALUE_r11 682 +#define _COPY_r01 683 +#define _COPY_1_r02 684 +#define _COPY_1_r12 685 +#define _COPY_1_r23 686 +#define _COPY_2_r03 687 +#define _COPY_2_r13 688 +#define _COPY_2_r23 689 +#define _COPY_3_r03 690 +#define _COPY_3_r13 691 +#define _COPY_3_r23 692 +#define _COPY_3_r33 693 +#define _COPY_FREE_VARS_r00 694 +#define _COPY_FREE_VARS_r11 695 +#define _COPY_FREE_VARS_r22 696 +#define _COPY_FREE_VARS_r33 697 +#define _CREATE_INIT_FRAME_r01 698 +#define _DELETE_ATTR_r10 699 +#define _DELETE_DEREF_r00 700 +#define _DELETE_FAST_r00 701 +#define _DELETE_GLOBAL_r00 702 +#define _DELETE_NAME_r00 703 +#define _DELETE_SUBSCR_r20 704 +#define _DEOPT_r00 705 +#define _DEOPT_r10 706 +#define _DEOPT_r20 707 +#define _DEOPT_r30 708 +#define _DICT_MERGE_r10 709 +#define _DICT_UPDATE_r10 710 +#define _DO_CALL_r01 711 +#define _DO_CALL_FUNCTION_EX_r31 712 +#define _DO_CALL_KW_r11 713 +#define _DYNAMIC_EXIT_r00 714 +#define _DYNAMIC_EXIT_r10 715 +#define _DYNAMIC_EXIT_r20 716 +#define _DYNAMIC_EXIT_r30 717 +#define _END_FOR_r10 718 +#define _END_SEND_r21 719 +#define _ERROR_POP_N_r00 720 +#define _EXIT_INIT_CHECK_r10 721 +#define _EXIT_TRACE_r00 722 +#define _EXIT_TRACE_r10 723 +#define _EXIT_TRACE_r20 724 +#define _EXIT_TRACE_r30 725 +#define _EXPAND_METHOD_r00 726 +#define _EXPAND_METHOD_KW_r11 727 +#define _FATAL_ERROR_r00 728 +#define _FATAL_ERROR_r11 729 +#define _FATAL_ERROR_r22 730 +#define _FATAL_ERROR_r33 731 +#define _FORMAT_SIMPLE_r11 732 +#define _FORMAT_WITH_SPEC_r21 733 +#define _FOR_ITER_r23 734 +#define _FOR_ITER_GEN_FRAME_r03 735 +#define _FOR_ITER_GEN_FRAME_r13 736 +#define _FOR_ITER_GEN_FRAME_r23 737 +#define _FOR_ITER_TIER_TWO_r23 738 +#define _GET_AITER_r11 739 +#define _GET_ANEXT_r12 740 +#define _GET_AWAITABLE_r11 741 +#define _GET_ITER_r12 742 +#define _GET_LEN_r12 743 +#define _GET_YIELD_FROM_ITER_r11 744 +#define _GUARD_BINARY_OP_EXTEND_r22 745 +#define _GUARD_CALLABLE_ISINSTANCE_r03 746 +#define _GUARD_CALLABLE_ISINSTANCE_r13 747 +#define _GUARD_CALLABLE_ISINSTANCE_r23 748 +#define _GUARD_CALLABLE_ISINSTANCE_r33 749 +#define _GUARD_CALLABLE_LEN_r03 750 +#define _GUARD_CALLABLE_LEN_r13 751 +#define _GUARD_CALLABLE_LEN_r23 752 +#define _GUARD_CALLABLE_LEN_r33 753 +#define _GUARD_CALLABLE_LIST_APPEND_r03 754 +#define _GUARD_CALLABLE_LIST_APPEND_r13 755 +#define _GUARD_CALLABLE_LIST_APPEND_r23 756 +#define _GUARD_CALLABLE_LIST_APPEND_r33 757 +#define _GUARD_CALLABLE_STR_1_r03 758 +#define _GUARD_CALLABLE_STR_1_r13 759 +#define _GUARD_CALLABLE_STR_1_r23 760 +#define _GUARD_CALLABLE_STR_1_r33 761 +#define _GUARD_CALLABLE_TUPLE_1_r03 762 +#define _GUARD_CALLABLE_TUPLE_1_r13 763 +#define _GUARD_CALLABLE_TUPLE_1_r23 764 +#define _GUARD_CALLABLE_TUPLE_1_r33 765 +#define _GUARD_CALLABLE_TYPE_1_r03 766 +#define _GUARD_CALLABLE_TYPE_1_r13 767 +#define _GUARD_CALLABLE_TYPE_1_r23 768 +#define _GUARD_CALLABLE_TYPE_1_r33 769 +#define _GUARD_DORV_NO_DICT_r01 770 +#define _GUARD_DORV_NO_DICT_r11 771 +#define _GUARD_DORV_NO_DICT_r22 772 +#define _GUARD_DORV_NO_DICT_r33 773 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 774 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 775 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 776 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 777 +#define _GUARD_GLOBALS_VERSION_r00 778 +#define _GUARD_GLOBALS_VERSION_r11 779 +#define _GUARD_GLOBALS_VERSION_r22 780 +#define _GUARD_GLOBALS_VERSION_r33 781 +#define _GUARD_IP_RETURN_GENERATOR_r00 782 +#define _GUARD_IP_RETURN_GENERATOR_r11 783 +#define _GUARD_IP_RETURN_GENERATOR_r22 784 +#define _GUARD_IP_RETURN_GENERATOR_r33 785 +#define _GUARD_IP_RETURN_VALUE_r00 786 +#define _GUARD_IP_RETURN_VALUE_r11 787 +#define _GUARD_IP_RETURN_VALUE_r22 788 +#define _GUARD_IP_RETURN_VALUE_r33 789 +#define _GUARD_IP_YIELD_VALUE_r00 790 +#define _GUARD_IP_YIELD_VALUE_r11 791 +#define _GUARD_IP_YIELD_VALUE_r22 792 +#define _GUARD_IP_YIELD_VALUE_r33 793 +#define _GUARD_IP__PUSH_FRAME_r00 794 +#define _GUARD_IP__PUSH_FRAME_r11 795 +#define _GUARD_IP__PUSH_FRAME_r22 796 +#define _GUARD_IP__PUSH_FRAME_r33 797 +#define _GUARD_IS_FALSE_POP_r00 798 +#define _GUARD_IS_FALSE_POP_r10 799 +#define _GUARD_IS_FALSE_POP_r21 800 +#define _GUARD_IS_FALSE_POP_r32 801 +#define _GUARD_IS_NONE_POP_r00 802 +#define _GUARD_IS_NONE_POP_r10 803 +#define _GUARD_IS_NONE_POP_r21 804 +#define _GUARD_IS_NONE_POP_r32 805 +#define _GUARD_IS_NOT_NONE_POP_r10 806 +#define _GUARD_IS_TRUE_POP_r00 807 +#define _GUARD_IS_TRUE_POP_r10 808 +#define _GUARD_IS_TRUE_POP_r21 809 +#define _GUARD_IS_TRUE_POP_r32 810 +#define _GUARD_KEYS_VERSION_r01 811 +#define _GUARD_KEYS_VERSION_r11 812 +#define _GUARD_KEYS_VERSION_r22 813 +#define _GUARD_KEYS_VERSION_r33 814 +#define _GUARD_NOS_DICT_r02 815 +#define _GUARD_NOS_DICT_r12 816 +#define _GUARD_NOS_DICT_r22 817 +#define _GUARD_NOS_DICT_r33 818 +#define _GUARD_NOS_FLOAT_r02 819 +#define _GUARD_NOS_FLOAT_r12 820 +#define _GUARD_NOS_FLOAT_r22 821 +#define _GUARD_NOS_FLOAT_r33 822 +#define _GUARD_NOS_INT_r02 823 +#define _GUARD_NOS_INT_r12 824 +#define _GUARD_NOS_INT_r22 825 +#define _GUARD_NOS_INT_r33 826 +#define _GUARD_NOS_LIST_r02 827 +#define _GUARD_NOS_LIST_r12 828 +#define _GUARD_NOS_LIST_r22 829 +#define _GUARD_NOS_LIST_r33 830 +#define _GUARD_NOS_NOT_NULL_r02 831 +#define _GUARD_NOS_NOT_NULL_r12 832 +#define _GUARD_NOS_NOT_NULL_r22 833 +#define _GUARD_NOS_NOT_NULL_r33 834 +#define _GUARD_NOS_NULL_r02 835 +#define _GUARD_NOS_NULL_r12 836 +#define _GUARD_NOS_NULL_r22 837 +#define _GUARD_NOS_NULL_r33 838 +#define _GUARD_NOS_OVERFLOWED_r02 839 +#define _GUARD_NOS_OVERFLOWED_r12 840 +#define _GUARD_NOS_OVERFLOWED_r22 841 +#define _GUARD_NOS_OVERFLOWED_r33 842 +#define _GUARD_NOS_TUPLE_r02 843 +#define _GUARD_NOS_TUPLE_r12 844 +#define _GUARD_NOS_TUPLE_r22 845 +#define _GUARD_NOS_TUPLE_r33 846 +#define _GUARD_NOS_UNICODE_r02 847 +#define _GUARD_NOS_UNICODE_r12 848 +#define _GUARD_NOS_UNICODE_r22 849 +#define _GUARD_NOS_UNICODE_r33 850 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 851 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 852 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 853 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 854 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 855 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 856 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 857 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 858 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 859 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 860 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 861 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 862 +#define _GUARD_THIRD_NULL_r03 863 +#define _GUARD_THIRD_NULL_r13 864 +#define _GUARD_THIRD_NULL_r23 865 +#define _GUARD_THIRD_NULL_r33 866 +#define _GUARD_TOS_ANY_SET_r01 867 +#define _GUARD_TOS_ANY_SET_r11 868 +#define _GUARD_TOS_ANY_SET_r22 869 +#define _GUARD_TOS_ANY_SET_r33 870 +#define _GUARD_TOS_DICT_r01 871 +#define _GUARD_TOS_DICT_r11 872 +#define _GUARD_TOS_DICT_r22 873 +#define _GUARD_TOS_DICT_r33 874 +#define _GUARD_TOS_FLOAT_r01 875 +#define _GUARD_TOS_FLOAT_r11 876 +#define _GUARD_TOS_FLOAT_r22 877 +#define _GUARD_TOS_FLOAT_r33 878 +#define _GUARD_TOS_INT_r01 879 +#define _GUARD_TOS_INT_r11 880 +#define _GUARD_TOS_INT_r22 881 +#define _GUARD_TOS_INT_r33 882 +#define _GUARD_TOS_LIST_r01 883 +#define _GUARD_TOS_LIST_r11 884 +#define _GUARD_TOS_LIST_r22 885 +#define _GUARD_TOS_LIST_r33 886 +#define _GUARD_TOS_OVERFLOWED_r01 887 +#define _GUARD_TOS_OVERFLOWED_r11 888 +#define _GUARD_TOS_OVERFLOWED_r22 889 +#define _GUARD_TOS_OVERFLOWED_r33 890 +#define _GUARD_TOS_SLICE_r01 891 +#define _GUARD_TOS_SLICE_r11 892 +#define _GUARD_TOS_SLICE_r22 893 +#define _GUARD_TOS_SLICE_r33 894 +#define _GUARD_TOS_TUPLE_r01 895 +#define _GUARD_TOS_TUPLE_r11 896 +#define _GUARD_TOS_TUPLE_r22 897 +#define _GUARD_TOS_TUPLE_r33 898 +#define _GUARD_TOS_UNICODE_r01 899 +#define _GUARD_TOS_UNICODE_r11 900 +#define _GUARD_TOS_UNICODE_r22 901 +#define _GUARD_TOS_UNICODE_r33 902 +#define _GUARD_TYPE_VERSION_r01 903 +#define _GUARD_TYPE_VERSION_r11 904 +#define _GUARD_TYPE_VERSION_r22 905 +#define _GUARD_TYPE_VERSION_r33 906 +#define _GUARD_TYPE_VERSION_AND_LOCK_r01 907 +#define _GUARD_TYPE_VERSION_AND_LOCK_r11 908 +#define _GUARD_TYPE_VERSION_AND_LOCK_r22 909 +#define _GUARD_TYPE_VERSION_AND_LOCK_r33 910 +#define _HANDLE_PENDING_AND_DEOPT_r00 911 +#define _HANDLE_PENDING_AND_DEOPT_r10 912 +#define _HANDLE_PENDING_AND_DEOPT_r20 913 +#define _HANDLE_PENDING_AND_DEOPT_r30 914 +#define _IMPORT_FROM_r12 915 +#define _IMPORT_NAME_r21 916 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 917 +#define _INIT_CALL_PY_EXACT_ARGS_r01 918 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 919 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 920 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 921 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 922 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 923 +#define _INSERT_NULL_r10 924 +#define _INSTRUMENTED_FOR_ITER_r23 925 +#define _INSTRUMENTED_INSTRUCTION_r00 926 +#define _INSTRUMENTED_JUMP_FORWARD_r00 927 +#define _INSTRUMENTED_JUMP_FORWARD_r11 928 +#define _INSTRUMENTED_JUMP_FORWARD_r22 929 +#define _INSTRUMENTED_JUMP_FORWARD_r33 930 +#define _INSTRUMENTED_LINE_r00 931 +#define _INSTRUMENTED_NOT_TAKEN_r00 932 +#define _INSTRUMENTED_NOT_TAKEN_r11 933 +#define _INSTRUMENTED_NOT_TAKEN_r22 934 +#define _INSTRUMENTED_NOT_TAKEN_r33 935 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 936 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 937 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 938 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 939 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 940 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 941 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 942 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 943 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 944 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 945 +#define _IS_NONE_r11 946 +#define _IS_OP_r03 947 +#define _IS_OP_r13 948 +#define _IS_OP_r23 949 +#define _ITER_CHECK_LIST_r02 950 +#define _ITER_CHECK_LIST_r12 951 +#define _ITER_CHECK_LIST_r22 952 +#define _ITER_CHECK_LIST_r33 953 +#define _ITER_CHECK_RANGE_r02 954 +#define _ITER_CHECK_RANGE_r12 955 +#define _ITER_CHECK_RANGE_r22 956 +#define _ITER_CHECK_RANGE_r33 957 +#define _ITER_CHECK_TUPLE_r02 958 +#define _ITER_CHECK_TUPLE_r12 959 +#define _ITER_CHECK_TUPLE_r22 960 +#define _ITER_CHECK_TUPLE_r33 961 +#define _ITER_JUMP_LIST_r02 962 +#define _ITER_JUMP_LIST_r12 963 +#define _ITER_JUMP_LIST_r22 964 +#define _ITER_JUMP_LIST_r33 965 +#define _ITER_JUMP_RANGE_r02 966 +#define _ITER_JUMP_RANGE_r12 967 +#define _ITER_JUMP_RANGE_r22 968 +#define _ITER_JUMP_RANGE_r33 969 +#define _ITER_JUMP_TUPLE_r02 970 +#define _ITER_JUMP_TUPLE_r12 971 +#define _ITER_JUMP_TUPLE_r22 972 +#define _ITER_JUMP_TUPLE_r33 973 +#define _ITER_NEXT_LIST_r23 974 +#define _ITER_NEXT_LIST_TIER_TWO_r23 975 +#define _ITER_NEXT_RANGE_r03 976 +#define _ITER_NEXT_RANGE_r13 977 +#define _ITER_NEXT_RANGE_r23 978 +#define _ITER_NEXT_TUPLE_r03 979 +#define _ITER_NEXT_TUPLE_r13 980 +#define _ITER_NEXT_TUPLE_r23 981 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 982 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 983 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 984 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 985 +#define _JUMP_TO_TOP_r00 986 +#define _LIST_APPEND_r10 987 +#define _LIST_EXTEND_r10 988 +#define _LOAD_ATTR_r10 989 +#define _LOAD_ATTR_CLASS_r11 990 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 991 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 992 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 993 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 994 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 995 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 996 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 997 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 998 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 999 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1000 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1001 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1002 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1003 +#define _LOAD_ATTR_MODULE_r11 1004 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1005 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1006 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1007 +#define _LOAD_ATTR_SLOT_r11 1008 +#define _LOAD_ATTR_WITH_HINT_r12 1009 +#define _LOAD_BUILD_CLASS_r01 1010 +#define _LOAD_BYTECODE_r00 1011 +#define _LOAD_COMMON_CONSTANT_r01 1012 +#define _LOAD_COMMON_CONSTANT_r12 1013 +#define _LOAD_COMMON_CONSTANT_r23 1014 +#define _LOAD_CONST_r01 1015 +#define _LOAD_CONST_r12 1016 +#define _LOAD_CONST_r23 1017 +#define _LOAD_CONST_INLINE_r01 1018 +#define _LOAD_CONST_INLINE_r12 1019 +#define _LOAD_CONST_INLINE_r23 1020 +#define _LOAD_CONST_INLINE_BORROW_r01 1021 +#define _LOAD_CONST_INLINE_BORROW_r12 1022 +#define _LOAD_CONST_INLINE_BORROW_r23 1023 +#define _LOAD_CONST_UNDER_INLINE_r02 1024 +#define _LOAD_CONST_UNDER_INLINE_r12 1025 +#define _LOAD_CONST_UNDER_INLINE_r23 1026 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1027 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1028 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1029 +#define _LOAD_DEREF_r01 1030 +#define _LOAD_FAST_r01 1031 +#define _LOAD_FAST_r12 1032 +#define _LOAD_FAST_r23 1033 +#define _LOAD_FAST_0_r01 1034 +#define _LOAD_FAST_0_r12 1035 +#define _LOAD_FAST_0_r23 1036 +#define _LOAD_FAST_1_r01 1037 +#define _LOAD_FAST_1_r12 1038 +#define _LOAD_FAST_1_r23 1039 +#define _LOAD_FAST_2_r01 1040 +#define _LOAD_FAST_2_r12 1041 +#define _LOAD_FAST_2_r23 1042 +#define _LOAD_FAST_3_r01 1043 +#define _LOAD_FAST_3_r12 1044 +#define _LOAD_FAST_3_r23 1045 +#define _LOAD_FAST_4_r01 1046 +#define _LOAD_FAST_4_r12 1047 +#define _LOAD_FAST_4_r23 1048 +#define _LOAD_FAST_5_r01 1049 +#define _LOAD_FAST_5_r12 1050 +#define _LOAD_FAST_5_r23 1051 +#define _LOAD_FAST_6_r01 1052 +#define _LOAD_FAST_6_r12 1053 +#define _LOAD_FAST_6_r23 1054 +#define _LOAD_FAST_7_r01 1055 +#define _LOAD_FAST_7_r12 1056 +#define _LOAD_FAST_7_r23 1057 +#define _LOAD_FAST_AND_CLEAR_r01 1058 +#define _LOAD_FAST_AND_CLEAR_r12 1059 +#define _LOAD_FAST_AND_CLEAR_r23 1060 +#define _LOAD_FAST_BORROW_r01 1061 +#define _LOAD_FAST_BORROW_r12 1062 +#define _LOAD_FAST_BORROW_r23 1063 +#define _LOAD_FAST_BORROW_0_r01 1064 +#define _LOAD_FAST_BORROW_0_r12 1065 +#define _LOAD_FAST_BORROW_0_r23 1066 +#define _LOAD_FAST_BORROW_1_r01 1067 +#define _LOAD_FAST_BORROW_1_r12 1068 +#define _LOAD_FAST_BORROW_1_r23 1069 +#define _LOAD_FAST_BORROW_2_r01 1070 +#define _LOAD_FAST_BORROW_2_r12 1071 +#define _LOAD_FAST_BORROW_2_r23 1072 +#define _LOAD_FAST_BORROW_3_r01 1073 +#define _LOAD_FAST_BORROW_3_r12 1074 +#define _LOAD_FAST_BORROW_3_r23 1075 +#define _LOAD_FAST_BORROW_4_r01 1076 +#define _LOAD_FAST_BORROW_4_r12 1077 +#define _LOAD_FAST_BORROW_4_r23 1078 +#define _LOAD_FAST_BORROW_5_r01 1079 +#define _LOAD_FAST_BORROW_5_r12 1080 +#define _LOAD_FAST_BORROW_5_r23 1081 +#define _LOAD_FAST_BORROW_6_r01 1082 +#define _LOAD_FAST_BORROW_6_r12 1083 +#define _LOAD_FAST_BORROW_6_r23 1084 +#define _LOAD_FAST_BORROW_7_r01 1085 +#define _LOAD_FAST_BORROW_7_r12 1086 +#define _LOAD_FAST_BORROW_7_r23 1087 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1088 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1089 +#define _LOAD_FAST_CHECK_r01 1090 +#define _LOAD_FAST_CHECK_r12 1091 +#define _LOAD_FAST_CHECK_r23 1092 +#define _LOAD_FAST_LOAD_FAST_r02 1093 +#define _LOAD_FAST_LOAD_FAST_r13 1094 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1095 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1096 +#define _LOAD_GLOBAL_r00 1097 +#define _LOAD_GLOBAL_BUILTINS_r01 1098 +#define _LOAD_GLOBAL_MODULE_r01 1099 +#define _LOAD_LOCALS_r01 1100 +#define _LOAD_LOCALS_r12 1101 +#define _LOAD_LOCALS_r23 1102 +#define _LOAD_NAME_r01 1103 +#define _LOAD_SMALL_INT_r01 1104 +#define _LOAD_SMALL_INT_r12 1105 +#define _LOAD_SMALL_INT_r23 1106 +#define _LOAD_SMALL_INT_0_r01 1107 +#define _LOAD_SMALL_INT_0_r12 1108 +#define _LOAD_SMALL_INT_0_r23 1109 +#define _LOAD_SMALL_INT_1_r01 1110 +#define _LOAD_SMALL_INT_1_r12 1111 +#define _LOAD_SMALL_INT_1_r23 1112 +#define _LOAD_SMALL_INT_2_r01 1113 +#define _LOAD_SMALL_INT_2_r12 1114 +#define _LOAD_SMALL_INT_2_r23 1115 +#define _LOAD_SMALL_INT_3_r01 1116 +#define _LOAD_SMALL_INT_3_r12 1117 +#define _LOAD_SMALL_INT_3_r23 1118 +#define _LOAD_SPECIAL_r00 1119 +#define _LOAD_SUPER_ATTR_ATTR_r31 1120 +#define _LOAD_SUPER_ATTR_METHOD_r32 1121 +#define _MAKE_CALLARGS_A_TUPLE_r33 1122 +#define _MAKE_CELL_r00 1123 +#define _MAKE_FUNCTION_r11 1124 +#define _MAKE_WARM_r00 1125 +#define _MAKE_WARM_r11 1126 +#define _MAKE_WARM_r22 1127 +#define _MAKE_WARM_r33 1128 +#define _MAP_ADD_r20 1129 +#define _MATCH_CLASS_r31 1130 +#define _MATCH_KEYS_r23 1131 +#define _MATCH_MAPPING_r02 1132 +#define _MATCH_MAPPING_r12 1133 +#define _MATCH_MAPPING_r23 1134 +#define _MATCH_SEQUENCE_r02 1135 +#define _MATCH_SEQUENCE_r12 1136 +#define _MATCH_SEQUENCE_r23 1137 +#define _MAYBE_EXPAND_METHOD_r00 1138 +#define _MAYBE_EXPAND_METHOD_KW_r11 1139 +#define _MONITOR_CALL_r00 1140 +#define _MONITOR_CALL_KW_r11 1141 +#define _MONITOR_JUMP_BACKWARD_r00 1142 +#define _MONITOR_JUMP_BACKWARD_r11 1143 +#define _MONITOR_JUMP_BACKWARD_r22 1144 +#define _MONITOR_JUMP_BACKWARD_r33 1145 +#define _MONITOR_RESUME_r00 1146 +#define _NOP_r00 1147 +#define _NOP_r11 1148 +#define _NOP_r22 1149 +#define _NOP_r33 1150 +#define _POP_CALL_r20 1151 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1152 +#define _POP_CALL_ONE_r30 1153 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1154 +#define _POP_CALL_TWO_r30 1155 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1156 +#define _POP_EXCEPT_r10 1157 +#define _POP_ITER_r20 1158 +#define _POP_JUMP_IF_FALSE_r00 1159 +#define _POP_JUMP_IF_FALSE_r10 1160 +#define _POP_JUMP_IF_FALSE_r21 1161 +#define _POP_JUMP_IF_FALSE_r32 1162 +#define _POP_JUMP_IF_TRUE_r00 1163 +#define _POP_JUMP_IF_TRUE_r10 1164 +#define _POP_JUMP_IF_TRUE_r21 1165 +#define _POP_JUMP_IF_TRUE_r32 1166 +#define _POP_TOP_r10 1167 +#define _POP_TOP_FLOAT_r00 1168 +#define _POP_TOP_FLOAT_r10 1169 +#define _POP_TOP_FLOAT_r21 1170 +#define _POP_TOP_FLOAT_r32 1171 +#define _POP_TOP_INT_r00 1172 +#define _POP_TOP_INT_r10 1173 +#define _POP_TOP_INT_r21 1174 +#define _POP_TOP_INT_r32 1175 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1176 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1177 +#define _POP_TOP_NOP_r00 1178 +#define _POP_TOP_NOP_r10 1179 +#define _POP_TOP_NOP_r21 1180 +#define _POP_TOP_NOP_r32 1181 +#define _POP_TOP_UNICODE_r00 1182 +#define _POP_TOP_UNICODE_r10 1183 +#define _POP_TOP_UNICODE_r21 1184 +#define _POP_TOP_UNICODE_r32 1185 +#define _POP_TWO_r20 1186 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1187 +#define _PUSH_EXC_INFO_r02 1188 +#define _PUSH_EXC_INFO_r12 1189 +#define _PUSH_EXC_INFO_r23 1190 +#define _PUSH_FRAME_r10 1191 +#define _PUSH_NULL_r01 1192 +#define _PUSH_NULL_r12 1193 +#define _PUSH_NULL_r23 1194 +#define _PUSH_NULL_CONDITIONAL_r00 1195 +#define _PY_FRAME_GENERAL_r01 1196 +#define _PY_FRAME_KW_r11 1197 +#define _QUICKEN_RESUME_r00 1198 +#define _QUICKEN_RESUME_r11 1199 +#define _QUICKEN_RESUME_r22 1200 +#define _QUICKEN_RESUME_r33 1201 +#define _REPLACE_WITH_TRUE_r11 1202 +#define _RESUME_CHECK_r00 1203 +#define _RESUME_CHECK_r11 1204 +#define _RESUME_CHECK_r22 1205 +#define _RESUME_CHECK_r33 1206 +#define _RETURN_GENERATOR_r01 1207 +#define _RETURN_VALUE_r11 1208 +#define _SAVE_RETURN_OFFSET_r00 1209 +#define _SAVE_RETURN_OFFSET_r11 1210 +#define _SAVE_RETURN_OFFSET_r22 1211 +#define _SAVE_RETURN_OFFSET_r33 1212 +#define _SEND_r22 1213 +#define _SEND_GEN_FRAME_r22 1214 +#define _SETUP_ANNOTATIONS_r00 1215 +#define _SET_ADD_r10 1216 +#define _SET_FUNCTION_ATTRIBUTE_r01 1217 +#define _SET_FUNCTION_ATTRIBUTE_r11 1218 +#define _SET_FUNCTION_ATTRIBUTE_r21 1219 +#define _SET_FUNCTION_ATTRIBUTE_r32 1220 +#define _SET_IP_r00 1221 +#define _SET_IP_r11 1222 +#define _SET_IP_r22 1223 +#define _SET_IP_r33 1224 +#define _SET_UPDATE_r10 1225 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1226 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1227 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1228 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1229 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1230 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1231 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1232 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1233 +#define _SPILL_OR_RELOAD_r01 1234 +#define _SPILL_OR_RELOAD_r02 1235 +#define _SPILL_OR_RELOAD_r03 1236 +#define _SPILL_OR_RELOAD_r10 1237 +#define _SPILL_OR_RELOAD_r12 1238 +#define _SPILL_OR_RELOAD_r13 1239 +#define _SPILL_OR_RELOAD_r20 1240 +#define _SPILL_OR_RELOAD_r21 1241 +#define _SPILL_OR_RELOAD_r23 1242 +#define _SPILL_OR_RELOAD_r30 1243 +#define _SPILL_OR_RELOAD_r31 1244 +#define _SPILL_OR_RELOAD_r32 1245 +#define _START_EXECUTOR_r00 1246 +#define _STORE_ATTR_r20 1247 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1248 +#define _STORE_ATTR_SLOT_r21 1249 +#define _STORE_ATTR_WITH_HINT_r21 1250 +#define _STORE_DEREF_r10 1251 +#define _STORE_FAST_r10 1252 +#define _STORE_FAST_0_r10 1253 +#define _STORE_FAST_1_r10 1254 +#define _STORE_FAST_2_r10 1255 +#define _STORE_FAST_3_r10 1256 +#define _STORE_FAST_4_r10 1257 +#define _STORE_FAST_5_r10 1258 +#define _STORE_FAST_6_r10 1259 +#define _STORE_FAST_7_r10 1260 +#define _STORE_FAST_LOAD_FAST_r11 1261 +#define _STORE_FAST_STORE_FAST_r20 1262 +#define _STORE_GLOBAL_r10 1263 +#define _STORE_NAME_r10 1264 +#define _STORE_SLICE_r30 1265 +#define _STORE_SUBSCR_r30 1266 +#define _STORE_SUBSCR_DICT_r31 1267 +#define _STORE_SUBSCR_LIST_INT_r32 1268 +#define _SWAP_r11 1269 +#define _SWAP_2_r02 1270 +#define _SWAP_2_r12 1271 +#define _SWAP_2_r22 1272 +#define _SWAP_2_r33 1273 +#define _SWAP_3_r03 1274 +#define _SWAP_3_r13 1275 +#define _SWAP_3_r23 1276 +#define _SWAP_3_r33 1277 +#define _TIER2_RESUME_CHECK_r00 1278 +#define _TIER2_RESUME_CHECK_r11 1279 +#define _TIER2_RESUME_CHECK_r22 1280 +#define _TIER2_RESUME_CHECK_r33 1281 +#define _TO_BOOL_r11 1282 +#define _TO_BOOL_BOOL_r01 1283 +#define _TO_BOOL_BOOL_r11 1284 +#define _TO_BOOL_BOOL_r22 1285 +#define _TO_BOOL_BOOL_r33 1286 +#define _TO_BOOL_INT_r11 1287 +#define _TO_BOOL_LIST_r11 1288 +#define _TO_BOOL_NONE_r01 1289 +#define _TO_BOOL_NONE_r11 1290 +#define _TO_BOOL_NONE_r22 1291 +#define _TO_BOOL_NONE_r33 1292 +#define _TO_BOOL_STR_r11 1293 +#define _TRACE_RECORD_r00 1294 +#define _UNARY_INVERT_r11 1295 +#define _UNARY_NEGATIVE_r11 1296 +#define _UNARY_NOT_r01 1297 +#define _UNARY_NOT_r11 1298 +#define _UNARY_NOT_r22 1299 +#define _UNARY_NOT_r33 1300 +#define _UNPACK_EX_r10 1301 +#define _UNPACK_SEQUENCE_r10 1302 +#define _UNPACK_SEQUENCE_LIST_r10 1303 +#define _UNPACK_SEQUENCE_TUPLE_r10 1304 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1305 +#define _WITH_EXCEPT_START_r33 1306 +#define _YIELD_VALUE_r11 1307 +#define MAX_UOP_REGS_ID 1307 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index c6d3670b193123..6262a14e266c4d 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -111,7 +111,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_MULTIPLY_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, - [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_BINARY_OP_EXTEND] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_EXTEND] = HAS_ESCAPES_FLAG, @@ -119,10 +119,10 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_LIST_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_STR_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_SUBSCR_STR_INT] = HAS_DEOPT_FLAG, [_GUARD_NOS_TUPLE] = HAS_EXIT_FLAG, [_GUARD_TOS_TUPLE] = HAS_EXIT_FLAG, - [_BINARY_OP_SUBSCR_TUPLE_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_SUBSCR_TUPLE_INT] = HAS_DEOPT_FLAG, [_GUARD_NOS_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_DICT] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -191,7 +191,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG, [_LOAD_ATTR_INSTANCE_VALUE] = HAS_DEOPT_FLAG, [_LOAD_ATTR_MODULE] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, - [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG, [_LOAD_ATTR_SLOT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG, [_LOAD_ATTR_CLASS] = HAS_ESCAPES_FLAG, @@ -204,7 +204,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_COMPARE_OP_FLOAT] = HAS_ARG_FLAG, [_COMPARE_OP_INT] = HAS_ARG_FLAG, [_COMPARE_OP_STR] = HAS_ARG_FLAG, - [_IS_OP] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_IS_OP] = HAS_ARG_FLAG, [_CONTAINS_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_TOS_ANY_SET] = HAS_DEOPT_FLAG, [_CONTAINS_OP_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -269,7 +269,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_NOS_NOT_NULL] = HAS_EXIT_FLAG, [_GUARD_THIRD_NULL] = HAS_DEOPT_FLAG, [_GUARD_CALLABLE_TYPE_1] = HAS_DEOPT_FLAG, - [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_CALL_TYPE_1] = HAS_ARG_FLAG, [_GUARD_CALLABLE_STR_1] = HAS_DEOPT_FLAG, [_CALL_STR_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_TUPLE_1] = HAS_DEOPT_FLAG, @@ -335,6 +335,8 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_POP_TWO_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, [_POP_CALL_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = 0, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = 0, [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, [_LOAD_CONST_UNDER_INLINE] = 0, [_LOAD_CONST_UNDER_INLINE_BORROW] = 0, @@ -1050,12 +1052,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_BINARY_OP_ADD_UNICODE] = { - .best = { 0, 1, 2, 3 }, + .best = { 0, 1, 2, 2 }, .entries = { - { 1, 0, _BINARY_OP_ADD_UNICODE_r01 }, - { 1, 1, _BINARY_OP_ADD_UNICODE_r11 }, - { 1, 2, _BINARY_OP_ADD_UNICODE_r21 }, - { 2, 3, _BINARY_OP_ADD_UNICODE_r32 }, + { 3, 0, _BINARY_OP_ADD_UNICODE_r03 }, + { 3, 1, _BINARY_OP_ADD_UNICODE_r13 }, + { 3, 2, _BINARY_OP_ADD_UNICODE_r23 }, + { -1, -1, -1 }, }, }, [_BINARY_OP_INPLACE_ADD_UNICODE] = { @@ -1063,7 +1065,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 0, 2, _BINARY_OP_INPLACE_ADD_UNICODE_r20 }, + { 1, 2, _BINARY_OP_INPLACE_ADD_UNICODE_r21 }, { -1, -1, -1 }, }, }, @@ -1108,7 +1110,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _BINARY_OP_SUBSCR_LIST_INT_r21 }, + { 3, 2, _BINARY_OP_SUBSCR_LIST_INT_r23 }, { -1, -1, -1 }, }, }, @@ -1126,7 +1128,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _BINARY_OP_SUBSCR_STR_INT_r21 }, + { 3, 2, _BINARY_OP_SUBSCR_STR_INT_r23 }, { -1, -1, -1 }, }, }, @@ -1153,7 +1155,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _BINARY_OP_SUBSCR_TUPLE_INT_r21 }, + { 3, 2, _BINARY_OP_SUBSCR_TUPLE_INT_r23 }, { -1, -1, -1 }, }, }, @@ -1773,7 +1775,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _LOAD_ATTR_WITH_HINT_r11 }, + { 2, 1, _LOAD_ATTR_WITH_HINT_r12 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -1860,12 +1862,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_COMPARE_OP_FLOAT] = { - .best = { 0, 1, 2, 3 }, + .best = { 0, 1, 2, 2 }, .entries = { - { 1, 0, _COMPARE_OP_FLOAT_r01 }, - { 1, 1, _COMPARE_OP_FLOAT_r11 }, - { 1, 2, _COMPARE_OP_FLOAT_r21 }, - { 2, 3, _COMPARE_OP_FLOAT_r32 }, + { 3, 0, _COMPARE_OP_FLOAT_r03 }, + { 3, 1, _COMPARE_OP_FLOAT_r13 }, + { 3, 2, _COMPARE_OP_FLOAT_r23 }, + { -1, -1, -1 }, }, }, [_COMPARE_OP_INT] = { @@ -1882,16 +1884,16 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .entries = { { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 2, _COMPARE_OP_STR_r21 }, + { 3, 2, _COMPARE_OP_STR_r23 }, { -1, -1, -1 }, }, }, [_IS_OP] = { - .best = { 2, 2, 2, 2 }, + .best = { 0, 1, 2, 2 }, .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 2, _IS_OP_r21 }, + { 3, 0, _IS_OP_r03 }, + { 3, 1, _IS_OP_r13 }, + { 3, 2, _IS_OP_r23 }, { -1, -1, -1 }, }, }, @@ -2130,10 +2132,10 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_FOR_ITER_GEN_FRAME] = { - .best = { 2, 2, 2, 2 }, + .best = { 0, 1, 2, 2 }, .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, + { 3, 0, _FOR_ITER_GEN_FRAME_r03 }, + { 3, 1, _FOR_ITER_GEN_FRAME_r13 }, { 3, 2, _FOR_ITER_GEN_FRAME_r23 }, { -1, -1, -1 }, }, @@ -2472,12 +2474,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_CALL_TYPE_1] = { - .best = { 3, 3, 3, 3 }, + .best = { 0, 1, 2, 3 }, .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 3, _CALL_TYPE_1_r31 }, + { 2, 0, _CALL_TYPE_1_r02 }, + { 2, 1, _CALL_TYPE_1_r12 }, + { 2, 2, _CALL_TYPE_1_r22 }, + { 2, 3, _CALL_TYPE_1_r32 }, }, }, [_GUARD_CALLABLE_STR_1] = { @@ -2627,10 +2629,10 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_LIST_APPEND] = { .best = { 0, 1, 2, 3 }, .entries = { - { 2, 0, _CALL_LIST_APPEND_r02 }, - { 2, 1, _CALL_LIST_APPEND_r12 }, - { 2, 2, _CALL_LIST_APPEND_r22 }, - { 2, 3, _CALL_LIST_APPEND_r32 }, + { 3, 0, _CALL_LIST_APPEND_r03 }, + { 3, 1, _CALL_LIST_APPEND_r13 }, + { 3, 2, _CALL_LIST_APPEND_r23 }, + { 3, 3, _CALL_LIST_APPEND_r33 }, }, }, [_CALL_METHOD_DESCRIPTOR_O] = { @@ -3065,6 +3067,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 1, 3, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 }, }, }, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 }, + { 2, 1, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 }, + { 2, 2, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 }, + { 2, 3, _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 }, + }, + }, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 3, 0, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 }, + { 3, 1, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 }, + { 3, 2, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 }, + { 3, 3, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 }, + }, + }, [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = { .best = { 3, 3, 3, 3 }, .entries = { @@ -3414,18 +3434,17 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT_r03] = _BINARY_OP_SUBTRACT_FLOAT, [_BINARY_OP_SUBTRACT_FLOAT_r13] = _BINARY_OP_SUBTRACT_FLOAT, [_BINARY_OP_SUBTRACT_FLOAT_r23] = _BINARY_OP_SUBTRACT_FLOAT, - [_BINARY_OP_ADD_UNICODE_r01] = _BINARY_OP_ADD_UNICODE, - [_BINARY_OP_ADD_UNICODE_r11] = _BINARY_OP_ADD_UNICODE, - [_BINARY_OP_ADD_UNICODE_r21] = _BINARY_OP_ADD_UNICODE, - [_BINARY_OP_ADD_UNICODE_r32] = _BINARY_OP_ADD_UNICODE, - [_BINARY_OP_INPLACE_ADD_UNICODE_r20] = _BINARY_OP_INPLACE_ADD_UNICODE, + [_BINARY_OP_ADD_UNICODE_r03] = _BINARY_OP_ADD_UNICODE, + [_BINARY_OP_ADD_UNICODE_r13] = _BINARY_OP_ADD_UNICODE, + [_BINARY_OP_ADD_UNICODE_r23] = _BINARY_OP_ADD_UNICODE, + [_BINARY_OP_INPLACE_ADD_UNICODE_r21] = _BINARY_OP_INPLACE_ADD_UNICODE, [_GUARD_BINARY_OP_EXTEND_r22] = _GUARD_BINARY_OP_EXTEND, [_BINARY_OP_EXTEND_r21] = _BINARY_OP_EXTEND, [_BINARY_SLICE_r31] = _BINARY_SLICE, [_STORE_SLICE_r30] = _STORE_SLICE, - [_BINARY_OP_SUBSCR_LIST_INT_r21] = _BINARY_OP_SUBSCR_LIST_INT, + [_BINARY_OP_SUBSCR_LIST_INT_r23] = _BINARY_OP_SUBSCR_LIST_INT, [_BINARY_OP_SUBSCR_LIST_SLICE_r21] = _BINARY_OP_SUBSCR_LIST_SLICE, - [_BINARY_OP_SUBSCR_STR_INT_r21] = _BINARY_OP_SUBSCR_STR_INT, + [_BINARY_OP_SUBSCR_STR_INT_r23] = _BINARY_OP_SUBSCR_STR_INT, [_GUARD_NOS_TUPLE_r02] = _GUARD_NOS_TUPLE, [_GUARD_NOS_TUPLE_r12] = _GUARD_NOS_TUPLE, [_GUARD_NOS_TUPLE_r22] = _GUARD_NOS_TUPLE, @@ -3434,7 +3453,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_TUPLE_r11] = _GUARD_TOS_TUPLE, [_GUARD_TOS_TUPLE_r22] = _GUARD_TOS_TUPLE, [_GUARD_TOS_TUPLE_r33] = _GUARD_TOS_TUPLE, - [_BINARY_OP_SUBSCR_TUPLE_INT_r21] = _BINARY_OP_SUBSCR_TUPLE_INT, + [_BINARY_OP_SUBSCR_TUPLE_INT_r23] = _BINARY_OP_SUBSCR_TUPLE_INT, [_GUARD_NOS_DICT_r02] = _GUARD_NOS_DICT, [_GUARD_NOS_DICT_r12] = _GUARD_NOS_DICT, [_GUARD_NOS_DICT_r22] = _GUARD_NOS_DICT, @@ -3533,7 +3552,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_INSTANCE_VALUE_r12] = _LOAD_ATTR_INSTANCE_VALUE, [_LOAD_ATTR_INSTANCE_VALUE_r23] = _LOAD_ATTR_INSTANCE_VALUE, [_LOAD_ATTR_MODULE_r11] = _LOAD_ATTR_MODULE, - [_LOAD_ATTR_WITH_HINT_r11] = _LOAD_ATTR_WITH_HINT, + [_LOAD_ATTR_WITH_HINT_r12] = _LOAD_ATTR_WITH_HINT, [_LOAD_ATTR_SLOT_r11] = _LOAD_ATTR_SLOT, [_CHECK_ATTR_CLASS_r01] = _CHECK_ATTR_CLASS, [_CHECK_ATTR_CLASS_r11] = _CHECK_ATTR_CLASS, @@ -3549,13 +3568,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_STORE_ATTR_WITH_HINT_r21] = _STORE_ATTR_WITH_HINT, [_STORE_ATTR_SLOT_r21] = _STORE_ATTR_SLOT, [_COMPARE_OP_r21] = _COMPARE_OP, - [_COMPARE_OP_FLOAT_r01] = _COMPARE_OP_FLOAT, - [_COMPARE_OP_FLOAT_r11] = _COMPARE_OP_FLOAT, - [_COMPARE_OP_FLOAT_r21] = _COMPARE_OP_FLOAT, - [_COMPARE_OP_FLOAT_r32] = _COMPARE_OP_FLOAT, + [_COMPARE_OP_FLOAT_r03] = _COMPARE_OP_FLOAT, + [_COMPARE_OP_FLOAT_r13] = _COMPARE_OP_FLOAT, + [_COMPARE_OP_FLOAT_r23] = _COMPARE_OP_FLOAT, [_COMPARE_OP_INT_r23] = _COMPARE_OP_INT, - [_COMPARE_OP_STR_r21] = _COMPARE_OP_STR, - [_IS_OP_r21] = _IS_OP, + [_COMPARE_OP_STR_r23] = _COMPARE_OP_STR, + [_IS_OP_r03] = _IS_OP, + [_IS_OP_r13] = _IS_OP, + [_IS_OP_r23] = _IS_OP, [_CONTAINS_OP_r21] = _CONTAINS_OP, [_GUARD_TOS_ANY_SET_r01] = _GUARD_TOS_ANY_SET, [_GUARD_TOS_ANY_SET_r11] = _GUARD_TOS_ANY_SET, @@ -3611,6 +3631,8 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_ITER_NEXT_RANGE_r03] = _ITER_NEXT_RANGE, [_ITER_NEXT_RANGE_r13] = _ITER_NEXT_RANGE, [_ITER_NEXT_RANGE_r23] = _ITER_NEXT_RANGE, + [_FOR_ITER_GEN_FRAME_r03] = _FOR_ITER_GEN_FRAME, + [_FOR_ITER_GEN_FRAME_r13] = _FOR_ITER_GEN_FRAME, [_FOR_ITER_GEN_FRAME_r23] = _FOR_ITER_GEN_FRAME, [_INSERT_NULL_r10] = _INSERT_NULL, [_LOAD_SPECIAL_r00] = _LOAD_SPECIAL, @@ -3687,7 +3709,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_TYPE_1_r13] = _GUARD_CALLABLE_TYPE_1, [_GUARD_CALLABLE_TYPE_1_r23] = _GUARD_CALLABLE_TYPE_1, [_GUARD_CALLABLE_TYPE_1_r33] = _GUARD_CALLABLE_TYPE_1, - [_CALL_TYPE_1_r31] = _CALL_TYPE_1, + [_CALL_TYPE_1_r02] = _CALL_TYPE_1, + [_CALL_TYPE_1_r12] = _CALL_TYPE_1, + [_CALL_TYPE_1_r22] = _CALL_TYPE_1, + [_CALL_TYPE_1_r32] = _CALL_TYPE_1, [_GUARD_CALLABLE_STR_1_r03] = _GUARD_CALLABLE_STR_1, [_GUARD_CALLABLE_STR_1_r13] = _GUARD_CALLABLE_STR_1, [_GUARD_CALLABLE_STR_1_r23] = _GUARD_CALLABLE_STR_1, @@ -3719,10 +3744,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_LIST_APPEND_r13] = _GUARD_CALLABLE_LIST_APPEND, [_GUARD_CALLABLE_LIST_APPEND_r23] = _GUARD_CALLABLE_LIST_APPEND, [_GUARD_CALLABLE_LIST_APPEND_r33] = _GUARD_CALLABLE_LIST_APPEND, - [_CALL_LIST_APPEND_r02] = _CALL_LIST_APPEND, - [_CALL_LIST_APPEND_r12] = _CALL_LIST_APPEND, - [_CALL_LIST_APPEND_r22] = _CALL_LIST_APPEND, - [_CALL_LIST_APPEND_r32] = _CALL_LIST_APPEND, + [_CALL_LIST_APPEND_r03] = _CALL_LIST_APPEND, + [_CALL_LIST_APPEND_r13] = _CALL_LIST_APPEND, + [_CALL_LIST_APPEND_r23] = _CALL_LIST_APPEND, + [_CALL_LIST_APPEND_r33] = _CALL_LIST_APPEND, [_CALL_METHOD_DESCRIPTOR_O_r01] = _CALL_METHOD_DESCRIPTOR_O, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = _CALL_METHOD_DESCRIPTOR_NOARGS, @@ -3818,6 +3843,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_POP_TWO_LOAD_CONST_INLINE_BORROW_r21] = _POP_TWO_LOAD_CONST_INLINE_BORROW, [_POP_CALL_LOAD_CONST_INLINE_BORROW_r21] = _POP_CALL_LOAD_CONST_INLINE_BORROW, [_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31] = _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32] = _SHUFFLE_2_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33] = _SHUFFLE_3_LOAD_CONST_INLINE_BORROW, [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31] = _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_UNDER_INLINE_r02] = _LOAD_CONST_UNDER_INLINE, [_LOAD_CONST_UNDER_INLINE_r12] = _LOAD_CONST_UNDER_INLINE, @@ -3906,14 +3939,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_ADD_INT_r13] = "_BINARY_OP_ADD_INT_r13", [_BINARY_OP_ADD_INT_r23] = "_BINARY_OP_ADD_INT_r23", [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", - [_BINARY_OP_ADD_UNICODE_r01] = "_BINARY_OP_ADD_UNICODE_r01", - [_BINARY_OP_ADD_UNICODE_r11] = "_BINARY_OP_ADD_UNICODE_r11", - [_BINARY_OP_ADD_UNICODE_r21] = "_BINARY_OP_ADD_UNICODE_r21", - [_BINARY_OP_ADD_UNICODE_r32] = "_BINARY_OP_ADD_UNICODE_r32", + [_BINARY_OP_ADD_UNICODE_r03] = "_BINARY_OP_ADD_UNICODE_r03", + [_BINARY_OP_ADD_UNICODE_r13] = "_BINARY_OP_ADD_UNICODE_r13", + [_BINARY_OP_ADD_UNICODE_r23] = "_BINARY_OP_ADD_UNICODE_r23", [_BINARY_OP_EXTEND] = "_BINARY_OP_EXTEND", [_BINARY_OP_EXTEND_r21] = "_BINARY_OP_EXTEND_r21", [_BINARY_OP_INPLACE_ADD_UNICODE] = "_BINARY_OP_INPLACE_ADD_UNICODE", - [_BINARY_OP_INPLACE_ADD_UNICODE_r20] = "_BINARY_OP_INPLACE_ADD_UNICODE_r20", + [_BINARY_OP_INPLACE_ADD_UNICODE_r21] = "_BINARY_OP_INPLACE_ADD_UNICODE_r21", [_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT", [_BINARY_OP_MULTIPLY_FLOAT_r03] = "_BINARY_OP_MULTIPLY_FLOAT_r03", [_BINARY_OP_MULTIPLY_FLOAT_r13] = "_BINARY_OP_MULTIPLY_FLOAT_r13", @@ -3932,13 +3964,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBSCR_INIT_CALL_r21] = "_BINARY_OP_SUBSCR_INIT_CALL_r21", [_BINARY_OP_SUBSCR_INIT_CALL_r31] = "_BINARY_OP_SUBSCR_INIT_CALL_r31", [_BINARY_OP_SUBSCR_LIST_INT] = "_BINARY_OP_SUBSCR_LIST_INT", - [_BINARY_OP_SUBSCR_LIST_INT_r21] = "_BINARY_OP_SUBSCR_LIST_INT_r21", + [_BINARY_OP_SUBSCR_LIST_INT_r23] = "_BINARY_OP_SUBSCR_LIST_INT_r23", [_BINARY_OP_SUBSCR_LIST_SLICE] = "_BINARY_OP_SUBSCR_LIST_SLICE", [_BINARY_OP_SUBSCR_LIST_SLICE_r21] = "_BINARY_OP_SUBSCR_LIST_SLICE_r21", [_BINARY_OP_SUBSCR_STR_INT] = "_BINARY_OP_SUBSCR_STR_INT", - [_BINARY_OP_SUBSCR_STR_INT_r21] = "_BINARY_OP_SUBSCR_STR_INT_r21", + [_BINARY_OP_SUBSCR_STR_INT_r23] = "_BINARY_OP_SUBSCR_STR_INT_r23", [_BINARY_OP_SUBSCR_TUPLE_INT] = "_BINARY_OP_SUBSCR_TUPLE_INT", - [_BINARY_OP_SUBSCR_TUPLE_INT_r21] = "_BINARY_OP_SUBSCR_TUPLE_INT_r21", + [_BINARY_OP_SUBSCR_TUPLE_INT_r23] = "_BINARY_OP_SUBSCR_TUPLE_INT_r23", [_BINARY_OP_SUBTRACT_FLOAT] = "_BINARY_OP_SUBTRACT_FLOAT", [_BINARY_OP_SUBTRACT_FLOAT_r03] = "_BINARY_OP_SUBTRACT_FLOAT_r03", [_BINARY_OP_SUBTRACT_FLOAT_r13] = "_BINARY_OP_SUBTRACT_FLOAT_r13", @@ -3984,10 +4016,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_LEN] = "_CALL_LEN", [_CALL_LEN_r33] = "_CALL_LEN_r33", [_CALL_LIST_APPEND] = "_CALL_LIST_APPEND", - [_CALL_LIST_APPEND_r02] = "_CALL_LIST_APPEND_r02", - [_CALL_LIST_APPEND_r12] = "_CALL_LIST_APPEND_r12", - [_CALL_LIST_APPEND_r22] = "_CALL_LIST_APPEND_r22", - [_CALL_LIST_APPEND_r32] = "_CALL_LIST_APPEND_r32", + [_CALL_LIST_APPEND_r03] = "_CALL_LIST_APPEND_r03", + [_CALL_LIST_APPEND_r13] = "_CALL_LIST_APPEND_r13", + [_CALL_LIST_APPEND_r23] = "_CALL_LIST_APPEND_r23", + [_CALL_LIST_APPEND_r33] = "_CALL_LIST_APPEND_r33", [_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST", [_CALL_METHOD_DESCRIPTOR_FAST_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_r01", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", @@ -4003,7 +4035,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_TUPLE_1] = "_CALL_TUPLE_1", [_CALL_TUPLE_1_r32] = "_CALL_TUPLE_1_r32", [_CALL_TYPE_1] = "_CALL_TYPE_1", - [_CALL_TYPE_1_r31] = "_CALL_TYPE_1_r31", + [_CALL_TYPE_1_r02] = "_CALL_TYPE_1_r02", + [_CALL_TYPE_1_r12] = "_CALL_TYPE_1_r12", + [_CALL_TYPE_1_r22] = "_CALL_TYPE_1_r22", + [_CALL_TYPE_1_r32] = "_CALL_TYPE_1_r32", [_CHECK_AND_ALLOCATE_OBJECT] = "_CHECK_AND_ALLOCATE_OBJECT", [_CHECK_AND_ALLOCATE_OBJECT_r00] = "_CHECK_AND_ALLOCATE_OBJECT_r00", [_CHECK_ATTR_CLASS] = "_CHECK_ATTR_CLASS", @@ -4079,14 +4114,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_COMPARE_OP] = "_COMPARE_OP", [_COMPARE_OP_r21] = "_COMPARE_OP_r21", [_COMPARE_OP_FLOAT] = "_COMPARE_OP_FLOAT", - [_COMPARE_OP_FLOAT_r01] = "_COMPARE_OP_FLOAT_r01", - [_COMPARE_OP_FLOAT_r11] = "_COMPARE_OP_FLOAT_r11", - [_COMPARE_OP_FLOAT_r21] = "_COMPARE_OP_FLOAT_r21", - [_COMPARE_OP_FLOAT_r32] = "_COMPARE_OP_FLOAT_r32", + [_COMPARE_OP_FLOAT_r03] = "_COMPARE_OP_FLOAT_r03", + [_COMPARE_OP_FLOAT_r13] = "_COMPARE_OP_FLOAT_r13", + [_COMPARE_OP_FLOAT_r23] = "_COMPARE_OP_FLOAT_r23", [_COMPARE_OP_INT] = "_COMPARE_OP_INT", [_COMPARE_OP_INT_r23] = "_COMPARE_OP_INT_r23", [_COMPARE_OP_STR] = "_COMPARE_OP_STR", - [_COMPARE_OP_STR_r21] = "_COMPARE_OP_STR_r21", + [_COMPARE_OP_STR_r23] = "_COMPARE_OP_STR_r23", [_CONTAINS_OP] = "_CONTAINS_OP", [_CONTAINS_OP_r21] = "_CONTAINS_OP_r21", [_CONTAINS_OP_DICT] = "_CONTAINS_OP_DICT", @@ -4170,6 +4204,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_FORMAT_WITH_SPEC] = "_FORMAT_WITH_SPEC", [_FORMAT_WITH_SPEC_r21] = "_FORMAT_WITH_SPEC_r21", [_FOR_ITER_GEN_FRAME] = "_FOR_ITER_GEN_FRAME", + [_FOR_ITER_GEN_FRAME_r03] = "_FOR_ITER_GEN_FRAME_r03", + [_FOR_ITER_GEN_FRAME_r13] = "_FOR_ITER_GEN_FRAME_r13", [_FOR_ITER_GEN_FRAME_r23] = "_FOR_ITER_GEN_FRAME_r23", [_FOR_ITER_TIER_TWO] = "_FOR_ITER_TIER_TWO", [_FOR_ITER_TIER_TWO_r23] = "_FOR_ITER_TIER_TWO_r23", @@ -4422,7 +4458,9 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_IS_NONE] = "_IS_NONE", [_IS_NONE_r11] = "_IS_NONE_r11", [_IS_OP] = "_IS_OP", - [_IS_OP_r21] = "_IS_OP_r21", + [_IS_OP_r03] = "_IS_OP_r03", + [_IS_OP_r13] = "_IS_OP_r13", + [_IS_OP_r23] = "_IS_OP_r23", [_ITER_CHECK_LIST] = "_ITER_CHECK_LIST", [_ITER_CHECK_LIST_r02] = "_ITER_CHECK_LIST_r02", [_ITER_CHECK_LIST_r12] = "_ITER_CHECK_LIST_r12", @@ -4485,7 +4523,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT", [_LOAD_ATTR_SLOT_r11] = "_LOAD_ATTR_SLOT_r11", [_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT", - [_LOAD_ATTR_WITH_HINT_r11] = "_LOAD_ATTR_WITH_HINT_r11", + [_LOAD_ATTR_WITH_HINT_r12] = "_LOAD_ATTR_WITH_HINT_r12", [_LOAD_BUILD_CLASS] = "_LOAD_BUILD_CLASS", [_LOAD_BUILD_CLASS_r01] = "_LOAD_BUILD_CLASS_r01", [_LOAD_COMMON_CONSTANT] = "_LOAD_COMMON_CONSTANT", @@ -4764,6 +4802,16 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_SET_IP_r33] = "_SET_IP_r33", [_SET_UPDATE] = "_SET_UPDATE", [_SET_UPDATE_r10] = "_SET_UPDATE_r10", + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW", + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02", + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12", + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22", + [_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32] = "_SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32", + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW", + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03", + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13", + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23", + [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33] = "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33", [_SPILL_OR_RELOAD] = "_SPILL_OR_RELOAD", [_SPILL_OR_RELOAD_r01] = "_SPILL_OR_RELOAD_r01", [_SPILL_OR_RELOAD_r02] = "_SPILL_OR_RELOAD_r02", @@ -5481,6 +5529,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW: return 3; + case _SHUFFLE_2_LOAD_CONST_INLINE_BORROW: + return 3; + case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW: + return 3; case _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW: return 4; case _LOAD_CONST_UNDER_INLINE: diff --git a/InternalDocs/profiling_binary_format.md b/InternalDocs/profiling_binary_format.md new file mode 100644 index 00000000000000..7e4592a0d89705 --- /dev/null +++ b/InternalDocs/profiling_binary_format.md @@ -0,0 +1,541 @@ +# Profiling Binary Format + +The profiling module includes a binary file format for storing sampling +profiler data. This document describes the format's structure and the +design decisions behind it. + +The implementation is in +[`Modules/_remote_debugging/binary_io_writer.c`](../Modules/_remote_debugging/binary_io_writer.c) +and [`Modules/_remote_debugging/binary_io_reader.c`](../Modules/_remote_debugging/binary_io_reader.c), +with declarations in +[`Modules/_remote_debugging/binary_io.h`](../Modules/_remote_debugging/binary_io.h). + +## Overview + +The sampling profiler can generate enormous amounts of data. A typical +profiling session sampling at 1000 Hz for 60 seconds produces 60,000 samples. +Each sample contains a full call stack, often 20-50 frames deep, and each +frame includes a filename, function name, and line number. In a text-based +format like collapsed stacks, this would mean repeating the same long file +paths and function names thousands of times. + +The binary format addresses this through two key strategies: + +1. **Deduplication**: Strings and frames are stored once in lookup tables, + then referenced by small integer indices. A 100-character file path that + appears in 50,000 samples is stored once, not 50,000 times. + +2. **Compact encoding**: Variable-length integers (varints) encode small + values in fewer bytes. Since most indices are small (under 128), they + typically need only one byte instead of four. + +Together with optional zstd compression, these techniques reduce file sizes +by 10-50x compared to text formats while also enabling faster I/O. + +## File Layout + +The file consists of five sections: + +``` ++------------------+ Offset 0 +| Header | 64 bytes (fixed) ++------------------+ Offset 64 +| | +| Sample Data | Variable size (optionally compressed) +| | ++------------------+ string_table_offset +| String Table | Variable size ++------------------+ frame_table_offset +| Frame Table | Variable size ++------------------+ file_size - 32 +| Footer | 32 bytes (fixed) ++------------------+ file_size +``` + +The layout is designed for streaming writes during profiling. The profiler +cannot know in advance how many unique strings or frames will be encountered, +so these tables must be built incrementally and written at the end. + +The header comes first so readers can quickly validate the file and locate +the metadata tables. The sample data follows immediately, allowing the writer +to stream samples directly to disk (or through a compression stream) without +buffering the entire dataset in memory. + +The string and frame tables are placed after sample data because they grow +as new unique entries are discovered during profiling. By deferring their +output until finalization, the writer avoids the complexity of reserving +space or rewriting portions of the file. + +The footer at the end contains counts needed to allocate arrays before +parsing the tables. Placing it at a fixed offset from the end (rather than +at a variable offset recorded in the header) means readers can locate it +with a single seek to `file_size - 32`, without first reading the header. + +## Header + +``` + Offset Size Type Description ++--------+------+---------+----------------------------------------+ +| 0 | 4 | uint32 | Magic number (0x54414348 = "TACH") | +| 4 | 4 | uint32 | Format version | +| 8 | 4 | bytes | Python version (major, minor, micro, | +| | | | reserved) | +| 12 | 8 | uint64 | Start timestamp (microseconds) | +| 20 | 8 | uint64 | Sample interval (microseconds) | +| 28 | 4 | uint32 | Total sample count | +| 32 | 4 | uint32 | Thread count | +| 36 | 8 | uint64 | String table offset | +| 44 | 8 | uint64 | Frame table offset | +| 52 | 4 | uint32 | Compression type (0=none, 1=zstd) | +| 56 | 8 | bytes | Reserved (zero-filled) | ++--------+------+---------+----------------------------------------+ +``` + +The magic number `0x54414348` ("TACH" for Tachyon) identifies the file format +and also serves as an **endianness marker**. When read on a system with +different byte order than the writer, it appears as `0x48434154`. The reader +uses this to detect cross-endian files and automatically byte-swap all +multi-byte integer fields. + +The Python version field records the major, minor, and micro version numbers +of the Python interpreter that generated the file. This allows analysis tools +to detect version mismatches when replaying data collected on a different +Python version, which may have different internal structures or behaviors. + +The header is written as zeros initially, then overwritten with actual values +during finalization. This requires the output stream to be seekable, which +is acceptable since the format targets regular files rather than pipes or +network streams. + +## Sample Data + +Sample data begins at offset 64 and extends to `string_table_offset`. Samples +use delta compression to minimize redundancy when consecutive samples from the +same thread have identical or similar call stacks. + +### Stack Encoding Types + +Each sample record begins with thread identification, then an encoding byte: + +| Code | Name | Description | +|------|------|-------------| +| 0x00 | REPEAT | RLE: identical stack repeated N times | +| 0x01 | FULL | Complete stack (first sample or no match) | +| 0x02 | SUFFIX | Shares N frames from bottom of previous stack | +| 0x03 | POP_PUSH | Remove M frames from top, add N new frames | + +### Record Formats + +**REPEAT (0x00) - Run-Length Encoded Identical Stacks:** +``` ++-----------------+-----------+----------------------------------------+ +| thread_id | 8 bytes | Thread identifier (uint64, fixed) | +| interpreter_id | 4 bytes | Interpreter ID (uint32, fixed) | +| encoding | 1 byte | 0x00 (REPEAT) | +| count | varint | Number of samples in this RLE group | +| samples | varies | Interleaved: [delta: varint, status: 1]| +| | | repeated count times | ++-----------------+-----------+----------------------------------------+ +``` +The stack is inherited from this thread's previous sample. Each sample in the +group gets its own timestamp delta and status byte, stored as interleaved pairs +(delta1, status1, delta2, status2, ...) rather than separate arrays. + +**FULL (0x01) - Complete Stack:** +``` ++-----------------+-----------+----------------------------------------+ +| thread_id | 8 bytes | Thread identifier (uint64, fixed) | +| interpreter_id | 4 bytes | Interpreter ID (uint32, fixed) | +| encoding | 1 byte | 0x01 (FULL) | +| timestamp_delta | varint | Microseconds since thread's last sample| +| status | 1 byte | Thread state flags | +| stack_depth | varint | Number of frames in call stack | +| frame_indices | varint[] | Array of frame table indices | ++-----------------+-----------+----------------------------------------+ +``` +Used for the first sample from a thread, or when delta encoding would not +provide savings. + +**SUFFIX (0x02) - Shared Suffix Match:** +``` ++-----------------+-----------+----------------------------------------+ +| thread_id | 8 bytes | Thread identifier (uint64, fixed) | +| interpreter_id | 4 bytes | Interpreter ID (uint32, fixed) | +| encoding | 1 byte | 0x02 (SUFFIX) | +| timestamp_delta | varint | Microseconds since thread's last sample| +| status | 1 byte | Thread state flags | +| shared_count | varint | Frames shared from bottom of prev stack| +| new_count | varint | New frames at top of stack | +| new_frames | varint[] | Array of new_count frame indices | ++-----------------+-----------+----------------------------------------+ +``` +Used when a function call added frames to the top of the stack. The shared +frames from the previous stack are kept, and new frames are prepended. + +**POP_PUSH (0x03) - Pop and Push:** +``` ++-----------------+-----------+----------------------------------------+ +| thread_id | 8 bytes | Thread identifier (uint64, fixed) | +| interpreter_id | 4 bytes | Interpreter ID (uint32, fixed) | +| encoding | 1 byte | 0x03 (POP_PUSH) | +| timestamp_delta | varint | Microseconds since thread's last sample| +| status | 1 byte | Thread state flags | +| pop_count | varint | Frames to remove from top of prev stack| +| push_count | varint | New frames to add at top | +| new_frames | varint[] | Array of push_count frame indices | ++-----------------+-----------+----------------------------------------+ +``` +Used when the code path changed: some frames were popped (function returns) +and new frames were pushed (different function calls). + +### Thread and Interpreter Identification + +Thread IDs are 64-bit values that can be large (memory addresses on some +platforms) and vary unpredictably. Using a fixed 8-byte encoding avoids +the overhead of varint encoding for large values and simplifies parsing +since the reader knows exactly where each field begins. + +The interpreter ID identifies which Python sub-interpreter the thread +belongs to, allowing analysis tools to separate activity across interpreters +in processes using multiple sub-interpreters. + +### Status Byte + +The status byte is a bitfield encoding thread state at sample time: + +| Bit | Flag | Meaning | +|-----|-----------------------|--------------------------------------------| +| 0 | THREAD_STATUS_HAS_GIL | Thread holds the GIL (Global Interpreter Lock) | +| 1 | THREAD_STATUS_ON_CPU | Thread is actively running on a CPU core | +| 2 | THREAD_STATUS_UNKNOWN | Thread state could not be determined | +| 3 | THREAD_STATUS_GIL_REQUESTED | Thread is waiting to acquire the GIL | +| 4 | THREAD_STATUS_HAS_EXCEPTION | Thread has a pending exception | + +Multiple flags can be set simultaneously (e.g., a thread can hold the GIL +while also running on CPU). Analysis tools use these to filter samples or +visualize thread states over time. + +### Timestamp Delta Encoding + +Timestamps use delta encoding rather than absolute values. Absolute +timestamps in microseconds require 8 bytes each, but consecutive samples +from the same thread are typically separated by the sampling interval +(e.g., 1000 microseconds), so the delta between them is small and fits +in 1-2 varint bytes. The writer tracks the previous timestamp for each +thread separately. The first sample from a thread encodes its delta from +the profiling start time; subsequent samples encode the delta from that +thread's previous sample. This per-thread tracking is necessary because +samples are interleaved across threads in arrival order, not grouped by +thread. + +For REPEAT (RLE) records, timestamp deltas and status bytes are stored as +interleaved pairs (delta, status, delta, status, ...) - one pair per +repeated sample - allowing efficient batching while preserving the exact +timing and state of each sample. + +### Frame Indexing + +Each frame in a call stack is represented by an index into the frame table +rather than inline data. This provides massive space savings because call +stacks are highly repetitive: the same function appears in many samples +(hot functions), call stacks often share common prefixes (main -> app -> +handler -> ...), and recursive functions create repeated frame sequences. +A frame index is typically 1-2 varint bytes. Inline frame data would be +20-200+ bytes (two strings plus a line number). For a profile with 100,000 +samples averaging 30 frames each, this reduces frame data from potentially +gigabytes to tens of megabytes. + +Frame indices are written innermost-first (the currently executing frame +has index 0 in the array). This ordering works well with delta compression: +function calls typically add frames at the top (index 0), while shared +frames remain at the bottom. + +## String Table + +The string table stores deduplicated UTF-8 strings (filenames and function +names). It begins at `string_table_offset` and contains entries in order of +their assignment during writing: + +``` ++----------------+ +| length: varint | +| data: bytes | ++----------------+ (repeated for each string) +``` + +Strings are stored in the order they were first encountered during writing. +The first unique filename gets index 0, the second gets index 1, and so on. +Length-prefixing (rather than null-termination) allows strings containing +null bytes and enables readers to allocate exact-sized buffers. The varint +length encoding means short strings (under 128 bytes) need only one length +byte. + +## Frame Table + +The frame table stores deduplicated frame entries with full source position +information and bytecode opcode: + +``` ++----------------------------+ +| filename_idx: varint | +| funcname_idx: varint | +| lineno: svarint | +| end_lineno_delta: svarint | +| column: svarint | +| end_column_delta: svarint | +| opcode: u8 | ++----------------------------+ (repeated for each frame) +``` + +### Field Definitions + +| Field | Type | Description | +|------------------|---------------|----------------------------------------------------------| +| filename_idx | varint | Index into string table for file name | +| funcname_idx | varint | Index into string table for function name | +| lineno | zigzag varint | Start line number (-1 for synthetic frames) | +| end_lineno_delta | zigzag varint | Delta from lineno (end_lineno = lineno + delta) | +| column | zigzag varint | Start column offset in UTF-8 bytes (-1 if not available) | +| end_column_delta | zigzag varint | Delta from column (end_column = column + delta) | +| opcode | u8 | Python bytecode opcode (0-254) or 255 for None | + +### Delta Encoding + +Position end values use delta encoding for efficiency: + +- `end_lineno = lineno + end_lineno_delta` +- `end_column = column + end_column_delta` + +Typical values: +- `end_lineno_delta`: Usually 0 (single-line expressions) → encodes to 1 byte +- `end_column_delta`: Usually 5-20 (expression width) → encodes to 1 byte + +This saves ~1-2 bytes per frame compared to absolute encoding. When the base +value (lineno or column) is -1 (not available), the delta is stored as 0 and +the reconstructed value is -1. + +### Sentinel Values + +- `opcode = 255`: No opcode captured +- `lineno = -1`: Synthetic frame (no source location) +- `column = -1`: Column offset not available + +### Deduplication + +Each unique (filename, funcname, lineno, end_lineno, column, end_column, +opcode) combination gets one entry. This enables instruction-level profiling +where multiple bytecode instructions on the same line can be distinguished. + +Strings and frames are deduplicated separately because they have different +cardinalities and reference patterns. A codebase might have hundreds of +unique source files but thousands of unique functions. Many functions share +the same filename, so storing the filename index in each frame entry (rather +than the full string) provides an additional layer of deduplication. A frame +entry is typically 7-9 bytes rather than two full strings plus location data. + +### Size Analysis + +Typical frame size with delta encoding: +- file_idx: 1-2 bytes +- func_idx: 1-2 bytes +- lineno: 1-2 bytes +- end_lineno_delta: 1 byte (usually 0) +- column: 1 byte (usually < 64) +- end_column_delta: 1 byte (usually < 64) +- opcode: 1 byte + +**Total: ~7-9 bytes per frame** + +Line numbers and columns use signed varint (zigzag encoding) to handle +sentinel values efficiently. Synthetic frames—generated frames that don't +correspond directly to Python source code, such as C extension boundaries or +internal interpreter frames—use -1 to indicate the absence of a source +location. Zigzag encoding ensures these small negative values encode +efficiently (−1 becomes 1, which is one byte) rather than requiring the +maximum varint length. + +## Footer + +``` + Offset Size Type Description ++--------+------+---------+----------------------------------------+ +| 0 | 4 | uint32 | String count | +| 4 | 4 | uint32 | Frame count | +| 8 | 8 | uint64 | Total file size | +| 16 | 16 | bytes | Checksum (reserved, currently zeros) | ++--------+------+---------+----------------------------------------+ +``` + +The string and frame counts allow readers to pre-allocate arrays of the +correct size before parsing the tables. Without these counts, readers would +need to either scan the tables twice (once to count, once to parse) or use +dynamically-growing arrays. + +The file size field provides a consistency check: if the actual file size +does not match, the file may be truncated or corrupted. + +The checksum field is reserved for future use. A checksum would allow +detection of corruption but adds complexity and computation cost. The +current implementation leaves this as zeros. + +## Variable-Length Integer Encoding + +The format uses LEB128 (Little Endian Base 128) for unsigned integers and +zigzag + LEB128 for signed integers. These encodings are widely used +(Protocol Buffers, DWARF debug info, WebAssembly) and well-understood. + +### Unsigned Varint (LEB128) + +Each byte stores 7 bits of data. The high bit indicates whether more bytes +follow: + +``` +Value Encoded bytes +0-127 [0xxxxxxx] (1 byte) +128-16383 [1xxxxxxx] [0xxxxxxx] (2 bytes) +16384+ [1xxxxxxx] [1xxxxxxx] ... (3+ bytes) +``` + +Most indices in profiling data are small. A profile with 1000 unique frames +needs at most 2 bytes per frame index. The common case (indices under 128) +needs only 1 byte. + +### Signed Varint (Zigzag) + +Standard LEB128 encodes −1 as a very large unsigned value, requiring many +bytes. Zigzag encoding interleaves positive and negative values: + +``` + 0 -> 0 -1 -> 1 1 -> 2 -2 -> 3 2 -> 4 +``` + +This ensures small-magnitude values (whether positive or negative) encode +in few bytes. + +## Compression + +When compression is enabled, the sample data region contains a zstd stream. +The string table, frame table, and footer remain uncompressed so readers can +access metadata without decompressing the entire file. A tool that only needs +to report "this file contains 50,000 samples of 3 threads" can read the header +and footer without touching the compressed sample data. This also simplifies +the format: the header's offset fields point directly to the tables rather +than to positions within a decompressed stream. + +Zstd provides an excellent balance of compression ratio and speed. Profiling +data compresses very well (often 5-10x) due to repetitive patterns: the same +small set of frame indices appears repeatedly, and delta-encoded timestamps +cluster around the sampling interval. Zstd's streaming API allows compression +without buffering the entire dataset. The writer feeds sample data through +the compressor incrementally, flushing compressed chunks to disk as they +become available. + +Level 5 compression is used as a default. Lower levels (1-3) are faster but +compress less; higher levels (6+) compress more but slow down writing. Level +5 provides good compression with minimal impact on profiling overhead. + +## Reading and Writing + +### Writing + +1. Open the output file and write 64 zero bytes as a placeholder header +2. Initialize empty string and frame dictionaries for deduplication +3. For each sample: + - Intern any new strings, assigning sequential indices + - Intern any new frames, assigning sequential indices + - Encode the sample record and write to the buffer + - Flush the buffer through compression (if enabled) when full +4. Flush remaining buffered data and finalize compression +5. Write the string table (length-prefixed strings in index order) +6. Write the frame table (varint-encoded entries in index order) +7. Write the footer with final counts +8. Seek to offset 0 and write the header with actual values + +The writer maintains two dictionaries: one mapping strings to indices, one +mapping (filename_idx, funcname_idx, lineno) tuples to frame indices. These +enable O(1) lookup during interning. + +### Reading + +1. Read the header magic number to detect endianness (set `needs_swap` flag + if the magic appears byte-swapped) +2. Validate version and read remaining header fields (byte-swapping if needed) +3. Seek to end − 32 and read the footer (byte-swapping counts if needed) +4. Allocate string array of `string_count` elements +5. Parse the string table, populating the array +6. Allocate frame array of `frame_count * 3` uint32 elements +7. Parse the frame table, populating the array +8. If compressed, decompress the sample data region +9. Iterate through samples, resolving indices to strings/frames + (byte-swapping thread_id and interpreter_id if needed) + +The reader builds lookup arrays rather than dictionaries since it only needs +index-to-value mapping, not value-to-index. + +## Platform Considerations + +### Byte Ordering and Cross-Platform Portability + +The binary format uses **native byte order** for all multi-byte integer +fields when writing. However, the reader supports **cross-endian reading**: +files written on a little-endian system (x86, ARM) can be read on a +big-endian system (s390x, PowerPC), and vice versa. + +The magic number doubles as an endianness marker. When read on a system with +different byte order, it appears byte-swapped (`0x48434154` instead of +`0x54414348`). The reader detects this and automatically byte-swaps all +fixed-width integer fields during parsing. + +Writers must use `memcpy()` from properly-sized integer types when writing +fixed-width integer fields. When the source variable's type differs from the +field width (e.g., `size_t` written as 4 bytes), explicit casting to the +correct type (e.g., `uint32_t`) is required before `memcpy()`. On big-endian +systems, copying from an oversized type would copy the wrong bytes—high-order +zeros instead of the actual value. + +The reader tracks whether byte-swapping is needed via a `needs_swap` flag set +during header parsing. All fixed-width fields in the header, footer, and +sample data are conditionally byte-swapped using Python's internal byte-swap +functions (`_Py_bswap32`, `_Py_bswap64` from `pycore_bitutils.h`). + +Variable-length integers (varints) are byte-order independent since they +encode values one byte at a time using the LEB128 scheme, so they require +no special handling for cross-endian reading. + +### Memory-Mapped I/O + +On Unix systems (Linux, macOS), the reader uses `mmap()` to map the file +into the process address space. The kernel handles paging data in and out +as needed, no explicit read() calls or buffer management are required, +multiple readers can share the same physical pages, and sequential access +patterns benefit from kernel read-ahead. + +The implementation uses `madvise()` to hint the access pattern to the kernel: +`MADV_SEQUENTIAL` indicates the file will be read linearly, enabling +aggressive read-ahead. `MADV_WILLNEED` requests pre-faulting of pages. +On Linux, `MAP_POPULATE` pre-faults all pages at mmap time rather than on +first access, moving page fault overhead from the parsing loop to the +initial mapping for more predictable performance. For large files (over +32 MB), `MADV_HUGEPAGE` requests transparent huge pages (2 MB instead of +4 KB) to reduce TLB pressure when accessing large amounts of data. + +On Windows, the implementation falls back to standard file I/O with full +file buffering. Profiling data files are typically small enough (tens to +hundreds of megabytes) that this is acceptable. + +The writer uses a 512 KB buffer to batch small writes. Each sample record +is typically tens of bytes; writing these individually would incur excessive +syscall overhead. The buffer accumulates data until full, then flushes in +one write() call (or feeds through the compression stream). + +## Future Considerations + +The format reserves space for future extensions. The 12 reserved bytes in +the header could hold additional metadata. The 16-byte checksum field in +the footer is currently unused. The version field allows incompatible +changes with graceful rejection. New compression types could be added +(compression_type > 1). + +Any changes that alter the meaning of existing fields or the parsing logic +should increment the version number to prevent older readers from +misinterpreting new files. diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index e681cb17e43e04..b3dce93710a23f 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -28,6 +28,7 @@ "BINARY_OP_SUBSCR_STR_INT", "BINARY_OP_SUBSCR_DICT", "BINARY_OP_SUBSCR_GETITEM", + "BINARY_OP_INPLACE_ADD_UNICODE", "BINARY_OP_EXTEND", "BINARY_OP_INPLACE_ADD_UNICODE", ], @@ -125,6 +126,7 @@ 'BINARY_OP_ADD_UNICODE': 131, 'BINARY_OP_EXTEND': 132, 'BINARY_OP_INPLACE_ADD_UNICODE': 3, + 'BINARY_OP_INPLACE_ADD_UNICODE': 3, 'BINARY_OP_MULTIPLY_FLOAT': 133, 'BINARY_OP_MULTIPLY_INT': 134, 'BINARY_OP_SUBSCR_DICT': 135, diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py index d078ebfa4cedbe..afbb70bbcab930 100644 --- a/Lib/asyncio/__main__.py +++ b/Lib/asyncio/__main__.py @@ -86,14 +86,15 @@ def run(self): global return_code try: - banner = ( - f'asyncio REPL {sys.version} on {sys.platform}\n' - f'Use "await" directly instead of "asyncio.run()".\n' - f'Type "help", "copyright", "credits" or "license" ' - f'for more information.\n' - ) + if not sys.flags.quiet: + banner = ( + f'asyncio REPL {sys.version} on {sys.platform}\n' + f'Use "await" directly instead of "asyncio.run()".\n' + f'Type "help", "copyright", "credits" or "license" ' + f'for more information.\n' + ) - console.write(banner) + console.write(banner) if startup_path := os.getenv("PYTHONSTARTUP"): sys.audit("cpython.run_startup", startup_path) @@ -240,4 +241,5 @@ def interrupt(self) -> None: break console.write('exiting asyncio REPL...\n') + loop.close() sys.exit(return_code) diff --git a/Lib/base64.py b/Lib/base64.py index 341bf8eaf1891e..c2fdee8eab9690 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -508,9 +508,9 @@ def b85decode(b): ) _z85_encode_translation = bytes.maketrans(_b85alphabet, _z85alphabet) -def z85encode(s): +def z85encode(s, pad=False): """Encode bytes-like object b in z85 format and return a bytes object.""" - return b85encode(s).translate(_z85_encode_translation) + return b85encode(s, pad).translate(_z85_encode_translation) def z85decode(s): """Decode the z85-encoded bytes-like object or ASCII string b diff --git a/Lib/configparser.py b/Lib/configparser.py index 18af1eadaad111..d435a5c2fe0da2 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -794,7 +794,8 @@ def read_dict(self, dictionary, source=''): """ elements_added = set() for section, keys in dictionary.items(): - section = str(section) + if section is not UNNAMED_SECTION: + section = str(section) try: self.add_section(section) except (DuplicateSectionError, ValueError): diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py index 6795a606de037e..05a34a4c105233 100644 --- a/Lib/email/_encoded_words.py +++ b/Lib/email/_encoded_words.py @@ -219,7 +219,7 @@ def encode(string, charset='utf-8', encoding=None, lang=''): """ if charset == 'unknown-8bit': - bstring = string.encode('ascii', 'surrogateescape') + bstring = string.encode('utf-8', 'surrogateescape') else: bstring = string.encode(charset) if encoding is None: diff --git a/Lib/locale.py b/Lib/locale.py index 37cafb4a601b3c..dea3ee55cf4d24 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -214,7 +214,7 @@ def format_string(f, val, grouping=False, monetary=False): Grouping is applied if the third parameter is true. Conversion uses monetary thousands separator and grouping strings if - forth parameter monetary is true.""" + fourth parameter monetary is true.""" global _percent_re if _percent_re is None: import re @@ -559,12 +559,6 @@ def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): """ - import warnings - warnings._deprecated( - "locale.getdefaultlocale", - "{name!r} is deprecated and slated for removal in Python {remove}. " - "Use setlocale(), getencoding() and getlocale() instead.", - remove=(3, 15)) return _getdefaultlocale(envvars) diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 4a44642765cc9a..65923e9c5de324 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -2181,11 +2181,7 @@ def _unlock_file(f): def _create_carefully(path): """Create a file if it doesn't exist and open for reading and writing.""" - fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o666) - try: - return open(path, 'rb+') - finally: - os.close(fd) + return open(path, 'xb+') def _create_temporary(path): """Create a temp file based on path and open for reading and writing.""" diff --git a/Lib/multiprocessing/spawn.py b/Lib/multiprocessing/spawn.py index daac1ecc34b55e..d43864c939cb63 100644 --- a/Lib/multiprocessing/spawn.py +++ b/Lib/multiprocessing/spawn.py @@ -184,7 +184,7 @@ def get_preparation_data(name): sys_argv=sys.argv, orig_dir=process.ORIGINAL_DIR, dir=os.getcwd(), - start_method=get_start_method(), + start_method=get_start_method(allow_none=True), ) # Figure out whether to initialise main in the subprocess as a module diff --git a/Lib/pdb.py b/Lib/pdb.py index c1a5db080dc7ef..eee0273fdc463f 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -391,17 +391,22 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, # Read ~/.pdbrc and ./.pdbrc self.rcLines = [] if readrc: + home_rcfile = os.path.expanduser("~/.pdbrc") + local_rcfile = os.path.abspath(".pdbrc") + try: - with open(os.path.expanduser('~/.pdbrc'), encoding='utf-8') as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass - try: - with open(".pdbrc", encoding='utf-8') as rcFile: - self.rcLines.extend(rcFile) + with open(home_rcfile, encoding='utf-8') as rcfile: + self.rcLines.extend(rcfile) except OSError: pass + if local_rcfile != home_rcfile: + try: + with open(local_rcfile, encoding='utf-8') as rcfile: + self.rcLines.extend(rcfile) + except OSError: + pass + self.commands = {} # associates a command list to breakpoint numbers self.commands_defining = False # True while in the process of defining # a command list @@ -1315,7 +1320,14 @@ def do_commands(self, arg): reached. """ if not arg: - bnum = len(bdb.Breakpoint.bpbynumber) - 1 + for bp in reversed(bdb.Breakpoint.bpbynumber): + if bp is None: + continue + bnum = bp.number + break + else: + self.error('cannot set commands: no existing breakpoint') + return else: try: bnum = int(arg) diff --git a/Lib/profiling/sampling/_child_monitor.py b/Lib/profiling/sampling/_child_monitor.py index e06c550d938b13..ec56f75719f9d1 100644 --- a/Lib/profiling/sampling/_child_monitor.py +++ b/Lib/profiling/sampling/_child_monitor.py @@ -16,7 +16,7 @@ _CHILD_POLL_INTERVAL_SEC = 0.1 # Default timeout for waiting on child profilers -_DEFAULT_WAIT_TIMEOUT = 30.0 +_DEFAULT_WAIT_TIMEOUT_SEC = 30.0 # Maximum number of child profilers to spawn (prevents resource exhaustion) _MAX_CHILD_PROFILERS = 100 @@ -138,7 +138,7 @@ def spawned_profilers(self): with self._lock: return list(self._spawned_profilers) - def wait_for_profilers(self, timeout=_DEFAULT_WAIT_TIMEOUT): + def wait_for_profilers(self, timeout=_DEFAULT_WAIT_TIMEOUT_SEC): """ Wait for all spawned child profilers to complete. diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css index 03eb2274d23e68..24e67bedee5242 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.css @@ -346,10 +346,10 @@ body.resizing-sidebar { position: relative; } -.summary-card:nth-child(1) { --i: 0; --card-color: 55, 118, 171; } -.summary-card:nth-child(2) { --i: 1; --card-color: 40, 167, 69; } -.summary-card:nth-child(3) { --i: 2; --card-color: 255, 193, 7; } -.summary-card:nth-child(4) { --i: 3; --card-color: 111, 66, 193; } +.summary-card:nth-child(1) { --i: 0; --card-color: var(--card-blue); } +.summary-card:nth-child(2) { --i: 1; --card-color: var(--card-green); } +.summary-card:nth-child(3) { --i: 2; --card-color: var(--card-yellow); } +.summary-card:nth-child(4) { --i: 3; --card-color: var(--card-purple); } .summary-card:hover { border-color: rgba(var(--card-color), 0.6); @@ -405,21 +405,18 @@ body.resizing-sidebar { text-overflow: ellipsis; } -/* Efficiency Bar */ -.efficiency-section { - margin-top: 10px; - padding-top: 10px; - border-top: 1px solid var(--border); -} +/* -------------------------------------------------------------------------- + Progress Bars + -------------------------------------------------------------------------- */ -.efficiency-header { +.bar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px; } -.efficiency-label { +.bar-label { font-size: 9px; font-weight: 600; color: var(--text-secondary); @@ -427,21 +424,21 @@ body.resizing-sidebar { letter-spacing: 0.2px; } -.efficiency-value { +.bar-value { font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: var(--accent); } -.efficiency-bar { +.bar { height: 6px; background: var(--bg-tertiary); border-radius: 3px; overflow: hidden; } -.efficiency-fill { +.bar-fill { height: 100%; background: linear-gradient(90deg, #28a745 0%, #20c997 50%, #17a2b8 100%); border-radius: 3px; @@ -450,7 +447,7 @@ body.resizing-sidebar { overflow: hidden; } -.efficiency-fill::after { +.bar-fill::after { content: ''; position: absolute; top: 0; @@ -467,68 +464,56 @@ body.resizing-sidebar { } /* -------------------------------------------------------------------------- - Thread Stats Grid (in Sidebar) + Efficiency Section Container + -------------------------------------------------------------------------- */ + +.efficiency-section { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid var(--border); +} + +/* -------------------------------------------------------------------------- + Thread Stats Progress Bars (in Sidebar) -------------------------------------------------------------------------- */ .thread-stats-section { display: block; } -.stats-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; +.stats-container { + display: flex; + flex-direction: column; + gap: 10px; } -.stat-tile { - background: var(--bg-primary); - border-radius: 8px; - padding: 10px; - text-align: center; - border: 2px solid var(--border); - transition: all var(--transition-fast); +.stat-item { animation: fadeIn 0.4s ease-out backwards; animation-delay: calc(var(--i, 0) * 0.05s); } -.stat-tile:nth-child(1) { --i: 0; } -.stat-tile:nth-child(2) { --i: 1; } -.stat-tile:nth-child(3) { --i: 2; } -.stat-tile:nth-child(4) { --i: 3; } +.stat-item:nth-child(1) { --i: 0; } +.stat-item:nth-child(2) { --i: 1; } +.stat-item:nth-child(3) { --i: 2; } +.stat-item:nth-child(4) { --i: 3; } +.stat-item:nth-child(5) { --i: 4; } -.stat-tile:hover { - transform: translateY(-2px); - box-shadow: var(--shadow-sm); +/* Color variants for bar-fill */ +.bar-fill--green { + background: linear-gradient(90deg, #28a745 0%, #20c997 100%); } -.stat-tile-value { - font-family: var(--font-mono); - font-size: 16px; - font-weight: 700; - color: var(--text-primary); - line-height: 1.2; +.bar-fill--yellow { + background: linear-gradient(90deg, #ffc107 0%, #ffdb4d 100%); } -.stat-tile-label { - font-size: 9px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.3px; - color: var(--text-muted); - margin-top: 2px; +.bar-fill--purple { + background: linear-gradient(90deg, #6f42c1 0%, #9b6dd6 100%); } -/* Stat tile color variants */ -.stat-tile--green { --tile-color: 40, 167, 69; --tile-text: #28a745; } -.stat-tile--red { --tile-color: 220, 53, 69; --tile-text: #dc3545; } -.stat-tile--yellow { --tile-color: 255, 193, 7; --tile-text: #d39e00; } -.stat-tile--purple { --tile-color: 111, 66, 193; --tile-text: #6f42c1; } - -.stat-tile[class*="--"] { - border-color: rgba(var(--tile-color), 0.4); - background: linear-gradient(135deg, rgba(var(--tile-color), 0.08) 0%, var(--bg-primary) 100%); +.bar-fill--red { + background: linear-gradient(90deg, #dc3545 0%, #ff6b7a 100%); } -.stat-tile[class*="--"] .stat-tile-value { color: var(--tile-text); } /* -------------------------------------------------------------------------- Hotspot Cards @@ -985,10 +970,6 @@ body.resizing-sidebar { .brand-info { display: none; } - - .stats-grid { - grid-template-columns: 1fr; - } } /* -------------------------------------------------------------------------- diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js index 17fd95af859587..1a51802ffefac7 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js @@ -742,24 +742,38 @@ function populateThreadStats(data, selectedThreadId = null) { if (gilReleasedStat) gilReleasedStat.style.display = 'block'; if (gilWaitingStat) gilWaitingStat.style.display = 'block'; + const gilHeldPct = threadStats.has_gil_pct || 0; const gilHeldPctElem = document.getElementById('gil-held-pct'); - if (gilHeldPctElem) gilHeldPctElem.textContent = `${(threadStats.has_gil_pct || 0).toFixed(1)}%`; + if (gilHeldPctElem) gilHeldPctElem.textContent = `${gilHeldPct.toFixed(1)}%`; + const gilHeldFill = document.getElementById('gil-held-fill'); + if (gilHeldFill) gilHeldFill.style.width = `${gilHeldPct}%`; - const gilReleasedPctElem = document.getElementById('gil-released-pct'); // GIL Released = not holding GIL and not waiting for it const gilReleasedPct = Math.max(0, 100 - (threadStats.has_gil_pct || 0) - (threadStats.gil_requested_pct || 0)); + const gilReleasedPctElem = document.getElementById('gil-released-pct'); if (gilReleasedPctElem) gilReleasedPctElem.textContent = `${gilReleasedPct.toFixed(1)}%`; + const gilReleasedFill = document.getElementById('gil-released-fill'); + if (gilReleasedFill) gilReleasedFill.style.width = `${gilReleasedPct}%`; + const gilWaitingPct = threadStats.gil_requested_pct || 0; const gilWaitingPctElem = document.getElementById('gil-waiting-pct'); - if (gilWaitingPctElem) gilWaitingPctElem.textContent = `${(threadStats.gil_requested_pct || 0).toFixed(1)}%`; + if (gilWaitingPctElem) gilWaitingPctElem.textContent = `${gilWaitingPct.toFixed(1)}%`; + const gilWaitingFill = document.getElementById('gil-waiting-fill'); + if (gilWaitingFill) gilWaitingFill.style.width = `${gilWaitingPct}%`; } + const gcPct = threadStats.gc_pct || 0; const gcPctElem = document.getElementById('gc-pct'); - if (gcPctElem) gcPctElem.textContent = `${(threadStats.gc_pct || 0).toFixed(1)}%`; + if (gcPctElem) gcPctElem.textContent = `${gcPct.toFixed(1)}%`; + const gcFill = document.getElementById('gc-fill'); + if (gcFill) gcFill.style.width = `${gcPct}%`; // Exception stats + const excPct = threadStats.has_exception_pct || 0; const excPctElem = document.getElementById('exc-pct'); - if (excPctElem) excPctElem.textContent = `${(threadStats.has_exception_pct || 0).toFixed(1)}%`; + if (excPctElem) excPctElem.textContent = `${excPct.toFixed(1)}%`; + const excFill = document.getElementById('exc-fill'); + if (excFill) excFill.style.width = `${excPct}%`; } // ============================================================================ diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html index 936c9adfc8c519..195a555d68e98b 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html @@ -159,21 +159,21 @@

Profile Summary