diff --git a/.gitattributes b/.gitattributes index b8189f12ded..f4d65dfd1df 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,6 +34,9 @@ Lib/test/xmltestdata/* noeol Lib/venv/scripts/common/activate text eol=lf Lib/venv/scripts/posix/* text eol=lf +# Prevent GitHub's web conflict editor from converting LF to CRLF +*.rst text eol=lf + # CRLF files [attr]dos text eol=crlf diff --git a/.github/workflows/add-issue-header.yml b/.github/workflows/add-issue-header.yml index 00b7ae50cb9..4c25976b9c2 100644 --- a/.github/workflows/add-issue-header.yml +++ b/.github/workflows/add-issue-header.yml @@ -12,7 +12,8 @@ on: # Only ever run once - opened -permissions: {} +permissions: + contents: read jobs: add-header: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c34f8f699d8..33a5950c148 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,8 @@ on: - 'main' - '3.*' -permissions: {} +permissions: + contents: read concurrency: # https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency @@ -353,7 +354,7 @@ jobs: with: persist-credentials: false - name: Build and test - run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android + run: python3 Platforms/Android ci --fast-ci ${{ matrix.arch }}-linux-android build-ios: name: iOS @@ -612,6 +613,7 @@ jobs: needs.build-context.outputs.run-ci-fuzz == 'true' || needs.build-context.outputs.run-ci-fuzz-stdlib == 'true' permissions: + contents: read security-events: write strategy: fail-fast: false diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 81d75ef1820..e63fe9e1284 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -15,7 +15,8 @@ on: paths: *paths workflow_dispatch: -permissions: {} +permissions: + contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fb2b94b7362..e9a4eb2b080 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,7 +2,8 @@ name: Lint on: [push, pull_request, workflow_dispatch] -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 583dc1808df..7f6571ef954 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -19,6 +19,7 @@ on: - "Tools/build/consts_getter.py" - "Tools/build/deepfreeze.py" - "Tools/build/generate-build-details.py" + - "Tools/build/generate_levenshtein_examples.py" - "Tools/build/generate_sbom.py" - "Tools/build/generate_stdlib_module_names.py" - "Tools/build/mypy.ini" @@ -33,7 +34,8 @@ on: - "Tools/requirements-dev.txt" workflow_dispatch: -permissions: {} +permissions: + contents: read env: PIP_DISABLE_PIP_VERSION_CHECK: 1 diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index be375a970a4..1267361040c 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -5,7 +5,8 @@ on: types: - opened -permissions: {} +permissions: + contents: read jobs: notify-new-bugs-announce: diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index 262299fc30f..f3e26668795 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -4,7 +4,8 @@ on: pull_request: types: [opened, reopened, labeled, unlabeled, synchronize] -permissions: {} +permissions: + contents: read jobs: label-dnm: diff --git a/.github/workflows/reusable-check-c-api-docs.yml b/.github/workflows/reusable-check-c-api-docs.yml index 5fae57a1dbd..49e5ef7f768 100644 --- a/.github/workflows/reusable-check-c-api-docs.yml +++ b/.github/workflows/reusable-check-c-api-docs.yml @@ -3,7 +3,8 @@ name: Reusable C API Docs Check on: workflow_call: -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml index 03ed714ca58..4f827c55cac 100644 --- a/.github/workflows/reusable-check-html-ids.yml +++ b/.github/workflows/reusable-check-html-ids.yml @@ -3,7 +3,8 @@ name: Reusable check HTML IDs on: workflow_call: -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-cifuzz.yml b/.github/workflows/reusable-cifuzz.yml index 093b2c859ef..0d022326863 100644 --- a/.github/workflows/reusable-cifuzz.yml +++ b/.github/workflows/reusable-cifuzz.yml @@ -13,7 +13,8 @@ on: required: true type: string -permissions: {} +permissions: + contents: read jobs: cifuzz: diff --git a/.github/workflows/reusable-context.yml b/.github/workflows/reusable-context.yml index cc9841ebf32..b8a9e2960ec 100644 --- a/.github/workflows/reusable-context.yml +++ b/.github/workflows/reusable-context.yml @@ -54,7 +54,8 @@ on: # yamllint disable-line rule:truthy description: Whether to run the Windows tests value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool -permissions: {} +permissions: + contents: read jobs: compute-changes: diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index 3d534feb2ed..0453b6ab555 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -4,7 +4,8 @@ on: workflow_call: workflow_dispatch: -permissions: {} +permissions: + contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/reusable-emscripten.yml b/.github/workflows/reusable-emscripten.yml index 300731deb78..69a780a9aeb 100644 --- a/.github/workflows/reusable-emscripten.yml +++ b/.github/workflows/reusable-emscripten.yml @@ -3,7 +3,8 @@ name: Reusable Emscripten on: workflow_call: -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml index a372d571529..f10503055b2 100644 --- a/.github/workflows/reusable-macos.yml +++ b/.github/workflows/reusable-macos.yml @@ -12,7 +12,8 @@ on: required: true type: string -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index c55fad77ff0..33f6f0ef455 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -12,7 +12,8 @@ on: type: boolean default: false -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 @@ -39,17 +40,15 @@ jobs: # Install clang wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh + sudo ./llvm.sh 20 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 100 + sudo update-alternatives --set clang /usr/bin/clang-20 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 100 + sudo update-alternatives --set clang++ /usr/bin/clang++-20 if [ "${SANITIZER}" = "TSan" ]; then - sudo ./llvm.sh 17 # gh-121946: llvm-18 package is temporarily broken - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100 - sudo update-alternatives --set clang /usr/bin/clang-17 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100 - sudo update-alternatives --set clang++ /usr/bin/clang++-17 # Reduce ASLR to avoid TSan crashing sudo sysctl -w vm.mmap_rnd_bits=28 - else - sudo ./llvm.sh 20 fi - name: Sanitizer option setup diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index b2ab525c976..87fba6221fb 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -23,7 +23,8 @@ on: type: string default: '' -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 83f9d2399ce..48fb70cbff8 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -3,7 +3,8 @@ name: Reusable WASI on: workflow_call: -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index 7c724f184f3..a74724323ec 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -8,7 +8,8 @@ on: required: true type: string -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 2cfe338a652..4c8d0c8a2f9 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -17,7 +17,8 @@ on: required: true type: string -permissions: {} +permissions: + contents: read env: FORCE_COLOR: 1 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index a862fde5e14..01fe5ba8fda 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -4,7 +4,8 @@ on: schedule: - cron: "0 */6 * * *" -permissions: {} +permissions: + contents: read jobs: stale: diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 35c62acb28b..656a14906b3 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -11,7 +11,8 @@ on: paths: *paths workflow_dispatch: -permissions: {} +permissions: + contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index 4ac25bc909b..cb40f6abc0b 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -13,7 +13,8 @@ on: - '.github/workflows/verify-ensurepip-wheels.yml' - 'Tools/build/verify_ensurepip_wheels.py' -permissions: {} +permissions: + contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/verify-expat.yml b/.github/workflows/verify-expat.yml index e193dfa4603..472a11db2da 100644 --- a/.github/workflows/verify-expat.yml +++ b/.github/workflows/verify-expat.yml @@ -11,7 +11,8 @@ on: - 'Modules/expat/**' - '.github/workflows/verify-expat.yml' -permissions: {} +permissions: + contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.gitignore b/.gitignore index f9d2cdfc32b..3bf5187d531 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.cover *.iml *.o +*.o.tmp *.lto *.a *.so diff --git a/Doc/c-api/allocation.rst b/Doc/c-api/allocation.rst index 59044d2d88c..09c9ed3ca54 100644 --- a/Doc/c-api/allocation.rst +++ b/Doc/c-api/allocation.rst @@ -2,7 +2,7 @@ .. _allocating-objects: -Allocating Objects on the Heap +Allocating objects on the heap ============================== @@ -153,10 +153,12 @@ Allocating Objects on the Heap To allocate and create extension modules. -Deprecated aliases -^^^^^^^^^^^^^^^^^^ +Soft-deprecated aliases +^^^^^^^^^^^^^^^^^^^^^^^ -These are :term:`soft deprecated` aliases to existing functions and macros. +.. soft-deprecated:: 3.15 + +These are aliases to existing functions and macros. They exist solely for backwards compatibility. @@ -164,7 +166,7 @@ They exist solely for backwards compatibility. :widths: auto :header-rows: 1 - * * Deprecated alias + * * Soft-deprecated alias * Function * * .. c:macro:: PyObject_NEW(type, typeobj) * :c:macro:`PyObject_New` diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index fe950196297..dc3e0f37c36 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -258,7 +258,9 @@ readonly, format .. c:macro:: PyBUF_WRITEABLE - This is a :term:`soft deprecated` alias to :c:macro:`PyBUF_WRITABLE`. + This is an alias to :c:macro:`PyBUF_WRITABLE`. + + .. soft-deprecated:: 3.13 .. c:macro:: PyBUF_FORMAT diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst index d1fde1baf71..f56bcd6333a 100644 --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -47,9 +47,9 @@ called with a non-bytes parameter. *len* on success, and ``NULL`` on failure. If *v* is ``NULL``, the contents of the bytes object are uninitialized. - .. deprecated:: 3.15 - ``PyBytes_FromStringAndSize(NULL, len)`` is :term:`soft deprecated`, - use the :c:type:`PyBytesWriter` API instead. + .. soft-deprecated:: 3.15 + Use the :c:type:`PyBytesWriter` API instead of + ``PyBytes_FromStringAndSize(NULL, len)``. .. c:function:: PyObject* PyBytes_FromFormat(const char *format, ...) @@ -238,9 +238,8 @@ called with a non-bytes parameter. *\*bytes* is set to ``NULL``, :exc:`MemoryError` is set, and ``-1`` is returned. - .. deprecated:: 3.15 - The function is :term:`soft deprecated`, - use the :c:type:`PyBytesWriter` API instead. + .. soft-deprecated:: 3.15 + Use the :c:type:`PyBytesWriter` API instead. .. c:function:: PyObject *PyBytes_Repr(PyObject *bytes, int smartquotes) diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index be2c85ec974..57b77f92a7d 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -212,7 +212,7 @@ bound into a function. .. c:function:: PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj) - This is a :term:`soft deprecated` function that does nothing. + This is a function that does nothing. Prior to Python 3.10, this function would perform basic optimizations to a code object. @@ -220,6 +220,8 @@ bound into a function. .. versionchanged:: 3.10 This function now does nothing. + .. soft-deprecated:: 3.13 + .. _c_codeobject_flags: diff --git a/Doc/c-api/descriptor.rst b/Doc/c-api/descriptor.rst index b913e24b3c7..539c4610ce4 100644 --- a/Doc/c-api/descriptor.rst +++ b/Doc/c-api/descriptor.rst @@ -140,7 +140,7 @@ found in the dictionary of type objects. .. c:macro:: PyDescr_COMMON - This is a :term:`soft deprecated` macro including the common fields for a + This is a macro including the common fields for a descriptor object. This was included in Python's C API by mistake; do not use it in extensions. @@ -148,6 +148,8 @@ found in the dictionary of type objects. descriptor protocol (:c:member:`~PyTypeObject.tp_descr_get` and :c:member:`~PyTypeObject.tp_descr_set`). + .. soft-deprecated:: 3.15 + Built-in descriptors ^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 7a925870a62..a2a0d0d8065 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -76,6 +76,11 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -105,6 +110,11 @@ Dictionary objects ``0`` on success or ``-1`` on failure. This function *does not* steal a reference to *val*. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val) @@ -120,6 +130,11 @@ Dictionary objects If *key* is not in the dictionary, :exc:`KeyError` is raised. Return ``0`` on success or ``-1`` on failure. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: int PyDict_DelItemString(PyObject *p, const char *key) @@ -140,6 +155,11 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 .. versionchanged:: 3.15 @@ -162,6 +182,13 @@ Dictionary objects :meth:`~object.__eq__` methods are silently ignored. Prefer the :c:func:`PyDict_GetItemWithError` function instead. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which + returns a :term:`strong reference`. + .. versionchanged:: 3.10 Calling this API without an :term:`attached thread state` had been allowed for historical reason. It is no longer allowed. @@ -177,6 +204,13 @@ Dictionary objects occurred. Return ``NULL`` **without** an exception set if the key wasn't present. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which + returns a :term:`strong reference`. + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -195,6 +229,13 @@ Dictionary objects Prefer using the :c:func:`PyDict_GetItemWithError` function with your own :c:func:`PyUnicode_FromString` *key* instead. + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_GetItemStringRef`, + which returns a :term:`strong reference`. + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -221,6 +262,14 @@ Dictionary objects .. versionadded:: 3.4 + .. note:: + + In the :term:`free-threaded build`, the returned + :term:`borrowed reference` may become invalid if another thread modifies + the dictionary concurrently. Prefer :c:func:`PyDict_SetDefaultRef`, + which returns a :term:`strong reference`. + + .. c:function:: int PyDict_SetDefaultRef(PyObject *p, PyObject *key, PyObject *default_value, PyObject **result) @@ -240,6 +289,11 @@ Dictionary objects These may refer to the same object: in that case you hold two separate references to it. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 @@ -257,6 +311,11 @@ Dictionary objects Similar to :meth:`dict.pop`, but without the default value and not raising :exc:`KeyError` if the key is missing. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. versionadded:: 3.13 @@ -403,6 +462,13 @@ Dictionary objects only be added if there is not a matching key in *a*. Return ``0`` on success or ``-1`` if an exception was raised. + .. note:: + + In the :term:`free-threaded build`, when *b* is a + :class:`dict` (with the standard iterator), both *a* and *b* are locked + for the duration of the operation. When *b* is a non-dict mapping, only + *a* is locked; *b* may be concurrently modified by another thread. + .. c:function:: int PyDict_Update(PyObject *a, PyObject *b) @@ -412,6 +478,13 @@ Dictionary objects argument has no "keys" attribute. Return ``0`` on success or ``-1`` if an exception was raised. + .. note:: + + In the :term:`free-threaded build`, when *b* is a + :class:`dict` (with the standard iterator), both *a* and *b* are locked + for the duration of the operation. When *b* is a non-dict mapping, only + *a* is locked; *b* may be concurrently modified by another thread. + .. c:function:: int PyDict_MergeFromSeq2(PyObject *a, PyObject *seq2, int override) @@ -427,6 +500,13 @@ Dictionary objects if override or key not in a: a[key] = value + .. note:: + + In the :term:`free-threaded ` build, only *a* is locked. + The iteration over *seq2* is not synchronized; *seq2* may be concurrently + modified by another thread. + + .. c:function:: int PyDict_AddWatcher(PyDict_WatchCallback callback) Register *callback* as a dictionary watcher. Return a non-negative integer @@ -434,6 +514,13 @@ Dictionary objects of error (e.g. no more watcher IDs available), return ``-1`` and set an exception. + .. note:: + + This function is not internally synchronized. In the + :term:`free-threaded ` build, callers should ensure no + concurrent calls to :c:func:`PyDict_AddWatcher` or + :c:func:`PyDict_ClearWatcher` are in progress. + .. versionadded:: 3.12 .. c:function:: int PyDict_ClearWatcher(int watcher_id) @@ -442,6 +529,13 @@ Dictionary objects :c:func:`PyDict_AddWatcher`. Return ``0`` on success, ``-1`` on error (e.g. if the given *watcher_id* was never registered.) + .. note:: + + This function is not internally synchronized. In the + :term:`free-threaded ` build, callers should ensure no + concurrent calls to :c:func:`PyDict_AddWatcher` or + :c:func:`PyDict_ClearWatcher` are in progress. + .. versionadded:: 3.12 .. c:function:: int PyDict_Watch(int watcher_id, PyObject *dict) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 8ecd7c62517..7a07818b7b4 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -818,7 +818,7 @@ Exception Classes .. c:macro:: PyException_HEAD - This is a :term:`soft deprecated` macro including the base fields for an + This is a macro including the base fields for an exception object. This was included in Python's C API by mistake and is not designed for use @@ -826,6 +826,8 @@ Exception Classes :c:func:`PyErr_NewException` or otherwise create a class inheriting from :c:data:`PyExc_BaseException`. + .. soft-deprecated:: 3.15 + Exception Objects ================= diff --git a/Doc/c-api/extension-modules.rst b/Doc/c-api/extension-modules.rst index 92b531665e1..7bc04970b19 100644 --- a/Doc/c-api/extension-modules.rst +++ b/Doc/c-api/extension-modules.rst @@ -191,10 +191,10 @@ the :c:data:`Py_mod_multiple_interpreters` slot. ``PyInit`` function ................... -.. deprecated:: 3.15 +.. soft-deprecated:: 3.15 - This functionality is :term:`soft deprecated`. - It will not get new features, but there are no plans to remove it. + This functionality will not get new features, + but there are no plans to remove it. Instead of :c:func:`PyModExport_modulename`, an extension module can define an older-style :dfn:`initialization function` with the signature: @@ -272,10 +272,9 @@ For example, a module called ``spam`` would be defined like this:: Legacy single-phase initialization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. deprecated:: 3.15 +.. soft-deprecated:: 3.15 - Single-phase initialization is :term:`soft deprecated`. - It is a legacy mechanism to initialize extension + Single-phase initialization is a legacy mechanism to initialize extension modules, with known drawbacks and design flaws. Extension module authors are encouraged to use multi-phase initialization instead. diff --git a/Doc/c-api/file.rst b/Doc/c-api/file.rst index d89072ab24e..dcafefdc045 100644 --- a/Doc/c-api/file.rst +++ b/Doc/c-api/file.rst @@ -2,7 +2,7 @@ .. _fileobjects: -File Objects +File objects ------------ .. index:: pair: object; file @@ -136,11 +136,12 @@ the :mod:`io` APIs instead. failure; the appropriate exception will be set. -Deprecated API -^^^^^^^^^^^^^^ +Soft-deprecated API +^^^^^^^^^^^^^^^^^^^ +.. soft-deprecated:: 3.15 -These are :term:`soft deprecated` APIs that were included in Python's C API +These are APIs that were included in Python's C API by mistake. They are documented solely for completeness; use other ``PyFile*`` APIs instead. diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index 929b56bd8e8..a12ad11abb1 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -86,8 +86,7 @@ Floating-Point Objects It is equivalent to the :c:macro:`!INFINITY` macro from the C11 standard ```` header. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_NAN @@ -103,8 +102,7 @@ Floating-Point Objects Equivalent to :c:macro:`!INFINITY`. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.14 .. c:macro:: Py_MATH_E @@ -161,8 +159,8 @@ Floating-Point Objects that is, it is normal, subnormal or zero, but not infinite or NaN. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isfinite` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isfinite` instead. .. c:macro:: Py_IS_INFINITY(X) @@ -170,8 +168,8 @@ Floating-Point Objects Return ``1`` if the given floating-point number *X* is positive or negative infinity. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isinf` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isinf` instead. .. c:macro:: Py_IS_NAN(X) @@ -179,8 +177,8 @@ Floating-Point Objects Return ``1`` if the given floating-point number *X* is a not-a-number (NaN) value. Return ``0`` otherwise. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. Use :c:macro:`!isnan` instead. + .. soft-deprecated:: 3.14 + Use :c:macro:`!isnan` instead. Pack and Unpack functions diff --git a/Doc/c-api/frame.rst b/Doc/c-api/frame.rst index 967cfc72765..4159ff6e596 100644 --- a/Doc/c-api/frame.rst +++ b/Doc/c-api/frame.rst @@ -1,6 +1,6 @@ .. highlight:: c -Frame Objects +Frame objects ------------- .. c:type:: PyFrameObject @@ -147,7 +147,7 @@ See also :ref:`Reflection `. Return the line number that *frame* is currently executing. -Frame Locals Proxies +Frame locals proxies ^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.13 @@ -169,7 +169,7 @@ See :pep:`667` for more information. Return non-zero if *obj* is a frame :func:`locals` proxy. -Legacy Local Variable APIs +Legacy local variable APIs ^^^^^^^^^^^^^^^^^^^^^^^^^^ These APIs are :term:`soft deprecated`. As of Python 3.13, they do nothing. @@ -178,40 +178,34 @@ They exist solely for backwards compatibility. .. c:function:: void PyFrame_LocalsToFast(PyFrameObject *f, int clear) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function would copy the :attr:`~frame.f_locals` attribute of *f* to the internal "fast" array of local variables, allowing changes in frame objects to be visible to the interpreter. If *clear* was true, this function would process variables that were unset in the locals dictionary. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. .. c:function:: void PyFrame_FastToLocals(PyFrameObject *f) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function would copy the internal "fast" array of local variables (which is used by the interpreter) to the :attr:`~frame.f_locals` attribute of *f*, allowing changes in local variables to be visible to frame objects. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. .. c:function:: int PyFrame_FastToLocalsWithError(PyFrameObject *f) - This function is :term:`soft deprecated` and does nothing. - Prior to Python 3.13, this function was similar to :c:func:`PyFrame_FastToLocals`, but would return ``0`` on success, and ``-1`` with an exception set on failure. - .. versionchanged:: 3.13 + .. soft-deprecated:: 3.13 This function now does nothing. @@ -219,7 +213,7 @@ They exist solely for backwards compatibility. :pep:`667` -Internal Frames +Internal frames ^^^^^^^^^^^^^^^ Unless using :pep:`523`, you will not need this. @@ -249,5 +243,3 @@ Unless using :pep:`523`, you will not need this. Return the currently executing line number, or -1 if there is no line number. .. versionadded:: 3.12 - - diff --git a/Doc/c-api/gen.rst b/Doc/c-api/gen.rst index 74db49a6814..ed121726b89 100644 --- a/Doc/c-api/gen.rst +++ b/Doc/c-api/gen.rst @@ -90,7 +90,9 @@ Deprecated API .. c:macro:: PyAsyncGenASend_CheckExact(op) - This is a :term:`soft deprecated` API that was included in Python's C API + This is an API that was included in Python's C API by mistake. It is solely here for completeness; do not use this API. + + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst index 189d8e424f6..186ab4370bc 100644 --- a/Doc/c-api/interp-lifecycle.rst +++ b/Doc/c-api/interp-lifecycle.rst @@ -410,6 +410,11 @@ Initializing and finalizing the interpreter (zero) if not. After :c:func:`Py_FinalizeEx` is called, this returns false until :c:func:`Py_Initialize` is called again. + .. versionchanged:: next + This function no longer returns true until initialization has fully + completed, including import of the :mod:`site` module. Previously it + could return true while :c:func:`Py_Initialize` was still running. + .. c:function:: int Py_IsFinalizing() diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 2a22a023bda..500f2818e2e 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -536,16 +536,14 @@ have been standardized in C11 (or previous standards). Use the standard ``alignas`` specifier rather than this macro. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: PY_FORMAT_SIZE_T The :c:func:`printf` formatting modifier for :c:type:`size_t`. Use ``"z"`` directly instead. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_LL(number) Py_ULL(number) @@ -558,8 +556,7 @@ have been standardized in C11 (or previous standards). Consider using the C99 standard suffixes ``LL`` and ``LLU`` directly. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: PY_LONG_LONG PY_INT32_T @@ -572,8 +569,7 @@ have been standardized in C11 (or previous standards). respectively. Historically, these types needed compiler-specific extensions. - .. deprecated:: 3.15 - These macros are :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: PY_LLONG_MIN PY_LLONG_MAX @@ -587,16 +583,14 @@ have been standardized in C11 (or previous standards). The required header, ````, :ref:`is included ` in ``Python.h``. - .. deprecated:: 3.15 - These macros are :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_MEMCPY(dest, src, n) - This is a :term:`soft deprecated` alias to :c:func:`!memcpy`. - Use :c:func:`!memcpy` directly instead. + This is an alias to :c:func:`!memcpy`. - .. deprecated:: 3.14 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.14 + Use :c:func:`!memcpy` directly instead. .. c:macro:: Py_UNICODE_SIZE @@ -606,29 +600,25 @@ have been standardized in C11 (or previous standards). The required header for the latter, ````, :ref:`is included ` in ``Python.h``. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_UNICODE_WIDE Defined if ``wchar_t`` can hold a Unicode character (UCS-4). Use ``sizeof(wchar_t) >= 4`` instead - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. c:macro:: Py_VA_COPY - This is a :term:`soft deprecated` alias to the C99-standard ``va_copy`` - function. + This is an alias to the C99-standard ``va_copy`` function. Historically, this would use a compiler-specific method to copy a ``va_list``. .. versionchanged:: 3.6 This is now an alias to ``va_copy``. - .. deprecated:: 3.15 - The macro is :term:`soft deprecated`. + .. soft-deprecated:: 3.15 .. _api-objects: diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 790ec8da109..60e3ae4a064 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -197,12 +197,10 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long PyLong_AS_LONG(PyObject *obj) - A :term:`soft deprecated` alias. Exactly equivalent to the preferred ``PyLong_AsLong``. In particular, it can fail with :exc:`OverflowError` or another exception. - .. deprecated:: 3.14 - The function is soft deprecated. + .. soft-deprecated:: 3.14 .. c:function:: int PyLong_AsInt(PyObject *obj) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 8b967c285ac..b67ca671a2a 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -685,6 +685,12 @@ remove it. Usually, there is only one variable of this type for each extension module defined this way. + The struct, including all members, is part of the + :ref:`Stable ABI ` for non-free-threaded builds (``abi3``). + In the Stable ABI for free-threaded builds (``abi3t``), + this struct is opaque, and unusable in practice; see :ref:`pymoduledef_slot` + for a replacement. + .. c:member:: PyModuleDef_Base m_base Always initialize this member to :c:macro:`PyModuleDef_HEAD_INIT`: @@ -695,6 +701,11 @@ remove it. The type of :c:member:`!PyModuleDef.m_base`. + The struct is part of the :ref:`Stable ABI ` for + non-free-threaded builds (``abi3``). + In the Stable ABI for Free-Threaded Builds + (``abi3t``), this struct is opaque, and unusable in practice. + .. c:macro:: PyModuleDef_HEAD_INIT The required initial value for :c:member:`!PyModuleDef.m_base`. @@ -954,9 +965,7 @@ or code that creates modules dynamically. // PyModule_AddObject() stole a reference to obj: // Py_XDECREF(obj) is not needed here. - .. deprecated:: 3.13 - - :c:func:`PyModule_AddObject` is :term:`soft deprecated`. + .. soft-deprecated:: 3.13 .. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value) diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index b0227c2f4fa..4bfcb86abf5 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -205,6 +205,4 @@ would typically correspond to a Python function. .. versionadded:: 3.13 - .. deprecated:: 3.14 - - This function is :term:`soft deprecated`. + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index df5bf6b64a9..6bae8f25ad7 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -109,9 +109,8 @@ Sequence Protocol Alias for :c:func:`PySequence_Contains`. - .. deprecated:: 3.14 - The function is :term:`soft deprecated` and should no longer be used to - write new code. + .. soft-deprecated:: 3.14 + The function should no longer be used to write new code. .. c:function:: Py_ssize_t PySequence_Index(PyObject *o, PyObject *value) diff --git a/Doc/c-api/set.rst b/Doc/c-api/set.rst index 6974f74fbd5..db537aff2e6 100644 --- a/Doc/c-api/set.rst +++ b/Doc/c-api/set.rst @@ -89,6 +89,11 @@ the constructor functions work with any iterable Python object. actually iterable. The constructor is also useful for copying a set (``c=set(s)``). + .. note:: + + The operation is atomic on :term:`free threading ` + when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`. + .. c:function:: PyObject* PyFrozenSet_New(PyObject *iterable) @@ -97,6 +102,11 @@ the constructor functions work with any iterable Python object. set on success or ``NULL`` on failure. Raise :exc:`TypeError` if *iterable* is not actually iterable. + .. note:: + + The operation is atomic on :term:`free threading ` + when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`. + The following functions and macros are available for instances of :class:`set` or :class:`frozenset` or instances of their subtypes. @@ -124,6 +134,10 @@ or :class:`frozenset` or instances of their subtypes. the *key* is unhashable. Raise :exc:`SystemError` if *anyset* is not a :class:`set`, :class:`frozenset`, or an instance of a subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. .. c:function:: int PySet_Add(PyObject *set, PyObject *key) @@ -135,6 +149,12 @@ or :class:`frozenset` or instances of their subtypes. :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + + The following functions are available for instances of :class:`set` or its subtypes but not for instances of :class:`frozenset` or its subtypes. @@ -149,6 +169,11 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. temporary frozensets. Raise :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + The operation is atomic on :term:`free threading ` + when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`. + .. c:function:: PyObject* PySet_Pop(PyObject *set) @@ -164,13 +189,19 @@ subtypes but not for instances of :class:`frozenset` or its subtypes. success. Return ``-1`` and raise :exc:`SystemError` if *set* is not an instance of :class:`set` or its subtype. + .. note:: + + In the :term:`free-threaded build`, the set is emptied before its entries + are cleared, so other threads will observe an empty set rather than + intermediate states. + Deprecated API ^^^^^^^^^^^^^^ .. c:macro:: PySet_MINSIZE - A :term:`soft deprecated` constant representing the size of an internal + A constant representing the size of an internal preallocated table inside :c:type:`PySetObject` instances. This is documented solely for completeness, as there are no guarantees @@ -180,3 +211,5 @@ Deprecated API :c:macro:`!PySet_MINSIZE` can be replaced with a small constant like ``8``. If looking for the size of a set, use :c:func:`PySet_Size` instead. + + .. soft-deprecated:: 3.14 diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index fe2cb89f999..fe92f72f8eb 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -51,145 +51,212 @@ It is generally intended for specialized, low-level tools like debuggers. Projects that use this API are expected to follow CPython development and spend extra effort adjusting to changes. +.. _stable-abi: .. _stable-application-binary-interface: -Stable Application Binary Interface -=================================== +Stable Application Binary Interfaces +==================================== -For simplicity, this document talks about *extensions*, but the Limited API -and Stable ABI work the same way for all uses of the API – for example, -embedding Python. - -.. _limited-c-api: - -Limited C API -------------- - -Python 3.2 introduced the *Limited API*, a subset of Python's C API. -Extensions that only use the Limited API can be -compiled once and be loaded on multiple versions of Python. -Contents of the Limited API are :ref:`listed below `. - -.. c:macro:: Py_LIMITED_API - - Define this macro before including ``Python.h`` to opt in to only use - the Limited API, and to select the Limited API version. - - Define ``Py_LIMITED_API`` to the value of :c:macro:`PY_VERSION_HEX` - corresponding to the lowest Python version your extension supports. - The extension will be ABI-compatible with all Python 3 releases - from the specified one onward, and can use Limited API introduced up to that - version. - - Rather than using the ``PY_VERSION_HEX`` macro directly, hardcode a minimum - minor version (e.g. ``0x030A0000`` for Python 3.10) for stability when - compiling with future Python versions. - - You can also define ``Py_LIMITED_API`` to ``3``. This works the same as - ``0x03020000`` (Python 3.2, the version that introduced Limited API). - -.. c:macro:: Py_TARGET_ABI3T - - Define this macro before including ``Python.h`` to opt in to only use - the Limited API for :term:`free-threaded builds `, - and to select the Limited API version. - - .. seealso:: :pep:`803` - - .. versionadded:: 3.15 - - -.. _stable-abi: - -Stable ABI ----------- - -To enable this, Python provides a *Stable ABI*: a set of symbols that will -remain ABI-compatible across Python 3.x versions. +Python's :dfn:`Stable ABI` allows extensions to be compatible with multiple +versions of Python, without recompilation. .. note:: - The Stable ABI prevents ABI issues, like linker errors due to missing - symbols or data corruption due to changes in structure layouts or function - signatures. - However, other changes in Python can change the *behavior* of extensions. - See Python's Backwards Compatibility Policy (:pep:`387`) for details. + For simplicity, this document talks about *extensions*, but Stable ABI + works the same way for all uses of the API – for example, embedding Python. -The Stable ABI contains symbols exposed in the :ref:`Limited API -`, but also other ones – for example, functions necessary to -support older versions of the Limited API. +There are two Stable ABIs: -On Windows, extensions that use the Stable ABI should be linked against +- ``abi3``, introduced in Python 3.2, is compatible with + **non**-:term:`free-threaded ` builds of CPython. + +- ``abi3t``, introduced in Python 3.15, is compatible with + :term:`free-threaded ` builds of CPython. + It has stricter API limitations than ``abi3``. + + .. versionadded:: next + + ``abi3t`` was added in :pep:`803` + +It is possible for an extension to be compiled for *both* ``abi3`` and +``abi3t`` at the same time; the result will be compatible with +both free-threaded and non-free-threaded builds of Python. +Currently, this has no downsides compared to compiling for ``abi3t`` only. + +Each Stable ABI is versioned using the first two numbers of the Python version. +For example, Stable ABI 3.14 corresponds to Python 3.14. +An extension compiled for Stable ABI 3.x is ABI-compatible with Python 3.x +and above. + +Extensions that target a stable ABI must only use a limited subset of +the C API. This subset is known as the :dfn:`Limited API`; its contents +are :ref:`listed below `. + +On Windows, extensions that use a Stable ABI should be linked against ``python3.dll`` rather than a version-specific library such as ``python39.dll``. +This library only exposes the relevant symbols. On some platforms, Python will look for and load shared library files named -with the ``abi3`` tag (e.g. ``mymodule.abi3.so``). -It does not check if such extensions conform to a Stable ABI. -The user (or their packaging tools) need to ensure that, for example, -extensions built with the 3.10+ Limited API are not installed for lower +with the ``abi3`` or ``abi3t`` tag (for example, ``mymodule.abi3.so``). +:term:`Free-threaded ` interpreters only recognize the +``abi3t`` tag, while non-free-threaded ones will prefer ``abi3`` but fall back +to ``abi3t``. +Thus, extensions compatible with both ABIs should use the ``abi3t`` tag. + +Python does not necessarily check that extensions it loads +have compatible ABI. +Extension authors are encouraged to add a check using the :c:macro:`Py_mod_abi` +slot or the :c:func:`PyABIInfo_Check` function, but the user +(or their packaging tool) is ultimately responsible for ensuring that, +for example, extensions built for Stable ABI 3.10 are not installed for lower versions of Python. -All functions in the Stable ABI are present as functions in Python's shared -library, not solely as macros. This makes them usable from languages that don't -use the C preprocessor. +All functions in Stable ABI are present as functions in Python's shared +library, not solely as macros. +This makes them usable are usable from languages that don't use the C +preprocessor, including Python's :py:mod:`ctypes`. -Limited API Scope and Performance ---------------------------------- +.. _abi3-compiling: -The goal for the Limited API is to allow everything that is possible with the +Compiling for Stable ABI +------------------------ + +.. note:: + + Build tools (such as, for example, meson-python, scikit-build-core, + or Setuptools) often have a mechanism for setting macros and synchronizing + them with extension filenames and other metadata. + Prefer using such a mechanism, if it exists, over defining the + macros manually. + + The rest of this section is mainly relevant for tool authors, and for + people who compile extensions manually. + + .. seealso:: `list of recommended tools`_ in the Python Packaging User Guide + + .. _list of recommended tools: https://packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-for-extension-modules + +To compile for a Stable ABI, define one or both of the following macros +to the lowest Python version your extension should support, in +:c:macro:`Py_PACK_VERSION` format. +Typically, you should choose a specific value rather than the version of +the Python headers you are compiling against. + +The macros must be defined before including ``Python.h``. +Since :c:macro:`Py_PACK_VERSION` is not available at this point, you +will need to use the numeric value directly. +For reference, the values for a few recent Python versions are: + +.. version-hex-cheatsheet:: + +When one of the macros is defined, ``Python.h`` will only expose API that is +compatible with the given Stable ABI -- that is, the +:ref:`Limited API ` plus some definitions that need to be +visible to the compiler but should not be used directly. +When both are defined, ``Python.h`` will only expose API compatible with +both Stable ABIs. + +.. c:macro:: Py_LIMITED_API + + Target ``abi3``, that is, + non-:term:`free-threaded builds ` of CPython. + See :ref:`above ` for common information. + +.. c:macro:: Py_TARGET_ABI3T + + Target ``abi3t``, that is, + :term:`free-threaded builds ` of CPython. + See :ref:`above ` for common information. + + .. versionadded:: next + +Both macros specify a target ABI; the different naming style is due to +backwards compatibility. + +.. admonition:: Historical note + + You can also define ``Py_LIMITED_API`` as ``3``. This works the same as + ``0x03020000`` (Python 3.2, the version that introduced Stable ABI). + +When both are defined, ``Python.h`` may, or may not, redefine +:c:macro:`!Py_LIMITED_API` to match :c:macro:`!Py_TARGET_ABI3T`. + +On a :term:`free-threaded build` -- that is, when +:c:macro:`Py_GIL_DISABLED` is defined -- :c:macro:`!Py_TARGET_ABI3T` +defaults to the value of :c:macro:`!Py_LIMITED_API`. +This means that there are two ways to build for both ``abi3`` and ``abi3t``: + +- define both :c:macro:`!Py_LIMITED_API` and :c:macro:`!Py_TARGET_ABI3T`, or +- define only :c:macro:`!Py_LIMITED_API` and: + + - on Windows, define :c:macro:`!Py_GIL_DISABLED`; + - on other systems, use the headers of free-threaded build of Python. + + +.. _limited-api-scope-and-performance: + +Stable ABI Scope and Performance +-------------------------------- + +The goal for Stable ABI is to allow everything that is possible with the full C API, but possibly with a performance penalty. +Generally, compatibility with Stable ABI will require some changes to an +extension's source code. -For example, while :c:func:`PyList_GetItem` is available, its “unsafe” macro +For example, while :c:func:`PyList_GetItem` is available, its "unsafe" macro variant :c:func:`PyList_GET_ITEM` is not. The macro can be faster because it can rely on version-specific implementation details of the list object. -Without ``Py_LIMITED_API`` defined, some C API functions are inlined or -replaced by macros. -Defining ``Py_LIMITED_API`` disables this inlining, allowing stability as +For another example, when *not* compiling for Stable ABI, some C API +functions are inlined or replaced by macros. +Compiling for Stable ABI disables this inlining, allowing stability as Python's data structures are improved, but possibly reducing performance. -By leaving out the ``Py_LIMITED_API`` definition, it is possible to compile -a Limited API extension with a version-specific ABI. This can improve -performance for that Python version, but will limit compatibility. -Compiling with ``Py_LIMITED_API`` will then yield an extension that can be -distributed where a version-specific one is not available – for example, -for prereleases of an upcoming Python version. +By leaving out the :c:macro:`!Py_LIMITED_API` or :c:macro:`!Py_TARGET_ABI3T` +definition, it is possible to compile Stable-ABI-compatible source +for a version-specific ABI. +A potentially faster version-specific extension can then be distributed +alongside a version compiled for Stable ABI -- a slower but more compatible +fallback. -Limited API Caveats -------------------- +.. _limited-api-caveats: -Note that compiling with ``Py_LIMITED_API`` is *not* a complete guarantee that -code conforms to the :ref:`Limited API ` or the :ref:`Stable ABI -`. ``Py_LIMITED_API`` only covers definitions, but an API also -includes other issues, such as expected semantics. +Stable ABI Caveats +------------------ -One issue that ``Py_LIMITED_API`` does not guard against is calling a function -with arguments that are invalid in a lower Python version. +Note that compiling for Stable ABI is *not* a complete guarantee that code will +be compatible with the expected Python versions. +Stable ABI prevents *ABI* issues, like linker errors due to missing +symbols or data corruption due to changes in structure layouts or function +signatures. +However, other changes in Python can change the *behavior* of extensions. + +One issue that the :c:macro:`Py_TARGET_ABI3T` and :c:macro:`Py_LIMITED_API` +macros do not guard against is calling a function with arguments that are +invalid in a lower Python version. For example, consider a function that starts accepting ``NULL`` for an argument. In Python 3.9, ``NULL`` now selects a default behavior, but in Python 3.8, the argument will be used directly, causing a ``NULL`` dereference and crash. A similar argument works for fields of structs. -Another issue is that some struct fields are currently not hidden when -``Py_LIMITED_API`` is defined, even though they're part of the Limited API. - For these reasons, we recommend testing an extension with *all* minor Python -versions it supports, and preferably to build with the *lowest* such version. +versions it supports. We also recommend reviewing documentation of all used API to check if it is explicitly part of the Limited API. Even with ``Py_LIMITED_API`` defined, a few private declarations are exposed for technical reasons (or even unintentionally, as bugs). -Also note that the Limited API is not necessarily stable: compiling with -``Py_LIMITED_API`` with Python 3.8 means that the extension will -run with Python 3.12, but it will not necessarily *compile* with Python 3.12. -In particular, parts of the Limited API may be deprecated and removed, -provided that the Stable ABI stays stable. +Also note that while compiling with ``Py_LIMITED_API`` 3.8 means that the +extension should *load* on Python 3.12, and *compile* with Python 3.12, +the same source will not necessarily compile with ``Py_LIMITED_API`` +set to 3.12. +In general, parts of the Limited API may be deprecated and removed, +provided that Stable ABI stays stable. .. _stable-abi-platform: @@ -199,12 +266,12 @@ Platform Considerations ABI stability depends not only on Python, but also on the compiler used, lower-level libraries and compiler options. For the purposes of -the :ref:`Stable ABI `, these details define a “platform”. They +the :ref:`Stable ABIs `, these details define a “platform”. They usually depend on the OS type and processor architecture It is the responsibility of each particular distributor of Python to ensure that all Python versions on a particular platform are built -in a way that does not break the Stable ABI. +in a way that does not break the Stable ABIs, or the version-specific ABIs. This is the case with Windows and macOS releases from ``python.org`` and many third-party distributors. @@ -312,7 +379,7 @@ The full API is described below for advanced use cases. .. c:macro:: PyABIInfo_STABLE - Specifies that the stable ABI is used. + Specifies that Stable ABI is used. .. c:macro:: PyABIInfo_INTERNAL @@ -323,15 +390,22 @@ The full API is described below for advanced use cases. .. c:macro:: PyABIInfo_FREETHREADED - Specifies ABI compatible with free-threading builds of CPython. + Specifies ABI compatible with :term:`free-threaded builds + ` of CPython. (That is, ones compiled with :option:`--disable-gil`; with ``t`` in :py:data:`sys.abiflags`) .. c:macro:: PyABIInfo_GIL - Specifies ABI compatible with non-free-threading builds of CPython + Specifies ABI compatible with non-free-threaded builds of CPython (ones compiled *without* :option:`--disable-gil`). + .. c:macro:: PyABIInfo_FREETHREADING_AGNOSTIC + + Specifies ABI compatible with both free-threaded and + non-free-threaded builds of CPython, that is, both + ``abi3`` and ``abi3t``. + .. c:member:: uint32_t build_version The version of the Python headers used to build the code, in the format @@ -345,10 +419,11 @@ The full API is described below for advanced use cases. The ABI version. - For the Stable ABI, this field should be the value of - :c:macro:`Py_LIMITED_API` - (except if :c:macro:`Py_LIMITED_API` is ``3``; use - :c:expr:`Py_PACK_VERSION(3, 2)` in that case). + For Stable ABI, this field should be the value of + :c:macro:`Py_LIMITED_API` or :c:macro:`Py_TARGET_ABI3T`. + If both are defined, use the smaller value. + (If :c:macro:`Py_LIMITED_API` is ``3``; use + :c:expr:`Py_PACK_VERSION(3, 2)` instead of ``3``.) Otherwise, it should be set to :c:macro:`PY_VERSION_HEX`. @@ -365,12 +440,13 @@ The full API is described below for advanced use cases. .. versionadded:: 3.15 +.. _limited-c-api: .. _limited-api-list: Contents of Limited API ======================= - -Currently, the :ref:`Limited API ` includes the following items: +This is the definitive list of :ref:`Limited API ` for +Python |version|: .. limited-api-list:: diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index c0d2663adef..aeca4126103 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -33,6 +33,13 @@ under :ref:`reference counting `. The members must not be accessed directly; instead use macros such as :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. + In the :ref:`Stable ABI ` for Free-Threaded Builds (``abi3t``), + this struct is opaque; its size and layout may change between + Python versions. + In Stable ABI for non-free-threaded builds (``abi3``), the + :c:member:`!ob_refcnt` and :c:member:`!ob_type` fields are available, + but using them directly is discouraged. + .. c:member:: Py_ssize_t ob_refcnt The object's reference count, as returned by :c:macro:`Py_REFCNT`. @@ -72,6 +79,19 @@ under :ref:`reference counting `. instead use macros such as :c:macro:`Py_SIZE`, :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. + In the :ref:`Stable ABI ` for Free-Threaded Builds (``abi3t``), + this struct is opaque; its size and layout may change between + Python versions. + In Stable ABI for non-free-threaded builds (``abi3``), the + :c:member:`!ob_base` and :c:member:`!ob_size` fields are available, + but using them directly is discouraged. + + .. c:member:: PyObject ob_base + + Common object header. + Typically, this field is not accessed directly; instead + :c:type:`!PyVarObject` can be cast to :c:type:`PyObject`. + .. c:member:: Py_ssize_t ob_size A size field, whose contents should be considered an object's internal diff --git a/Doc/c-api/subinterpreters.rst b/Doc/c-api/subinterpreters.rst index 44e3fc96841..83c3fc3d801 100644 --- a/Doc/c-api/subinterpreters.rst +++ b/Doc/c-api/subinterpreters.rst @@ -399,6 +399,27 @@ High-level APIs .. versionadded:: 3.9 +.. c:function:: void _PyInterpreterState_SetEvalFrameAllowSpecialization(PyInterpreterState *interp, int allow_specialization) + + Enables or disables specialization why a custom frame evaluator is in place. + + If *allow_specialization* is non-zero, the adaptive specializer will + continue to specialize bytecodes even though a custom eval frame function + is set. When *allow_specialization* is zero, setting a custom eval frame + disables specialization. The standard interpreter loop will continue to deopt + while a frame evaluation API is in place - the frame evaluation function needs + to handle the specialized opcodes to take advantage of this. + + .. versionadded:: 3.15 + +.. c:function:: int _PyInterpreterState_IsSpecializationEnabled(PyInterpreterState *interp) + + Return non-zero if adaptive specialization is enabled for the interpreter. + Specialization is enabled when no custom eval frame function is set, or + when one is set with *allow_specialization* enabled. + + .. versionadded:: 3.15 + Low-level APIs -------------- diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index c3960d6ff87..d3d8239365f 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1391,8 +1391,8 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. versionchanged:: 3.9 - Renamed to the current name, without the leading underscore. - The old provisional name is :term:`soft deprecated`. + Renamed to the current name, without the leading underscore. + The old provisional name is :term:`soft deprecated`. .. versionchanged:: 3.12 @@ -1501,11 +1501,13 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. c:macro:: Py_TPFLAGS_HAVE_VERSION_TAG - This is a :term:`soft deprecated` macro that does nothing. + This macro does nothing. Historically, this would indicate that the :c:member:`~PyTypeObject.tp_version_tag` field was available and initialized. + .. soft-deprecated:: 3.13 + .. c:macro:: Py_TPFLAGS_INLINE_VALUES diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 4a7fbdf60bf..4ae5e999f0b 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -470,8 +470,8 @@ func,PyMemoryView_GetContiguous,3.2,, data,PyMemoryView_Type,3.2,, type,PyMethodDef,3.2,,full-abi data,PyMethodDescr_Type,3.2,, -type,PyModuleDef,3.2,,full-abi -type,PyModuleDef_Base,3.2,,full-abi +type,PyModuleDef,3.2,,abi3t-opaque +type,PyModuleDef_Base,3.2,,abi3t-opaque func,PyModuleDef_Init,3.5,, type,PyModuleDef_Slot,3.5,,full-abi data,PyModuleDef_Type,3.5,, diff --git a/Doc/data/threadsafety.dat b/Doc/data/threadsafety.dat index 7c381ecb70c..ea5a24a5505 100644 --- a/Doc/data/threadsafety.dat +++ b/Doc/data/threadsafety.dat @@ -14,10 +14,71 @@ # The function name must match the C domain identifier used in the documentation. # Synchronization primitives (Doc/c-api/synchronization.rst) -PyMutex_Lock:shared: -PyMutex_Unlock:shared: +PyMutex_Lock:atomic: +PyMutex_Unlock:atomic: PyMutex_IsLocked:atomic: + +# Dictionary objects (Doc/c-api/dict.rst) + +# Type checks - read ob_type pointer, always safe +PyDict_Check:atomic: +PyDict_CheckExact:atomic: + +# Creation - pure allocation, no shared state +PyDict_New:atomic: + +# Lock-free lookups - use _Py_dict_lookup_threadsafe(), no locking. +# Atomic with simple types. +PyDict_Contains:shared: +PyDict_ContainsString:atomic: +PyDict_GetItemRef:shared: +PyDict_GetItemStringRef:atomic: +PyDict_Size:atomic: +PyDict_GET_SIZE:atomic: + +# Borrowed-reference lookups - lock-free dict access but returned +# borrowed reference is unsafe in free-threaded builds without +# external synchronization +PyDict_GetItem:compatible: +PyDict_GetItemWithError:compatible: +PyDict_GetItemString:compatible: +PyDict_SetDefault:compatible: + +# Iteration - no locking; returns borrowed refs +PyDict_Next:compatible: + +# Single-item mutations - protected by per-object critical section +PyDict_SetItem:shared: +PyDict_SetItemString:atomic: +PyDict_DelItem:shared: +PyDict_DelItemString:atomic: +PyDict_SetDefaultRef:shared: +PyDict_Pop:shared: +PyDict_PopString:atomic: + +# Bulk reads - hold per-object lock for duration +PyDict_Clear:atomic: +PyDict_Copy:atomic: +PyDict_Keys:atomic: +PyDict_Values:atomic: +PyDict_Items:atomic: + +# Merge/update - lock target dict; also lock source when it is a dict +PyDict_Update:shared: +PyDict_Merge:shared: +PyDict_MergeFromSeq2:shared: + +# Watcher registration - no synchronization on interpreter state +PyDict_AddWatcher:compatible: +PyDict_ClearWatcher:compatible: + +# Per-dict watcher tags - non-atomic RMW on _ma_watcher_tag; +# safe on distinct dicts only +PyDict_Watch:distinct: +PyDict_Unwatch:distinct: + + # List objects (Doc/c-api/list.rst) # Type checks - read ob_type pointer, always safe @@ -125,6 +186,29 @@ PyByteArray_GET_SIZE:atomic: PyByteArray_AsString:compatible: PyByteArray_AS_STRING:compatible: +# Creation - may iterate the iterable argument, calling arbitrary code. +# Atomic for sets, frozensets, dicts, and frozendicts. +PySet_New:shared: +PyFrozenSet_New:shared: + +# Size - uses atomic load on free-threaded builds +PySet_Size:atomic: +PySet_GET_SIZE:atomic: + +# Contains - lock-free, atomic with simple types +PySet_Contains:shared: + +# Mutations - hold per-object lock for duration +# atomic with simple types +PySet_Add:shared: +PySet_Discard:shared: + +# Pop - hold per-object lock for duration +PySet_Pop:atomic: + +# Clear - empties the set before clearing +PySet_Clear:atomic: + # Capsule objects (Doc/c-api/capsule.rst) # Type check - read ob_type pointer, always safe diff --git a/Doc/deprecations/index.rst b/Doc/deprecations/index.rst index bb8bfb5c227..eedcd2e9c9d 100644 --- a/Doc/deprecations/index.rst +++ b/Doc/deprecations/index.rst @@ -15,6 +15,8 @@ Deprecations .. include:: pending-removal-in-future.rst +.. include:: soft-deprecations.rst + C API deprecations ------------------ diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index e7f27f73664..1d9a3095813 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -60,7 +60,7 @@ Pending removal in Python 3.15 * :mod:`types`: - * :class:`types.CodeType`: Accessing :attr:`~codeobject.co_lnotab` was + * :class:`types.CodeType`: Accessing :attr:`!codeobject.co_lnotab` was deprecated in :pep:`626` since 3.10 and was planned to be removed in 3.12, but it only got a proper :exc:`DeprecationWarning` in 3.12. diff --git a/Doc/deprecations/pending-removal-in-3.17.rst b/Doc/deprecations/pending-removal-in-3.17.rst index e769c9d371e..952ffad6435 100644 --- a/Doc/deprecations/pending-removal-in-3.17.rst +++ b/Doc/deprecations/pending-removal-in-3.17.rst @@ -1,6 +1,14 @@ Pending removal in Python 3.17 ------------------------------ +* :mod:`datetime`: + + * :meth:`~datetime.datetime.strptime` calls using a format string containing + ``%e`` (day of month) without a year. + This has been deprecated since Python 3.15. + (Contributed by Stan Ulbrych in :gh:`70647`.) + + * :mod:`collections.abc`: - :class:`collections.abc.ByteString` is scheduled for removal in Python 3.17. @@ -27,7 +35,7 @@ Pending removal in Python 3.17 - Passing non-ascii *encoding* names to :func:`encodings.normalize_encoding` is deprecated and scheduled for removal in Python 3.17. - (Contributed by Stan Ulbrych in :gh:`136702`) + (Contributed by Stan Ulbrych in :gh:`136702`.) * :mod:`typing`: diff --git a/Doc/deprecations/pending-removal-in-future.rst b/Doc/deprecations/pending-removal-in-future.rst index e8306b8efee..74f98d33a4b 100644 --- a/Doc/deprecations/pending-removal-in-future.rst +++ b/Doc/deprecations/pending-removal-in-future.rst @@ -47,7 +47,7 @@ although there is currently no date scheduled for their removal. * :mod:`codecs`: use :func:`open` instead of :func:`codecs.open`. (:gh:`133038`) -* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method +* :attr:`!codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method instead. * :mod:`datetime`: diff --git a/Doc/deprecations/soft-deprecations.rst b/Doc/deprecations/soft-deprecations.rst new file mode 100644 index 00000000000..a270052788e --- /dev/null +++ b/Doc/deprecations/soft-deprecations.rst @@ -0,0 +1,21 @@ +Soft deprecations +----------------- + +There are no plans to remove :term:`soft deprecated` APIs. + +* :func:`re.match` and :meth:`re.Pattern.match` are now + :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and + :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, + more explicit names. These are intended to be used to alleviate confusion + around what *match* means by following the Zen of Python's *"Explicit is + better than implicit"* mantra. Most other language regular expression + libraries use an API named *match* to mean what Python has always called + *search*. + + We **do not** plan to remove the older :func:`!match` name, as it has been + used in code for over 30 years. Code supporting older versions of Python + should continue to use :func:`!match`, while new code should prefer + :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. + + (Contributed by Gregory P. Smith in :gh:`86519` and + Hugo van Kemenade in :gh:`148100`.) diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 5260c2ca4ad..2fe5814bb04 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -371,7 +371,7 @@ Equality comparisons are defined though:: >>> Color.BLUE == Color.BLUE True -Comparisons against non-enumeration values will always compare not equal +Equality comparisons against non-enumeration values will always return ``False`` (again, :class:`IntEnum` was explicitly designed to behave differently, see below):: diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst index 2f089a3d896..b21ed1c8f37 100644 --- a/Doc/howto/free-threading-extensions.rst +++ b/Doc/howto/free-threading-extensions.rst @@ -416,11 +416,9 @@ C API extensions need to be built specifically for the free-threaded build. The wheels, shared libraries, and binaries are indicated by a ``t`` suffix. * `pypa/manylinux `_ supports the - free-threaded build, with the ``t`` suffix, such as ``python3.13t``. -* `pypa/cibuildwheel `_ supports the - free-threaded build on Python 3.13 and 3.14. On Python 3.14, free-threaded - wheels will be built by default. On Python 3.13, you will need to set - `CIBW_ENABLE to cpython-freethreading `_. + free-threaded build, with the ``t`` suffix, such as ``python3.14t``. +* `pypa/cibuildwheel `_ supports + building wheels for the free-threaded build of Python 3.14 and newer. Limited C API and Stable ABI ............................ diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 21df6ba858d..0ee4c0086dd 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -3877,7 +3877,7 @@ subclassed handler which looks something like this:: def format(self, record): version = 1 asctime = dt.datetime.fromtimestamp(record.created).isoformat() - m = self.tz_offset.match(time.strftime('%z')) + m = self.tz_offset.prefixmatch(time.strftime('%z')) has_offset = False if m and time.timezone: hrs, mins = m.groups() diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 84ec535ca98..6fc087c3f1c 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -362,12 +362,13 @@ for a complete listing. +------------------+-----------------------------------------------+ | Method/Attribute | Purpose | +==================+===============================================+ -| ``match()`` | Determine if the RE matches at the beginning | -| | of the string. | -+------------------+-----------------------------------------------+ | ``search()`` | Scan through a string, looking for any | | | location where this RE matches. | +------------------+-----------------------------------------------+ +| ``prefixmatch()``| Determine if the RE matches at the beginning | +| | of the string. Previously named :ref:`match() | +| | `. | ++------------------+-----------------------------------------------+ | ``findall()`` | Find all substrings where the RE matches, and | | | return them as a list. | +------------------+-----------------------------------------------+ @@ -375,7 +376,7 @@ for a complete listing. | | return them as an :term:`iterator`. | +------------------+-----------------------------------------------+ -:meth:`~re.Pattern.match` and :meth:`~re.Pattern.search` return ``None`` if no match can be found. If +:meth:`~re.Pattern.search` and :meth:`~re.Pattern.prefixmatch` return ``None`` if no match can be found. If they're successful, a :ref:`match object ` instance is returned, containing information about the match: where it starts and ends, the substring it matched, and more. @@ -393,19 +394,19 @@ Python interpreter, import the :mod:`re` module, and compile a RE:: Now, you can try matching various strings against the RE ``[a-z]+``. An empty string shouldn't match at all, since ``+`` means 'one or more repetitions'. -:meth:`~re.Pattern.match` should return ``None`` in this case, which will cause the +:meth:`~re.Pattern.search` should return ``None`` in this case, which will cause the interpreter to print no output. You can explicitly print the result of -:meth:`!match` to make this clear. :: +:meth:`!search` to make this clear. :: - >>> p.match("") - >>> print(p.match("")) + >>> p.search("") + >>> print(p.search("")) None Now, let's try it on a string that it should match, such as ``tempo``. In this -case, :meth:`~re.Pattern.match` will return a :ref:`match object `, so you +case, :meth:`~re.Pattern.search` will return a :ref:`match object `, so you should store the result in a variable for later use. :: - >>> m = p.match('tempo') + >>> m = p.search('tempo') >>> m @@ -437,27 +438,28 @@ Trying these methods will soon clarify their meaning:: :meth:`~re.Match.group` returns the substring that was matched by the RE. :meth:`~re.Match.start` and :meth:`~re.Match.end` return the starting and ending index of the match. :meth:`~re.Match.span` -returns both start and end indexes in a single tuple. Since the :meth:`~re.Pattern.match` -method only checks if the RE matches at the start of a string, :meth:`!start` -will always be zero. However, the :meth:`~re.Pattern.search` method of patterns -scans through the string, so the match may not start at zero in that -case. :: +returns both start and end indexes in a single tuple. +The :meth:`~re.Pattern.search` method of patterns +scans through the string, so the match may not start at zero. +However, the :meth:`~re.Pattern.prefixmatch` +method only checks if the RE matches at the start of a string, so :meth:`!start` +will always be zero in that case. :: - >>> print(p.match('::: message')) - None >>> m = p.search('::: message'); print(m) >>> m.group() 'message' >>> m.span() (4, 11) + >>> print(p.prefixmatch('::: message')) + None In actual programs, the most common style is to store the :ref:`match object ` in a variable, and then check if it was ``None``. This usually looks like:: p = re.compile( ... ) - m = p.match( 'string goes here' ) + m = p.search( 'string goes here' ) if m: print('Match found: ', m.group()) else: @@ -495,15 +497,15 @@ Module-level functions ---------------------- You don't have to create a pattern object and call its methods; the -:mod:`re` module also provides top-level functions called :func:`~re.match`, -:func:`~re.search`, :func:`~re.findall`, :func:`~re.sub`, and so forth. These functions +:mod:`re` module also provides top-level functions called :func:`~re.search`, +:func:`~re.prefixmatch`, :func:`~re.findall`, :func:`~re.sub`, and so forth. These functions take the same arguments as the corresponding pattern method with the RE string added as the first argument, and still return either ``None`` or a :ref:`match object ` instance. :: - >>> print(re.match(r'From\s+', 'Fromage amk')) + >>> print(re.prefixmatch(r'From\s+', 'Fromage amk')) None - >>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998') #doctest: +ELLIPSIS + >>> re.prefixmatch(r'From\s+', 'From amk Thu May 14 19:12:10 1998') #doctest: +ELLIPSIS Under the hood, these functions simply create a pattern object for you @@ -812,7 +814,7 @@ of a group with a quantifier, such as ``*``, ``+``, ``?``, or ``ab``. :: >>> p = re.compile('(ab)*') - >>> print(p.match('ababababab').span()) + >>> print(p.search('ababababab').span()) (0, 10) Groups indicated with ``'('``, ``')'`` also capture the starting and ending @@ -825,7 +827,7 @@ argument. Later we'll see how to express groups that don't capture the span of text that they match. :: >>> p = re.compile('(a)b') - >>> m = p.match('ab') + >>> m = p.search('ab') >>> m.group() 'ab' >>> m.group(0) @@ -836,7 +838,7 @@ to determine the number, just count the opening parenthesis characters, going from left to right. :: >>> p = re.compile('(a(b)c)d') - >>> m = p.match('abcd') + >>> m = p.search('abcd') >>> m.group(0) 'abcd' >>> m.group(1) @@ -912,10 +914,10 @@ but aren't interested in retrieving the group's contents. You can make this fact explicit by using a non-capturing group: ``(?:...)``, where you can replace the ``...`` with any other regular expression. :: - >>> m = re.match("([abc])+", "abc") + >>> m = re.search("([abc])+", "abc") >>> m.groups() ('c',) - >>> m = re.match("(?:[abc])+", "abc") + >>> m = re.search("(?:[abc])+", "abc") >>> m.groups() () @@ -949,7 +951,7 @@ given numbers, so you can retrieve information about a group in two ways:: Additionally, you can retrieve named groups as a dictionary with :meth:`~re.Match.groupdict`:: - >>> m = re.match(r'(?P\w+) (?P\w+)', 'Jane Doe') + >>> m = re.search(r'(?P\w+) (?P\w+)', 'Jane Doe') >>> m.groupdict() {'first': 'Jane', 'last': 'Doe'} @@ -1274,21 +1276,26 @@ In short, before turning to the :mod:`re` module, consider whether your problem can be solved with a faster and simpler string method. -match() versus search() ------------------------ +.. _match-versus-search: -The :func:`~re.match` function only checks if the RE matches at the beginning of the -string while :func:`~re.search` will scan forward through the string for a match. -It's important to keep this distinction in mind. Remember, :func:`!match` will -only report a successful match which will start at 0; if the match wouldn't -start at zero, :func:`!match` will *not* report it. :: +prefixmatch() (aka match) versus search() +----------------------------------------- - >>> print(re.match('super', 'superstition').span()) +:func:`~re.prefixmatch` was added in Python 3.15 as the :ref:`preferred name +` for :func:`~re.match`. Before this, it was only known +as :func:`!match` and the distinction with :func:`~re.search` was often +misunderstood. + +:func:`!prefixmatch` aka :func:`!match` only checks if the RE matches at the +beginning of the string while :func:`!search` scans forward through the +string for a match. :: + + >>> print(re.prefixmatch('super', 'superstition').span()) (0, 5) - >>> print(re.match('super', 'insuperable')) + >>> print(re.prefixmatch('super', 'insuperable')) None -On the other hand, :func:`~re.search` will scan forward through the string, +On the other hand, :func:`~re.search` scans forward through the string, reporting the first match it finds. :: >>> print(re.search('super', 'superstition').span()) @@ -1296,18 +1303,8 @@ reporting the first match it finds. :: >>> print(re.search('super', 'insuperable').span()) (2, 7) -Sometimes you'll be tempted to keep using :func:`re.match`, and just add ``.*`` -to the front of your RE. Resist this temptation and use :func:`re.search` -instead. The regular expression compiler does some analysis of REs in order to -speed up the process of looking for a match. One such analysis figures out what -the first character of a match must be; for example, a pattern starting with -``Crow`` must match starting with a ``'C'``. The analysis lets the engine -quickly scan through the string looking for the starting character, only trying -the full match if a ``'C'`` is found. - -Adding ``.*`` defeats this optimization, requiring scanning to the end of the -string and then backtracking to find a match for the rest of the RE. Use -:func:`re.search` instead. +This distinction is important to remember when using the old :func:`~re.match` +name in code requiring compatibility with older Python versions. Greedy versus non-greedy @@ -1322,9 +1319,9 @@ doesn't work because of the greedy nature of ``.*``. :: >>> s = 'Title' >>> len(s) 32 - >>> print(re.match('<.*>', s).span()) + >>> print(re.prefixmatch('<.*>', s).span()) (0, 32) - >>> print(re.match('<.*>', s).group()) + >>> print(re.prefixmatch('<.*>', s).group()) Title The RE matches the ``'<'`` in ``''``, and the ``.*`` consumes the rest of @@ -1340,7 +1337,7 @@ example, the ``'>'`` is tried immediately after the first ``'<'`` matches, and when it fails, the engine advances a character at a time, retrying the ``'>'`` at every step. This produces just the right result:: - >>> print(re.match('<.*?>', s).group()) + >>> print(re.prefixmatch('<.*?>', s).group()) (Note that parsing HTML or XML with regular expressions is painful. diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 8ba11b7d12d..e37afd6d0b6 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1970,7 +1970,7 @@ FileType objects run and then use the :keyword:`with`-statement to manage the files. .. versionchanged:: 3.4 - Added the *encodings* and *errors* parameters. + Added the *encoding* and *errors* parameters. .. deprecated:: 3.14 @@ -2032,6 +2032,9 @@ Argument groups Note that any arguments not in your user-defined groups will end up back in the usual "positional arguments" and "optional arguments" sections. + Within each argument group, arguments are displayed in help output in the + order in which they are added. + .. deprecated-removed:: 3.11 3.14 Calling :meth:`add_argument_group` on an argument group now raises an exception. This nesting was never supported, often failed to work diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 9b4e7ae1834..e23506768a7 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -2480,7 +2480,7 @@ and classes for traversing abstract syntax trees: node = YourTransformer().visit(node) -.. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False) +.. function:: dump(node, annotate_fields=True, include_attributes=False, *, color=False, indent=None, show_empty=False) Return a formatted dump of the tree in *node*. This is mainly useful for debugging purposes. If *annotate_fields* is true (by default), @@ -2490,6 +2490,10 @@ and classes for traversing abstract syntax trees: numbers and column offsets are not dumped by default. If this is wanted, *include_attributes* can be set to true. + If *color* is ``True``, the returned string is syntax highlighted using + ANSI escape sequences. + If ``False`` (the default), colored output is always disabled. + If *indent* is a non-negative integer or string, then the tree will be pretty-printed with that indent level. An indent level of 0, negative, or ``""`` will only insert newlines. ``None`` (the default) @@ -2527,6 +2531,9 @@ and classes for traversing abstract syntax trees: .. versionchanged:: 3.15 Omit optional ``Load()`` values by default. + .. versionchanged:: next + Added the *color* parameter. + .. _ast-compiler-flags: @@ -2584,6 +2591,10 @@ Command-line usage .. versionadded:: 3.9 +.. versionchanged:: next + The output is now syntax highlighted by default. This can be + :ref:`controlled using environment variables `. + The :mod:`!ast` module can be executed as a script from the command line. It is as simple as: diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index f3409bcd2df..713b40d7466 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -304,7 +304,7 @@ generator can occur in an unexpected order:: try: yield 2 finally: - await asyncio.sleep(0.1) # immitate some async work + await asyncio.sleep(0.1) # imitate some async work work_done = True diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 4e60eee4429..f0fe91b363d 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -355,6 +355,34 @@ and reliable way to wait for all tasks in the group to finish. Passes on all *kwargs* to :meth:`loop.create_task` + .. method:: cancel() + + Cancel the task group. This is a non-exceptional, early exit of the + task group's lifetime -- useful once the group's goal has been met or + its services no longer needed. + + :meth:`~asyncio.Task.cancel` will be called on any tasks in the group that + aren't yet done, as well as the parent (body) of the group. The task group + context manager will exit *without* :exc:`asyncio.CancelledError` being raised. + + If :meth:`cancel` is called before entering the task group, the group will be + cancelled upon entry. This is useful for patterns where one piece of + code passes an unused :class:`asyncio.TaskGroup` instance to another in order to have + the ability to cancel anything run within the group. + + :meth:`cancel` is idempotent and may be called after the task group has + already exited. + + Some ways to use :meth:`cancel`: + + * call it from the task group body based on some condition or event + * pass the task group instance to child tasks via :meth:`create_task`, allowing a child + task to conditionally cancel the entire entire group + * pass the task group instance or bound :meth:`cancel` method to some other task *before* + opening the task group, allowing remote cancellation + + .. versionadded:: next + Example:: async def main(): @@ -366,7 +394,8 @@ Example:: The ``async with`` statement will wait for all tasks in the group to finish. While waiting, new tasks may still be added to the group (for example, by passing ``tg`` into one of the coroutines -and calling ``tg.create_task()`` in that coroutine). +and calling ``tg.create_task()`` in that coroutine). There is also opportunity +to short-circuit the entire task group with ``tg.cancel()``, based on some condition. Once the last task has finished and the ``async with`` block is exited, no new tasks may be added to the group. @@ -427,53 +456,6 @@ reported by :meth:`asyncio.Task.cancelling`. Improved handling of simultaneous internal and external cancellations and correct preservation of cancellation counts. -Terminating a task group ------------------------- - -While terminating a task group is not natively supported by the standard -library, termination can be achieved by adding an exception-raising task -to the task group and ignoring the raised exception: - -.. code-block:: python - - import asyncio - from asyncio import TaskGroup - - class TerminateTaskGroup(Exception): - """Exception raised to terminate a task group.""" - - async def force_terminate_task_group(): - """Used to force termination of a task group.""" - raise TerminateTaskGroup() - - async def job(task_id, sleep_time): - print(f'Task {task_id}: start') - await asyncio.sleep(sleep_time) - print(f'Task {task_id}: done') - - async def main(): - try: - async with TaskGroup() as group: - # spawn some tasks - group.create_task(job(1, 0.5)) - group.create_task(job(2, 1.5)) - # sleep for 1 second - await asyncio.sleep(1) - # add an exception-raising task to force the group to terminate - group.create_task(force_terminate_task_group()) - except* TerminateTaskGroup: - pass - - asyncio.run(main()) - -Expected output: - -.. code-block:: text - - Task 1: start - Task 2: start - Task 1: done - Sleeping ======== diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 5e08d56fd66..32da8294c5a 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -73,8 +73,8 @@ POST request. Added the *padded* and *wrapcol* parameters. -.. function:: b64decode(s, altchars=None, validate=False, *, padded=True) - b64decode(s, altchars=None, validate=True, *, ignorechars, padded=True) +.. function:: b64decode(s, altchars=None, validate=False, *, padded=True, canonical=False) + b64decode(s, altchars=None, validate=True, *, ignorechars, padded=True, canonical=False) Decode the Base64 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -112,10 +112,13 @@ POST request. If *validate* is true, these non-alphabet characters in the input result in a :exc:`binascii.Error`. + If *canonical* is true, non-zero padding bits are rejected. + See :func:`binascii.a2b_base64` for details. + For more information about the strict base64 check, see :func:`binascii.a2b_base64` .. versionchanged:: 3.15 - Added the *ignorechars* and *padded* parameters. + Added the *canonical*, *ignorechars*, and *padded* parameters. .. deprecated:: 3.15 Accepting the ``+`` and ``/`` characters with an alternative alphabet @@ -179,7 +182,7 @@ POST request. Added the *padded* and *wrapcol* parameters. -.. function:: b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'') +.. function:: b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'', canonical=False) Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -205,12 +208,15 @@ POST request. *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. + If *canonical* is true, non-zero padding bits are rejected. + See :func:`binascii.a2b_base32` for details. + A :exc:`binascii.Error` is raised if *s* is incorrectly padded or if there are non-alphabet characters present in the input. .. versionchanged:: 3.15 - Added the *ignorechars* and *padded* parameters. + Added the *canonical*, *ignorechars*, and *padded* parameters. .. function:: b32hexencode(s, *, padded=True, wrapcol=0) @@ -224,7 +230,7 @@ POST request. Added the *padded* and *wrapcol* parameters. -.. function:: b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'') +.. function:: b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'', canonical=False) Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. @@ -237,7 +243,7 @@ POST request. .. versionadded:: 3.10 .. versionchanged:: 3.15 - Added the *ignorechars* and *padded* parameters. + Added the *canonical*, *ignorechars*, and *padded* parameters. .. function:: b16encode(s, *, wrapcol=0) @@ -317,7 +323,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 -.. function:: a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v') +.. function:: a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v', canonical=False) Decode the Ascii85 encoded :term:`bytes-like object` or ASCII string *b* and return the decoded :class:`bytes`. @@ -334,8 +340,16 @@ Refer to the documentation of the individual functions for more information. This should only contain whitespace characters, and by default contains all whitespace characters in ASCII. + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_ascii85` for details. + .. versionadded:: 3.4 + .. versionchanged:: next + Added the *canonical* parameter. + Single-character final groups are now always rejected as encoding + violations. + .. function:: b85encode(b, pad=False, *, wrapcol=0) @@ -355,7 +369,7 @@ Refer to the documentation of the individual functions for more information. Added the *wrapcol* parameter. -.. function:: b85decode(b, *, ignorechars=b'') +.. function:: b85decode(b, *, ignorechars=b'', canonical=False) Decode the base85-encoded :term:`bytes-like object` or ASCII string *b* and return the decoded :class:`bytes`. Padding is implicitly removed, if @@ -364,10 +378,15 @@ Refer to the documentation of the individual functions for more information. *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_base85` for details. + .. versionadded:: 3.4 .. versionchanged:: 3.15 - Added the *ignorechars* parameter. + Added the *canonical* and *ignorechars* parameters. + Single-character final groups are now always rejected as encoding + violations. .. function:: z85encode(s, pad=False, *, wrapcol=0) @@ -392,7 +411,7 @@ Refer to the documentation of the individual functions for more information. Added the *wrapcol* parameter. -.. function:: z85decode(s, *, ignorechars=b'') +.. function:: z85decode(s, *, ignorechars=b'', canonical=False) Decode the Z85-encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. See `Z85 specification @@ -401,10 +420,15 @@ Refer to the documentation of the individual functions for more information. *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. + If *canonical* is true, non-canonical encodings are rejected. + See :func:`binascii.a2b_base85` for details. + .. versionadded:: 3.13 .. versionchanged:: 3.15 - Added the *ignorechars* parameter. + Added the *canonical* and *ignorechars* parameters. + Single-character final groups are now always rejected as encoding + violations. .. _base64-legacy: diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 08a82cc4b5f..8b4ba6ae9fb 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -48,8 +48,8 @@ The :mod:`!binascii` module defines the following functions: Added the *backtick* parameter. -.. function:: a2b_base64(string, /, *, padded=True, alphabet=BASE64_ALPHABET, strict_mode=False) - a2b_base64(string, /, *, ignorechars, padded=True, alphabet=BASE64_ALPHABET, strict_mode=True) +.. function:: a2b_base64(string, /, *, padded=True, alphabet=BASE64_ALPHABET, strict_mode=False, canonical=False) + a2b_base64(string, /, *, ignorechars, padded=True, alphabet=BASE64_ALPHABET, strict_mode=True, canonical=False) Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. @@ -83,11 +83,15 @@ The :mod:`!binascii` module defines the following functions: * Contains no excess data after padding (including excess padding, newlines, etc.). * Does not start with a padding. + If *canonical* is true, non-zero padding bits in the last group are rejected + with :exc:`binascii.Error`, enforcing canonical encoding as defined in + :rfc:`4648` section 3.5. This check is independent of *strict_mode*. + .. versionchanged:: 3.11 Added the *strict_mode* parameter. .. versionchanged:: 3.15 - Added the *alphabet*, *ignorechars* and *padded* parameters. + Added the *alphabet*, *canonical*, *ignorechars*, and *padded* parameters. .. function:: b2a_base64(data, *, padded=True, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True) @@ -113,7 +117,7 @@ The :mod:`!binascii` module defines the following functions: Added the *alphabet*, *padded* and *wrapcol* parameters. -.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'') +.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'', canonical=False) Convert Ascii85 data back to binary and return the binary data. @@ -122,7 +126,8 @@ The :mod:`!binascii` module defines the following functions: characters). Each group encodes 32 bits of binary data in the range from ``0`` to ``2 ** 32 - 1``, inclusive. The special character ``z`` is accepted as a short form of the group ``!!!!!``, which encodes four - consecutive null bytes. + consecutive null bytes. A single-character final group is always rejected + as an encoding violation. *foldspaces* is a flag that specifies whether the 'y' short sequence should be accepted as shorthand for 4 consecutive spaces (ASCII 0x20). @@ -135,6 +140,12 @@ The :mod:`!binascii` module defines the following functions: to ignore from the input. This should only contain whitespace characters. + If *canonical* is true, non-canonical encodings are rejected with + :exc:`binascii.Error`. Here "canonical" means the encoding that + :func:`b2a_ascii85` would produce: the ``z`` abbreviation must be used + for all-zero groups (rather than ``!!!!!``), and partial final groups + must use the same padding digits as the encoder. + Invalid Ascii85 data will raise :exc:`binascii.Error`. .. versionadded:: 3.15 @@ -163,7 +174,7 @@ The :mod:`!binascii` module defines the following functions: .. versionadded:: 3.15 -.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET, ignorechars=b'') +.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET, ignorechars=b'', canonical=False) Convert Base85 data back to binary and return the binary data. More than one line may be passed at a time. @@ -171,7 +182,8 @@ The :mod:`!binascii` module defines the following functions: Valid Base85 data contains characters from the Base85 alphabet in groups of five (except for the final group, which may have from two to five characters). Each group encodes 32 bits of binary data in the range from - ``0`` to ``2 ** 32 - 1``, inclusive. + ``0`` to ``2 ** 32 - 1``, inclusive. A single-character final group is + always rejected as an encoding violation. Optional *alphabet* must be a :class:`bytes` object of length 85 which specifies an alternative alphabet. @@ -179,6 +191,11 @@ The :mod:`!binascii` module defines the following functions: *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. + If *canonical* is true, non-canonical encodings are rejected with + :exc:`binascii.Error`. Here "canonical" means the encoding that + :func:`b2a_base85` would produce: partial final groups must use the + same padding digits as the encoder. + Invalid Base85 data will raise :exc:`binascii.Error`. .. versionadded:: 3.15 @@ -202,7 +219,7 @@ The :mod:`!binascii` module defines the following functions: .. versionadded:: 3.15 -.. function:: a2b_base32(string, /, *, padded=True, alphabet=BASE32_ALPHABET, ignorechars=b'') +.. function:: a2b_base32(string, /, *, padded=True, alphabet=BASE32_ALPHABET, ignorechars=b'', canonical=False) Convert base32 data back to binary and return the binary data. @@ -231,6 +248,10 @@ The :mod:`!binascii` module defines the following functions: presented before the end of the encoded data and the excess pad characters will be ignored. + If *canonical* is true, non-zero padding bits in the last group are rejected + with :exc:`binascii.Error`, enforcing canonical encoding as defined in + :rfc:`4648` section 3.5. + Invalid base32 data will raise :exc:`binascii.Error`. .. versionadded:: 3.15 diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst index 7b94341fe29..3eb3f741eee 100644 --- a/Doc/library/calendar.rst +++ b/Doc/library/calendar.rst @@ -54,13 +54,13 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is .. method:: setfirstweekday(firstweekday) - Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6) + Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6). Identical to setting the :attr:`~Calendar.firstweekday` property. .. method:: iterweekdays() - Return an iterator for the week day numbers that will be used for one + Return an iterator for the weekday numbers that will be used for one week. The first value from the iterator will be the same as the value of the :attr:`~Calendar.firstweekday` property. @@ -86,7 +86,7 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is Return an iterator for the month *month* in the year *year* similar to :meth:`itermonthdates`, but not restricted by the :class:`datetime.date` range. Days returned will be tuples consisting of a day of the month - number and a week day number. + number and a weekday number. .. method:: itermonthdays3(year, month) @@ -408,7 +408,7 @@ For simple text calendars this module provides the following functions. .. function:: monthrange(year, month) - Returns weekday of first day of the month and number of days in month, for the + Returns weekday of first day of the month and number of days in month, for the specified *year* and *month*. @@ -446,7 +446,7 @@ For simple text calendars this module provides the following functions. An unrelated but handy function that takes a time tuple such as returned by the :func:`~time.gmtime` function in the :mod:`time` module, and returns the corresponding Unix timestamp value, assuming an epoch of 1970, and the POSIX - encoding. In fact, :func:`time.gmtime` and :func:`timegm` are each others' + encoding. In fact, :func:`time.gmtime` and :func:`timegm` are each other's inverse. @@ -580,9 +580,14 @@ The :mod:`!calendar` module defines the following exceptions: .. exception:: IllegalMonthError(month) - A subclass of :exc:`ValueError`, + A subclass of :exc:`ValueError` and :exc:`IndexError`, raised when the given month number is outside of the range 1-12 (inclusive). + .. versionchanged:: 3.12 + :exc:`IllegalMonthError` is now also a subclass of + :exc:`ValueError`. New code should avoid catching + :exc:`IndexError`. + .. attribute:: month The invalid month number. diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index c8dcaef8018..e42bdc06be0 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -326,7 +326,7 @@ For example:: .. versionadded:: 3.10 The usual dictionary methods are available for :class:`Counter` objects - except for two which work differently for counters. + except for these two which work differently for counters: .. method:: fromkeys(iterable) @@ -1346,7 +1346,14 @@ attribute. A real dictionary used to store the contents of the :class:`UserDict` class. + :class:`!UserDict` instances also override the following method: + .. method:: popitem + + Remove and return a ``(key, value)`` pair from the wrapped dictionary. Pairs are + returned in the same order as ``data.popitem()``. (For the default + :meth:`dict.popitem`, this order is :abbr:`LIFO (last-in, first-out)`.) If the + dictionary is empty, raises a :exc:`KeyError`. :class:`UserList` objects ------------------------- diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 571975d4674..b8d615565a5 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1735,7 +1735,7 @@ If wrapping a shared library with :mod:`!ctypes`, consider determining the shared library name at development time, and hardcoding it into the wrapper module instead of using :func:`!find_library` to locate the library at runtime. -Also consider addding a configuration option or environment variable to let +Also consider adding a configuration option or environment variable to let users select a library to use, and then perhaps use :func:`!find_library` as a default or fallback. @@ -1756,11 +1756,10 @@ as a default or fallback. (or by) Python. It is recommended to only use this function as a default or fallback, - .. deprecated:: 3.15 + .. soft-deprecated:: 3.15 - This function is :term:`soft deprecated`. - It is kept for use in cases where it works, but not expected to be - updated for additional platforms and configurations. + This function is kept for use in cases where it works, but not expected to + be updated for additional platforms and configurations. On Linux, :func:`!find_library` tries to run external programs (``/sbin/ldconfig``, ``gcc``, ``objdump`` and ``ld``) to find the @@ -3191,8 +3190,8 @@ Arrays and pointers Equivalent to ``type * length``, where *type* is a :mod:`!ctypes` data type and *length* an integer. - This function is :term:`soft deprecated` in favor of multiplication. - There are no plans to remove it. + .. soft-deprecated:: 3.14 + In favor of multiplication. .. class:: _Pointer diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index fd8e0c0bea1..0bce3e5b762 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -371,8 +371,8 @@ Module contents Converts the dataclass *obj* to a dict (by using the factory function *dict_factory*). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. Other objects are copied with - :func:`copy.deepcopy`. + frozendicts, lists, and tuples are recursed into. Other objects are copied + with :func:`copy.deepcopy`. Example of using :func:`!asdict` on nested dataclasses:: @@ -402,8 +402,8 @@ Module contents Converts the dataclass *obj* to a tuple (by using the factory function *tuple_factory*). Each dataclass is converted - to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. Other objects are copied with + to a tuple of its field values. dataclasses, dicts, frozendicts, lists, + and tuples are recursed into. Other objects are copied with :func:`copy.deepcopy`. Continuing from the previous example:: diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 8993049a720..f3c4ef91990 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -606,12 +606,11 @@ Other constructors, all class methods: .. note:: - If *format* specifies a day of month without a year a - :exc:`DeprecationWarning` is emitted. This is to avoid a quadrennial + If *format* specifies a day of month (``%d``) without a year, + :exc:`ValueError` is raised. This is to avoid a quadrennial leap year bug in code seeking to parse only a month and day as the default year used in absence of one in the format is not a leap year. - Such *format* values may raise an error as of Python 3.15. The - workaround is to always include a year in your *format*. If parsing + The workaround is to always include a year in your *format*. If parsing *date_string* values that do not have a year, explicitly add a year that is a leap year before parsing: @@ -1180,14 +1179,13 @@ Other constructors, all class methods: time tuple. See also :ref:`strftime-strptime-behavior` and :meth:`datetime.fromisoformat`. - .. versionchanged:: 3.13 + .. versionchanged:: 3.15 - If *format* specifies a day of month without a year a - :exc:`DeprecationWarning` is now emitted. This is to avoid a quadrennial + If *format* specifies a day of month (``%d``) without a year, + :exc:`ValueError` is raised. This is to avoid a quadrennial leap year bug in code seeking to parse only a month and day as the default year used in absence of one in the format is not a leap year. - Such *format* values may raise an error as of Python 3.15. The - workaround is to always include a year in your *format*. If parsing + The workaround is to always include a year in your *format*. If parsing *date_string* values that do not have a year, explicitly add a year that is a leap year before parsing: @@ -2572,13 +2570,13 @@ requires, and these work on all supported platforms. | | truncated to an integer as a | | | | | zero-padded decimal number. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%d`` | Day of the month as a | 01, 02, ..., 31 | \(9) | -| | zero-padded decimal number. | | | +| ``%d`` | Day of the month as a | 01, 02, ..., 31 | \(9), | +| | zero-padded decimal number. | | \(10) | +-----------+--------------------------------+------------------------+-------+ | ``%D`` | Equivalent to ``%m/%d/%y``. | 11/28/25 | \(9) | | | | | | +-----------+--------------------------------+------------------------+-------+ -| ``%e`` | The day of the month as a | ␣1, ␣2, ..., 31 | | +| ``%e`` | The day of the month as a | ␣1, ␣2, ..., 31 | \(10) | | | space-padded decimal number. | | | +-----------+--------------------------------+------------------------+-------+ | ``%F`` | Equivalent to ``%Y-%m-%d``, | 2025-10-11, | | @@ -2919,11 +2917,12 @@ Notes: >>> dt.datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug. datetime.datetime(1984, 2, 29, 0, 0) - .. deprecated-removed:: 3.13 3.15 + .. versionchanged:: 3.15 + Using ``%d`` without a year now raises :exc:`ValueError`. + + .. deprecated-removed:: 3.15 3.17 :meth:`~.datetime.strptime` calls using a format string containing - a day of month without a year now emit a - :exc:`DeprecationWarning`. In 3.15 or later we may change this into - an error or change the default year to a leap year. See :gh:`70647`. + ``%e`` without a year now emit a :exc:`DeprecationWarning`. .. rubric:: Footnotes diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 1f7014e9cd4..3e7ae509fed 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -400,7 +400,7 @@ operation is being performed, so the intermediate analysis object isn't useful: .. versionchanged:: 3.10 The :pep:`626` :meth:`~codeobject.co_lines` method is used instead of the - :attr:`~codeobject.co_firstlineno` and :attr:`~codeobject.co_lnotab` + :attr:`~codeobject.co_firstlineno` and :attr:`!codeobject.co_lnotab` attributes of the :ref:`code object `. .. versionchanged:: 3.13 diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 0a1d2a0bac3..be7f59b0fce 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -240,7 +240,7 @@ Data types .. method:: EnumType.__len__(cls) - Returns the number of member in *cls*:: + Returns the number of members in *cls*:: >>> len(Color) 3 @@ -502,7 +502,7 @@ Data types Using :class:`auto` with :class:`Enum` results in integers of increasing value, starting with ``1``. - .. versionchanged:: 3.12 Added :ref:`enum-dataclass-support` + .. versionchanged:: 3.12 Added :ref:`enum-dataclass-support`. .. method:: Enum._add_alias_ @@ -977,9 +977,9 @@ Utilities and decorators *auto* can be used in place of a value. If used, the *Enum* machinery will call an :class:`Enum`'s :meth:`~Enum._generate_next_value_` to get an appropriate value. - For :class:`Enum` and :class:`IntEnum` that appropriate value will be the last value plus - one; for :class:`Flag` and :class:`IntFlag` it will be the first power-of-two greater - than the highest value; for :class:`StrEnum` it will be the lower-cased version of + For :class:`Enum` and :class:`IntEnum` that appropriate value will be the highest value seen + plus one; for :class:`Flag` and :class:`IntFlag` it will be the first power-of-two greater + than the highest value seen; for :class:`StrEnum` it will be the lower-cased version of the member's name. Care must be taken if mixing *auto()* with manually specified values. @@ -989,8 +989,8 @@ Utilities and decorators * ``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 - create the ``THREE`` enum member) + * ``THIRD = [auto(), -3]`` will *not* work (``[, -3]`` is used to + create the ``THIRD`` enum member) .. versionchanged:: 3.11.1 @@ -1000,7 +1000,7 @@ Utilities and decorators ``_generate_next_value_`` can be overridden to customize the values used by *auto*. - .. note:: in 3.13 the default ``_generate_next_value_`` will always return + .. note:: In version 3.13 the default ``_generate_next_value_`` will always return the highest member value incremented by 1, and will fail if any member is an incompatible type. @@ -1010,7 +1010,7 @@ Utilities and decorators enumerations. It allows member attributes to have the same names as members themselves. - .. note:: the *property* and the member must be defined in separate classes; + .. note:: The *property* and the member must be defined in separate classes; for example, the *value* and *name* attributes are defined in the *Enum* class, and *Enum* subclasses can define members with the names ``value`` and ``name``. diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst index ee654b7a83e..a213679e4e2 100644 --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -103,7 +103,8 @@ functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`, :func:`.filter .. function:: translate(pat) Return the shell-style pattern *pat* converted to a regular expression for - using with :func:`re.match`. The pattern is expected to be a :class:`str`. + using with :func:`re.prefixmatch`. The pattern is expected to be a + :class:`str`. Example: @@ -113,7 +114,7 @@ functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`, :func:`.filter >>> regex '(?s:.*\\.txt)\\z' >>> reobj = re.compile(regex) - >>> reobj.match('foobar.txt') + >>> reobj.prefixmatch('foobar.txt') diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e8c4605d057..119141d2e6d 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -644,7 +644,7 @@ are always available. They are listed here in alphabetical order. If the given source is a string, then leading and trailing spaces and tabs are stripped. - See :func:`ast.literal_eval` for a function that can safely evaluate strings + See :func:`ast.literal_eval` for a function to evaluate strings with expressions containing only literals. .. audit-event:: exec code_object eval diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index b24e4da7bc8..942f23d216f 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -140,7 +140,8 @@ The :mod:`!glob` module defines the following functions: .. function:: translate(pathname, *, recursive=False, include_hidden=False, seps=None) Convert the given path specification to a regular expression for use with - :func:`re.match`. The path specification can contain shell-style wildcards. + :func:`re.prefixmatch`. The path specification can contain shell-style + wildcards. For example: @@ -150,7 +151,7 @@ The :mod:`!glob` module defines the following functions: >>> regex '(?s:(?:.+/)?[^/]*\\.txt)\\z' >>> reobj = re.compile(regex) - >>> reobj.match('foo/bar/baz.txt') + >>> reobj.prefixmatch('foo/bar/baz.txt') Path separators and segments are meaningful to this function, unlike diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index cb8b5f0df88..33ecaae5c87 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -99,7 +99,7 @@ instantiation, of which this module provides three different variants: This class is used to handle the HTTP requests that arrive at the server. By itself, it cannot respond to any actual HTTP requests; it must be subclassed - to handle each request method (e.g. GET or POST). + to handle each request method (for example, ``'GET'`` or ``'POST'``). :class:`BaseHTTPRequestHandler` provides a number of class and instance variables, and methods for use by subclasses. @@ -241,7 +241,7 @@ instantiation, of which this module provides three different variants: request header it responds back with a ``100 Continue`` followed by ``200 OK`` headers. This method can be overridden to raise an error if the server does not - want the client to continue. For e.g. server can choose to send ``417 + want the client to continue. For example, the server can choose to send ``417 Expectation Failed`` as a response header and ``return False``. .. versionadded:: 3.2 @@ -469,7 +469,9 @@ Command-line interface :mod:`!http.server` can also be invoked directly using the :option:`-m` switch of the interpreter. The following example illustrates how to serve -files relative to the current directory:: +files relative to the current directory: + +.. code-block:: bash python -m http.server [OPTIONS] [port] @@ -480,7 +482,9 @@ The following options are accepted: .. option:: port The server listens to port 8000 by default. The default can be overridden - by passing the desired port number as an argument:: + by passing the desired port number as an argument: + + .. code-block:: bash python -m http.server 9000 @@ -489,7 +493,9 @@ The following options are accepted: Specifies a specific address to which it should bind. Both IPv4 and IPv6 addresses are supported. By default, the server binds itself to all interfaces. For example, the following command causes the server to bind - to localhost only:: + to localhost only: + + .. code-block:: bash python -m http.server --bind 127.0.0.1 @@ -502,7 +508,9 @@ The following options are accepted: Specifies a directory to which it should serve the files. By default, the server uses the current directory. For example, the following command - uses a specific directory:: + uses a specific directory: + + .. code-block:: bash python -m http.server --directory /tmp/ @@ -512,7 +520,9 @@ The following options are accepted: Specifies the HTTP version to which the server is conformant. By default, the server is conformant to HTTP/1.0. For example, the following command - runs an HTTP/1.1 conformant server:: + runs an HTTP/1.1 conformant server: + + .. code-block:: bash python -m http.server --protocol HTTP/1.1 @@ -520,7 +530,9 @@ The following options are accepted: .. option:: --tls-cert - Specifies a TLS certificate chain for HTTPS connections:: + Specifies a TLS certificate chain for HTTPS connections: + + .. code-block:: bash python -m http.server --tls-cert fullchain.pem @@ -536,14 +548,16 @@ The following options are accepted: .. option:: --tls-password-file - Specifies the password file for password-protected private keys:: + Specifies the password file for password-protected private keys: + + .. code-block:: bash python -m http.server \ --tls-cert cert.pem \ --tls-key key.pem \ --tls-password-file password.txt - This option requires `--tls-cert`` to be specified. + This option requires ``--tls-cert`` to be specified. .. versionadded:: 3.14 @@ -561,7 +575,7 @@ to be served. Methods :meth:`BaseHTTPRequestHandler.send_header` and :meth:`BaseHTTPRequestHandler.send_response_only` assume sanitized input -and does not perform input validation such as checking for the presence of CRLF +and do not perform input validation such as checking for the presence of CRLF sequences. Untrusted input may result in HTTP Header injection attacks. Earlier versions of Python did not scrub control characters from the diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 785f6c614b4..0b76020eacc 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -286,7 +286,7 @@ ABC hierarchy:: This method can potentially yield a very large number of objects, and it may carry out IO operations when computing these values. - Because of this, it will generaly be desirable to compute the result + Because of this, it will generally be desirable to compute the result values on-the-fly, as they are needed. As such, the returned object is only guaranteed to be an :class:`iterable `, instead of a :class:`list` or other @@ -340,7 +340,7 @@ ABC hierarchy:: This method can potentially yield a very large number of objects, and it may carry out IO operations when computing these values. - Because of this, it will generaly be desirable to compute the result + Because of this, it will generally be desirable to compute the result values on-the-fly, as they are needed. As such, the returned object is only guaranteed to be an :class:`iterable `, instead of a :class:`list` or other diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index ff893a45139..e23449886a3 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -195,10 +195,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): | | | read more :ref:`here | | | | `| +-----------------+-------------------+---------------------------+ -| | co_lnotab | encoded mapping of line | -| | | numbers to bytecode | -| | | indices | -+-----------------+-------------------+---------------------------+ | | co_freevars | tuple of names of free | | | | variables (referenced via | | | | a function's closure) | diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 5a0ac60ab7d..06f8bf2a8b6 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -833,6 +833,7 @@ and :term:`generators ` which incur interpreter overhead. from collections import Counter, deque from contextlib import suppress from functools import reduce + from heapq import heappush, heappushpop, heappush_max, heappushpop_max from math import comb, isqrt, prod, sumprod from operator import getitem, is_not, itemgetter, mul, neg, truediv @@ -848,11 +849,6 @@ and :term:`generators ` which incur interpreter overhead. # prepend(1, [2, 3, 4]) → 1 2 3 4 return chain([value], iterable) - def running_mean(iterable): - "Yield the average of all values seen so far." - # running_mean([8.5, 9.5, 7.5, 6.5]) → 8.5 9.0 8.5 8.0 - return map(truediv, accumulate(iterable), count(1)) - def repeatfunc(function, times=None, *args): "Repeat calls to a function with specified arguments." if times is None: @@ -1150,6 +1146,49 @@ and :term:`generators ` which incur interpreter overhead. return n + # ==== Running statistics ==== + + def running_mean(iterable): + "Average of values seen so far." + # running_mean([37, 33, 38, 28]) → 37 35 36 34 + return map(truediv, accumulate(iterable), count(1)) + + def running_min(iterable): + "Smallest of values seen so far." + # running_min([37, 33, 38, 28]) → 37 33 33 28 + return accumulate(iterable, func=min) + + def running_max(iterable): + "Largest of values seen so far." + # running_max([37, 33, 38, 28]) → 37 37 38 38 + return accumulate(iterable, func=max) + + def running_median(iterable): + "Median of values seen so far." + # running_median([37, 33, 38, 28]) → 37 35 37 35 + read = iter(iterable).__next__ + lo = [] # max-heap + hi = [] # min-heap the same size as or one smaller than lo + with suppress(StopIteration): + while True: + heappush_max(lo, heappushpop(hi, read())) + yield lo[0] + heappush(hi, heappushpop_max(lo, read())) + yield (lo[0] + hi[0]) / 2 + + def running_statistics(iterable): + "Aggregate statistics for values seen so far." + # Generate tuples: (size, minimum, median, maximum, mean) + t0, t1, t2, t3 = tee(iterable, 4) + return zip( + count(1), + running_min(t0), + running_median(t1), + running_max(t2), + running_mean(t3), + ) + + .. doctest:: :hide: @@ -1226,10 +1265,6 @@ and :term:`generators ` which incur interpreter overhead. [(0, 'a'), (1, 'b'), (2, 'c')] - >>> list(running_mean([8.5, 9.5, 7.5, 6.5])) - [8.5, 9.0, 8.5, 8.0] - - >>> for _ in loops(5): ... print('hi') ... @@ -1789,6 +1824,28 @@ and :term:`generators ` which incur interpreter overhead. True + >>> list(running_mean([8.5, 9.5, 7.5, 6.5])) + [8.5, 9.0, 8.5, 8.0] + >>> list(running_mean([37, 33, 38, 28])) + [37.0, 35.0, 36.0, 34.0] + + + >>> list(running_min([37, 33, 38, 28])) + [37, 33, 33, 28] + + + >>> list(running_max([37, 33, 38, 28])) + [37, 37, 38, 38] + + + >>> list(running_median([37, 33, 38, 28])) + [37, 35.0, 37, 35.0] + + + >>> list(running_statistics([37, 33, 38, 28])) + [(1, 37, 37, 37, 37.0), (2, 33, 35.0, 37, 35.0), (3, 33, 37, 38, 36.0), (4, 28, 35.0, 38, 34.0)] + + .. testcode:: :hide: diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 4a11aec15df..9cc8c5d6886 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -781,9 +781,8 @@ the following functions from the :mod:`math.integer` module: Floats with integral values (like ``5.0``) are no longer accepted in the :func:`factorial` function. -.. deprecated:: 3.15 - These aliases are :term:`soft deprecated` in favor of the - :mod:`math.integer` functions. +.. soft-deprecated:: 3.15 + Use the :mod:`math.integer` functions instead of these aliases. Constants diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst index 1e599bde8bc..0facacd50fd 100644 --- a/Doc/library/mimetypes.rst +++ b/Doc/library/mimetypes.rst @@ -54,8 +54,8 @@ the information :func:`init` sets up. .. versionchanged:: 3.8 Added support for *url* being a :term:`path-like object`. - .. deprecated:: 3.13 - Passing a file path instead of URL is :term:`soft deprecated`. + .. soft-deprecated:: 3.13 + Passing a file path instead of URL. Use :func:`guess_file_type` for this. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 2b67d10d7bf..3ceb5e717c4 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -932,7 +932,8 @@ For an example of the usage of queues for interprocess communication see standard library's :mod:`queue` module are raised to signal timeouts. :class:`Queue` implements all the methods of :class:`queue.Queue` except for - :meth:`~queue.Queue.task_done` and :meth:`~queue.Queue.join`. + :meth:`~queue.Queue.task_done`, :meth:`~queue.Queue.join`, and + :meth:`~queue.Queue.shutdown`. .. method:: qsize() @@ -1335,12 +1336,12 @@ Connection objects are usually created using Note that multiple connection objects may be polled at once by using :func:`multiprocessing.connection.wait`. - .. method:: send_bytes(buffer[, offset[, size]]) + .. method:: send_bytes(buf[, offset[, size]]) Send byte data from a :term:`bytes-like object` as a complete message. - If *offset* is given then data is read from that position in *buffer*. If - *size* is given then that many bytes will be read from buffer. Very large + If *offset* is given then data is read from that position in *buf*. If + *size* is given then that many bytes will be read from *buf*. Very large buffers (approximately 32 MiB+, though it depends on the OS) may raise a :exc:`ValueError` exception @@ -1360,18 +1361,18 @@ Connection objects are usually created using alias of :exc:`OSError`. - .. method:: recv_bytes_into(buffer[, offset]) + .. method:: recv_bytes_into(buf[, offset]) - Read into *buffer* a complete message of byte data sent from the other end + Read into *buf* a complete message of byte data sent from the other end of the connection and return the number of bytes in the message. Blocks until there is something to receive. Raises :exc:`EOFError` if there is nothing left to receive and the other end was closed. - *buffer* must be a writable :term:`bytes-like object`. If + *buf* must be a writable :term:`bytes-like object`. If *offset* is given then the message will be written into the buffer from that position. Offset must be a non-negative integer less than the - length of *buffer* (in bytes). + length of *buf* (in bytes). If the buffer is too short then a :exc:`BufferTooShort` exception is raised and the complete message is available as ``e.args[0]`` where ``e`` diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 7547967c6b3..d2534b3e974 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -5110,9 +5110,8 @@ written in Python, such as a mail server's external command delivery program. Use :class:`subprocess.Popen` or :func:`subprocess.run` to control options like encodings. - .. deprecated:: 3.14 - The function is :term:`soft deprecated` and should no longer be used to - write new code. The :mod:`subprocess` module is recommended instead. + .. soft-deprecated:: 3.14 + The :mod:`subprocess` module is recommended instead. .. function:: posix_spawn(path, argv, env, *, file_actions=None, \ @@ -5340,9 +5339,8 @@ written in Python, such as a mail server's external command delivery program. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. - .. deprecated:: 3.14 - These functions are :term:`soft deprecated` and should no longer be used - to write new code. The :mod:`subprocess` module is recommended instead. + .. soft-deprecated:: 3.14 + The :mod:`subprocess` module is recommended instead. .. data:: P_NOWAIT diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index a6ce2f30ead..790d3600180 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -17,7 +17,7 @@ -------------- -.. image:: tachyon-logo.png +.. image:: ../../Lib/profiling/sampling/_assets/tachyon-logo.png :alt: Tachyon logo :align: center :width: 300px diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 43fb7295876..a46fd424581 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -52,7 +52,7 @@ fine-tuning parameters. .. _re-syntax: -Regular Expression Syntax +Regular expression syntax ------------------------- A regular expression (or RE) specifies a set of strings that matches it; the @@ -205,7 +205,7 @@ The special characters are: *without* establishing any backtracking points. This is the possessive version of the quantifier above. For example, on the 6-character string ``'aaaaaa'``, ``a{3,5}+aa`` - attempt to match 5 ``'a'`` characters, then, requiring 2 more ``'a'``\ s, + attempts to match 5 ``'a'`` characters, then, requiring 2 more ``'a'``\ s, will need more characters than available and thus fail, while ``a{3,5}aa`` will match with ``a{3,5}`` capturing 5, then 4 ``'a'``\ s by backtracking and then the final 2 ``'a'``\ s are matched by the final @@ -717,7 +717,7 @@ three digits in length. .. _contents-of-module-re: -Module Contents +Module contents --------------- The module defines several functions, constants, and an exception. Some of the @@ -833,8 +833,8 @@ Flags will be conditionally ORed with other flags. Example of use as a default value:: - def myfunc(text, flag=re.NOFLAG): - return re.search(text, flag) + def myfunc(pattern, text, flag=re.NOFLAG): + return re.search(pattern, text, flag) .. versionadded:: 3.11 @@ -931,7 +931,6 @@ Functions .. function:: prefixmatch(pattern, string, flags=0) -.. function:: match(pattern, string, flags=0) If zero or more characters at the beginning of *string* match the regular expression *pattern*, return a corresponding :class:`~re.Match`. Return @@ -954,9 +953,14 @@ Functions :func:`~re.match`. Use that name when you need to retain compatibility with older Python versions. - .. versionchanged:: 3.15 - The alternate :func:`~re.prefixmatch` name of this API was added as a - more explicitly descriptive name than :func:`~re.match`. Use it to better + .. versionadded:: 3.15 + +.. function:: match(pattern, string, flags=0) + + .. soft-deprecated:: 3.15 + :func:`~re.match` has been :term:`soft deprecated` in favor of + the alternate :func:`~re.prefixmatch` name of this API which is + more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term *match* to refer to the behavior of what Python has always called :func:`~re.search`. @@ -1246,7 +1250,7 @@ Exceptions .. _re-objects: -Regular Expression Objects +Regular expression objects -------------------------- .. class:: Pattern @@ -1284,7 +1288,6 @@ Regular Expression Objects .. method:: Pattern.prefixmatch(string[, pos[, endpos]]) -.. method:: Pattern.match(string[, pos[, endpos]]) If zero or more characters at the *beginning* of *string* match this regular expression, return a corresponding :class:`~re.Match`. Return ``None`` if the @@ -1309,9 +1312,14 @@ Regular Expression Objects :meth:`~Pattern.match`. Use that name when you need to retain compatibility with older Python versions. - .. versionchanged:: 3.15 - The alternate :meth:`~Pattern.prefixmatch` name of this API was added as - a more explicitly descriptive name than :meth:`~Pattern.match`. Use it to + .. versionadded:: 3.15 + +.. method:: Pattern.match(string[, pos[, endpos]]) + + .. soft-deprecated:: 3.15 + :meth:`~Pattern.match` has been :term:`soft deprecated` in favor of + the alternate :meth:`~Pattern.prefixmatch` name of this API which is + more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term *match* to refer to the behavior of what Python has always called :meth:`~Pattern.search`. @@ -1396,7 +1404,7 @@ Regular Expression Objects .. _match-objects: -Match Objects +Match objects ------------- Match objects always have a boolean value of ``True``. @@ -1615,11 +1623,11 @@ when there is no match, you can test whether there was a match with a simple .. _re-examples: -Regular Expression Examples +Regular expression examples --------------------------- -Checking for a Pair +Checking for a pair ^^^^^^^^^^^^^^^^^^^ In this example, we'll use the following helper function to display match @@ -1705,15 +1713,21 @@ expressions. | ``%x``, ``%X`` | ``[-+]?(0[xX])?[\dA-Fa-f]+`` | +--------------------------------+---------------------------------------------+ -To extract the filename and numbers from a string like :: +To extract the filename and numbers from a string like: + +.. code-block:: text /usr/sbin/sendmail - 0 errors, 4 warnings -you would use a :c:func:`!scanf` format like :: +you would use a :c:func:`!scanf` format like: + +.. code-block:: text %s - %d errors, %d warnings -The equivalent regular expression would be :: +The equivalent regular expression would be: + +.. code-block:: text (\S+) - (\d+) errors, (\d+) warnings @@ -1772,18 +1786,24 @@ not familiar with the Python API's divergence from what otherwise become the industry norm. Quoting from the Zen Of Python (``python3 -m this``): *"Explicit is better than -implicit"*. Anyone reading the name :func:`~re.prefixmatch` is likely to -understand the intended semantics. When reading :func:`~re.match` there remains +implicit"*. Anyone reading the name :func:`!prefixmatch` is likely to +understand the intended semantics. When reading :func:`!match` there remains a seed of doubt about the intended behavior to anyone not already familiar with this old Python gotcha. -We **do not** plan to deprecate and remove the older *match* name, +We **do not** plan to remove the older :func:`!match` name, as it has been used in code for over 30 years. -Code supporting older versions of Python should continue to use *match*. +It has been :term:`soft deprecated`: +code supporting older versions of Python should continue to use :func:`!match`, +while new code should prefer :func:`!prefixmatch`. .. versionadded:: 3.15 + :func:`!prefixmatch` -Making a Phonebook +.. soft-deprecated:: 3.15 + :func:`!match` + +Making a phonebook ^^^^^^^^^^^^^^^^^^ :func:`split` splits a string into a list delimited by the passed pattern. The @@ -1844,7 +1864,7 @@ house number from the street name: ['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']] -Text Munging +Text munging ^^^^^^^^^^^^ :func:`sub` replaces every occurrence of a pattern with a string or the @@ -1864,7 +1884,7 @@ in each word of a sentence except for the first and last characters:: 'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.' -Finding all Adverbs +Finding all adverbs ^^^^^^^^^^^^^^^^^^^ :func:`findall` matches *all* occurrences of a pattern, not just the first @@ -1877,7 +1897,7 @@ the following manner:: ['carefully', 'quickly'] -Finding all Adverbs and their Positions +Finding all adverbs and their positions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If one wants more information about all matches of a pattern than the matched @@ -1893,7 +1913,7 @@ to find all of the adverbs *and their positions* in some text, they would use 40-47: quickly -Raw String Notation +Raw string notation ^^^^^^^^^^^^^^^^^^^ Raw string notation (``r"text"``) keeps regular expressions sane. Without it, @@ -1917,7 +1937,7 @@ functionally identical:: -Writing a Tokenizer +Writing a tokenizer ^^^^^^^^^^^^^^^^^^^ A `tokenizer or scanner `_ @@ -1933,7 +1953,7 @@ successive matches:: class Token(NamedTuple): type: str - value: str + value: int | float | str line: int column: int diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index ff1676c5bfb..484260e63dd 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -55,7 +55,7 @@ This document includes four main sections: PEP written by Marc-André Lemburg. -.. We use the following practises for SQL code: +.. We use the following practices for SQL code: - UPPERCASE for keywords - snake_case for schema - single quotes for string literals diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index 4a460479e4a..7cca6f2bcda 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -11,9 +11,9 @@ .. note:: :mod:`!sys.monitoring` is a namespace within the :mod:`sys` module, - not an independent module, so there is no need to - ``import sys.monitoring``, simply ``import sys`` and then use - ``sys.monitoring``. + not an independent module, and ``import sys.monitoring`` would fail + with a :exc:`ModuleNotFoundError`. Instead, simply ``import sys`` + and then use ``sys.monitoring``. This namespace provides access to the functions and constants necessary to @@ -180,8 +180,8 @@ Local events '''''''''''' Local events are associated with normal execution of the program and happen -at clearly defined locations. All local events can be disabled. -The local events are: +at clearly defined locations. All local events can be disabled +per location. The local events are: * :monitoring-event:`PY_START` * :monitoring-event:`PY_RESUME` @@ -205,6 +205,8 @@ Using :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT` events will give much better performance as they can be disabled independently. +.. _monitoring-ancillary-events: + Ancillary events '''''''''''''''' @@ -226,7 +228,7 @@ Other events '''''''''''' Other events are not necessarily tied to a specific location in the -program and cannot be individually disabled via :data:`DISABLE`. +program and cannot be individually disabled per location. The other events that can be monitored are: @@ -234,6 +236,12 @@ The other events that can be monitored are: * :monitoring-event:`PY_UNWIND` * :monitoring-event:`RAISE` * :monitoring-event:`EXCEPTION_HANDLED` +* :monitoring-event:`RERAISE` + +.. versionchanged:: 3.15 + Other events can now be turned on and disabled on a per code object + basis. Returning :data:`DISABLE` from a callback disables the event + for the entire code object (for the current tool). The STOP_ITERATION event @@ -247,8 +255,7 @@ raise an exception unless it would be visible to other code. To allow tools to monitor for real exceptions without slowing down generators and coroutines, the :monitoring-event:`STOP_ITERATION` event is provided. -:monitoring-event:`STOP_ITERATION` can be locally disabled, unlike -:monitoring-event:`RAISE`. +:monitoring-event:`STOP_ITERATION` can be locally disabled. Note that the :monitoring-event:`STOP_ITERATION` event and the :monitoring-event:`RAISE` event for a :exc:`StopIteration` exception are @@ -314,15 +321,14 @@ location by returning :data:`sys.monitoring.DISABLE` from a callback function. This does not change which events are set, or any other code locations for the same event. -Disabling events for specific locations is very important for high -performance monitoring. For example, a program can be run under a -debugger with no overhead if the debugger disables all monitoring -except for a few breakpoints. +:ref:`Other events ` can be disabled on a per code +object basis by returning :data:`sys.monitoring.DISABLE` from a callback +function. This disables the event for the entire code object (for the current +tool). -If :data:`DISABLE` is returned by a callback for a -:ref:`global event `, :exc:`ValueError` will be raised -by the interpreter in a non-specific location (that is, no traceback will be -provided). +Disabling events for specific locations is very important for high performance +monitoring. For example, a program can be run under a debugger with no overhead +if the debugger disables all monitoring except for a few breakpoints. .. function:: restart_events() -> None diff --git a/Doc/library/tachyon-logo.png b/Doc/library/tachyon-logo.png deleted file mode 100644 index bf0901ec9f3..00000000000 Binary files a/Doc/library/tachyon-logo.png and /dev/null differ diff --git a/Doc/library/tokenize.rst b/Doc/library/tokenize.rst index 3db4cf42c17..72fbcaba160 100644 --- a/Doc/library/tokenize.rst +++ b/Doc/library/tokenize.rst @@ -28,7 +28,7 @@ type can be determined by checking the ``exact_type`` property on the **undefined** when providing invalid Python code and it can change at any point. -Tokenizing Input +Tokenizing input ---------------- The primary entry point is a :term:`generator`: @@ -146,7 +146,7 @@ function it uses to do this is available: .. _tokenize-cli: -Command-Line Usage +Command-line usage ------------------ .. versionadded:: 3.3 @@ -173,8 +173,12 @@ The following options are accepted: If :file:`filename.py` is specified its contents are tokenized to stdout. Otherwise, tokenization is performed on stdin. +.. versionadded:: next + Output is in color by default and can be + :ref:`controlled using environment variables `. + Examples ------------------- +-------- Example of a script rewriter that transforms float literals into Decimal objects:: @@ -227,7 +231,7 @@ Example of tokenizing from the command line. The script:: will be tokenized to the following output where the first column is the range of the line/column coordinates where the token is found, the second column is -the name of the token, and the final column is the value of the token (if any) +the name of the token, and the final column is the value of the token (if any): .. code-block:: shell-session diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 09e9103e1b8..1957cadcbb1 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1174,7 +1174,8 @@ These can be used as types in annotations. They all support subscription using or transforms parameters of another callable. Usage is in the form ``Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]``. ``Concatenate`` - is currently only valid when used as the first argument to a :ref:`Callable `. + is valid when used in :ref:`Callable ` type hints + and when instantiating user-defined generic classes with :class:`ParamSpec` parameters. The last parameter to ``Concatenate`` must be a :class:`ParamSpec` or ellipsis (``...``). @@ -1980,7 +1981,7 @@ without the dedicated syntax, as documented below. .. _typevartuple: -.. class:: TypeVarTuple(name, *, default=typing.NoDefault) +.. class:: TypeVarTuple(name, *, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault) Type variable tuple. A specialized form of :ref:`type variable ` that enables *variadic* generics. @@ -2090,6 +2091,24 @@ without the dedicated syntax, as documented below. The name of the type variable tuple. + .. attribute:: __covariant__ + + Whether the type variable tuple has been explicitly marked as covariant. + + .. versionadded:: 3.15 + + .. attribute:: __contravariant__ + + Whether the type variable tuple has been explicitly marked as contravariant. + + .. versionadded:: 3.15 + + .. attribute:: __infer_variance__ + + Whether the type variable tuple's variance should be inferred by type checkers. + + .. versionadded:: 3.15 + .. attribute:: __default__ The default value of the type variable tuple, or :data:`typing.NoDefault` if it @@ -2116,6 +2135,11 @@ without the dedicated syntax, as documented below. .. versionadded:: 3.13 + Type variable tuples created with ``covariant=True`` or + ``contravariant=True`` can be used to declare covariant or contravariant + generic types. The ``bound`` argument is also accepted, similar to + :class:`TypeVar`, but its actual semantics are yet to be decided. + .. versionadded:: 3.11 .. versionchanged:: 3.12 @@ -2127,6 +2151,11 @@ without the dedicated syntax, as documented below. Support for default values was added. + .. versionchanged:: 3.15 + + Added support for the ``bound``, ``covariant``, ``contravariant``, and + ``infer_variance`` parameters. + .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault) Parameter specification variable. A specialized version of @@ -2196,6 +2225,20 @@ without the dedicated syntax, as documented below. The name of the parameter specification. + .. attribute:: __covariant__ + + Whether the parameter specification has been explicitly marked as covariant. + + .. attribute:: __contravariant__ + + Whether the parameter specification has been explicitly marked as contravariant. + + .. attribute:: __infer_variance__ + + Whether the parameter specification's variance should be inferred by type checkers. + + .. versionadded:: 3.12 + .. attribute:: __default__ The default value of the parameter specification, or :data:`typing.NoDefault` if it @@ -3358,6 +3401,36 @@ Functions and decorators .. versionadded:: 3.12 +.. decorator:: disjoint_base + + Decorator to mark a class as a disjoint base. + + Type checkers do not allow child classes of a disjoint base ``C`` to + inherit from other disjoint bases that are not parent or child classes of ``C``. + + For example:: + + @disjoint_base + class Disjoint1: pass + + @disjoint_base + class Disjoint2: pass + + class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error + + Type checkers can use knowledge of disjoint bases to detect unreachable code + and determine when two types can overlap. + + The corresponding runtime concept is a solid base (see :ref:`multiple-inheritance`). + Classes that are solid bases at runtime can be marked with ``@disjoint_base`` in stub files. + Users may also mark other classes as disjoint bases to indicate to type checkers that + multiple inheritance with other disjoint bases should not be allowed. + + Note that the concept of a solid base is a CPython implementation + detail, and the exact set of standard library classes that are + disjoint bases at runtime may change in future versions of Python. + + .. versionadded:: next .. decorator:: type_check_only @@ -3380,13 +3453,13 @@ Functions and decorators Introspection helpers --------------------- -.. function:: get_type_hints(obj, globalns=None, localns=None, include_extras=False) +.. function:: get_type_hints(obj, globalns=None, localns=None, include_extras=False, *, format=Format.VALUE) Return a dictionary containing type hints for a function, method, module, class object, or other callable object. - This is often the same as ``obj.__annotations__``, but this function makes - the following changes to the annotations dictionary: + This is often the same as :func:`annotationlib.get_annotations`, but this + function makes the following changes to the annotations dictionary: * Forward references encoded as string literals or :class:`ForwardRef` objects are handled by evaluating them in *globalns*, *localns*, and @@ -3400,17 +3473,15 @@ Introspection helpers annotations from ``C``'s base classes with those on ``C`` directly. This is done by traversing :attr:`C.__mro__ ` and iteratively combining - ``__annotations__`` dictionaries. Annotations on classes appearing - earlier in the :term:`method resolution order` always take precedence over - annotations on classes appearing later in the method resolution order. + :term:`annotations ` of each base class. Annotations + on classes appearing earlier in the :term:`method resolution order` always + take precedence over annotations on classes appearing later in the method + resolution order. * The function recursively replaces all occurrences of ``Annotated[T, ...]``, ``Required[T]``, ``NotRequired[T]``, and ``ReadOnly[T]`` with ``T``, unless *include_extras* is set to ``True`` (see :class:`Annotated` for more information). - See also :func:`annotationlib.get_annotations`, a lower-level function that - returns annotations more directly. - .. caution:: This function may execute arbitrary code contained in annotations. @@ -3418,11 +3489,12 @@ Introspection helpers .. note:: - If any forward references in the annotations of *obj* are not resolvable - or are not valid Python code, this function will raise an exception - such as :exc:`NameError`. For example, this can happen with imported - :ref:`type aliases ` that include forward references, - or with names imported under :data:`if TYPE_CHECKING `. + If :attr:`Format.VALUE ` is used and any + forward references in the annotations of *obj* are not resolvable, a + :exc:`NameError` exception is raised. For example, this can happen + with names imported under :data:`if TYPE_CHECKING `. + More generally, any kind of exception can be raised if an annotation + contains invalid Python code. .. note:: @@ -3440,6 +3512,10 @@ Introspection helpers if a default value equal to ``None`` was set. Now the annotation is returned unchanged. + .. versionchanged:: 3.14 + Added the ``format`` parameter. See the documentation on + :func:`annotationlib.get_annotations` for more information. + .. versionchanged:: 3.14 Calling :func:`get_type_hints` on instances is no longer supported. Some instances were accepted in earlier versions as an undocumented @@ -3797,7 +3873,7 @@ Aliases to other concrete types Match Deprecated aliases corresponding to the return types from - :func:`re.compile` and :func:`re.match`. + :func:`re.compile` and :func:`re.search`. These types (and the corresponding functions) are generic over :data:`AnyStr`. ``Pattern`` can be specialised as ``Pattern[str]`` or diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index c7682c22746..6e0df0648fb 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1223,9 +1223,9 @@ Test cases | :meth:`assertNotRegex(s, r) | ``not r.search(s)`` | 3.2 | | ` | | | +---------------------------------------+--------------------------------+--------------+ - | :meth:`assertCountEqual(a, b) | *a* and *b* have the same | 3.2 | - | ` | elements in the same number, | | - | | regardless of their order. | | + | :meth:`assertCountEqual(a, b) | *a* contains the same elements | 3.2 | + | ` | as *b*, regardless of their | | + | | order. | | +---------------------------------------+--------------------------------+--------------+ | :meth:`assertStartsWith(a, b) | ``a.startswith(b)`` | 3.14 | | ` | | | diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 0cf0a41bfb4..72e1cad3bbd 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -858,7 +858,7 @@ A literal pattern corresponds to most : | "None" : | "True" : | "False" - signed_number: ["-"] NUMBER + signed_number: ["+" | "-"] NUMBER The rule ``strings`` and the token ``NUMBER`` are defined in the :doc:`standard Python grammar <./grammar>`. Triple-quoted strings are diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1e53c0e0e6f..aef5bbe151c 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -926,6 +926,7 @@ Attribute assignment updates the module's namespace dictionary, e.g., single: __doc__ (module attribute) single: __annotations__ (module attribute) single: __annotate__ (module attribute) + single: __lazy_modules__ (module attribute) pair: module; namespace .. _import-mod-attrs: @@ -1121,6 +1122,20 @@ the following writable attributes: .. versionadded:: 3.14 +.. attribute:: module.__lazy_modules__ + + A container (an object implementing :meth:`~object.__contains__`) of fully + qualified module name strings. When defined + at module scope, any regular :keyword:`import` statement in that module whose + target module name appears in this container is treated as a + :ref:`lazy import `, as if the :keyword:`lazy` keyword had + been used. Imports inside functions, class bodies, or + :keyword:`try`/:keyword:`except`/:keyword:`finally` blocks are unaffected. + + See :ref:`lazy-modules-compat` for details and examples. + + .. versionadded:: 3.15 + Module dictionaries ^^^^^^^^^^^^^^^^^^^ @@ -1461,7 +1476,6 @@ indirectly) to mutable objects. single: co_filename (code object attribute) single: co_firstlineno (code object attribute) single: co_flags (code object attribute) - single: co_lnotab (code object attribute) single: co_name (code object attribute) single: co_names (code object attribute) single: co_nlocals (code object attribute) @@ -1534,14 +1548,6 @@ Special read-only attributes * - .. attribute:: codeobject.co_firstlineno - The line number of the first line of the function - * - .. attribute:: codeobject.co_lnotab - - A string encoding the mapping from :term:`bytecode` offsets to line - numbers. For details, see the source code of the interpreter. - - .. deprecated:: 3.12 - This attribute of code objects is deprecated, and may be removed in - Python 3.15. - * - .. attribute:: codeobject.co_stacksize - The required stack size of the code object diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 9b84c2e9ac7..648e3a9bf54 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -920,6 +920,56 @@ See :pep:`810` for the full specification of lazy imports. .. versionadded:: 3.15 +.. _lazy-modules-compat: + +Compatibility via ``__lazy_modules__`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. index:: + single: __lazy_modules__ + +As an alternative to using the :keyword:`lazy` keyword, a module can opt +into lazy loading for specific imports by defining a module-level +:attr:`~module.__lazy_modules__` variable. When present, it must be a +container of fully qualified module name strings. Any regular (non-``lazy``) +:keyword:`import` statement at module scope whose target appears in +:attr:`!__lazy_modules__` is treated as a lazy import, exactly as if the +:keyword:`lazy` keyword had been used. + +This provides a way to enable lazy loading for specific dependencies without +changing individual ``import`` statements. This is useful when supporting +Python versions older than 3.15 while using lazy imports in 3.15+:: + + __lazy_modules__ = ["json", "pathlib"] + + import json # loaded lazily (name is in __lazy_modules__) + import os # loaded eagerly (name not in __lazy_modules__) + + import pathlib # loaded lazily + +Relative imports are resolved to their absolute name before the lookup, so +:attr:`!__lazy_modules__` must always contain fully qualified module names. + +For ``from``-style imports, the relevant name is the module following +``from``, not the names of its members:: + + # In mypackage/mymodule.py + __lazy_modules__ = ["mypackage", "mypackage.sub.utils"] + + from . import helper # loaded lazily: . resolves to mypackage + from .sub.utils import func # loaded lazily: .sub.utils resolves to mypackage.sub.utils + import json # loaded eagerly (not in __lazy_modules__) + +Imports inside functions, class bodies, or +:keyword:`try`/:keyword:`except`/:keyword:`finally` blocks are always eager, +regardless of :attr:`!__lazy_modules__`. + +Setting ``-X lazy_imports=none`` (or the :envvar:`PYTHON_LAZY_IMPORTS` +environment variable to ``none``) overrides :attr:`!__lazy_modules__` and +forces all imports to be eager. + +.. versionadded:: 3.15 + .. _future: Future statements diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index 724dea625c4..1409c77aed9 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -249,18 +249,17 @@ def _stable_abi_annotation( reftype="ref", refexplicit="False", ) - struct_abi_kind = record.struct_abi_kind - if struct_abi_kind in {"opaque", "members"}: - ref_node += nodes.Text(sphinx_gettext("Limited API")) - else: - ref_node += nodes.Text(sphinx_gettext("Stable ABI")) + ref_node += nodes.Text(sphinx_gettext("Stable ABI")) emph_node += ref_node + struct_abi_kind = record.struct_abi_kind if struct_abi_kind == "opaque": emph_node += nodes.Text(" " + sphinx_gettext("(as an opaque struct)")) elif struct_abi_kind == "full-abi": emph_node += nodes.Text( " " + sphinx_gettext("(including all members)") ) + elif struct_abi_kind in {"members", "abi3t-opaque"}: + emph_node += nodes.Text(" " + sphinx_gettext("(see below)")) if record.ifdef_note: emph_node += nodes.Text(f" {record.ifdef_note}") if stable_added == "3.2": @@ -271,11 +270,7 @@ def _stable_abi_annotation( " " + sphinx_gettext("since version %s") % stable_added ) emph_node += nodes.Text(".") - if struct_abi_kind == "members": - msg = " " + sphinx_gettext( - "(Only some members are part of the stable ABI.)" - ) - emph_node += nodes.Text(msg) + return emph_node @@ -378,6 +373,33 @@ def run(self) -> list[nodes.Node]: return [node] +class VersionHexCheatsheet(SphinxDirective): + """Show results of Py_PACK_VERSION(3, x) for a few relevant Python versions + + This is useful for defining version before Python.h is included. + It should auto-update with the version being documented, so it must be an + extension. + """ + + has_content = False + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = True + + def run(self) -> list[nodes.Node]: + content = [ + ".. code-block:: c", + "", + ] + current_minor = int(self.config.version.removeprefix('3.')) + for minor in range(current_minor - 5, current_minor + 1): + value = (3 << 24) | (minor << 16) + content.append(f' {value:#x} /* Py_PACK_VERSION(3.{minor}) */') + node = nodes.paragraph() + self.state.nested_parse(StringList(content), 0, node) + return [node] + + class CorrespondingTypeSlot(SphinxDirective): """Type slot annotations @@ -443,6 +465,7 @@ def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value("stable_abi_file", "", "env", types={str}) app.add_config_value("threadsafety_file", "", "env", types={str}) app.add_directive("limited-api-list", LimitedAPIList) + app.add_directive("version-hex-cheatsheet", VersionHexCheatsheet) app.add_directive("corresponding-type-slot", CorrespondingTypeSlot) app.connect("builder-inited", init_annotations) app.connect("doctree-read", add_annotations) diff --git a/Doc/tools/extensions/changes.py b/Doc/tools/extensions/changes.py index 8de5e7f78c6..02dc51b3a76 100644 --- a/Doc/tools/extensions/changes.py +++ b/Doc/tools/extensions/changes.py @@ -2,8 +2,10 @@ from __future__ import annotations -from typing import TYPE_CHECKING +import re +from docutils import nodes +from sphinx import addnodes from sphinx.domains.changeset import ( VersionChange, versionlabel_classes, @@ -11,6 +13,7 @@ ) from sphinx.locale import _ as sphinx_gettext +TYPE_CHECKING = False if TYPE_CHECKING: from docutils.nodes import Node from sphinx.application import Sphinx @@ -73,6 +76,76 @@ def run(self) -> list[Node]: versionlabel_classes[self.name] = "" +class SoftDeprecated(PyVersionChange): + """Directive for soft deprecations that auto-links to the glossary term. + + Usage:: + + .. soft-deprecated:: 3.15 + + Use :func:`new_thing` instead. + + Renders as: "Soft deprecated since version 3.15: Use new_thing() instead." + with "Soft deprecated" linking to the glossary definition. + """ + + _TERM_RE = re.compile(r":term:`([^`]+)`") + + def run(self) -> list[Node]: + versionlabels[self.name] = sphinx_gettext( + ":term:`Soft deprecated` since version %s" + ) + versionlabel_classes[self.name] = "soft-deprecated" + try: + result = super().run() + finally: + versionlabels[self.name] = "" + versionlabel_classes[self.name] = "" + + for node in result: + # Add "versionchanged" class so existing theme CSS applies + node["classes"] = node.get("classes", []) + ["versionchanged"] + # Replace the plain-text "Soft deprecated" with a glossary reference + for inline in node.findall(nodes.inline): + if "versionmodified" in inline.get("classes", []): + self._add_glossary_link(inline) + + return result + + @classmethod + def _add_glossary_link(cls, inline: nodes.inline) -> None: + """Replace :term:`soft deprecated` text with a cross-reference to the + 'Soft deprecated' glossary entry.""" + for child in inline.children: + if not isinstance(child, nodes.Text): + continue + + text = str(child) + match = cls._TERM_RE.search(text) + if match is None: + continue + + ref = addnodes.pending_xref( + "", + nodes.Text(match.group(1)), + refdomain="std", + reftype="term", + reftarget="soft deprecated", + refwarn=True, + ) + + start, end = match.span() + new_nodes: list[nodes.Node] = [] + if start > 0: + new_nodes.append(nodes.Text(text[:start])) + new_nodes.append(ref) + if end < len(text): + new_nodes.append(nodes.Text(text[end:])) + + child.parent.replace(child, new_nodes) + break + + def setup(app: Sphinx) -> ExtensionMetadata: # Override Sphinx's directives with support for 'next' app.add_directive("versionadded", PyVersionChange, override=True) @@ -83,6 +156,9 @@ def setup(app: Sphinx) -> ExtensionMetadata: # Register the ``.. deprecated-removed::`` directive app.add_directive("deprecated-removed", DeprecatedRemoved) + # Register the ``.. soft-deprecated::`` directive + app.add_directive("soft-deprecated", SoftDeprecated) + return { "version": "1.0", "parallel_read_safe": True, diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index f3cd8bf0ef5..5e3ef2efe27 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -1 +1,7 @@ # HTML IDs excluded from the check-html-ids.py check. + +# Remove from here in 3.16 +c-api/allocation.html: deprecated-aliases +c-api/file.html: deprecated-api + +library/asyncio-task.html: terminating-a-task-group diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 75f6607d8f3..699e518801c 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -29,6 +29,7 @@ {% trans %}Deprecated since version %s, will be removed in version %s{% endtrans %} {% trans %}Deprecated since version %s, removed in version %s{% endtrans %} +{% trans %}:term:`Soft deprecated` since version %s{% endtrans %} In docsbuild-scripts, when rewriting indexsidebar.html with actual versions: diff --git a/Doc/using/android.rst b/Doc/using/android.rst index 45345d045dd..60a13569318 100644 --- a/Doc/using/android.rst +++ b/Doc/using/android.rst @@ -30,7 +30,7 @@ Adding Python to an Android app Most app developers should use one of the following tools, which will provide a much easier experience: -* `Briefcase `__, from the BeeWare project +* `Briefcase `__, from the BeeWare project * `Buildozer `__, from the Kivy project * `Chaquopy `__ * `pyqtdeploy `__ diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index bf25de7cc90..d5c17560b66 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -1012,6 +1012,21 @@ Linker options .. versionadded:: 3.10 +.. option:: --enable-static-libpython-for-interpreter + + Do not link the Python interpreter binary (``python3``) against the + shared Python library; instead, statically link the interpreter + against ``libpython`` as if ``--enable-shared`` had not been used, + but continue to build the shared ``libpython`` (for use by other + programs). + + This option does nothing if ``--enable-shared`` is not used. + + The default (when ``-enable-shared`` is used) is to link the Python + interpreter against the built shared library. + + .. versionadded:: next + Libraries options ----------------- diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 1a913c624e9..eea1e2f64a4 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -778,6 +778,14 @@ directory containing the configuration file that specified them. - True to suppress visible warnings when a shebang launches an application other than a Python runtime. + * - ``source_settings`` + - A mapping from source URL to settings specific to that index. + When multiple configuration files include this section, URL settings are + added or overwritten, but individual settings are not merged. + These settings are currently only for :ref:`index signatures + `. + + .. _install-freethreaded-windows: Installing free-threaded binaries @@ -799,6 +807,101 @@ installed, then ``python`` will launch this one. Otherwise, you will need to use ``py -V:3.14t ...`` or, if you have added the global aliases directory to your :envvar:`PATH` environment variable, the ``python3.14t.exe`` commands. + +.. _pymanager-index-signatures: + +Index signatures +---------------- + +.. versionadded:: 26.2 + +Index files may be signed to detect tampering. A signature is a catalog file +at the same URL as the index with ``.cat`` added to the filename. The catalog +file should contain the hash of its matching index file, and should be signed +with a valid Authenticode signature. This allows standard tooling (on Windows) +to generate a signature, and any certificate may be used as long as the client +operating system already trusts its certification authority (root CA). + +Index signatures are only downloaded and checked when the local configuration's +``source_settings`` section includes the index URL and ``requires_signature`` is +true, or the index JSON contains ``requires_signature`` set to true. When the +setting exists in local configuration, even when false, settings in the index +are ignored. + +As well as requiring a valid signature, the ``required_root_subject`` and +``required_publisher_subject`` settings can further restrict acceptable +signatures based on the certificate Subject fields. Any attribute specified in +the configuration must match the attribute in the certificate (additional +attributes in the certificate are ignored). Typical attributes are ``CN=`` for +the common name, ``O=`` for the organizational unit, and ``C=`` for the +publisher's country. + +Finally, the ``required_publisher_eku`` setting allows requiring that a specific +Enhanced Key Usage (EKU) has been assigned to the publisher certificate. For +example, the EKU ``1.3.6.1.5.5.7.3.3`` indicates that the certificate was +intended for code signing (as opposed to server or client authentication). +In combination with a specific root CA, this provides another mechanism to +verify a legitimate signature. + +This is an example ``source_settings`` section from a configuration file. In +this case, the publisher of the feed is uniquely identified by the combination +of the Microsoft Identity Verification root and the EKU assigned by that root. +The signature for this case would be found at +``https://www.python.org/ftp/python/index-windows.json.cat``. + +.. code:: json5 + + { + "source_settings": { + "https://www.python.org/ftp/python/index-windows.json": { + "requires_signature": true, + "required_root_subject": "CN=Microsoft Identity Verification Root Certificate Authority 2020", + "required_publisher_subject": "CN=Python Software Foundation", + "required_publisher_eku": "1.3.6.1.4.1.311.97.608394634.79987812.305991749.578777327" + } + } + } + +The same settings could be specified in the ``index.json`` file instead. In this +case, the root and EKU are omitted, meaning that the signature must be valid and +have a specific common name in the publisher's certificate, but no other checks +are used. + +.. code:: json5 + + { + "requires_signature": true, + "required_publisher_subject": "CN=Python Software Foundation", + "versions": [ + // ... + ] + } + +When settings from inside a feed are used, the user is notified and the settings +are shown in the log file or verbose output. It is recommended to copy these +settings into a local configuration file for feeds that will be used frequently, +so that unauthorised modifications to the feed cannot disable verification. + +It is not possible to override the location of the signature file in the feed or +through a configuration file. Administrators can provide their own +``source_settings`` in a mandatory configuration file (see +:ref:`pymanager-admin-config`). + +If signature validation fails, you will be notified and prompted to continue. +When interactive confirmation is not allowed (for example, because ``--yes`` was +specified), it will always abort. To use a feed with invalid configuration in +this scenario, you must provide a configuration file that disables signature +checking for that feed. + +.. code:: json5 + + "source_settings": { + "https://www.example.com/feed-with-invalid-signature.json": { + "requires_signature": false + } + } + + .. _pymanager-troubleshoot: Troubleshooting diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 4b092b13959..8a78dbd9038 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -402,7 +402,7 @@ Tracing events, with the correct line number, are generated for all lines of cod The :attr:`~frame.f_lineno` attribute of frame objects will always contain the expected line number. -The :attr:`~codeobject.co_lnotab` attribute of +The :attr:`!codeobject.co_lnotab` attribute of :ref:`code objects ` is deprecated and will be removed in 3.12. Code that needs to convert from offset to line number should use the new diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 221956f3dd3..df6cc98eaf1 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -1347,7 +1347,7 @@ Deprecated ``int``, convert to int explicitly: ``~int(x)``. (Contributed by Tim Hoffmann in :gh:`103487`.) -* Accessing :attr:`~codeobject.co_lnotab` on code objects was deprecated in +* Accessing :attr:`!codeobject.co_lnotab` on code objects was deprecated in Python 3.10 via :pep:`626`, but it only got a proper :exc:`DeprecationWarning` in 3.12. May be removed in 3.15. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index f2bd4c77c7f..d80a84b3b17 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -80,8 +80,10 @@ Summary -- Release highlights * :pep:`728`: ``TypedDict`` with typed extra items * :pep:`747`: :ref:`Annotating type forms with TypeForm ` +* :pep:`800`: Disjoint bases in the type system * :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object ` +* :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds ` * :ref:`The JIT compiler has been significantly upgraded ` * :ref:`Improved error messages ` * :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter @@ -140,7 +142,7 @@ In the case where loading a lazily imported module fails (for example, if the module does not exist), Python raises the exception at the point of first use rather than at import time. The associated traceback includes both the location where the name was accessed and the original import statement, -making it straightforward to diagnose & debug the failure. +making it straightforward to diagnose and debug the failure. For cases where you want to enable lazy loading globally without modifying source code, Python provides the :option:`-X lazy_imports <-X>` command-line @@ -182,6 +184,18 @@ function, class body, or ``try``/``except``/``finally`` block raises a (``lazy from module import *`` and ``lazy from __future__ import ...`` both raise :exc:`SyntaxError`). +For code that cannot use the ``lazy`` keyword directly (for example, when +supporting Python versions older than 3.15 while still using lazy +imports on 3.15+), a module can define +:attr:`~module.__lazy_modules__` as a container of fully qualified module +name strings. Regular ``import`` statements for those modules are then treated +as lazy, with the same semantics as the ``lazy`` keyword:: + + __lazy_modules__ = ["json", "pathlib"] + + import json # lazy + import os # still eager + .. seealso:: :pep:`810` for the full specification and rationale. (Contributed by Pablo Galindo Salgado and Dino Viehland in :gh:`142349`.) @@ -258,7 +272,7 @@ The :mod:`profile` module is deprecated and will be removed in Python 3.17. Tachyon: High frequency statistical sampling profiler ----------------------------------------------------- -.. image:: ../library/tachyon-logo.png +.. image:: ../../Lib/profiling/sampling/_assets/tachyon-logo.png :alt: Tachyon profiler logo :align: center :width: 200px @@ -381,6 +395,41 @@ agen() for x in a)``. (Contributed by Adam Hartz in :gh:`143055`.) +.. _whatsnew315-abi3t: + +:pep:`803`: ``abi3t`` -- Stable ABI for Free-Threaded Builds +------------------------------------------------------------ + +C extensions that target the :ref:`Stable ABI ` can now be +compiled for the new *Stable ABI for Free-Threaded Builds* (also known +as ``abi3t``), which makes them compatible with +:term:`free-threaded builds ` of CPython. +This usually requires some non-trivial changes to the source code; +specifically: + +- Switching to API introduced in :pep:`697` (Python 3.12), such as + negative :c:member:`~PyType_Spec.basicsize` and + :c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject` + part of the instance struct; and +- Switching from a ``PyInit_`` function to a new export hook, + :c:func:`PyModExport_* `, introduced for this + purpose in :pep:`793`. + +Note that Stable ABI does not offer all the functionality that CPython +has to offer. +Extensions that cannot switch to ``abi3t`` should continue to build for +the existing Stable ABI (``abi3``) and the version-specific ABI for +free-threading (``cp315t``) separately. + +Stable ABI for Free-Threaded Builds should typically +be selected in a build tool (such as, for example, Setuptools, meson-python, +scikit-build-core, or Maturin). +At the time of writing, these tools did **not** support ``abi3t``. +If this is the case for your tool, compile for ``cp315t`` separately. +If not using a build tool -- or when writing such a tool -- you can select +``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed +in :ref:`abi3-compiling`. + .. _whatsnew315-improved-error-messages: @@ -414,14 +463,36 @@ Improved error messages Running this code now produces a clearer suggestion: - .. code-block:: pycon + .. code-block:: pytb Traceback (most recent call last): - File "/home/pablogsal/github/python/main/lel.py", line 42, in - print(container.area) - ^^^^^^^^^^^^^^ + File "/home/pablogsal/github/python/main/lel.py", line 42, in + print(container.area) + ^^^^^^^^^^^^^^ AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'? +* The interpreter now tries to provide a suggestion when + :func:`delattr` fails due to a missing attribute. + When an attribute name that closely resembles an existing attribute is used, + the interpreter will suggest the correct attribute name in the error message. + For example: + + .. doctest:: + + >>> class A: + ... pass + >>> a = A() + >>> a.abcde = 1 + >>> del a.abcdf # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? + + (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) + +* Several error messages incorrectly using the term "argument" have been corrected. + (Contributed by Stan Ulbrych in :gh:`133382`.) + Other language changes ====================== @@ -453,28 +524,6 @@ Other language changes (Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.) -* Several error messages incorrectly using the term "argument" have been corrected. - (Contributed by Stan Ulbrych in :gh:`133382`.) - -* The interpreter now tries to provide a suggestion when - :func:`delattr` fails due to a missing attribute. - When an attribute name that closely resembles an existing attribute is used, - the interpreter will suggest the correct attribute name in the error message. - For example: - - .. doctest:: - - >>> class A: - ... pass - >>> a = A() - >>> a.abcde = 1 - >>> del a.abcdf # doctest: +ELLIPSIS - Traceback (most recent call last): - ... - AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'? - - (Contributed by Nikita Sobolev and Pranjal Prajapati in :gh:`136588`.) - * Unraisable exceptions are now highlighted with color by default. This can be controlled by :ref:`environment variables `. (Contributed by Peter Bierma in :gh:`134170`.) @@ -608,6 +657,10 @@ Other language changes * Allow the *count* argument of :meth:`bytes.replace` to be a keyword. (Contributed by Stan Ulbrych in :gh:`147856`.) +* Unary plus is now accepted in :keyword:`match` literal patterns, mirroring + the existing support for unary minus. + (Contributed by Bartosz Sławecki in :gh:`145239`.) + New modules =========== @@ -651,6 +704,20 @@ array (Contributed by Sergey B Kirpichev in :gh:`146238`.) +ast +--- + +* Add *color* parameter to :func:`~ast.dump`. + If ``True``, the returned string is syntax highlighted using ANSI escape + sequences. + If ``False`` (the default), colored output is always disabled. + (Contributed by Stan Ulbrych in :gh:`148981`.) + +* The :ref:`command-line ` output is now syntax highlighted by default. + This can be :ref:`controlled using environment variables `. + (Contributed by Stan Ulbrych in :gh:`148981`.) + + base64 ------ @@ -671,11 +738,20 @@ base64 (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.) * Added the *ignorechars* parameter in :func:`~base64.b16decode`, - :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, :func:`~base64.b64decode`, :func:`~base64.b85decode`, and :func:`~base64.z85decode`. (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) +* Added the *canonical* parameter in + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64decode`, :func:`~base64.urlsafe_b64decode`, + :func:`~base64.a85decode`, :func:`~base64.b85decode`, and + :func:`~base64.z85decode`, + to reject encodings with non-zero padding bits or other non-canonical + forms. + (Contributed by Gregory P. Smith in :gh:`146311`.) + binascii -------- @@ -709,6 +785,10 @@ binascii :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`. (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) +* Added the *canonical* parameter in :func:`~binascii.a2b_base64`, + to reject encodings with non-zero padding bits. + (Contributed by Gregory P. Smith in :gh:`146311`.) + calendar -------- @@ -848,13 +928,13 @@ inspect json ---- -* Add the *array_hook* parameter to :func:`~json.load` and +* Add the *array_hook* parameter to :func:`~json.load` and :func:`~json.loads` functions: allow a callback for JSON literal array types to customize Python lists in the resulting decoded object. Passing combined :class:`frozendict` to *object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a deeply nested immutable Python structure representing the JSON data. - (Contributed by Joao S. O. Bueno in :gh:`146440`) + (Contributed by Joao S. O. Bueno in :gh:`146440`.) locale @@ -882,23 +962,11 @@ math mimetypes --------- -* Add ``application/dicom`` MIME type for ``.dcm`` extension. - (Contributed by Benedikt Johannes in :gh:`144217`.) -* Add ``application/efi``. (Contributed by Charlie Lin in :gh:`145720`.) -* Add ``application/node`` MIME type for ``.cjs`` extension. - (Contributed by John Franey in :gh:`140937`.) -* Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.) -* Add ``application/sql`` and ``application/vnd.sqlite3``. - (Contributed by Charlie Lin in :gh:`145698`.) -* Add the following MIME types: - - - ``application/vnd.ms-cab-compressed`` for ``.cab`` extension - - ``application/vnd.ms-htmlhelp`` for ``.chm`` extension - - ``application/vnd.ms-officetheme`` for ``.thmx`` extension - - (Contributed by Charlie Lin in :gh:`145718`.) - -* Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) +* Add more MIME types. + (Contributed by Benedikt Johannes, Charlie Lin, Foolbar, Gil Forcada and + John Franey + in :gh:`144217`, :gh:`145720`, :gh:`140937`, :gh:`139959`, :gh:`145698`, + :gh:`145718` and :gh:`144213`.) * Rename ``application/x-texinfo`` to ``application/texinfo``. (Contributed by Charlie Lin in :gh:`140165`.) * Changed the MIME type for ``.ai`` files to ``application/pdf``. @@ -947,12 +1015,27 @@ pickle (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) +pprint +------ + +* Add an *expand* keyword argument for :func:`pprint.pprint`, + :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be + formatted similar to pretty-printed :func:`json.dumps` when + *indent* is supplied. + (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in + :gh:`112632`.) + +* Add t-string support to :mod:`pprint`. + (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.) + + re -- -* :func:`re.prefixmatch` and a corresponding :meth:`~re.Pattern.prefixmatch` - have been added as alternate more explicit names for the existing - :func:`re.match` and :meth:`~re.Pattern.match` APIs. These are intended +* :func:`re.prefixmatch` and a corresponding :meth:`re.Pattern.prefixmatch` + have been added as alternate, more explicit names for the existing + and now :term:`soft deprecated` + :func:`re.match` and :meth:`re.Pattern.match` APIs. These are intended to be used to alleviate confusion around what *match* means by following the Zen of Python's *"Explicit is better than implicit"* mantra. Most other language regular expression libraries use an API named *match* to mean what @@ -1067,7 +1150,7 @@ subprocess If none of these mechanisms are available, the function falls back to the traditional busy loop (non-blocking call and short sleeps). - (Contributed by Giampaolo Rodola in :gh:`83069`). + (Contributed by Giampaolo Rodola in :gh:`83069`.) symtable @@ -1084,6 +1167,19 @@ sys (Contributed by Klaus Zimmermann in :gh:`137476`.) +sys.monitoring +-------------- + +* The :ref:`other events ` + (:monitoring-event:`PY_THROW`, :monitoring-event:`PY_UNWIND`, + :monitoring-event:`RAISE`, :monitoring-event:`EXCEPTION_HANDLED`, and + :monitoring-event:`RERAISE`) can now be turned on and disabled on a per code + object basis. Returning :data:`~sys.monitoring.DISABLE` from a callback for + one of these events disables the event for the entire code object (for the + current tool), rather than raising :exc:`ValueError` as in prior versions. + (Contributed by Gabriele N. Tornetta in :gh:`146182`.) + + tarfile ------- @@ -1124,7 +1220,7 @@ timeit * Make the target time of :meth:`timeit.Timer.autorange` configurable and add ``--target-time`` option to the command-line interface. - (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`140283`.) + (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`80642`.) tkinter @@ -1153,6 +1249,15 @@ tkinter (Contributed by Matthias Kievernagel and Serhiy Storchaka in :gh:`47655`.) +tokenize +-------- + +* The output of the :mod:`tokenize` :ref:`command-line interface + ` is colored by default. This can be controlled with + :ref:`environment variables `. + (Contributed by Hugo van Kemenade in :gh:`148991`.) + + .. _whatsnew315-tomllib-1-1-0: tomllib @@ -1169,10 +1274,7 @@ tomllib Previously an inline table had to be on a single line and couldn't end with a trailing comma. This is now relaxed so that the following is valid: - .. syntax highlighting needs TOML 1.1.0 support in Pygments, - see https://github.com/pygments/pygments/issues/3026 - - .. code-block:: text + .. code-block:: toml tbl = { key = "a string", @@ -1184,7 +1286,7 @@ tomllib - Add ``\xHH`` notation to basic strings for codepoints under 255, and the ``\e`` escape for the escape character: - .. code-block:: text + .. code-block:: toml null = "null byte: \x00; letter a: \x61" csi = "\e[" @@ -1192,7 +1294,7 @@ tomllib - Seconds in datetime and time values are now optional. The following are now valid: - .. code-block:: text + .. code-block:: toml dt = 2010-02-03 14:15 t = 14:15 @@ -1244,6 +1346,18 @@ typing as it was incorrectly inferred in runtime before. (Contributed by Nikita Sobolev in :gh:`137191`.) +* :pep:`800`: Add :deco:`typing.disjoint_base`, a new decorator marking a class + as a disjoint base. This is an advanced feature primarily intended to allow + type checkers to faithfully reflect the runtime semantics of types defined + as builtins or in compiled extensions. If a class ``C`` is a disjoint base, then + child classes of that class cannot inherit from other disjoint bases that are + not parent or child classes of ``C``. (Contributed by Jelle Zijlstra in :gh:`148639`.) + +* :class:`~typing.TypeVarTuple` now accepts ``bound``, ``covariant``, + ``contravariant``, and ``infer_variance`` keyword arguments, matching the + interface of :class:`~typing.TypeVar` and :class:`~typing.ParamSpec`. + ``bound`` semantics remain undefined in the specification. + unicodedata ----------- @@ -1367,7 +1481,7 @@ Optimizations ============= * ``mimalloc`` is now used as the default allocator for - for raw memory allocations such as via :c:func:`PyMem_RawMalloc` + raw memory allocations such as via :c:func:`PyMem_RawMalloc` for better performance on :term:`free-threaded builds `. (Contributed by Kumar Aditya in :gh:`144914`.) @@ -1386,7 +1500,7 @@ base64 & binascii * Implementation for Base32 has been rewritten in C. Encoding and decoding is now two orders of magnitude faster. - (Contributed by James Seo in :gh:`146192`) + (Contributed by James Seo in :gh:`146192`.) csv @@ -1433,7 +1547,6 @@ end users running Python do not need LLVM installed. Instructions for installing LLVM can be found in the `JIT compiler documentation `__ for all supported platforms. - (Contributed by Savannah Ostrowski in :gh:`140973`.) .. rubric:: A new tracing frontend @@ -1445,7 +1558,6 @@ code. For example, simple Python object creation is now understood by the supported. This was made possible by an overhauled JIT tracing frontend that records actual execution paths through code, rather than estimating them as the previous implementation did. - (Contributed by Ken Jin in :gh:`139109`. Support for Windows added by Mark Shannon in :gh:`141703`.) @@ -1455,7 +1567,6 @@ A basic form of register allocation has been added to the JIT compiler's optimizer. This allows the JIT compiler to avoid certain stack operations altogether and instead operate on registers. This allows the JIT to produce more efficient traces by avoiding reads and writes to memory. - (Contributed by Mark Shannon in :gh:`135379`.) .. rubric:: More JIT optimizations @@ -1463,27 +1574,37 @@ more efficient traces by avoiding reads and writes to memory. More `constant-propagation `__ is now performed. This means when the JIT compiler detects that certain user code results in constants, the code can be simplified by the JIT. - (Contributed by Ken Jin and Savannah Ostrowski in :gh:`132732`.) -The JIT avoids :term:`reference count`\ s where possible. This generally +:term:`Reference count`\ s are avoided whenever it is safe to do so. This generally reduces the cost of most operations in Python. - (Contributed by Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, Reiden Ong, Noam Cohen, Tomas Roun, PuQing, Cajetan Rodrigues, and Sacul in :gh:`134584`.) +By tracking unique references to objects, the JIT optimizer can now eliminate +reference count updates and perform inplace operations on ints and floats. +(Contributed by Reiden Ong, and Pieter Eendebak in :gh:`143414` and :gh:`146306`.) + +The JIT optimizer now supports significantly more operations than in 3.14. +(Contributed by Kumar Aditya, Ken Jin, Jiahao Li, and Sacul in :gh:`131798`.) + .. rubric:: Better machine code generation The JIT compiler's machine code generator now produces better machine code for x86-64 and AArch64 macOS and Linux targets. In general, users should experience lower memory usage for generated machine code and more efficient -machine code versus the old JIT. - -(Contributed by Brandt Bucher in :gh:`136528` and :gh:`136528`. +machine code versus 3.14. +(Contributed by Brandt Bucher in :gh:`136528` and :gh:`135905`. Implementation for AArch64 contributed by Mark Shannon in :gh:`139855`. Additional optimizations for AArch64 contributed by Mark Shannon and Diego Russo in :gh:`140683` and :gh:`142305`.) +.. rubric:: Maintainability + +The JIT optimizer's operations have been simplified. +This was made possible by a refactoring of JIT data structures. +(Contributed by Zhongtian Zheng in :gh:`148211` and Hai Zhu in :gh:`143421`.) + Removed ======== @@ -1504,6 +1625,15 @@ ctypes (Contributed by Bénédikt Tran in :gh:`133866`.) +datetime +-------- + +* :meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the + format string contains ``%d`` (day of month) without a year directive. + This has been deprecated since Python 3.13. + (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`70647`.) + + glob ---- @@ -1546,16 +1676,6 @@ platform (Contributed by Alexey Makridenko in :gh:`133604`.) -pprint ------- - -* Add an *expand* keyword argument for :func:`pprint.pprint`, - :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be - formatted similar to pretty-printed :func:`json.dumps` when - *indent* is supplied. - (Contributed by Stefan Todoran and Semyon Moroz in :gh:`112632`.) - - sre_* ----- @@ -1579,6 +1699,14 @@ threading (Contributed by Bénédikt Tran in :gh:`134087`.) +types +----- + +* Removed deprecated in :pep:`626` since Python 3.12 + :attr:`!codeobject.co_lnotab` from :class:`types.CodeType`. + (Contributed by Nikita Sobolev in :gh:`134690`.) + + typing ------ @@ -1598,6 +1726,9 @@ typing or ``TD = TypedDict("TD", {})`` instead. (Contributed by Bénédikt Tran in :gh:`133823`.) +* Deprecated :func:`!typing.no_type_check_decorator` has been removed. + (Contributed by Nikita Sobolev in :gh:`133601`.) + wave ---- @@ -1670,6 +1801,27 @@ New deprecations (Contributed by Bénédikt Tran in :gh:`134978`.) + +* :mod:`re`: + + * :func:`re.match` and :meth:`re.Pattern.match` are now + :term:`soft deprecated` in favor of the new :func:`re.prefixmatch` and + :meth:`re.Pattern.prefixmatch` APIs, which have been added as alternate, + more explicit names. These are intended to be used to alleviate confusion + around what *match* means by following the Zen of Python's *"Explicit is + better than implicit"* mantra. Most other language regular expression + libraries use an API named *match* to mean what Python has always called + *search*. + + We **do not** plan to remove the older :func:`!match` name, as it has been + used in code for over 30 years. Code supporting older versions of Python + should continue to use :func:`!match`, while new code should prefer + :func:`!prefixmatch`. See :ref:`prefixmatch-vs-match`. + + (Contributed by Gregory P. Smith in :gh:`86519` and + Hugo van Kemenade in :gh:`148100`.) + + * :mod:`struct`: * Calling the ``Struct.__new__()`` without required argument now is @@ -1692,8 +1844,6 @@ New deprecations :func:`issubclass`, but warnings were not previously emitted if it was merely imported or accessed from the :mod:`!typing` module. - * Deprecated :func:`!typing.no_type_check_decorator` has been removed. - (Contributed by Nikita Sobolev in :gh:`133601`.) * ``__version__`` @@ -1742,6 +1892,8 @@ New deprecations .. include:: ../deprecations/pending-removal-in-future.rst +.. include:: ../deprecations/soft-deprecations.rst + C API changes ============= @@ -1978,8 +2130,8 @@ Deprecated C APIs - :c:macro:`Py_ALIGNED`: Prefer ``alignas`` instead. - :c:macro:`PY_FORMAT_SIZE_T`: Use ``"z"`` directly. - - :c:macro:`Py_LL` & :c:macro:`Py_ULL`: - Use standard suffixes, ``LL`` & ``ULL``. + - :c:macro:`Py_LL` and :c:macro:`Py_ULL`: + Use standard suffixes, ``LL`` and ``ULL``. - :c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, :c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, :c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`: diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 9eafc09dbee..bdd35d39e36 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -2173,7 +2173,7 @@ Changes in the Python API * :c:func:`PyErr_SetImportError` now sets :exc:`TypeError` when its **msg** argument is not set. Previously only ``NULL`` was returned. -* The format of the :attr:`~codeobject.co_lnotab` attribute of code objects +* The format of the :attr:`!codeobject.co_lnotab` attribute of code objects changed to support a negative line number delta. By default, Python does not emit bytecode with a negative line number delta. Functions using :attr:`frame.f_lineno`, diff --git a/Grammar/python.gram b/Grammar/python.gram index 3a91d426c36..9bf3a67939f 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -554,10 +554,12 @@ complex_number[expr_ty]: signed_number[expr_ty]: | NUMBER + | '+' number=NUMBER { number } | '-' number=NUMBER { _PyAST_UnaryOp(USub, number, EXTRA) } signed_real_number[expr_ty]: | real_number + | '+' real=real_number { real } | '-' real=real_number { _PyAST_UnaryOp(USub, real, EXTRA) } real_number[expr_ty]: @@ -565,6 +567,7 @@ real_number[expr_ty]: imaginary_number[expr_ty]: | imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } + | '+' imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } capture_pattern[pattern_ty]: | target=pattern_capture_target { _PyAST_MatchAs(NULL, target->v.Name.id, EXTRA) } diff --git a/Include/Python.h b/Include/Python.h index e6e5cab67e2..8b76195b320 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -9,10 +9,11 @@ // is not needed. -// Include Python header files -#include "patchlevel.h" -#include "pyconfig.h" -#include "pymacconfig.h" +// Include Python configuration headers +#include "patchlevel.h" // the Python version +#include "pyconfig.h" // information from configure +#include "pymacconfig.h" // overrides for pyconfig +#include "pyabi.h" // feature/ABI selection // Include standard header files @@ -46,13 +47,11 @@ # endif #endif -#if defined(Py_GIL_DISABLED) -# if defined(_MSC_VER) -# include // __readgsqword() -# endif - -# if defined(__MINGW32__) -# include // __readgsqword() +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) +# if defined(_MSC_VER) || defined(__MINGW32__) +# include // __readgsqword() +# endif # endif #endif // Py_GIL_DISABLED @@ -67,6 +66,7 @@ __pragma(warning(disable: 4201)) // Include Python header files #include "pyport.h" +#include "exports.h" #include "pymacro.h" #include "pymath.h" #include "pymem.h" diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 5094c8c23ae..c93271f6ca9 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -24,9 +24,10 @@ extern "C" { #define PY_MONITORING_EVENT_STOP_ITERATION 10 #define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ - ((ev) < _PY_MONITORING_LOCAL_EVENTS) +((ev) <= PY_MONITORING_EVENT_STOP_ITERATION) -/* Other events, mainly exceptions */ +/* Other events, mainly exceptions. + * These can now be turned on and disabled on a per code object basis. */ #define PY_MONITORING_EVENT_RAISE 11 #define PY_MONITORING_EVENT_EXCEPTION_HANDLED 12 @@ -34,6 +35,9 @@ extern "C" { #define PY_MONITORING_EVENT_PY_THROW 14 #define PY_MONITORING_EVENT_RERAISE 15 +#define _PY_MONITORING_IS_UNGROUPED_EVENT(ev) \ +((ev) < _PY_MONITORING_UNGROUPED_EVENTS) + /* Ancillary events */ diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 80d30c7765f..0b50d2a9dd8 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -230,6 +230,8 @@ struct _typeobject { destructor tp_finalize; vectorcallfunc tp_vectorcall; + /* Below here all fields are internal to the VM */ + /* bitset of which type-watchers care about this type */ unsigned char tp_watched; @@ -239,6 +241,7 @@ struct _typeobject { * Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere). */ uint16_t tp_versions_used; + _Py_iteritemfunc _tp_iteritem; /* Virtual iterator next function */ }; #define _Py_ATTR_CACHE_UNUSED (30000) // (see tp_versions_used) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 1c56ad5af80..0cb57679df3 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -319,3 +319,8 @@ PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc( PyInterpreterState *interp, _PyFrameEvalFunction eval_frame); +PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameAllowSpecialization( + PyInterpreterState *interp, + int allow_specialization); +PyAPI_FUNC(int) _PyInterpreterState_IsSpecializationEnabled( + PyInterpreterState *interp); diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h index e473110eca7..5d1f44988a6 100644 --- a/Include/cpython/pystats.h +++ b/Include/cpython/pystats.h @@ -144,6 +144,7 @@ typedef struct _optimization_stats { uint64_t unknown_callee; uint64_t trace_immediately_deopts; uint64_t executors_invalidated; + uint64_t fitness_terminated_traces; UOpStats opcode[PYSTATS_MAX_UOP_ID + 1]; uint64_t unsupported_opcode[256]; uint64_t trace_length_hist[_Py_UOP_HIST_SIZE]; diff --git a/Include/exports.h b/Include/exports.h index 97a674ec240..a863ecb3307 100644 --- a/Include/exports.h +++ b/Include/exports.h @@ -36,7 +36,7 @@ #define Py_LOCAL_SYMBOL #endif /* module init functions outside the core must be exported */ - #if defined(Py_BUILD_CORE) + #if defined(_PyEXPORTS_CORE) #define _PyINIT_EXPORTED_SYMBOL Py_EXPORTED_SYMBOL #else #define _PyINIT_EXPORTED_SYMBOL __declspec(dllexport) @@ -64,13 +64,13 @@ /* only get special linkage if built as shared or platform is Cygwin */ #if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__) # if defined(HAVE_DECLSPEC_DLL) -# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# if defined(_PyEXPORTS_CORE) && !defined(_PyEXPORTS_CORE_MODULE) /* module init functions inside the core need no external linkage */ /* except for Cygwin to handle embedding */ # if !defined(__CYGWIN__) # define _PyINIT_FUNC_DECLSPEC # endif /* __CYGWIN__ */ -# else /* Py_BUILD_CORE */ +# else /* _PyEXPORTS_CORE */ /* Building an extension module, or an embedded situation */ /* public Python functions and data are imported */ /* Under Cygwin, auto-import functions to prevent compilation */ @@ -80,7 +80,7 @@ # define PyAPI_FUNC(RTYPE) Py_IMPORTED_SYMBOL RTYPE # endif /* !__CYGWIN__ */ # define PyAPI_DATA(RTYPE) extern Py_IMPORTED_SYMBOL RTYPE -# endif /* Py_BUILD_CORE */ +# endif /* _PyEXPORTS_CORE */ # endif /* HAVE_DECLSPEC_DLL */ #endif /* Py_ENABLE_SHARED */ diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index 30809e09700..b9eb4fd9891 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -16,10 +16,11 @@ _PyIndex_Check(PyObject *obj) return (tp_as_number != NULL && tp_as_number->nb_index != NULL); } -PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); -PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); +PyAPI_FUNC(PyObject *) _PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); -extern int _PyObject_HasLen(PyObject *o); +PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); /* === Sequence protocol ================================================ */ diff --git a/Include/internal/pycore_blocks_output_buffer.h b/Include/internal/pycore_blocks_output_buffer.h index 016e7a18665..322c1e93344 100644 --- a/Include/internal/pycore_blocks_output_buffer.h +++ b/Include/internal/pycore_blocks_output_buffer.h @@ -242,9 +242,12 @@ static inline PyObject * _BlocksOutputBuffer_Finish(_BlocksOutputBuffer *buffer, const Py_ssize_t avail_out) { + PyObject *obj; assert(buffer->writer != NULL); - return PyBytesWriter_FinishWithSize(buffer->writer, - buffer->allocated - avail_out); + obj = PyBytesWriter_FinishWithSize(buffer->writer, + buffer->allocated - avail_out); + buffer->writer = NULL; + return obj; } /* Clean up the buffer when an error occurred. */ diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h index 8e8fa696ee0..177e6d10134 100644 --- a/Include/internal/pycore_bytesobject.h +++ b/Include/internal/pycore_bytesobject.h @@ -14,6 +14,11 @@ extern PyObject* _PyBytes_FormatEx( PyObject *args, int use_bytearray); +/* Concatenate two bytes objects. Used as the sq_concat slot and by the + * specializing interpreter. Unlike PyBytes_Concat(), this returns a new + * reference rather than modifying its first argument in place. */ +extern PyObject* _PyBytes_Concat(PyObject *a, PyObject *b); + extern PyObject* _PyBytes_FromHex( PyObject *string, int use_bytearray); diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h index e544b4cf49d..a9db8860e91 100644 --- a/Include/internal/pycore_call.h +++ b/Include/internal/pycore_call.h @@ -166,7 +166,8 @@ _PyStack_UnpackDict(PyThreadState *tstate, PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, PyObject **p_kwnames); -extern void _PyStack_UnpackDict_Free( +// Exported for external JIT support +PyAPI_FUNC(void) _PyStack_UnpackDict_Free( PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index c12f72216b3..f9507fda160 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -121,18 +121,11 @@ _PyEval_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwfl } #ifdef _Py_TIER2 -#ifdef _Py_JIT -_Py_CODEUNIT *_Py_LazyJitShim( - struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame, - _PyStackRef *stack_pointer, PyThreadState *tstate -); -#else _Py_CODEUNIT *_PyTier2Interpreter( struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate ); #endif -#endif extern _PyJitEntryFuncPtr _Py_jit_entry; @@ -320,7 +313,7 @@ PyObject * _PyEval_ImportNameWithImport( PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys); PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate); +PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate, _PyInterpreterFrame *frame); PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp); PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch); @@ -439,13 +432,13 @@ _Py_BuiltinCallFast_StackRef( int total_args); PyAPI_FUNC(PyObject *) -_Py_BuiltinCallFastWithKeywords_StackRefSteal( +_Py_BuiltinCallFastWithKeywords_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args); PyAPI_FUNC(PyObject *) -_PyCallMethodDescriptorFast_StackRefSteal( +_PyCallMethodDescriptorFast_StackRef( _PyStackRef callable, PyCFunctionFast cfunc, PyObject *self, @@ -453,7 +446,7 @@ _PyCallMethodDescriptorFast_StackRefSteal( int total_args); PyAPI_FUNC(PyObject *) -_PyCallMethodDescriptorFastWithKeywords_StackRefSteal( +_PyCallMethodDescriptorFastWithKeywords_StackRef( _PyStackRef callable, PyCFunctionFastWithKeywords cfunc, PyObject *self, @@ -461,7 +454,7 @@ _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( int total_args); PyAPI_FUNC(PyObject *) -_Py_CallBuiltinClass_StackRefSteal( +_Py_CallBuiltinClass_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args); diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index fe8d0a54f2a..4584f1bde79 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -141,6 +141,12 @@ typedef struct { #define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache) +typedef struct { + _Py_BackoffCounter counter; +} _PyGetIterCache; + +#define INLINE_CACHE_ENTRIES_GET_ITER CACHE_ENTRIES(_PyGetIterCache) + typedef struct { _Py_BackoffCounter counter; } _PySendCache; @@ -324,6 +330,7 @@ PyAPI_FUNC(void) _Py_Specialize_ContainsOp(_PyStackRef value, _Py_CODEUNIT *inst PyAPI_FUNC(void) _Py_GatherStats_GetIter(_PyStackRef iterable); PyAPI_FUNC(void) _Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame); +PyAPI_FUNC(void) _Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr); // Utility functions for reading/writing 32/64-bit values in the inline caches. // Great care should be taken to ensure that these functions remain correct and @@ -503,6 +510,11 @@ typedef struct { aliased to either operand). Used by the tier 2 optimizer to enable inplace follow-up ops. */ int result_unique; + /* Expected types of the left and right operands. Used by the tier 2 + optimizer to eliminate _GUARD_BINARY_OP_EXTEND when the operand + types are already known. NULL means unknown/don't eliminate. */ + PyTypeObject *lhs_type; + PyTypeObject *rhs_type; } _PyBinaryOpSpecializationDescr; /* Comparison bit masks. */ diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index d58539fa846..6c6e3b77e69 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -31,7 +31,8 @@ PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, Py_hash_t hash); -extern int _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key, +// Exported for external JIT support +PyAPI_FUNC(int) _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key, Py_hash_t hash); extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t); @@ -87,9 +88,15 @@ typedef struct { extern PyDictKeysObject *_PyDict_NewKeysForClass(PyHeapTypeObject *); extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); +/* Implementations of the `|` and `|=` operators for dict, used by the + * specializing interpreter. */ +extern PyObject *_PyDict_Or(PyObject *self, PyObject *other); +extern PyObject *_PyDict_IOr(PyObject *self, PyObject *other); + /* Gets a version number unique to the current state of the keys of dict, if possible. - * Returns the version number, or zero if it was not possible to get a version number. */ -extern uint32_t _PyDictKeys_GetVersionForCurrentState( + * Returns the version number, or zero if it was not possible to get a version number. + * Exported for external JIT support */ +PyAPI_FUNC(uint32_t) _PyDictKeys_GetVersionForCurrentState( PyInterpreterState *interp, PyDictKeysObject *dictkeys); /* Gets a version number unique to the current state of the keys of dict, if possible. @@ -99,8 +106,9 @@ extern uint32_t _PyDictKeys_GetVersionForCurrentState( * * The caller must hold the per-object lock on dict. * - * Returns the version number, or zero if it was not possible to get a version number. */ -extern uint32_t _PyDict_GetKeysVersionForCurrentState( + * Returns the version number, or zero if it was not possible to get a version number. + * Exported for external JIT support */ +PyAPI_FUNC(uint32_t) _PyDict_GetKeysVersionForCurrentState( PyInterpreterState *interp, PyDictObject *dict); extern size_t _PyDict_KeysSize(PyDictKeysObject *keys); @@ -109,16 +117,18 @@ extern void _PyDictKeys_DecRef(PyDictKeysObject *keys); /* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index]. * -1 when no entry found, -3 when compare raises error. + * Exported for external JIT support */ -extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); +PyAPI_FUNC(Py_ssize_t) _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); extern Py_ssize_t _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr); extern int _PyDict_GetMethodStackRef(PyDictObject *dict, PyObject *name, _PyStackRef *method); -extern Py_ssize_t _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **); -extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *); -extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); +// Exported for external JIT support +PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **); +PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndex(PyDictObject *, PyObject *); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); /* Look up a string key in an all unicode dict keys, assign the keys object a version, and * store it in version. @@ -127,9 +137,11 @@ extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject * strings. * * Returns DKIX_EMPTY if the key is not present. + * + * Exported for external JIT support */ -extern Py_ssize_t _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version); -extern Py_ssize_t _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version); +PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key); PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *); @@ -139,7 +151,8 @@ extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals); /* Consumes references to key and value */ PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); PyAPI_FUNC(int) _PyDict_SetItem_Take2_KnownHash(PyDictObject *op, PyObject *key, PyObject *value, Py_hash_t hash); -extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); +// Exported for external JIT support +PyAPI_FUNC(int) _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash); @@ -292,7 +305,7 @@ _PyDict_NotifyEvent(PyDict_WatchEvent event, PyObject *value) { assert(Py_REFCNT((PyObject*)mp) > 0); - int watcher_bits = mp->_ma_watcher_tag & DICT_WATCHER_MASK; + int watcher_bits = FT_ATOMIC_LOAD_UINT64_ACQUIRE(mp->_ma_watcher_tag) & DICT_WATCHER_MASK; if (watcher_bits) { RARE_EVENT_STAT_INC(watched_dict_modification); _PyDict_SendEvent(watcher_bits, event, mp, key, value); @@ -324,6 +337,10 @@ _PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix) values->size = size+1; } +// Exported for external JIT support +PyAPI_FUNC(void) +_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix); + static inline size_t shared_keys_usable_size(PyDictKeysObject *keys) { @@ -368,7 +385,7 @@ PyDictObject *_PyObject_MaterializeManagedDict_LockHeld(PyObject *); static inline Py_ssize_t _PyDict_UniqueId(PyDictObject *mp) { - return (Py_ssize_t)(mp->_ma_watcher_tag >> DICT_UNIQUE_ID_SHIFT); + return (Py_ssize_t)(FT_ATOMIC_LOAD_UINT64_RELAXED(mp->_ma_watcher_tag) >> DICT_UNIQUE_ID_SHIFT); } static inline void diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 5e73ae3c854..3c9ab99c34e 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -38,7 +38,8 @@ struct _frame { PyObject *_f_frame_data[1]; }; -extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); +// Exported for external JIT support +PyAPI_FUNC(PyFrameObject *) _PyFrame_New_NoTrack(PyCodeObject *code); /* other API */ diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index 99dacaf0fe7..2184f40956d 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -27,7 +27,8 @@ _PyFunction_IsVersionValid(uint32_t version) return version >= FUNC_VERSION_FIRST_VALID; } -extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); +// Exported for external JIT support +PyAPI_FUNC(uint32_t) _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); PyAPI_FUNC(void) _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version); void _PyFunction_ClearCodeByVersion(uint32_t version); diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h index a3badb59cb7..2c264c39ae9 100644 --- a/Include/internal/pycore_genobject.h +++ b/Include/internal/pycore_genobject.h @@ -33,6 +33,9 @@ PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); PyAPI_FUNC(PyObject *)_PyCoro_GetAwaitableIter(PyObject *o); PyAPI_FUNC(PyObject *)_PyAsyncGenValueWrapperNew(PyThreadState *state, PyObject *); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyCoro_ComputeOrigin(int origin_depth, _PyInterpreterFrame *current_frame); + extern PyTypeObject _PyCoroWrapper_Type; extern PyTypeObject _PyAsyncGenWrappedValue_Type; extern PyTypeObject _PyAsyncGenAThrow_Type; diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index beae65213a2..4fd42185d8a 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1636,6 +1636,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cancel)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(canonical)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capath)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capitals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(category)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index bb1c6dbaf03..f2d43c22069 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -359,6 +359,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(callable) STRUCT_FOR_ID(callback) STRUCT_FOR_ID(cancel) + STRUCT_FOR_ID(canonical) STRUCT_FOR_ID(capath) STRUCT_FOR_ID(capitals) STRUCT_FOR_ID(category) diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 1da8237e93f..56b55e93a01 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -70,16 +70,15 @@ PyAPI_DATA(PyObject) _PyInstrumentation_DISABLE; /* Total tool ids available */ #define PY_MONITORING_TOOL_IDS 8 -/* Count of all local monitoring events */ -#define _PY_MONITORING_LOCAL_EVENTS 11 -/* Count of all "real" monitoring events (not derived from other events) */ +/* Count of all "real" monitoring events (not derived from other events). + * "Other" events can now be turned on/disabled per code object. */ #define _PY_MONITORING_UNGROUPED_EVENTS 16 /* Count of all monitoring events */ #define _PY_MONITORING_EVENTS 19 /* Tables of which tools are active for each monitored event. */ typedef struct _Py_LocalMonitors { - uint8_t tools[_PY_MONITORING_LOCAL_EVENTS]; + uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS]; } _Py_LocalMonitors; typedef struct _Py_GlobalMonitors { @@ -122,6 +121,15 @@ typedef struct _PyCoMonitoringData { extern int _Py_Instrumentation_GetLine(PyCodeObject *code, _PyCoLineInstrumentationData *line_data, int index); +static inline uint8_t +_PyCode_GetOriginalOpcode(_PyCoLineInstrumentationData *line_data, int index) +{ + return line_data->data[index*line_data->bytes_per_entry]; +} + +// Exported for external JIT support +PyAPI_FUNC(uint8_t) _PyCode_Deinstrument(uint8_t opcode); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index c4b08464266..01adadd1485 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -449,6 +449,9 @@ typedef struct _PyOptimizationConfig { uint16_t side_exit_initial_value; uint16_t side_exit_initial_backoff; + // Trace fitness thresholds + uint16_t fitness_initial; + // Optimization flags bool specialization_enabled; bool uops_optimize_enabled; @@ -927,6 +930,7 @@ struct _is { PyObject *builtins_copy; // Initialized to _PyEval_EvalFrameDefault(). _PyFrameEvalFunction eval_frame; + int eval_frame_allow_specialization; PyFunction_WatchCallback func_watchers[FUNC_MAX_WATCHERS]; // One bit is set for each non-NULL entry in func_watchers diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index d744dd12cd0..28370ababc4 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -302,7 +302,8 @@ _PyFrame_GetFrameObject(_PyInterpreterFrame *frame) return _PyFrame_MakeAndSetFrameObject(frame); } -void +// Exported for external JIT support +PyAPI_FUNC(void) _PyFrame_ClearLocals(_PyInterpreterFrame *frame); /* Clears all references in the frame. @@ -313,8 +314,10 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame); * in the frame. * take should be set to 1 for heap allocated * frames like the ones in generators and coroutines. + * + * Exported for external JIT support */ -void + PyAPI_FUNC(void) _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame); int @@ -338,7 +341,8 @@ _PyThreadState_HasStackSpace(PyThreadState *tstate, int size) size < tstate->datastack_limit - tstate->datastack_top; } -extern _PyInterpreterFrame * +// Exported for external JIT support +PyAPI_FUNC(_PyInterpreterFrame *) _PyThreadState_PushFrame(PyThreadState *tstate, size_t size); PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame); diff --git a/Include/internal/pycore_jit.h b/Include/internal/pycore_jit.h index 70bccce4166..b3cadcce824 100644 --- a/Include/internal/pycore_jit.h +++ b/Include/internal/pycore_jit.h @@ -23,9 +23,13 @@ typedef _Py_CODEUNIT *(*jit_func)( _PyStackRef _tos_cache0, _PyStackRef _tos_cache1, _PyStackRef _tos_cache2 ); +_Py_CODEUNIT *_PyJIT( + _PyExecutorObject *executor, _PyInterpreterFrame *frame, + _PyStackRef *stack_pointer, PyThreadState *tstate +); + int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length); void _PyJIT_Free(_PyExecutorObject *executor); -void _PyJIT_Fini(void); PyAPI_FUNC(int) _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr); #endif // _Py_JIT diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index 6b92dc5d111..df0d00f7525 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -15,6 +15,7 @@ extern "C" { PyAPI_FUNC(PyObject*) _PyList_Extend(PyListObject *, PyObject *); PyAPI_FUNC(PyObject) *_PyList_SliceSubscript(PyObject*, PyObject*); PyAPI_FUNC(PyObject *) _PyList_BinarySlice(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyList_Concat(PyObject *, PyObject *); extern void _PyList_DebugMallocStats(FILE *out); // _PyList_GetItemRef should be used only when the object is known as a list // because it doesn't raise TypeError when the object is not a list, whereas PyList_GetItemRef does. diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 9d36165c8a8..fd918e13f2d 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -294,6 +294,8 @@ Known values: Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes) Python 3.15a8 3662 (Add counter to RESUME) Python 3.15a8 3663 (Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER) + Python 3.15a8 3664 (Fix __qualname__ for __annotate__ functions) + Python 3.15a8 3665 (Add FOR_ITER_VIRTUAL and GET_ITER specializations) Python 3.16 will start with 3700 @@ -307,7 +309,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3663 +#define PYC_MAGIC_NUMBER 3665 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index de701ced675..c2c508c1a71 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -879,14 +879,16 @@ PyAPI_FUNC(PyObject *) _PyType_NewManagedObject(PyTypeObject *type); extern PyTypeObject* _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *); extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *, int); -extern int _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name); +// Exported for external JIT support +PyAPI_FUNC(int) _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name); void _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp); extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value); extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr); -extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *, +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyType_LookupRefAndVersion(PyTypeObject *, PyObject *, unsigned int *); // Internal API to look for a name through the MRO. @@ -910,7 +912,9 @@ PyAPI_FUNC(_PyStackRef) _PyObject_GetAttrStackRef(PyObject *obj, PyObject *name) // deferred reference counting. // // Returns 1 if the value was cached or 0 otherwise. -extern int _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, +// +// Exported for external JIT support +PyAPI_FUNC(int) _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, PyObject *init, unsigned int tp_version); diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 5b50b58fc83..230335ead3a 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -220,6 +220,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 2; case FOR_ITER_TUPLE: return 2; + case FOR_ITER_VIRTUAL: + return 2; case GET_AITER: return 1; case GET_ANEXT: @@ -228,6 +230,10 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case GET_ITER: return 1; + case GET_ITER_SELF: + return 1; + case GET_ITER_VIRTUAL: + return 1; case GET_LEN: return 1; case IMPORT_FROM: @@ -711,6 +717,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 3; case FOR_ITER_TUPLE: return 3; + case FOR_ITER_VIRTUAL: + return 3; case GET_AITER: return 1; case GET_ANEXT: @@ -719,6 +727,10 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1; case GET_ITER: return 2; + case GET_ITER_SELF: + return 2; + case GET_ITER_VIRTUAL: + return 2; case GET_LEN: return 2; case IMPORT_FROM: @@ -800,7 +812,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_CLASS_WITH_METACLASS_CHECK: return 1 + (oparg & 1); case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return 1; + return 0; case LOAD_ATTR_INSTANCE_VALUE: return 1 + (oparg & 1); case LOAD_ATTR_METHOD_LAZY_DICT: @@ -1092,7 +1104,7 @@ struct opcode_metadata { PyAPI_DATA(const struct opcode_metadata) _PyOpcode_opcode_metadata[267]; #ifdef NEED_OPCODE_METADATA 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] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_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 | HAS_ERROR_NO_POP_FLAG }, @@ -1123,9 +1135,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_EX_NON_PY_GENERAL] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_EX_PY] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, @@ -1134,13 +1146,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_ISINSTANCE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_KW_BOUND_METHOD] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [CALL_KW_BOUND_METHOD] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_KW_NON_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_KW_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [CALL_KW_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_LEN] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_NON_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, @@ -1183,10 +1195,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, + [FOR_ITER_VIRTUAL] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [GET_ITER] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [GET_ITER_SELF] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [GET_ITER_VIRTUAL] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, [GET_LEN] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1223,7 +1238,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, @@ -1252,7 +1267,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SMALL_INT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, - [LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, @@ -1289,7 +1304,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG }, @@ -1345,7 +1360,7 @@ extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256]; #ifdef NEED_OPCODE_METADATA const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] = { - [BINARY_OP] = { .nuops = 3, .uops = { { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, + [BINARY_OP] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _RECORD_NOS_TYPE, OPARG_SIMPLE, 0 }, { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, 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 = 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 } } }, @@ -1371,25 +1386,25 @@ _PyOpcode_macro_expansion[256] = { [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, OPARG_SIMPLE, 0 } } }, [BUILD_TEMPLATE] = { .nuops = 1, .uops = { { _BUILD_TEMPLATE, OPARG_SIMPLE, 0 } } }, [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, OPARG_SIMPLE, 0 } } }, - [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 5, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_AND_ALLOCATE_OBJECT, 2, 1 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_OBJECT, 2, 1 }, { _ALLOCATE_OBJECT, OPARG_SIMPLE, 3 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 11, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_GENERAL] = { .nuops = 8, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _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_BUILTIN_CLASS] = { .nuops = 3, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_CLASS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_BUILTIN_FAST] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_BUILTIN_O] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_O, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_BUILTIN_O] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_O, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_EX_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CALL_FUNCTION_EX_NON_PY_GENERAL, OPARG_SIMPLE, 1 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 1 } } }, [CALL_EX_PY] = { .nuops = 7, .uops = { { _RECORD_4OS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CHECK_IS_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _PY_FRAME_EX, OPARG_SIMPLE, 1 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, [CALL_INTRINSIC_1] = { .nuops = 2, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [CALL_INTRINSIC_2] = { .nuops = 3, .uops = { { _CALL_INTRINSIC_2, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [CALL_ISINSTANCE] = { .nuops = 3, .uops = { { _GUARD_THIRD_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_ISINSTANCE, OPARG_SIMPLE, 3 }, { _CALL_ISINSTANCE, OPARG_SIMPLE, 3 } } }, - [CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_KW_BOUND_METHOD] = { .nuops = 7, .uops = { { _RECORD_CALLABLE_KW, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_KW_PY] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_KW_PY] = { .nuops = 7, .uops = { { _RECORD_CALLABLE_KW, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_LEN] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, [CALL_LIST_APPEND] = { .nuops = 6, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 3, .uops = { { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 5, .uops = { { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 8, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, @@ -1428,10 +1443,13 @@ _PyOpcode_macro_expansion[256] = { [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, OPARG_SIMPLE, 1 }, { _ITER_JUMP_LIST, OPARG_REPLACED, 1 }, { _ITER_NEXT_LIST, OPARG_REPLACED, 1 } } }, [FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_RANGE, OPARG_REPLACED, 1 }, { _ITER_NEXT_RANGE, OPARG_SIMPLE, 1 } } }, [FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_TUPLE, OPARG_REPLACED, 1 }, { _ITER_NEXT_TUPLE, OPARG_SIMPLE, 1 } } }, + [FOR_ITER_VIRTUAL] = { .nuops = 2, .uops = { { _GUARD_NOS_ITER_VIRTUAL, OPARG_SIMPLE, 1 }, { _FOR_ITER_VIRTUAL, OPARG_REPLACED, 1 } } }, [GET_AITER] = { .nuops = 1, .uops = { { _GET_AITER, OPARG_SIMPLE, 0 } } }, [GET_ANEXT] = { .nuops = 1, .uops = { { _GET_ANEXT, OPARG_SIMPLE, 0 } } }, [GET_AWAITABLE] = { .nuops = 1, .uops = { { _GET_AWAITABLE, OPARG_SIMPLE, 0 } } }, - [GET_ITER] = { .nuops = 1, .uops = { { _GET_ITER, OPARG_SIMPLE, 0 } } }, + [GET_ITER] = { .nuops = 2, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GET_ITER, OPARG_SIMPLE, 0 } } }, + [GET_ITER_SELF] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GUARD_ITERATOR, OPARG_SIMPLE, 1 }, { _PUSH_NULL, OPARG_SIMPLE, 1 } } }, + [GET_ITER_VIRTUAL] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _GUARD_ITER_VIRTUAL, OPARG_SIMPLE, 1 }, { _PUSH_TAGGED_ZERO, OPARG_SIMPLE, 1 } } }, [GET_LEN] = { .nuops = 1, .uops = { { _GET_LEN, OPARG_SIMPLE, 0 } } }, [IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } }, [IMPORT_NAME] = { .nuops = 1, .uops = { { _IMPORT_NAME, OPARG_SIMPLE, 0 } } }, @@ -1444,6 +1462,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR] = { .nuops = 1, .uops = { { _LOAD_ATTR, OPARG_SIMPLE, 8 } } }, [LOAD_ATTR_CLASS] = { .nuops = 3, .uops = { { _CHECK_ATTR_CLASS, 2, 1 }, { _LOAD_ATTR_CLASS, 4, 5 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_CLASS, 2, 3 }, { _LOAD_ATTR_CLASS, 4, 5 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, 2, 3 }, { _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 1, 3 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } }, [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } }, @@ -1451,7 +1470,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR_MODULE] = { .nuops = 4, .uops = { { _LOAD_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, OPERAND1_1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } }, [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _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 = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_PROPERTY] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 2, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_SLOT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_WITH_HINT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _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 } } }, @@ -1471,7 +1490,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, OPARG_SIMPLE, 0 } } }, [LOAD_NAME] = { .nuops = 1, .uops = { { _LOAD_NAME, OPARG_SIMPLE, 0 } } }, [LOAD_SMALL_INT] = { .nuops = 1, .uops = { { _LOAD_SMALL_INT, OPARG_SIMPLE, 0 } } }, - [LOAD_SPECIAL] = { .nuops = 2, .uops = { { _INSERT_NULL, OPARG_SIMPLE, 0 }, { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } }, + [LOAD_SPECIAL] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _INSERT_NULL, OPARG_SIMPLE, 0 }, { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } }, [LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, OPARG_SIMPLE, 1 } } }, [LOAD_SUPER_ATTR_METHOD] = { .nuops = 3, .uops = { { _RECORD_NOS, OPARG_SIMPLE, 0 }, { _GUARD_LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 }, { _LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 } } }, [MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, OPARG_SIMPLE, 0 } } }, @@ -1501,7 +1520,7 @@ _PyOpcode_macro_expansion[256] = { [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { _SET_FUNCTION_ATTRIBUTE, OPARG_SIMPLE, 0 } } }, [SET_UPDATE] = { .nuops = 2, .uops = { { _SET_UPDATE, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, OPARG_SIMPLE, 3 } } }, - [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 5, .uops = { { _LOCK_OBJECT, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION_LOCKED, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, + [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _LOCK_OBJECT, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION_LOCKED, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_SLOT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_WITH_HINT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_DEREF] = { .nuops = 1, .uops = { { _STORE_DEREF, OPARG_SIMPLE, 0 } } }, @@ -1630,10 +1649,13 @@ const char *_PyOpcode_OpName[267] = { [FOR_ITER_LIST] = "FOR_ITER_LIST", [FOR_ITER_RANGE] = "FOR_ITER_RANGE", [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE", + [FOR_ITER_VIRTUAL] = "FOR_ITER_VIRTUAL", [GET_AITER] = "GET_AITER", [GET_ANEXT] = "GET_ANEXT", [GET_AWAITABLE] = "GET_AWAITABLE", [GET_ITER] = "GET_ITER", + [GET_ITER_SELF] = "GET_ITER_SELF", + [GET_ITER_VIRTUAL] = "GET_ITER_VIRTUAL", [GET_LEN] = "GET_LEN", [IMPORT_FROM] = "IMPORT_FROM", [IMPORT_NAME] = "IMPORT_NAME", @@ -1800,6 +1822,7 @@ const uint8_t _PyOpcode_Caches[256] = { [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_NONE] = 1, [POP_JUMP_IF_NOT_NONE] = 1, + [GET_ITER] = 1, [FOR_ITER] = 1, [CALL] = 3, [CALL_KW] = 3, @@ -1819,9 +1842,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [125] = 125, [126] = 126, [127] = 127, - [214] = 214, - [215] = 215, - [216] = 216, [217] = 217, [218] = 218, [219] = 219, @@ -1929,10 +1949,13 @@ const uint8_t _PyOpcode_Deopt[256] = { [FOR_ITER_LIST] = FOR_ITER, [FOR_ITER_RANGE] = FOR_ITER, [FOR_ITER_TUPLE] = FOR_ITER, + [FOR_ITER_VIRTUAL] = FOR_ITER, [GET_AITER] = GET_AITER, [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, [GET_ITER] = GET_ITER, + [GET_ITER_SELF] = GET_ITER, + [GET_ITER_VIRTUAL] = GET_ITER, [GET_LEN] = GET_LEN, [IMPORT_FROM] = IMPORT_FROM, [IMPORT_NAME] = IMPORT_NAME, @@ -2080,9 +2103,6 @@ const uint8_t _PyOpcode_Deopt[256] = { case 125: \ case 126: \ case 127: \ - case 214: \ - case 215: \ - case 216: \ case 217: \ case 218: \ case 219: \ diff --git a/Include/internal/pycore_opcode_utils.h b/Include/internal/pycore_opcode_utils.h index 69178381993..1e71784c809 100644 --- a/Include/internal/pycore_opcode_utils.h +++ b/Include/internal/pycore_opcode_utils.h @@ -82,9 +82,10 @@ extern "C" { #define RESUME_AFTER_YIELD 1 #define RESUME_AFTER_YIELD_FROM 2 #define RESUME_AFTER_AWAIT 3 +#define RESUME_AT_GEN_EXPR_START 4 -#define RESUME_OPARG_LOCATION_MASK 0x3 -#define RESUME_OPARG_DEPTH1_MASK 0x4 +#define RESUME_OPARG_LOCATION_MASK 0x7 +#define RESUME_OPARG_DEPTH1_MASK 0x8 #define GET_ITER_YIELD_FROM 1 #define GET_ITER_YIELD_FROM_NO_CHECK 2 diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index cf01c620476..7c2e0e95a80 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -15,6 +15,50 @@ extern "C" { #include "pycore_optimizer_types.h" #include +/* Fitness controls how long a trace can grow. + * Starts at FITNESS_INITIAL, then decreases from per-bytecode buffer usage + * plus branch/frame heuristics. The trace stops when fitness drops below the + * current exit_quality. + * + * Design targets for the constants below: + * 1. Reaching the abstract frame-depth limit should drop fitness below + * EXIT_QUALITY_SPECIALIZABLE. + * 2. A backward edge should leave budget for roughly N_BACKWARD_SLACK more + * bytecodes, assuming AVG_SLOTS_PER_INSTRUCTION. + * 3. Roughly seven balanced branches should reduce fitness to + * EXIT_QUALITY_DEFAULT after per-slot costs. + * 4. A push followed by a matching return is net-zero on frame-specific + * fitness, excluding per-slot costs. + */ +#define MAX_TARGET_LENGTH (UOP_MAX_TRACE_LENGTH / 2) +#define OPTIMIZER_EFFECTIVENESS 2 +#define FITNESS_INITIAL (MAX_TARGET_LENGTH * OPTIMIZER_EFFECTIVENESS) + +/* Exit quality thresholds: trace stops when fitness < exit_quality. + * Higher = trace is more willing to stop here. */ +#define EXIT_QUALITY_CLOSE_LOOP (FITNESS_INITIAL - AVG_SLOTS_PER_INSTRUCTION*4) +#define EXIT_QUALITY_ENTER_EXECUTOR (FITNESS_INITIAL * 1 / 8) +#define EXIT_QUALITY_DEFAULT (FITNESS_INITIAL / 40) +#define EXIT_QUALITY_SPECIALIZABLE (FITNESS_INITIAL / 80) + +/* Estimated buffer slots per bytecode, used only to derive heuristics. + * Runtime charging uses trace-buffer capacity consumed for each bytecode. */ +#define AVG_SLOTS_PER_INSTRUCTION 6 + +/* Heuristic backward-edge exit quality: leave room for about 1 unroll and + * N_BACKWARD_SLACK more bytecodes before reaching EXIT_QUALITY_CLOSE_LOOP, + * based on AVG_SLOTS_PER_INSTRUCTION. */ +#define N_BACKWARD_SLACK 10 +#define EXIT_QUALITY_BACKWARD_EDGE (EXIT_QUALITY_CLOSE_LOOP / 2 - N_BACKWARD_SLACK * AVG_SLOTS_PER_INSTRUCTION) + +/* Penalty for a balanced branch. + * It is sized so repeated balanced branches can drive a trace toward + * EXIT_QUALITY_DEFAULT, while compute_branch_penalty() keeps any single branch + * from dominating the budget. + */ +#define FITNESS_BRANCH_BALANCED ((FITNESS_INITIAL - EXIT_QUALITY_DEFAULT - \ + (MAX_TARGET_LENGTH / 14 * AVG_SLOTS_PER_INSTRUCTION)) / (14)) + typedef struct _PyJitUopBuffer { _PyUOpInstruction *start; @@ -91,17 +135,20 @@ typedef struct _PyJitTracerInitialState { _Py_CODEUNIT *jump_backward_instr; } _PyJitTracerInitialState; +#define MAX_RECORDED_VALUES 3 typedef struct _PyJitTracerPreviousState { int instr_oparg; int instr_stacklevel; _Py_CODEUNIT *instr; PyCodeObject *instr_code; // Strong struct _PyInterpreterFrame *instr_frame; - PyObject *recorded_value; // Strong, may be NULL + PyObject *recorded_values[MAX_RECORDED_VALUES]; // Strong, may be NULL + int recorded_count; } _PyJitTracerPreviousState; typedef struct _PyJitTracerTranslatorState { - int jump_backward_seen; + int32_t fitness; // Current trace fitness, starts high, decrements + int frame_depth; // Current inline depth (0 = root frame) } _PyJitTracerTranslatorState; typedef struct _PyJitTracerState { @@ -400,6 +447,7 @@ extern JitOptRef _Py_uop_sym_new_null(JitOptContext *ctx); extern bool _Py_uop_sym_has_type(JitOptRef sym); extern bool _Py_uop_sym_matches_type(JitOptRef sym, PyTypeObject *typ); extern bool _Py_uop_sym_matches_type_version(JitOptRef sym, unsigned int version); +extern unsigned int _Py_uop_sym_get_type_version(JitOptRef sym); extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *typ); @@ -424,8 +472,6 @@ extern PyCodeObject *_Py_uop_sym_get_probable_func_code(JitOptRef sym); extern PyObject *_Py_uop_sym_get_probable_value(JitOptRef sym); extern PyTypeObject *_Py_uop_sym_get_probable_type(JitOptRef sym); extern JitOptRef *_Py_uop_sym_set_stack_depth(JitOptContext *ctx, int stack_depth, JitOptRef *current_sp); -extern uint32_t _Py_uop_sym_get_func_version(JitOptRef ref); -bool _Py_uop_sym_set_func_version(JitOptContext *ctx, JitOptRef ref, uint32_t version); extern void _Py_uop_abstractcontext_init(JitOptContext *ctx, _PyBloomFilter *dependencies); extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx); @@ -483,7 +529,12 @@ void _PyJit_TracerFree(_PyThreadStateImpl *_tstate); #ifdef _Py_TIER2 typedef void (*_Py_RecordFuncPtr)(_PyInterpreterFrame *frame, _PyStackRef *stackpointer, int oparg, PyObject **recorded_value); PyAPI_DATA(const _Py_RecordFuncPtr) _PyOpcode_RecordFunctions[]; -PyAPI_DATA(const uint8_t) _PyOpcode_RecordFunctionIndices[256]; + +typedef struct { + uint8_t count; + uint8_t indices[MAX_RECORDED_VALUES]; +} _PyOpcodeRecordEntry; +PyAPI_DATA(const _PyOpcodeRecordEntry) _PyOpcode_RecordEntries[256]; #endif #ifdef __cplusplus diff --git a/Include/internal/pycore_optimizer_types.h b/Include/internal/pycore_optimizer_types.h index 8ecfbea3874..a722652cc81 100644 --- a/Include/internal/pycore_optimizer_types.h +++ b/Include/internal/pycore_optimizer_types.h @@ -36,7 +36,6 @@ typedef enum _JitSymType { JIT_SYM_NON_NULL_TAG = 3, JIT_SYM_BOTTOM_TAG = 4, JIT_SYM_TYPE_VERSION_TAG = 5, - JIT_SYM_FUNC_VERSION_TAG = 6, JIT_SYM_KNOWN_CLASS_TAG = 7, JIT_SYM_KNOWN_VALUE_TAG = 8, JIT_SYM_TUPLE_TAG = 9, diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index c0f859a23e1..fafdd728a82 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -49,6 +49,10 @@ extern "C" { _Py_atomic_load_uint16_relaxed(&value) #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) \ _Py_atomic_load_uint32_relaxed(&value) +#define FT_ATOMIC_LOAD_UINT64_ACQUIRE(value) \ + _Py_atomic_load_uint64_acquire(&value) +#define FT_ATOMIC_LOAD_UINT64_RELAXED(value) \ + _Py_atomic_load_uint64_relaxed(&value) #define FT_ATOMIC_LOAD_ULONG_RELAXED(value) \ _Py_atomic_load_ulong_relaxed(&value) #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \ @@ -71,6 +75,12 @@ extern "C" { _Py_atomic_store_uint16_relaxed(&value, new_value) #define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) \ _Py_atomic_store_uint32_relaxed(&value, new_value) +#define FT_ATOMIC_AND_UINT64(value, new_value) \ + (void)_Py_atomic_and_uint64(&value, new_value) +#define FT_ATOMIC_OR_UINT64(value, new_value) \ + (void)_Py_atomic_or_uint64(&value, new_value) +#define FT_ATOMIC_ADD_UINT64(value, new_value) \ + (void)_Py_atomic_add_uint64(&value, new_value) #define FT_ATOMIC_STORE_CHAR_RELAXED(value, new_value) \ _Py_atomic_store_char_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_CHAR_RELAXED(value) \ @@ -146,6 +156,8 @@ extern "C" { #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value +#define FT_ATOMIC_LOAD_UINT64_ACQUIRE(value) value +#define FT_ATOMIC_LOAD_UINT64_RELAXED(value) value #define FT_ATOMIC_LOAD_ULONG_RELAXED(value) value #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value @@ -157,6 +169,9 @@ extern "C" { #define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINT16_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_AND_UINT64(value, new_value) (void)(value &= new_value) +#define FT_ATOMIC_OR_UINT64(value, new_value) (void)(value |= new_value) +#define FT_ATOMIC_ADD_UINT64(value, new_value) (void)(value += new_value) #define FT_ATOMIC_LOAD_CHAR_RELAXED(value) value #define FT_ATOMIC_STORE_CHAR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_LOAD_UCHAR_RELAXED(value) value diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 1023dbc3395..e436aa6bf12 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -29,7 +29,8 @@ PyAPI_FUNC(PyObject*) _PyErr_FormatFromCause( ... ); -extern int _PyException_AddNote( +// Export for 'pyexpat' shared extension. +PyAPI_FUNC(int) _PyException_AddNote( PyObject *exc, PyObject *note); @@ -169,7 +170,8 @@ extern PyObject* _PyErr_FormatFromCauseTstate( const char *format, ...); -extern PyObject* _PyExc_CreateExceptionGroup( +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup( const char *msg, PyObject *excs); @@ -180,7 +182,8 @@ extern PyObject* _PyExc_PrepReraiseStar( extern int _PyErr_CheckSignalsTstate(PyThreadState *tstate); extern void _Py_DumpExtensionModules(int fd, PyInterpreterState *interp); -extern PyObject* _Py_CalculateSuggestions(PyObject *dir, PyObject *name); +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _Py_CalculateSuggestions(PyObject *dir, PyObject *name); extern PyObject* _Py_Offer_Suggestions(PyObject* exception); // Export for '_testinternalcapi' shared extension diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index 7fc7f343fe6..fcd2ae9b1d1 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -56,6 +56,29 @@ _PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { } } +// Atomic so a thread that reads initialized=1 observes all writes +// from the initialization sequence (gh-146302). + +static inline int +_PyRuntimeState_GetCoreInitialized(_PyRuntimeState *runtime) { + return _Py_atomic_load_int(&runtime->core_initialized); +} + +static inline void +_PyRuntimeState_SetCoreInitialized(_PyRuntimeState *runtime, int initialized) { + _Py_atomic_store_int(&runtime->core_initialized, initialized); +} + +static inline int +_PyRuntimeState_GetInitialized(_PyRuntimeState *runtime) { + return _Py_atomic_load_int(&runtime->initialized); +} + +static inline void +_PyRuntimeState_SetInitialized(_PyRuntimeState *runtime, int initialized) { + _Py_atomic_store_int(&runtime->initialized, initialized); +} + #ifdef __cplusplus } diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 64b029797ab..6ee64a461d8 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1634,6 +1634,7 @@ extern "C" { INIT_ID(callable), \ INIT_ID(callback), \ INIT_ID(cancel), \ + INIT_ID(canonical), \ INIT_ID(capath), \ INIT_ID(capitals), \ INIT_ID(category), \ diff --git a/Include/internal/pycore_runtime_structs.h b/Include/internal/pycore_runtime_structs.h index 05369ef9f00..145e66de998 100644 --- a/Include/internal/pycore_runtime_structs.h +++ b/Include/internal/pycore_runtime_structs.h @@ -158,10 +158,18 @@ struct pyruntimestate { /* Is Python preinitialized? Set to 1 by Py_PreInitialize() */ int preinitialized; - /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ + /* Is Python core initialized? Set to 1 by _Py_InitializeCore(). + + Use _PyRuntimeState_GetCoreInitialized() and + _PyRuntimeState_SetCoreInitialized() to access it, + don't access it directly. */ int core_initialized; - /* Is Python fully initialized? Set to 1 by Py_Initialize() */ + /* Is Python fully initialized? Set to 1 by Py_Initialize(). + + Use _PyRuntimeState_GetInitialized() and + _PyRuntimeState_SetInitialized() to access it, + don't access it directly. */ int initialized; /* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize() diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 329045b5faa..ca4a7c216ed 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -71,8 +71,10 @@ static const _PyStackRef PyStackRef_NULL = { .index = 0 }; static const _PyStackRef PyStackRef_ERROR = { .index = (1 << Py_TAGGED_SHIFT) }; #define PyStackRef_None ((_PyStackRef){ .index = (2 << Py_TAGGED_SHIFT) } ) -#define PyStackRef_False ((_PyStackRef){ .index = (3 << Py_TAGGED_SHIFT) }) -#define PyStackRef_True ((_PyStackRef){ .index = (4 << Py_TAGGED_SHIFT) }) +#define _Py_STACKREF_FALSE_INDEX (3 << Py_TAGGED_SHIFT) +#define _Py_STACKREF_TRUE_INDEX (4 << Py_TAGGED_SHIFT) +#define PyStackRef_False ((_PyStackRef){ .index = _Py_STACKREF_FALSE_INDEX }) +#define PyStackRef_True ((_PyStackRef){ .index = _Py_STACKREF_TRUE_INDEX }) #define INITIAL_STACKREF_INDEX (5 << Py_TAGGED_SHIFT) diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index e1176c65c5c..c650a94a1ea 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -90,6 +90,7 @@ typedef struct _symtable_entry { PyObject *ste_id; /* int: key in ste_table->st_blocks */ PyObject *ste_symbols; /* dict: variable names to flags */ PyObject *ste_name; /* string: name of current block */ + PyObject *ste_function_name; /* string or NULL: for annotation blocks: name of the corresponding functions */ PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 8357cce9d89..6b5e24979d5 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -85,7 +85,8 @@ extern void _Py_DumpHexadecimal( uintptr_t value, Py_ssize_t width); -extern PyObject* _PyTraceBack_FromFrame( +// Exported for external JIT support +PyAPI_FUNC(PyObject *) _PyTraceBack_FromFrame( PyObject *tb_next, PyFrameObject *frame); diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 9409ec94976..bf80f96396e 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -28,6 +28,7 @@ PyAPI_FUNC(void) _PyStolenTuple_Free(PyObject *self); PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t); PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyTuple_Concat(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyTuple_FromPair(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyTuple_FromPairSteal(PyObject *, PyObject *); diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index 8207de67cf1..8d48cf6605c 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -60,7 +60,8 @@ extern void _PyStaticType_FiniBuiltin( extern void _PyStaticType_ClearWeakRefs( PyInterpreterState *interp, PyTypeObject *type); -extern managed_static_type_state * _PyStaticType_GetState( +// Exported for external JIT support +PyAPI_FUNC(managed_static_type_state *) _PyStaticType_GetState( PyInterpreterState *interp, PyTypeObject *type); @@ -156,8 +157,9 @@ typedef int (*_py_validate_type)(PyTypeObject *); // It will verify the ``ty`` through user-defined validation function ``validate``, // and if the validation is passed, it will set the ``tp_version`` as valid // tp_version_tag from the ``ty``. -extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version); -extern int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version); +// Exported for external JIT support +int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version); +int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version); // Precalculates count of non-unique slots and fills wrapperbase.name_count. extern int _PyType_InitSlotDefs(PyInterpreterState *interp); diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 461ee36dceb..bcb117e1091 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1216,6 +1216,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(canonical); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(capath); _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 50abb537d69..6b96f9bc78e 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -11,38 +11,42 @@ extern "C" { #define _EXIT_TRACE 300 #define _SET_IP 301 -#define _BINARY_OP 302 -#define _BINARY_OP_ADD_FLOAT 303 -#define _BINARY_OP_ADD_FLOAT_INPLACE 304 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT 305 -#define _BINARY_OP_ADD_INT 306 -#define _BINARY_OP_ADD_INT_INPLACE 307 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT 308 -#define _BINARY_OP_ADD_UNICODE 309 -#define _BINARY_OP_EXTEND 310 -#define _BINARY_OP_INPLACE_ADD_UNICODE 311 -#define _BINARY_OP_MULTIPLY_FLOAT 312 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE 313 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT 314 -#define _BINARY_OP_MULTIPLY_INT 315 -#define _BINARY_OP_MULTIPLY_INT_INPLACE 316 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT 317 -#define _BINARY_OP_SUBSCR_CHECK_FUNC 318 -#define _BINARY_OP_SUBSCR_DICT 319 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 320 -#define _BINARY_OP_SUBSCR_INIT_CALL 321 -#define _BINARY_OP_SUBSCR_LIST_INT 322 -#define _BINARY_OP_SUBSCR_LIST_SLICE 323 -#define _BINARY_OP_SUBSCR_STR_INT 324 -#define _BINARY_OP_SUBSCR_TUPLE_INT 325 -#define _BINARY_OP_SUBSCR_USTR_INT 326 -#define _BINARY_OP_SUBTRACT_FLOAT 327 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 328 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 329 -#define _BINARY_OP_SUBTRACT_INT 330 -#define _BINARY_OP_SUBTRACT_INT_INPLACE 331 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT 332 -#define _BINARY_SLICE 333 +#define _ALLOCATE_OBJECT 302 +#define _BINARY_OP 303 +#define _BINARY_OP_ADD_FLOAT 304 +#define _BINARY_OP_ADD_FLOAT_INPLACE 305 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT 306 +#define _BINARY_OP_ADD_INT 307 +#define _BINARY_OP_ADD_INT_INPLACE 308 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT 309 +#define _BINARY_OP_ADD_UNICODE 310 +#define _BINARY_OP_EXTEND 311 +#define _BINARY_OP_INPLACE_ADD_UNICODE 312 +#define _BINARY_OP_MULTIPLY_FLOAT 313 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE 314 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT 315 +#define _BINARY_OP_MULTIPLY_INT 316 +#define _BINARY_OP_MULTIPLY_INT_INPLACE 317 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT 318 +#define _BINARY_OP_SUBSCR_CHECK_FUNC 319 +#define _BINARY_OP_SUBSCR_DICT 320 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 321 +#define _BINARY_OP_SUBSCR_INIT_CALL 322 +#define _BINARY_OP_SUBSCR_LIST_INT 323 +#define _BINARY_OP_SUBSCR_LIST_SLICE 324 +#define _BINARY_OP_SUBSCR_STR_INT 325 +#define _BINARY_OP_SUBSCR_TUPLE_INT 326 +#define _BINARY_OP_SUBSCR_USTR_INT 327 +#define _BINARY_OP_SUBTRACT_FLOAT 328 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 329 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 330 +#define _BINARY_OP_SUBTRACT_INT 331 +#define _BINARY_OP_SUBTRACT_INT_INPLACE 332 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT 333 +#define _BINARY_OP_TRUEDIV_FLOAT 334 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE 335 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT 336 +#define _BINARY_SLICE 337 #define _BUILD_INTERPOLATION BUILD_INTERPOLATION #define _BUILD_LIST BUILD_LIST #define _BUILD_MAP BUILD_MAP @@ -51,186 +55,195 @@ extern "C" { #define _BUILD_STRING BUILD_STRING #define _BUILD_TEMPLATE BUILD_TEMPLATE #define _BUILD_TUPLE BUILD_TUPLE -#define _CALL_BUILTIN_CLASS 334 -#define _CALL_BUILTIN_FAST 335 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 336 -#define _CALL_BUILTIN_O 337 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL 338 -#define _CALL_INTRINSIC_1 339 -#define _CALL_INTRINSIC_2 340 -#define _CALL_ISINSTANCE 341 -#define _CALL_KW_NON_PY 342 -#define _CALL_LEN 343 -#define _CALL_LIST_APPEND 344 -#define _CALL_METHOD_DESCRIPTOR_FAST 345 -#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE 346 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 347 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE 348 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 349 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE 350 -#define _CALL_METHOD_DESCRIPTOR_O 351 -#define _CALL_METHOD_DESCRIPTOR_O_INLINE 352 -#define _CALL_NON_PY_GENERAL 353 -#define _CALL_STR_1 354 -#define _CALL_TUPLE_1 355 -#define _CALL_TYPE_1 356 -#define _CHECK_AND_ALLOCATE_OBJECT 357 -#define _CHECK_ATTR_CLASS 358 -#define _CHECK_ATTR_METHOD_LAZY_DICT 359 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 360 +#define _CALL_BUILTIN_CLASS 338 +#define _CALL_BUILTIN_FAST 339 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 340 +#define _CALL_BUILTIN_O 341 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL 342 +#define _CALL_INTRINSIC_1 343 +#define _CALL_INTRINSIC_2 344 +#define _CALL_ISINSTANCE 345 +#define _CALL_KW_NON_PY 346 +#define _CALL_LEN 347 +#define _CALL_LIST_APPEND 348 +#define _CALL_METHOD_DESCRIPTOR_FAST 349 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE 350 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 351 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE 352 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 353 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE 354 +#define _CALL_METHOD_DESCRIPTOR_O 355 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE 356 +#define _CALL_NON_PY_GENERAL 357 +#define _CALL_STR_1 358 +#define _CALL_TUPLE_1 359 +#define _CALL_TYPE_1 360 +#define _CHECK_ATTR_CLASS 361 +#define _CHECK_ATTR_METHOD_LAZY_DICT 362 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 363 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 361 -#define _CHECK_FUNCTION_VERSION 362 -#define _CHECK_FUNCTION_VERSION_INLINE 363 -#define _CHECK_FUNCTION_VERSION_KW 364 -#define _CHECK_IS_NOT_PY_CALLABLE 365 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 366 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 367 -#define _CHECK_IS_PY_CALLABLE_EX 368 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 369 -#define _CHECK_METHOD_VERSION 370 -#define _CHECK_METHOD_VERSION_KW 371 -#define _CHECK_PEP_523 372 -#define _CHECK_PERIODIC 373 -#define _CHECK_PERIODIC_AT_END 374 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 375 -#define _CHECK_RECURSION_LIMIT 376 -#define _CHECK_RECURSION_REMAINING 377 -#define _CHECK_STACK_SPACE 378 -#define _CHECK_STACK_SPACE_OPERAND 379 -#define _CHECK_VALIDITY 380 -#define _COLD_DYNAMIC_EXIT 381 -#define _COLD_EXIT 382 -#define _COMPARE_OP 383 -#define _COMPARE_OP_FLOAT 384 -#define _COMPARE_OP_INT 385 -#define _COMPARE_OP_STR 386 -#define _CONTAINS_OP 387 -#define _CONTAINS_OP_DICT 388 -#define _CONTAINS_OP_SET 389 +#define _CHECK_FUNCTION_EXACT_ARGS 364 +#define _CHECK_FUNCTION_VERSION 365 +#define _CHECK_FUNCTION_VERSION_INLINE 366 +#define _CHECK_FUNCTION_VERSION_KW 367 +#define _CHECK_IS_NOT_PY_CALLABLE 368 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 369 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 370 +#define _CHECK_IS_PY_CALLABLE_EX 371 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 372 +#define _CHECK_METHOD_VERSION 373 +#define _CHECK_METHOD_VERSION_KW 374 +#define _CHECK_OBJECT 375 +#define _CHECK_PEP_523 376 +#define _CHECK_PERIODIC 377 +#define _CHECK_PERIODIC_AT_END 378 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 379 +#define _CHECK_RECURSION_LIMIT 380 +#define _CHECK_RECURSION_REMAINING 381 +#define _CHECK_STACK_SPACE 382 +#define _CHECK_STACK_SPACE_OPERAND 383 +#define _CHECK_VALIDITY 384 +#define _COLD_DYNAMIC_EXIT 385 +#define _COLD_EXIT 386 +#define _COMPARE_OP 387 +#define _COMPARE_OP_FLOAT 388 +#define _COMPARE_OP_INT 389 +#define _COMPARE_OP_STR 390 +#define _CONTAINS_OP 391 +#define _CONTAINS_OP_DICT 392 +#define _CONTAINS_OP_SET 393 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 390 -#define _COPY_1 391 -#define _COPY_2 392 -#define _COPY_3 393 +#define _COPY 394 +#define _COPY_1 395 +#define _COPY_2 396 +#define _COPY_3 397 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 394 +#define _CREATE_INIT_FRAME 398 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 395 -#define _DICT_MERGE 396 -#define _DICT_UPDATE 397 -#define _DO_CALL 398 -#define _DO_CALL_FUNCTION_EX 399 -#define _DO_CALL_KW 400 -#define _DYNAMIC_EXIT 401 +#define _DEOPT 399 +#define _DICT_MERGE 400 +#define _DICT_UPDATE 401 +#define _DO_CALL 402 +#define _DO_CALL_FUNCTION_EX 403 +#define _DO_CALL_KW 404 +#define _DYNAMIC_EXIT 405 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 402 +#define _ERROR_POP_N 406 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 403 -#define _EXPAND_METHOD_KW 404 -#define _FATAL_ERROR 405 +#define _EXPAND_METHOD 407 +#define _EXPAND_METHOD_KW 408 +#define _FATAL_ERROR 409 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 406 -#define _FOR_ITER_GEN_FRAME 407 -#define _FOR_ITER_TIER_TWO 408 +#define _FOR_ITER 410 +#define _FOR_ITER_GEN_FRAME 411 +#define _FOR_ITER_TIER_TWO 412 +#define _FOR_ITER_VIRTUAL 413 +#define _FOR_ITER_VIRTUAL_TIER_TWO 414 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE -#define _GET_ITER GET_ITER +#define _GET_ITER 415 +#define _GET_ITER_TRAD 416 #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 409 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 410 -#define _GUARD_BIT_IS_SET_POP 411 -#define _GUARD_BIT_IS_SET_POP_4 412 -#define _GUARD_BIT_IS_SET_POP_5 413 -#define _GUARD_BIT_IS_SET_POP_6 414 -#define _GUARD_BIT_IS_SET_POP_7 415 -#define _GUARD_BIT_IS_UNSET_POP 416 -#define _GUARD_BIT_IS_UNSET_POP_4 417 -#define _GUARD_BIT_IS_UNSET_POP_5 418 -#define _GUARD_BIT_IS_UNSET_POP_6 419 -#define _GUARD_BIT_IS_UNSET_POP_7 420 -#define _GUARD_CALLABLE_BUILTIN_FAST 421 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 422 -#define _GUARD_CALLABLE_BUILTIN_O 423 -#define _GUARD_CALLABLE_ISINSTANCE 424 -#define _GUARD_CALLABLE_LEN 425 -#define _GUARD_CALLABLE_LIST_APPEND 426 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 427 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 428 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 429 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 430 -#define _GUARD_CALLABLE_STR_1 431 -#define _GUARD_CALLABLE_TUPLE_1 432 -#define _GUARD_CALLABLE_TYPE_1 433 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 434 -#define _GUARD_CODE_VERSION_RETURN_VALUE 435 -#define _GUARD_CODE_VERSION_YIELD_VALUE 436 -#define _GUARD_CODE_VERSION__PUSH_FRAME 437 -#define _GUARD_DORV_NO_DICT 438 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 439 -#define _GUARD_GLOBALS_VERSION 440 -#define _GUARD_IP_RETURN_GENERATOR 441 -#define _GUARD_IP_RETURN_VALUE 442 -#define _GUARD_IP_YIELD_VALUE 443 -#define _GUARD_IP__PUSH_FRAME 444 -#define _GUARD_IS_FALSE_POP 445 -#define _GUARD_IS_NONE_POP 446 -#define _GUARD_IS_NOT_NONE_POP 447 -#define _GUARD_IS_TRUE_POP 448 -#define _GUARD_KEYS_VERSION 449 -#define _GUARD_LOAD_SUPER_ATTR_METHOD 450 -#define _GUARD_NOS_ANY_DICT 451 -#define _GUARD_NOS_COMPACT_ASCII 452 -#define _GUARD_NOS_DICT 453 -#define _GUARD_NOS_FLOAT 454 -#define _GUARD_NOS_INT 455 -#define _GUARD_NOS_LIST 456 -#define _GUARD_NOS_NOT_NULL 457 -#define _GUARD_NOS_NULL 458 -#define _GUARD_NOS_OVERFLOWED 459 -#define _GUARD_NOS_TUPLE 460 -#define _GUARD_NOS_TYPE_VERSION 461 -#define _GUARD_NOS_UNICODE 462 -#define _GUARD_NOT_EXHAUSTED_LIST 463 -#define _GUARD_NOT_EXHAUSTED_RANGE 464 -#define _GUARD_NOT_EXHAUSTED_TUPLE 465 -#define _GUARD_THIRD_NULL 466 -#define _GUARD_TOS_ANY_DICT 467 -#define _GUARD_TOS_ANY_SET 468 -#define _GUARD_TOS_DICT 469 -#define _GUARD_TOS_FLOAT 470 -#define _GUARD_TOS_FROZENDICT 471 -#define _GUARD_TOS_FROZENSET 472 -#define _GUARD_TOS_INT 473 -#define _GUARD_TOS_LIST 474 -#define _GUARD_TOS_OVERFLOWED 475 -#define _GUARD_TOS_SET 476 -#define _GUARD_TOS_SLICE 477 -#define _GUARD_TOS_TUPLE 478 -#define _GUARD_TOS_UNICODE 479 -#define _GUARD_TYPE_VERSION 480 -#define _GUARD_TYPE_VERSION_LOCKED 481 -#define _HANDLE_PENDING_AND_DEOPT 482 +#define _GUARD_BINARY_OP_EXTEND 417 +#define _GUARD_BINARY_OP_EXTEND_LHS 418 +#define _GUARD_BINARY_OP_EXTEND_RHS 419 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 420 +#define _GUARD_BIT_IS_SET_POP 421 +#define _GUARD_BIT_IS_SET_POP_4 422 +#define _GUARD_BIT_IS_SET_POP_5 423 +#define _GUARD_BIT_IS_SET_POP_6 424 +#define _GUARD_BIT_IS_SET_POP_7 425 +#define _GUARD_BIT_IS_UNSET_POP 426 +#define _GUARD_BIT_IS_UNSET_POP_4 427 +#define _GUARD_BIT_IS_UNSET_POP_5 428 +#define _GUARD_BIT_IS_UNSET_POP_6 429 +#define _GUARD_BIT_IS_UNSET_POP_7 430 +#define _GUARD_CALLABLE_BUILTIN_CLASS 431 +#define _GUARD_CALLABLE_BUILTIN_FAST 432 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 433 +#define _GUARD_CALLABLE_BUILTIN_O 434 +#define _GUARD_CALLABLE_ISINSTANCE 435 +#define _GUARD_CALLABLE_LEN 436 +#define _GUARD_CALLABLE_LIST_APPEND 437 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 438 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 439 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 440 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 441 +#define _GUARD_CALLABLE_STR_1 442 +#define _GUARD_CALLABLE_TUPLE_1 443 +#define _GUARD_CALLABLE_TYPE_1 444 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 445 +#define _GUARD_CODE_VERSION_RETURN_VALUE 446 +#define _GUARD_CODE_VERSION_YIELD_VALUE 447 +#define _GUARD_CODE_VERSION__PUSH_FRAME 448 +#define _GUARD_DORV_NO_DICT 449 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 450 +#define _GUARD_GLOBALS_VERSION 451 +#define _GUARD_IP_RETURN_GENERATOR 452 +#define _GUARD_IP_RETURN_VALUE 453 +#define _GUARD_IP_YIELD_VALUE 454 +#define _GUARD_IP__PUSH_FRAME 455 +#define _GUARD_IS_FALSE_POP 456 +#define _GUARD_IS_NONE_POP 457 +#define _GUARD_IS_NOT_NONE_POP 458 +#define _GUARD_IS_TRUE_POP 459 +#define _GUARD_ITERATOR 460 +#define _GUARD_ITER_VIRTUAL 461 +#define _GUARD_KEYS_VERSION 462 +#define _GUARD_LOAD_SUPER_ATTR_METHOD 463 +#define _GUARD_NOS_ANY_DICT 464 +#define _GUARD_NOS_COMPACT_ASCII 465 +#define _GUARD_NOS_DICT 466 +#define _GUARD_NOS_FLOAT 467 +#define _GUARD_NOS_INT 468 +#define _GUARD_NOS_ITER_VIRTUAL 469 +#define _GUARD_NOS_LIST 470 +#define _GUARD_NOS_NOT_NULL 471 +#define _GUARD_NOS_NULL 472 +#define _GUARD_NOS_OVERFLOWED 473 +#define _GUARD_NOS_TUPLE 474 +#define _GUARD_NOS_TYPE_VERSION 475 +#define _GUARD_NOS_UNICODE 476 +#define _GUARD_NOT_EXHAUSTED_LIST 477 +#define _GUARD_NOT_EXHAUSTED_RANGE 478 +#define _GUARD_NOT_EXHAUSTED_TUPLE 479 +#define _GUARD_THIRD_NULL 480 +#define _GUARD_TOS_ANY_DICT 481 +#define _GUARD_TOS_ANY_SET 482 +#define _GUARD_TOS_DICT 483 +#define _GUARD_TOS_FLOAT 484 +#define _GUARD_TOS_FROZENDICT 485 +#define _GUARD_TOS_FROZENSET 486 +#define _GUARD_TOS_INT 487 +#define _GUARD_TOS_LIST 488 +#define _GUARD_TOS_OVERFLOWED 489 +#define _GUARD_TOS_SET 490 +#define _GUARD_TOS_SLICE 491 +#define _GUARD_TOS_TUPLE 492 +#define _GUARD_TOS_UNICODE 493 +#define _GUARD_TYPE 494 +#define _GUARD_TYPE_VERSION 495 +#define _GUARD_TYPE_VERSION_LOCKED 496 +#define _HANDLE_PENDING_AND_DEOPT 497 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 483 -#define _INIT_CALL_PY_EXACT_ARGS 484 -#define _INIT_CALL_PY_EXACT_ARGS_0 485 -#define _INIT_CALL_PY_EXACT_ARGS_1 486 -#define _INIT_CALL_PY_EXACT_ARGS_2 487 -#define _INIT_CALL_PY_EXACT_ARGS_3 488 -#define _INIT_CALL_PY_EXACT_ARGS_4 489 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 490 -#define _INSERT_NULL 491 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 498 +#define _INIT_CALL_PY_EXACT_ARGS 499 +#define _INIT_CALL_PY_EXACT_ARGS_0 500 +#define _INIT_CALL_PY_EXACT_ARGS_1 501 +#define _INIT_CALL_PY_EXACT_ARGS_2 502 +#define _INIT_CALL_PY_EXACT_ARGS_3 503 +#define _INIT_CALL_PY_EXACT_ARGS_4 504 +#define _INSERT_NULL 505 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -240,1139 +253,1167 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #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 492 -#define _IS_OP 493 -#define _ITER_CHECK_LIST 494 -#define _ITER_CHECK_RANGE 495 -#define _ITER_CHECK_TUPLE 496 -#define _ITER_JUMP_LIST 497 -#define _ITER_JUMP_RANGE 498 -#define _ITER_JUMP_TUPLE 499 -#define _ITER_NEXT_LIST 500 -#define _ITER_NEXT_LIST_TIER_TWO 501 -#define _ITER_NEXT_RANGE 502 -#define _ITER_NEXT_TUPLE 503 +#define _IS_NONE 506 +#define _IS_OP 507 +#define _ITER_CHECK_LIST 508 +#define _ITER_CHECK_RANGE 509 +#define _ITER_CHECK_TUPLE 510 +#define _ITER_JUMP_LIST 511 +#define _ITER_JUMP_RANGE 512 +#define _ITER_JUMP_TUPLE 513 +#define _ITER_NEXT_LIST 514 +#define _ITER_NEXT_LIST_TIER_TWO 515 +#define _ITER_NEXT_RANGE 516 +#define _ITER_NEXT_TUPLE 517 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 504 +#define _JUMP_TO_TOP 518 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 505 -#define _LOAD_ATTR 506 -#define _LOAD_ATTR_CLASS 507 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 508 -#define _LOAD_ATTR_METHOD_LAZY_DICT 509 -#define _LOAD_ATTR_METHOD_NO_DICT 510 -#define _LOAD_ATTR_METHOD_WITH_VALUES 511 -#define _LOAD_ATTR_MODULE 512 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 513 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 514 -#define _LOAD_ATTR_PROPERTY_FRAME 515 -#define _LOAD_ATTR_SLOT 516 -#define _LOAD_ATTR_WITH_HINT 517 +#define _LIST_EXTEND 519 +#define _LOAD_ATTR 520 +#define _LOAD_ATTR_CLASS 521 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME 522 +#define _LOAD_ATTR_INSTANCE_VALUE 523 +#define _LOAD_ATTR_METHOD_LAZY_DICT 524 +#define _LOAD_ATTR_METHOD_NO_DICT 525 +#define _LOAD_ATTR_METHOD_WITH_VALUES 526 +#define _LOAD_ATTR_MODULE 527 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 528 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 529 +#define _LOAD_ATTR_PROPERTY_FRAME 530 +#define _LOAD_ATTR_SLOT 531 +#define _LOAD_ATTR_WITH_HINT 532 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 518 +#define _LOAD_BYTECODE 533 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 519 -#define _LOAD_CONST_INLINE_BORROW 520 +#define _LOAD_CONST_INLINE 534 +#define _LOAD_CONST_INLINE_BORROW 535 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 521 -#define _LOAD_FAST_0 522 -#define _LOAD_FAST_1 523 -#define _LOAD_FAST_2 524 -#define _LOAD_FAST_3 525 -#define _LOAD_FAST_4 526 -#define _LOAD_FAST_5 527 -#define _LOAD_FAST_6 528 -#define _LOAD_FAST_7 529 +#define _LOAD_FAST 536 +#define _LOAD_FAST_0 537 +#define _LOAD_FAST_1 538 +#define _LOAD_FAST_2 539 +#define _LOAD_FAST_3 540 +#define _LOAD_FAST_4 541 +#define _LOAD_FAST_5 542 +#define _LOAD_FAST_6 543 +#define _LOAD_FAST_7 544 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 530 -#define _LOAD_FAST_BORROW_0 531 -#define _LOAD_FAST_BORROW_1 532 -#define _LOAD_FAST_BORROW_2 533 -#define _LOAD_FAST_BORROW_3 534 -#define _LOAD_FAST_BORROW_4 535 -#define _LOAD_FAST_BORROW_5 536 -#define _LOAD_FAST_BORROW_6 537 -#define _LOAD_FAST_BORROW_7 538 +#define _LOAD_FAST_BORROW 545 +#define _LOAD_FAST_BORROW_0 546 +#define _LOAD_FAST_BORROW_1 547 +#define _LOAD_FAST_BORROW_2 548 +#define _LOAD_FAST_BORROW_3 549 +#define _LOAD_FAST_BORROW_4 550 +#define _LOAD_FAST_BORROW_5 551 +#define _LOAD_FAST_BORROW_6 552 +#define _LOAD_FAST_BORROW_7 553 #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 539 -#define _LOAD_GLOBAL_BUILTINS 540 -#define _LOAD_GLOBAL_MODULE 541 +#define _LOAD_GLOBAL 554 +#define _LOAD_GLOBAL_BUILTINS 555 +#define _LOAD_GLOBAL_MODULE 556 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 542 -#define _LOAD_SMALL_INT_0 543 -#define _LOAD_SMALL_INT_1 544 -#define _LOAD_SMALL_INT_2 545 -#define _LOAD_SMALL_INT_3 546 -#define _LOAD_SPECIAL 547 +#define _LOAD_SMALL_INT 557 +#define _LOAD_SMALL_INT_0 558 +#define _LOAD_SMALL_INT_1 559 +#define _LOAD_SMALL_INT_2 560 +#define _LOAD_SMALL_INT_3 561 +#define _LOAD_SPECIAL 562 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR -#define _LOAD_SUPER_ATTR_METHOD 548 -#define _LOCK_OBJECT 549 -#define _MAKE_CALLARGS_A_TUPLE 550 +#define _LOAD_SUPER_ATTR_METHOD 563 +#define _LOCK_OBJECT 564 +#define _MAKE_CALLARGS_A_TUPLE 565 #define _MAKE_CELL MAKE_CELL -#define _MAKE_FUNCTION 551 -#define _MAKE_HEAP_SAFE 552 -#define _MAKE_WARM 553 +#define _MAKE_FUNCTION 566 +#define _MAKE_HEAP_SAFE 567 +#define _MAKE_WARM 568 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 554 +#define _MATCH_CLASS 569 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 555 -#define _MAYBE_EXPAND_METHOD_KW 556 -#define _MONITOR_CALL 557 -#define _MONITOR_CALL_KW 558 -#define _MONITOR_JUMP_BACKWARD 559 -#define _MONITOR_RESUME 560 +#define _MAYBE_EXPAND_METHOD 570 +#define _MAYBE_EXPAND_METHOD_KW 571 +#define _MONITOR_CALL 572 +#define _MONITOR_CALL_KW 573 +#define _MONITOR_JUMP_BACKWARD 574 +#define _MONITOR_RESUME 575 #define _NOP NOP -#define _POP_CALL 561 -#define _POP_CALL_ONE 562 -#define _POP_CALL_TWO 563 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 564 -#define _POP_JUMP_IF_TRUE 565 +#define _POP_JUMP_IF_FALSE 576 +#define _POP_JUMP_IF_TRUE 577 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 566 -#define _POP_TOP_INT 567 -#define _POP_TOP_LOAD_CONST_INLINE 568 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 569 -#define _POP_TOP_NOP 570 -#define _POP_TOP_OPARG 571 -#define _POP_TOP_UNICODE 572 -#define _POP_TWO 573 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 574 +#define _POP_TOP_FLOAT 578 +#define _POP_TOP_INT 579 +#define _POP_TOP_NOP 580 +#define _POP_TOP_OPARG 581 +#define _POP_TOP_UNICODE 582 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 575 +#define _PUSH_FRAME 583 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 576 -#define _PY_FRAME_EX 577 -#define _PY_FRAME_GENERAL 578 -#define _PY_FRAME_KW 579 -#define _RECORD_3OS_GEN_FUNC 580 -#define _RECORD_4OS 581 -#define _RECORD_BOUND_METHOD 582 -#define _RECORD_CALLABLE 583 -#define _RECORD_CODE 584 -#define _RECORD_NOS 585 -#define _RECORD_NOS_GEN_FUNC 586 -#define _RECORD_TOS 587 -#define _RECORD_TOS_TYPE 588 -#define _REPLACE_WITH_TRUE 589 -#define _RESUME_CHECK 590 +#define _PUSH_NULL_CONDITIONAL 584 +#define _PUSH_TAGGED_ZERO 585 +#define _PY_FRAME_EX 586 +#define _PY_FRAME_GENERAL 587 +#define _PY_FRAME_KW 588 +#define _RECORD_3OS_GEN_FUNC 589 +#define _RECORD_4OS 590 +#define _RECORD_BOUND_METHOD 591 +#define _RECORD_CALLABLE 592 +#define _RECORD_CALLABLE_KW 593 +#define _RECORD_CODE 594 +#define _RECORD_NOS 595 +#define _RECORD_NOS_GEN_FUNC 596 +#define _RECORD_NOS_TYPE 597 +#define _RECORD_TOS 598 +#define _RECORD_TOS_TYPE 599 +#define _REPLACE_WITH_TRUE 600 +#define _RESUME_CHECK 601 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 591 -#define _SAVE_RETURN_OFFSET 592 -#define _SEND 593 -#define _SEND_GEN_FRAME 594 +#define _RETURN_VALUE 602 +#define _SAVE_RETURN_OFFSET 603 +#define _SEND 604 +#define _SEND_GEN_FRAME 605 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 595 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 596 -#define _SPILL_OR_RELOAD 597 -#define _START_EXECUTOR 598 -#define _STORE_ATTR 599 -#define _STORE_ATTR_INSTANCE_VALUE 600 -#define _STORE_ATTR_SLOT 601 -#define _STORE_ATTR_WITH_HINT 602 +#define _SET_UPDATE 606 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 607 +#define _SPILL_OR_RELOAD 608 +#define _START_EXECUTOR 609 +#define _STORE_ATTR 610 +#define _STORE_ATTR_INSTANCE_VALUE 611 +#define _STORE_ATTR_SLOT 612 +#define _STORE_ATTR_WITH_HINT 613 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 603 -#define _STORE_SUBSCR 604 -#define _STORE_SUBSCR_DICT 605 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 606 -#define _STORE_SUBSCR_LIST_INT 607 -#define _SWAP 608 -#define _SWAP_2 609 -#define _SWAP_3 610 -#define _SWAP_FAST 611 -#define _SWAP_FAST_0 612 -#define _SWAP_FAST_1 613 -#define _SWAP_FAST_2 614 -#define _SWAP_FAST_3 615 -#define _SWAP_FAST_4 616 -#define _SWAP_FAST_5 617 -#define _SWAP_FAST_6 618 -#define _SWAP_FAST_7 619 -#define _TIER2_RESUME_CHECK 620 -#define _TO_BOOL 621 +#define _STORE_SLICE 614 +#define _STORE_SUBSCR 615 +#define _STORE_SUBSCR_DICT 616 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 617 +#define _STORE_SUBSCR_LIST_INT 618 +#define _SWAP 619 +#define _SWAP_2 620 +#define _SWAP_3 621 +#define _SWAP_FAST 622 +#define _SWAP_FAST_0 623 +#define _SWAP_FAST_1 624 +#define _SWAP_FAST_2 625 +#define _SWAP_FAST_3 626 +#define _SWAP_FAST_4 627 +#define _SWAP_FAST_5 628 +#define _SWAP_FAST_6 629 +#define _SWAP_FAST_7 630 +#define _TIER2_RESUME_CHECK 631 +#define _TO_BOOL 632 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 622 -#define _TO_BOOL_LIST 623 +#define _TO_BOOL_INT 633 +#define _TO_BOOL_LIST 634 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 624 +#define _TO_BOOL_STR 635 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 625 -#define _UNARY_NEGATIVE 626 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 627 +#define _UNARY_INVERT 636 +#define _UNARY_NEGATIVE 637 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 638 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 628 -#define _UNPACK_SEQUENCE_LIST 629 -#define _UNPACK_SEQUENCE_TUPLE 630 -#define _UNPACK_SEQUENCE_TWO_TUPLE 631 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 632 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 633 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 634 +#define _UNPACK_SEQUENCE 639 +#define _UNPACK_SEQUENCE_LIST 640 +#define _UNPACK_SEQUENCE_TUPLE 641 +#define _UNPACK_SEQUENCE_TWO_TUPLE 642 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 643 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 644 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 645 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 635 -#define MAX_UOP_ID 635 -#define _BINARY_OP_r23 636 -#define _BINARY_OP_ADD_FLOAT_r03 637 -#define _BINARY_OP_ADD_FLOAT_r13 638 -#define _BINARY_OP_ADD_FLOAT_r23 639 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 640 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 641 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 642 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 643 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 644 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 645 -#define _BINARY_OP_ADD_INT_r03 646 -#define _BINARY_OP_ADD_INT_r13 647 -#define _BINARY_OP_ADD_INT_r23 648 -#define _BINARY_OP_ADD_INT_INPLACE_r03 649 -#define _BINARY_OP_ADD_INT_INPLACE_r13 650 -#define _BINARY_OP_ADD_INT_INPLACE_r23 651 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 652 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 653 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 654 -#define _BINARY_OP_ADD_UNICODE_r03 655 -#define _BINARY_OP_ADD_UNICODE_r13 656 -#define _BINARY_OP_ADD_UNICODE_r23 657 -#define _BINARY_OP_EXTEND_r23 658 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 659 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 660 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 661 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 662 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 663 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 664 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 665 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 666 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 667 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 668 -#define _BINARY_OP_MULTIPLY_INT_r03 669 -#define _BINARY_OP_MULTIPLY_INT_r13 670 -#define _BINARY_OP_MULTIPLY_INT_r23 671 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 672 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 673 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 674 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 675 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 676 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 677 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 678 -#define _BINARY_OP_SUBSCR_DICT_r23 679 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 680 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 681 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 682 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 683 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 684 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 685 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 686 -#define _BINARY_OP_SUBSCR_STR_INT_r23 687 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 688 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 689 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 690 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 691 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 692 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 693 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 694 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 695 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 696 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 697 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 698 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 699 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 700 -#define _BINARY_OP_SUBTRACT_INT_r03 701 -#define _BINARY_OP_SUBTRACT_INT_r13 702 -#define _BINARY_OP_SUBTRACT_INT_r23 703 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 704 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 705 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 706 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 707 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 708 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 709 -#define _BINARY_SLICE_r31 710 -#define _BUILD_INTERPOLATION_r01 711 -#define _BUILD_LIST_r01 712 -#define _BUILD_MAP_r01 713 -#define _BUILD_SET_r01 714 -#define _BUILD_SLICE_r01 715 -#define _BUILD_STRING_r01 716 -#define _BUILD_TEMPLATE_r21 717 -#define _BUILD_TUPLE_r01 718 -#define _CALL_BUILTIN_CLASS_r01 719 -#define _CALL_BUILTIN_FAST_r00 720 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 721 -#define _CALL_BUILTIN_O_r03 722 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 723 -#define _CALL_INTRINSIC_1_r12 724 -#define _CALL_INTRINSIC_2_r23 725 -#define _CALL_ISINSTANCE_r31 726 -#define _CALL_KW_NON_PY_r11 727 -#define _CALL_LEN_r33 728 -#define _CALL_LIST_APPEND_r03 729 -#define _CALL_LIST_APPEND_r13 730 -#define _CALL_LIST_APPEND_r23 731 -#define _CALL_LIST_APPEND_r33 732 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 733 -#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 734 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 735 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 736 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 737 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 738 -#define _CALL_METHOD_DESCRIPTOR_O_r03 739 -#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 740 -#define _CALL_NON_PY_GENERAL_r01 741 -#define _CALL_STR_1_r32 742 -#define _CALL_TUPLE_1_r32 743 -#define _CALL_TYPE_1_r02 744 -#define _CALL_TYPE_1_r12 745 -#define _CALL_TYPE_1_r22 746 -#define _CALL_TYPE_1_r32 747 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 748 -#define _CHECK_ATTR_CLASS_r01 749 -#define _CHECK_ATTR_CLASS_r11 750 -#define _CHECK_ATTR_CLASS_r22 751 -#define _CHECK_ATTR_CLASS_r33 752 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 753 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 754 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 755 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 756 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 757 -#define _CHECK_EG_MATCH_r22 758 -#define _CHECK_EXC_MATCH_r22 759 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 760 -#define _CHECK_FUNCTION_VERSION_r00 761 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 762 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 763 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 764 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 765 -#define _CHECK_FUNCTION_VERSION_KW_r11 766 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 767 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 768 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 769 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 770 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 771 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 772 -#define _CHECK_IS_PY_CALLABLE_EX_r03 773 -#define _CHECK_IS_PY_CALLABLE_EX_r13 774 -#define _CHECK_IS_PY_CALLABLE_EX_r23 775 -#define _CHECK_IS_PY_CALLABLE_EX_r33 776 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 777 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 778 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 779 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 780 -#define _CHECK_METHOD_VERSION_r00 781 -#define _CHECK_METHOD_VERSION_KW_r11 782 -#define _CHECK_PEP_523_r00 783 -#define _CHECK_PEP_523_r11 784 -#define _CHECK_PEP_523_r22 785 -#define _CHECK_PEP_523_r33 786 -#define _CHECK_PERIODIC_r00 787 -#define _CHECK_PERIODIC_AT_END_r00 788 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 789 -#define _CHECK_RECURSION_LIMIT_r00 790 -#define _CHECK_RECURSION_LIMIT_r11 791 -#define _CHECK_RECURSION_LIMIT_r22 792 -#define _CHECK_RECURSION_LIMIT_r33 793 -#define _CHECK_RECURSION_REMAINING_r00 794 -#define _CHECK_RECURSION_REMAINING_r11 795 -#define _CHECK_RECURSION_REMAINING_r22 796 -#define _CHECK_RECURSION_REMAINING_r33 797 -#define _CHECK_STACK_SPACE_r00 798 -#define _CHECK_STACK_SPACE_OPERAND_r00 799 -#define _CHECK_STACK_SPACE_OPERAND_r11 800 -#define _CHECK_STACK_SPACE_OPERAND_r22 801 -#define _CHECK_STACK_SPACE_OPERAND_r33 802 -#define _CHECK_VALIDITY_r00 803 -#define _CHECK_VALIDITY_r11 804 -#define _CHECK_VALIDITY_r22 805 -#define _CHECK_VALIDITY_r33 806 -#define _COLD_DYNAMIC_EXIT_r00 807 -#define _COLD_EXIT_r00 808 -#define _COMPARE_OP_r21 809 -#define _COMPARE_OP_FLOAT_r03 810 -#define _COMPARE_OP_FLOAT_r13 811 -#define _COMPARE_OP_FLOAT_r23 812 -#define _COMPARE_OP_INT_r23 813 -#define _COMPARE_OP_STR_r23 814 -#define _CONTAINS_OP_r23 815 -#define _CONTAINS_OP_DICT_r23 816 -#define _CONTAINS_OP_SET_r23 817 -#define _CONVERT_VALUE_r11 818 -#define _COPY_r01 819 -#define _COPY_1_r02 820 -#define _COPY_1_r12 821 -#define _COPY_1_r23 822 -#define _COPY_2_r03 823 -#define _COPY_2_r13 824 -#define _COPY_2_r23 825 -#define _COPY_3_r03 826 -#define _COPY_3_r13 827 -#define _COPY_3_r23 828 -#define _COPY_3_r33 829 -#define _COPY_FREE_VARS_r00 830 -#define _COPY_FREE_VARS_r11 831 -#define _COPY_FREE_VARS_r22 832 -#define _COPY_FREE_VARS_r33 833 -#define _CREATE_INIT_FRAME_r01 834 -#define _DELETE_ATTR_r10 835 -#define _DELETE_DEREF_r00 836 -#define _DELETE_FAST_r00 837 -#define _DELETE_GLOBAL_r00 838 -#define _DELETE_NAME_r00 839 -#define _DELETE_SUBSCR_r20 840 -#define _DEOPT_r00 841 -#define _DEOPT_r10 842 -#define _DEOPT_r20 843 -#define _DEOPT_r30 844 -#define _DICT_MERGE_r11 845 -#define _DICT_UPDATE_r11 846 -#define _DO_CALL_r01 847 -#define _DO_CALL_FUNCTION_EX_r31 848 -#define _DO_CALL_KW_r11 849 -#define _DYNAMIC_EXIT_r00 850 -#define _DYNAMIC_EXIT_r10 851 -#define _DYNAMIC_EXIT_r20 852 -#define _DYNAMIC_EXIT_r30 853 -#define _END_FOR_r10 854 -#define _END_SEND_r31 855 -#define _ERROR_POP_N_r00 856 -#define _EXIT_INIT_CHECK_r10 857 -#define _EXIT_TRACE_r00 858 -#define _EXIT_TRACE_r10 859 -#define _EXIT_TRACE_r20 860 -#define _EXIT_TRACE_r30 861 -#define _EXPAND_METHOD_r00 862 -#define _EXPAND_METHOD_KW_r11 863 -#define _FATAL_ERROR_r00 864 -#define _FATAL_ERROR_r11 865 -#define _FATAL_ERROR_r22 866 -#define _FATAL_ERROR_r33 867 -#define _FORMAT_SIMPLE_r11 868 -#define _FORMAT_WITH_SPEC_r21 869 -#define _FOR_ITER_r23 870 -#define _FOR_ITER_GEN_FRAME_r03 871 -#define _FOR_ITER_GEN_FRAME_r13 872 -#define _FOR_ITER_GEN_FRAME_r23 873 -#define _FOR_ITER_TIER_TWO_r23 874 -#define _GET_AITER_r11 875 -#define _GET_ANEXT_r12 876 -#define _GET_AWAITABLE_r11 877 -#define _GET_ITER_r12 878 -#define _GET_LEN_r12 879 -#define _GUARD_BINARY_OP_EXTEND_r22 880 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 881 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 882 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 883 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 884 -#define _GUARD_BIT_IS_SET_POP_r00 885 -#define _GUARD_BIT_IS_SET_POP_r10 886 -#define _GUARD_BIT_IS_SET_POP_r21 887 -#define _GUARD_BIT_IS_SET_POP_r32 888 -#define _GUARD_BIT_IS_SET_POP_4_r00 889 -#define _GUARD_BIT_IS_SET_POP_4_r10 890 -#define _GUARD_BIT_IS_SET_POP_4_r21 891 -#define _GUARD_BIT_IS_SET_POP_4_r32 892 -#define _GUARD_BIT_IS_SET_POP_5_r00 893 -#define _GUARD_BIT_IS_SET_POP_5_r10 894 -#define _GUARD_BIT_IS_SET_POP_5_r21 895 -#define _GUARD_BIT_IS_SET_POP_5_r32 896 -#define _GUARD_BIT_IS_SET_POP_6_r00 897 -#define _GUARD_BIT_IS_SET_POP_6_r10 898 -#define _GUARD_BIT_IS_SET_POP_6_r21 899 -#define _GUARD_BIT_IS_SET_POP_6_r32 900 -#define _GUARD_BIT_IS_SET_POP_7_r00 901 -#define _GUARD_BIT_IS_SET_POP_7_r10 902 -#define _GUARD_BIT_IS_SET_POP_7_r21 903 -#define _GUARD_BIT_IS_SET_POP_7_r32 904 -#define _GUARD_BIT_IS_UNSET_POP_r00 905 -#define _GUARD_BIT_IS_UNSET_POP_r10 906 -#define _GUARD_BIT_IS_UNSET_POP_r21 907 -#define _GUARD_BIT_IS_UNSET_POP_r32 908 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 909 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 910 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 911 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 912 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 913 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 914 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 915 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 916 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 917 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 918 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 919 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 920 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 921 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 922 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 923 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 924 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 925 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 926 -#define _GUARD_CALLABLE_BUILTIN_O_r00 927 -#define _GUARD_CALLABLE_ISINSTANCE_r03 928 -#define _GUARD_CALLABLE_ISINSTANCE_r13 929 -#define _GUARD_CALLABLE_ISINSTANCE_r23 930 -#define _GUARD_CALLABLE_ISINSTANCE_r33 931 -#define _GUARD_CALLABLE_LEN_r03 932 -#define _GUARD_CALLABLE_LEN_r13 933 -#define _GUARD_CALLABLE_LEN_r23 934 -#define _GUARD_CALLABLE_LEN_r33 935 -#define _GUARD_CALLABLE_LIST_APPEND_r03 936 -#define _GUARD_CALLABLE_LIST_APPEND_r13 937 -#define _GUARD_CALLABLE_LIST_APPEND_r23 938 -#define _GUARD_CALLABLE_LIST_APPEND_r33 939 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 940 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 941 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 942 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 943 -#define _GUARD_CALLABLE_STR_1_r03 944 -#define _GUARD_CALLABLE_STR_1_r13 945 -#define _GUARD_CALLABLE_STR_1_r23 946 -#define _GUARD_CALLABLE_STR_1_r33 947 -#define _GUARD_CALLABLE_TUPLE_1_r03 948 -#define _GUARD_CALLABLE_TUPLE_1_r13 949 -#define _GUARD_CALLABLE_TUPLE_1_r23 950 -#define _GUARD_CALLABLE_TUPLE_1_r33 951 -#define _GUARD_CALLABLE_TYPE_1_r03 952 -#define _GUARD_CALLABLE_TYPE_1_r13 953 -#define _GUARD_CALLABLE_TYPE_1_r23 954 -#define _GUARD_CALLABLE_TYPE_1_r33 955 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 956 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 957 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 958 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 959 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 960 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 961 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 962 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 963 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 964 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 965 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 966 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 967 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 968 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 969 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 970 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 971 -#define _GUARD_DORV_NO_DICT_r01 972 -#define _GUARD_DORV_NO_DICT_r11 973 -#define _GUARD_DORV_NO_DICT_r22 974 -#define _GUARD_DORV_NO_DICT_r33 975 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 976 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 977 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 978 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 979 -#define _GUARD_GLOBALS_VERSION_r00 980 -#define _GUARD_GLOBALS_VERSION_r11 981 -#define _GUARD_GLOBALS_VERSION_r22 982 -#define _GUARD_GLOBALS_VERSION_r33 983 -#define _GUARD_IP_RETURN_GENERATOR_r00 984 -#define _GUARD_IP_RETURN_GENERATOR_r11 985 -#define _GUARD_IP_RETURN_GENERATOR_r22 986 -#define _GUARD_IP_RETURN_GENERATOR_r33 987 -#define _GUARD_IP_RETURN_VALUE_r00 988 -#define _GUARD_IP_RETURN_VALUE_r11 989 -#define _GUARD_IP_RETURN_VALUE_r22 990 -#define _GUARD_IP_RETURN_VALUE_r33 991 -#define _GUARD_IP_YIELD_VALUE_r00 992 -#define _GUARD_IP_YIELD_VALUE_r11 993 -#define _GUARD_IP_YIELD_VALUE_r22 994 -#define _GUARD_IP_YIELD_VALUE_r33 995 -#define _GUARD_IP__PUSH_FRAME_r00 996 -#define _GUARD_IP__PUSH_FRAME_r11 997 -#define _GUARD_IP__PUSH_FRAME_r22 998 -#define _GUARD_IP__PUSH_FRAME_r33 999 -#define _GUARD_IS_FALSE_POP_r00 1000 -#define _GUARD_IS_FALSE_POP_r10 1001 -#define _GUARD_IS_FALSE_POP_r21 1002 -#define _GUARD_IS_FALSE_POP_r32 1003 -#define _GUARD_IS_NONE_POP_r00 1004 -#define _GUARD_IS_NONE_POP_r10 1005 -#define _GUARD_IS_NONE_POP_r21 1006 -#define _GUARD_IS_NONE_POP_r32 1007 -#define _GUARD_IS_NOT_NONE_POP_r10 1008 -#define _GUARD_IS_TRUE_POP_r00 1009 -#define _GUARD_IS_TRUE_POP_r10 1010 -#define _GUARD_IS_TRUE_POP_r21 1011 -#define _GUARD_IS_TRUE_POP_r32 1012 -#define _GUARD_KEYS_VERSION_r01 1013 -#define _GUARD_KEYS_VERSION_r11 1014 -#define _GUARD_KEYS_VERSION_r22 1015 -#define _GUARD_KEYS_VERSION_r33 1016 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1017 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1018 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1019 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1020 -#define _GUARD_NOS_ANY_DICT_r02 1021 -#define _GUARD_NOS_ANY_DICT_r12 1022 -#define _GUARD_NOS_ANY_DICT_r22 1023 -#define _GUARD_NOS_ANY_DICT_r33 1024 -#define _GUARD_NOS_COMPACT_ASCII_r02 1025 -#define _GUARD_NOS_COMPACT_ASCII_r12 1026 -#define _GUARD_NOS_COMPACT_ASCII_r22 1027 -#define _GUARD_NOS_COMPACT_ASCII_r33 1028 -#define _GUARD_NOS_DICT_r02 1029 -#define _GUARD_NOS_DICT_r12 1030 -#define _GUARD_NOS_DICT_r22 1031 -#define _GUARD_NOS_DICT_r33 1032 -#define _GUARD_NOS_FLOAT_r02 1033 -#define _GUARD_NOS_FLOAT_r12 1034 -#define _GUARD_NOS_FLOAT_r22 1035 -#define _GUARD_NOS_FLOAT_r33 1036 -#define _GUARD_NOS_INT_r02 1037 -#define _GUARD_NOS_INT_r12 1038 -#define _GUARD_NOS_INT_r22 1039 -#define _GUARD_NOS_INT_r33 1040 -#define _GUARD_NOS_LIST_r02 1041 -#define _GUARD_NOS_LIST_r12 1042 -#define _GUARD_NOS_LIST_r22 1043 -#define _GUARD_NOS_LIST_r33 1044 -#define _GUARD_NOS_NOT_NULL_r02 1045 -#define _GUARD_NOS_NOT_NULL_r12 1046 -#define _GUARD_NOS_NOT_NULL_r22 1047 -#define _GUARD_NOS_NOT_NULL_r33 1048 -#define _GUARD_NOS_NULL_r02 1049 -#define _GUARD_NOS_NULL_r12 1050 -#define _GUARD_NOS_NULL_r22 1051 -#define _GUARD_NOS_NULL_r33 1052 -#define _GUARD_NOS_OVERFLOWED_r02 1053 -#define _GUARD_NOS_OVERFLOWED_r12 1054 -#define _GUARD_NOS_OVERFLOWED_r22 1055 -#define _GUARD_NOS_OVERFLOWED_r33 1056 -#define _GUARD_NOS_TUPLE_r02 1057 -#define _GUARD_NOS_TUPLE_r12 1058 -#define _GUARD_NOS_TUPLE_r22 1059 -#define _GUARD_NOS_TUPLE_r33 1060 -#define _GUARD_NOS_TYPE_VERSION_r02 1061 -#define _GUARD_NOS_TYPE_VERSION_r12 1062 -#define _GUARD_NOS_TYPE_VERSION_r22 1063 -#define _GUARD_NOS_TYPE_VERSION_r33 1064 -#define _GUARD_NOS_UNICODE_r02 1065 -#define _GUARD_NOS_UNICODE_r12 1066 -#define _GUARD_NOS_UNICODE_r22 1067 -#define _GUARD_NOS_UNICODE_r33 1068 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1069 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1070 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1071 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1072 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1073 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1074 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1075 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1076 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1077 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1078 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1079 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1080 -#define _GUARD_THIRD_NULL_r03 1081 -#define _GUARD_THIRD_NULL_r13 1082 -#define _GUARD_THIRD_NULL_r23 1083 -#define _GUARD_THIRD_NULL_r33 1084 -#define _GUARD_TOS_ANY_DICT_r01 1085 -#define _GUARD_TOS_ANY_DICT_r11 1086 -#define _GUARD_TOS_ANY_DICT_r22 1087 -#define _GUARD_TOS_ANY_DICT_r33 1088 -#define _GUARD_TOS_ANY_SET_r01 1089 -#define _GUARD_TOS_ANY_SET_r11 1090 -#define _GUARD_TOS_ANY_SET_r22 1091 -#define _GUARD_TOS_ANY_SET_r33 1092 -#define _GUARD_TOS_DICT_r01 1093 -#define _GUARD_TOS_DICT_r11 1094 -#define _GUARD_TOS_DICT_r22 1095 -#define _GUARD_TOS_DICT_r33 1096 -#define _GUARD_TOS_FLOAT_r01 1097 -#define _GUARD_TOS_FLOAT_r11 1098 -#define _GUARD_TOS_FLOAT_r22 1099 -#define _GUARD_TOS_FLOAT_r33 1100 -#define _GUARD_TOS_FROZENDICT_r01 1101 -#define _GUARD_TOS_FROZENDICT_r11 1102 -#define _GUARD_TOS_FROZENDICT_r22 1103 -#define _GUARD_TOS_FROZENDICT_r33 1104 -#define _GUARD_TOS_FROZENSET_r01 1105 -#define _GUARD_TOS_FROZENSET_r11 1106 -#define _GUARD_TOS_FROZENSET_r22 1107 -#define _GUARD_TOS_FROZENSET_r33 1108 -#define _GUARD_TOS_INT_r01 1109 -#define _GUARD_TOS_INT_r11 1110 -#define _GUARD_TOS_INT_r22 1111 -#define _GUARD_TOS_INT_r33 1112 -#define _GUARD_TOS_LIST_r01 1113 -#define _GUARD_TOS_LIST_r11 1114 -#define _GUARD_TOS_LIST_r22 1115 -#define _GUARD_TOS_LIST_r33 1116 -#define _GUARD_TOS_OVERFLOWED_r01 1117 -#define _GUARD_TOS_OVERFLOWED_r11 1118 -#define _GUARD_TOS_OVERFLOWED_r22 1119 -#define _GUARD_TOS_OVERFLOWED_r33 1120 -#define _GUARD_TOS_SET_r01 1121 -#define _GUARD_TOS_SET_r11 1122 -#define _GUARD_TOS_SET_r22 1123 -#define _GUARD_TOS_SET_r33 1124 -#define _GUARD_TOS_SLICE_r01 1125 -#define _GUARD_TOS_SLICE_r11 1126 -#define _GUARD_TOS_SLICE_r22 1127 -#define _GUARD_TOS_SLICE_r33 1128 -#define _GUARD_TOS_TUPLE_r01 1129 -#define _GUARD_TOS_TUPLE_r11 1130 -#define _GUARD_TOS_TUPLE_r22 1131 -#define _GUARD_TOS_TUPLE_r33 1132 -#define _GUARD_TOS_UNICODE_r01 1133 -#define _GUARD_TOS_UNICODE_r11 1134 -#define _GUARD_TOS_UNICODE_r22 1135 -#define _GUARD_TOS_UNICODE_r33 1136 -#define _GUARD_TYPE_VERSION_r01 1137 -#define _GUARD_TYPE_VERSION_r11 1138 -#define _GUARD_TYPE_VERSION_r22 1139 -#define _GUARD_TYPE_VERSION_r33 1140 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1141 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1142 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1143 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1144 -#define _HANDLE_PENDING_AND_DEOPT_r00 1145 -#define _HANDLE_PENDING_AND_DEOPT_r10 1146 -#define _HANDLE_PENDING_AND_DEOPT_r20 1147 -#define _HANDLE_PENDING_AND_DEOPT_r30 1148 -#define _IMPORT_FROM_r12 1149 -#define _IMPORT_NAME_r21 1150 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1151 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1152 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1153 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1154 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1155 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1156 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1157 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1158 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1159 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1160 -#define _INSERT_NULL_r10 1161 -#define _INSTRUMENTED_FOR_ITER_r23 1162 -#define _INSTRUMENTED_INSTRUCTION_r00 1163 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1164 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1165 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1166 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1167 -#define _INSTRUMENTED_LINE_r00 1168 -#define _INSTRUMENTED_NOT_TAKEN_r00 1169 -#define _INSTRUMENTED_NOT_TAKEN_r11 1170 -#define _INSTRUMENTED_NOT_TAKEN_r22 1171 -#define _INSTRUMENTED_NOT_TAKEN_r33 1172 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1173 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1174 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1175 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1176 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1177 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1178 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1179 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1180 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1181 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1182 -#define _IS_NONE_r11 1183 -#define _IS_OP_r03 1184 -#define _IS_OP_r13 1185 -#define _IS_OP_r23 1186 -#define _ITER_CHECK_LIST_r02 1187 -#define _ITER_CHECK_LIST_r12 1188 -#define _ITER_CHECK_LIST_r22 1189 -#define _ITER_CHECK_LIST_r33 1190 -#define _ITER_CHECK_RANGE_r02 1191 -#define _ITER_CHECK_RANGE_r12 1192 -#define _ITER_CHECK_RANGE_r22 1193 -#define _ITER_CHECK_RANGE_r33 1194 -#define _ITER_CHECK_TUPLE_r02 1195 -#define _ITER_CHECK_TUPLE_r12 1196 -#define _ITER_CHECK_TUPLE_r22 1197 -#define _ITER_CHECK_TUPLE_r33 1198 -#define _ITER_JUMP_LIST_r02 1199 -#define _ITER_JUMP_LIST_r12 1200 -#define _ITER_JUMP_LIST_r22 1201 -#define _ITER_JUMP_LIST_r33 1202 -#define _ITER_JUMP_RANGE_r02 1203 -#define _ITER_JUMP_RANGE_r12 1204 -#define _ITER_JUMP_RANGE_r22 1205 -#define _ITER_JUMP_RANGE_r33 1206 -#define _ITER_JUMP_TUPLE_r02 1207 -#define _ITER_JUMP_TUPLE_r12 1208 -#define _ITER_JUMP_TUPLE_r22 1209 -#define _ITER_JUMP_TUPLE_r33 1210 -#define _ITER_NEXT_LIST_r23 1211 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1212 -#define _ITER_NEXT_RANGE_r03 1213 -#define _ITER_NEXT_RANGE_r13 1214 -#define _ITER_NEXT_RANGE_r23 1215 -#define _ITER_NEXT_TUPLE_r03 1216 -#define _ITER_NEXT_TUPLE_r13 1217 -#define _ITER_NEXT_TUPLE_r23 1218 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1219 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1220 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1221 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1222 -#define _JUMP_TO_TOP_r00 1223 -#define _LIST_APPEND_r10 1224 -#define _LIST_EXTEND_r11 1225 -#define _LOAD_ATTR_r10 1226 -#define _LOAD_ATTR_CLASS_r11 1227 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1228 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1229 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1230 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1231 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1232 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1233 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1234 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1235 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1236 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1237 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1238 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1239 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1240 -#define _LOAD_ATTR_MODULE_r12 1241 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1242 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1243 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1244 -#define _LOAD_ATTR_SLOT_r02 1245 -#define _LOAD_ATTR_SLOT_r12 1246 -#define _LOAD_ATTR_SLOT_r23 1247 -#define _LOAD_ATTR_WITH_HINT_r12 1248 -#define _LOAD_BUILD_CLASS_r01 1249 -#define _LOAD_BYTECODE_r00 1250 -#define _LOAD_COMMON_CONSTANT_r01 1251 -#define _LOAD_COMMON_CONSTANT_r12 1252 -#define _LOAD_COMMON_CONSTANT_r23 1253 -#define _LOAD_CONST_r01 1254 -#define _LOAD_CONST_r12 1255 -#define _LOAD_CONST_r23 1256 -#define _LOAD_CONST_INLINE_r01 1257 -#define _LOAD_CONST_INLINE_r12 1258 -#define _LOAD_CONST_INLINE_r23 1259 -#define _LOAD_CONST_INLINE_BORROW_r01 1260 -#define _LOAD_CONST_INLINE_BORROW_r12 1261 -#define _LOAD_CONST_INLINE_BORROW_r23 1262 -#define _LOAD_DEREF_r01 1263 -#define _LOAD_FAST_r01 1264 -#define _LOAD_FAST_r12 1265 -#define _LOAD_FAST_r23 1266 -#define _LOAD_FAST_0_r01 1267 -#define _LOAD_FAST_0_r12 1268 -#define _LOAD_FAST_0_r23 1269 -#define _LOAD_FAST_1_r01 1270 -#define _LOAD_FAST_1_r12 1271 -#define _LOAD_FAST_1_r23 1272 -#define _LOAD_FAST_2_r01 1273 -#define _LOAD_FAST_2_r12 1274 -#define _LOAD_FAST_2_r23 1275 -#define _LOAD_FAST_3_r01 1276 -#define _LOAD_FAST_3_r12 1277 -#define _LOAD_FAST_3_r23 1278 -#define _LOAD_FAST_4_r01 1279 -#define _LOAD_FAST_4_r12 1280 -#define _LOAD_FAST_4_r23 1281 -#define _LOAD_FAST_5_r01 1282 -#define _LOAD_FAST_5_r12 1283 -#define _LOAD_FAST_5_r23 1284 -#define _LOAD_FAST_6_r01 1285 -#define _LOAD_FAST_6_r12 1286 -#define _LOAD_FAST_6_r23 1287 -#define _LOAD_FAST_7_r01 1288 -#define _LOAD_FAST_7_r12 1289 -#define _LOAD_FAST_7_r23 1290 -#define _LOAD_FAST_AND_CLEAR_r01 1291 -#define _LOAD_FAST_AND_CLEAR_r12 1292 -#define _LOAD_FAST_AND_CLEAR_r23 1293 -#define _LOAD_FAST_BORROW_r01 1294 -#define _LOAD_FAST_BORROW_r12 1295 -#define _LOAD_FAST_BORROW_r23 1296 -#define _LOAD_FAST_BORROW_0_r01 1297 -#define _LOAD_FAST_BORROW_0_r12 1298 -#define _LOAD_FAST_BORROW_0_r23 1299 -#define _LOAD_FAST_BORROW_1_r01 1300 -#define _LOAD_FAST_BORROW_1_r12 1301 -#define _LOAD_FAST_BORROW_1_r23 1302 -#define _LOAD_FAST_BORROW_2_r01 1303 -#define _LOAD_FAST_BORROW_2_r12 1304 -#define _LOAD_FAST_BORROW_2_r23 1305 -#define _LOAD_FAST_BORROW_3_r01 1306 -#define _LOAD_FAST_BORROW_3_r12 1307 -#define _LOAD_FAST_BORROW_3_r23 1308 -#define _LOAD_FAST_BORROW_4_r01 1309 -#define _LOAD_FAST_BORROW_4_r12 1310 -#define _LOAD_FAST_BORROW_4_r23 1311 -#define _LOAD_FAST_BORROW_5_r01 1312 -#define _LOAD_FAST_BORROW_5_r12 1313 -#define _LOAD_FAST_BORROW_5_r23 1314 -#define _LOAD_FAST_BORROW_6_r01 1315 -#define _LOAD_FAST_BORROW_6_r12 1316 -#define _LOAD_FAST_BORROW_6_r23 1317 -#define _LOAD_FAST_BORROW_7_r01 1318 -#define _LOAD_FAST_BORROW_7_r12 1319 -#define _LOAD_FAST_BORROW_7_r23 1320 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1321 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1322 -#define _LOAD_FAST_CHECK_r01 1323 -#define _LOAD_FAST_CHECK_r12 1324 -#define _LOAD_FAST_CHECK_r23 1325 -#define _LOAD_FAST_LOAD_FAST_r02 1326 -#define _LOAD_FAST_LOAD_FAST_r13 1327 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1328 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1329 -#define _LOAD_GLOBAL_r00 1330 -#define _LOAD_GLOBAL_BUILTINS_r01 1331 -#define _LOAD_GLOBAL_MODULE_r01 1332 -#define _LOAD_LOCALS_r01 1333 -#define _LOAD_LOCALS_r12 1334 -#define _LOAD_LOCALS_r23 1335 -#define _LOAD_NAME_r01 1336 -#define _LOAD_SMALL_INT_r01 1337 -#define _LOAD_SMALL_INT_r12 1338 -#define _LOAD_SMALL_INT_r23 1339 -#define _LOAD_SMALL_INT_0_r01 1340 -#define _LOAD_SMALL_INT_0_r12 1341 -#define _LOAD_SMALL_INT_0_r23 1342 -#define _LOAD_SMALL_INT_1_r01 1343 -#define _LOAD_SMALL_INT_1_r12 1344 -#define _LOAD_SMALL_INT_1_r23 1345 -#define _LOAD_SMALL_INT_2_r01 1346 -#define _LOAD_SMALL_INT_2_r12 1347 -#define _LOAD_SMALL_INT_2_r23 1348 -#define _LOAD_SMALL_INT_3_r01 1349 -#define _LOAD_SMALL_INT_3_r12 1350 -#define _LOAD_SMALL_INT_3_r23 1351 -#define _LOAD_SPECIAL_r00 1352 -#define _LOAD_SUPER_ATTR_ATTR_r31 1353 -#define _LOAD_SUPER_ATTR_METHOD_r32 1354 -#define _LOCK_OBJECT_r01 1355 -#define _LOCK_OBJECT_r11 1356 -#define _LOCK_OBJECT_r22 1357 -#define _LOCK_OBJECT_r33 1358 -#define _MAKE_CALLARGS_A_TUPLE_r33 1359 -#define _MAKE_CELL_r00 1360 -#define _MAKE_FUNCTION_r12 1361 -#define _MAKE_HEAP_SAFE_r01 1362 -#define _MAKE_HEAP_SAFE_r11 1363 -#define _MAKE_HEAP_SAFE_r22 1364 -#define _MAKE_HEAP_SAFE_r33 1365 -#define _MAKE_WARM_r00 1366 -#define _MAKE_WARM_r11 1367 -#define _MAKE_WARM_r22 1368 -#define _MAKE_WARM_r33 1369 -#define _MAP_ADD_r20 1370 -#define _MATCH_CLASS_r33 1371 -#define _MATCH_KEYS_r23 1372 -#define _MATCH_MAPPING_r02 1373 -#define _MATCH_MAPPING_r12 1374 -#define _MATCH_MAPPING_r23 1375 -#define _MATCH_SEQUENCE_r02 1376 -#define _MATCH_SEQUENCE_r12 1377 -#define _MATCH_SEQUENCE_r23 1378 -#define _MAYBE_EXPAND_METHOD_r00 1379 -#define _MAYBE_EXPAND_METHOD_KW_r11 1380 -#define _MONITOR_CALL_r00 1381 -#define _MONITOR_CALL_KW_r11 1382 -#define _MONITOR_JUMP_BACKWARD_r00 1383 -#define _MONITOR_JUMP_BACKWARD_r11 1384 -#define _MONITOR_JUMP_BACKWARD_r22 1385 -#define _MONITOR_JUMP_BACKWARD_r33 1386 -#define _MONITOR_RESUME_r00 1387 -#define _NOP_r00 1388 -#define _NOP_r11 1389 -#define _NOP_r22 1390 -#define _NOP_r33 1391 -#define _POP_CALL_r20 1392 -#define _POP_CALL_ONE_r30 1393 -#define _POP_CALL_TWO_r30 1394 -#define _POP_EXCEPT_r10 1395 -#define _POP_ITER_r20 1396 -#define _POP_JUMP_IF_FALSE_r00 1397 -#define _POP_JUMP_IF_FALSE_r10 1398 -#define _POP_JUMP_IF_FALSE_r21 1399 -#define _POP_JUMP_IF_FALSE_r32 1400 -#define _POP_JUMP_IF_TRUE_r00 1401 -#define _POP_JUMP_IF_TRUE_r10 1402 -#define _POP_JUMP_IF_TRUE_r21 1403 -#define _POP_JUMP_IF_TRUE_r32 1404 -#define _POP_TOP_r10 1405 -#define _POP_TOP_FLOAT_r00 1406 -#define _POP_TOP_FLOAT_r10 1407 -#define _POP_TOP_FLOAT_r21 1408 -#define _POP_TOP_FLOAT_r32 1409 -#define _POP_TOP_INT_r00 1410 -#define _POP_TOP_INT_r10 1411 -#define _POP_TOP_INT_r21 1412 -#define _POP_TOP_INT_r32 1413 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1414 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1415 -#define _POP_TOP_NOP_r00 1416 -#define _POP_TOP_NOP_r10 1417 -#define _POP_TOP_NOP_r21 1418 -#define _POP_TOP_NOP_r32 1419 -#define _POP_TOP_OPARG_r00 1420 -#define _POP_TOP_UNICODE_r00 1421 -#define _POP_TOP_UNICODE_r10 1422 -#define _POP_TOP_UNICODE_r21 1423 -#define _POP_TOP_UNICODE_r32 1424 -#define _POP_TWO_r20 1425 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1426 -#define _PUSH_EXC_INFO_r02 1427 -#define _PUSH_EXC_INFO_r12 1428 -#define _PUSH_EXC_INFO_r23 1429 -#define _PUSH_FRAME_r10 1430 -#define _PUSH_NULL_r01 1431 -#define _PUSH_NULL_r12 1432 -#define _PUSH_NULL_r23 1433 -#define _PUSH_NULL_CONDITIONAL_r00 1434 -#define _PY_FRAME_EX_r31 1435 -#define _PY_FRAME_GENERAL_r01 1436 -#define _PY_FRAME_KW_r11 1437 -#define _REPLACE_WITH_TRUE_r02 1438 -#define _REPLACE_WITH_TRUE_r12 1439 -#define _REPLACE_WITH_TRUE_r23 1440 -#define _RESUME_CHECK_r00 1441 -#define _RESUME_CHECK_r11 1442 -#define _RESUME_CHECK_r22 1443 -#define _RESUME_CHECK_r33 1444 -#define _RETURN_GENERATOR_r01 1445 -#define _RETURN_VALUE_r11 1446 -#define _SAVE_RETURN_OFFSET_r00 1447 -#define _SAVE_RETURN_OFFSET_r11 1448 -#define _SAVE_RETURN_OFFSET_r22 1449 -#define _SAVE_RETURN_OFFSET_r33 1450 -#define _SEND_r33 1451 -#define _SEND_GEN_FRAME_r33 1452 -#define _SETUP_ANNOTATIONS_r00 1453 -#define _SET_ADD_r10 1454 -#define _SET_FUNCTION_ATTRIBUTE_r01 1455 -#define _SET_FUNCTION_ATTRIBUTE_r11 1456 -#define _SET_FUNCTION_ATTRIBUTE_r21 1457 -#define _SET_FUNCTION_ATTRIBUTE_r32 1458 -#define _SET_IP_r00 1459 -#define _SET_IP_r11 1460 -#define _SET_IP_r22 1461 -#define _SET_IP_r33 1462 -#define _SET_UPDATE_r11 1463 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1464 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1465 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1466 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1467 -#define _SPILL_OR_RELOAD_r01 1468 -#define _SPILL_OR_RELOAD_r02 1469 -#define _SPILL_OR_RELOAD_r03 1470 -#define _SPILL_OR_RELOAD_r10 1471 -#define _SPILL_OR_RELOAD_r12 1472 -#define _SPILL_OR_RELOAD_r13 1473 -#define _SPILL_OR_RELOAD_r20 1474 -#define _SPILL_OR_RELOAD_r21 1475 -#define _SPILL_OR_RELOAD_r23 1476 -#define _SPILL_OR_RELOAD_r30 1477 -#define _SPILL_OR_RELOAD_r31 1478 -#define _SPILL_OR_RELOAD_r32 1479 -#define _START_EXECUTOR_r00 1480 -#define _STORE_ATTR_r20 1481 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1482 -#define _STORE_ATTR_SLOT_r21 1483 -#define _STORE_ATTR_WITH_HINT_r21 1484 -#define _STORE_DEREF_r10 1485 -#define _STORE_FAST_LOAD_FAST_r11 1486 -#define _STORE_FAST_STORE_FAST_r20 1487 -#define _STORE_GLOBAL_r10 1488 -#define _STORE_NAME_r10 1489 -#define _STORE_SLICE_r30 1490 -#define _STORE_SUBSCR_r30 1491 -#define _STORE_SUBSCR_DICT_r31 1492 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1493 -#define _STORE_SUBSCR_LIST_INT_r32 1494 -#define _SWAP_r11 1495 -#define _SWAP_2_r02 1496 -#define _SWAP_2_r12 1497 -#define _SWAP_2_r22 1498 -#define _SWAP_2_r33 1499 -#define _SWAP_3_r03 1500 -#define _SWAP_3_r13 1501 -#define _SWAP_3_r23 1502 -#define _SWAP_3_r33 1503 -#define _SWAP_FAST_r01 1504 -#define _SWAP_FAST_r11 1505 -#define _SWAP_FAST_r22 1506 -#define _SWAP_FAST_r33 1507 -#define _SWAP_FAST_0_r01 1508 -#define _SWAP_FAST_0_r11 1509 -#define _SWAP_FAST_0_r22 1510 -#define _SWAP_FAST_0_r33 1511 -#define _SWAP_FAST_1_r01 1512 -#define _SWAP_FAST_1_r11 1513 -#define _SWAP_FAST_1_r22 1514 -#define _SWAP_FAST_1_r33 1515 -#define _SWAP_FAST_2_r01 1516 -#define _SWAP_FAST_2_r11 1517 -#define _SWAP_FAST_2_r22 1518 -#define _SWAP_FAST_2_r33 1519 -#define _SWAP_FAST_3_r01 1520 -#define _SWAP_FAST_3_r11 1521 -#define _SWAP_FAST_3_r22 1522 -#define _SWAP_FAST_3_r33 1523 -#define _SWAP_FAST_4_r01 1524 -#define _SWAP_FAST_4_r11 1525 -#define _SWAP_FAST_4_r22 1526 -#define _SWAP_FAST_4_r33 1527 -#define _SWAP_FAST_5_r01 1528 -#define _SWAP_FAST_5_r11 1529 -#define _SWAP_FAST_5_r22 1530 -#define _SWAP_FAST_5_r33 1531 -#define _SWAP_FAST_6_r01 1532 -#define _SWAP_FAST_6_r11 1533 -#define _SWAP_FAST_6_r22 1534 -#define _SWAP_FAST_6_r33 1535 -#define _SWAP_FAST_7_r01 1536 -#define _SWAP_FAST_7_r11 1537 -#define _SWAP_FAST_7_r22 1538 -#define _SWAP_FAST_7_r33 1539 -#define _TIER2_RESUME_CHECK_r00 1540 -#define _TIER2_RESUME_CHECK_r11 1541 -#define _TIER2_RESUME_CHECK_r22 1542 -#define _TIER2_RESUME_CHECK_r33 1543 -#define _TO_BOOL_r11 1544 -#define _TO_BOOL_BOOL_r01 1545 -#define _TO_BOOL_BOOL_r11 1546 -#define _TO_BOOL_BOOL_r22 1547 -#define _TO_BOOL_BOOL_r33 1548 -#define _TO_BOOL_INT_r02 1549 -#define _TO_BOOL_INT_r12 1550 -#define _TO_BOOL_INT_r23 1551 -#define _TO_BOOL_LIST_r02 1552 -#define _TO_BOOL_LIST_r12 1553 -#define _TO_BOOL_LIST_r23 1554 -#define _TO_BOOL_NONE_r01 1555 -#define _TO_BOOL_NONE_r11 1556 -#define _TO_BOOL_NONE_r22 1557 -#define _TO_BOOL_NONE_r33 1558 -#define _TO_BOOL_STR_r02 1559 -#define _TO_BOOL_STR_r12 1560 -#define _TO_BOOL_STR_r23 1561 -#define _TRACE_RECORD_r00 1562 -#define _UNARY_INVERT_r12 1563 -#define _UNARY_NEGATIVE_r12 1564 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1565 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1566 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1567 -#define _UNARY_NOT_r01 1568 -#define _UNARY_NOT_r11 1569 -#define _UNARY_NOT_r22 1570 -#define _UNARY_NOT_r33 1571 -#define _UNPACK_EX_r10 1572 -#define _UNPACK_SEQUENCE_r10 1573 -#define _UNPACK_SEQUENCE_LIST_r10 1574 -#define _UNPACK_SEQUENCE_TUPLE_r10 1575 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1576 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1577 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1578 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1579 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1580 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1581 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1582 -#define _WITH_EXCEPT_START_r33 1583 -#define _YIELD_VALUE_r11 1584 -#define MAX_UOP_REGS_ID 1584 +#define _YIELD_VALUE 646 +#define MAX_UOP_ID 646 +#define _ALLOCATE_OBJECT_r00 647 +#define _BINARY_OP_r23 648 +#define _BINARY_OP_ADD_FLOAT_r03 649 +#define _BINARY_OP_ADD_FLOAT_r13 650 +#define _BINARY_OP_ADD_FLOAT_r23 651 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 652 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 653 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 654 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 655 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 656 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 657 +#define _BINARY_OP_ADD_INT_r03 658 +#define _BINARY_OP_ADD_INT_r13 659 +#define _BINARY_OP_ADD_INT_r23 660 +#define _BINARY_OP_ADD_INT_INPLACE_r03 661 +#define _BINARY_OP_ADD_INT_INPLACE_r13 662 +#define _BINARY_OP_ADD_INT_INPLACE_r23 663 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 664 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 665 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 666 +#define _BINARY_OP_ADD_UNICODE_r03 667 +#define _BINARY_OP_ADD_UNICODE_r13 668 +#define _BINARY_OP_ADD_UNICODE_r23 669 +#define _BINARY_OP_EXTEND_r23 670 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 671 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 672 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 673 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 674 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 675 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 676 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 677 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_MULTIPLY_INT_r03 681 +#define _BINARY_OP_MULTIPLY_INT_r13 682 +#define _BINARY_OP_MULTIPLY_INT_r23 683 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 684 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 685 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 686 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 687 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 688 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 689 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 690 +#define _BINARY_OP_SUBSCR_DICT_r23 691 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 692 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 693 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 694 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 695 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 696 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 697 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 698 +#define _BINARY_OP_SUBSCR_STR_INT_r23 699 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 700 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 701 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 702 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 703 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 704 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 705 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 706 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 707 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 708 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 709 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 710 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 711 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 712 +#define _BINARY_OP_SUBTRACT_INT_r03 713 +#define _BINARY_OP_SUBTRACT_INT_r13 714 +#define _BINARY_OP_SUBTRACT_INT_r23 715 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 716 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 717 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 718 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 719 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 720 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 721 +#define _BINARY_OP_TRUEDIV_FLOAT_r23 722 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 723 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 724 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 725 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 726 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 727 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 728 +#define _BINARY_SLICE_r31 729 +#define _BUILD_INTERPOLATION_r01 730 +#define _BUILD_LIST_r01 731 +#define _BUILD_MAP_r01 732 +#define _BUILD_SET_r01 733 +#define _BUILD_SLICE_r01 734 +#define _BUILD_STRING_r01 735 +#define _BUILD_TEMPLATE_r21 736 +#define _BUILD_TUPLE_r01 737 +#define _CALL_BUILTIN_CLASS_r00 738 +#define _CALL_BUILTIN_FAST_r00 739 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 740 +#define _CALL_BUILTIN_O_r03 741 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 742 +#define _CALL_INTRINSIC_1_r12 743 +#define _CALL_INTRINSIC_2_r23 744 +#define _CALL_ISINSTANCE_r31 745 +#define _CALL_KW_NON_PY_r11 746 +#define _CALL_LEN_r33 747 +#define _CALL_LIST_APPEND_r03 748 +#define _CALL_LIST_APPEND_r13 749 +#define _CALL_LIST_APPEND_r23 750 +#define _CALL_LIST_APPEND_r33 751 +#define _CALL_METHOD_DESCRIPTOR_FAST_r00 752 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 753 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 754 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 755 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 756 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 757 +#define _CALL_METHOD_DESCRIPTOR_O_r03 758 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 759 +#define _CALL_NON_PY_GENERAL_r01 760 +#define _CALL_STR_1_r32 761 +#define _CALL_TUPLE_1_r32 762 +#define _CALL_TYPE_1_r02 763 +#define _CALL_TYPE_1_r12 764 +#define _CALL_TYPE_1_r22 765 +#define _CALL_TYPE_1_r32 766 +#define _CHECK_ATTR_CLASS_r01 767 +#define _CHECK_ATTR_CLASS_r11 768 +#define _CHECK_ATTR_CLASS_r22 769 +#define _CHECK_ATTR_CLASS_r33 770 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 771 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 772 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 773 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 774 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 775 +#define _CHECK_EG_MATCH_r22 776 +#define _CHECK_EXC_MATCH_r22 777 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 778 +#define _CHECK_FUNCTION_VERSION_r00 779 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 780 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 781 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 782 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 783 +#define _CHECK_FUNCTION_VERSION_KW_r11 784 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 785 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 786 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 787 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 788 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 789 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 790 +#define _CHECK_IS_PY_CALLABLE_EX_r03 791 +#define _CHECK_IS_PY_CALLABLE_EX_r13 792 +#define _CHECK_IS_PY_CALLABLE_EX_r23 793 +#define _CHECK_IS_PY_CALLABLE_EX_r33 794 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 795 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 796 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 797 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 798 +#define _CHECK_METHOD_VERSION_r00 799 +#define _CHECK_METHOD_VERSION_KW_r11 800 +#define _CHECK_OBJECT_r00 801 +#define _CHECK_PEP_523_r00 802 +#define _CHECK_PEP_523_r11 803 +#define _CHECK_PEP_523_r22 804 +#define _CHECK_PEP_523_r33 805 +#define _CHECK_PERIODIC_r00 806 +#define _CHECK_PERIODIC_AT_END_r00 807 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 808 +#define _CHECK_RECURSION_LIMIT_r00 809 +#define _CHECK_RECURSION_LIMIT_r11 810 +#define _CHECK_RECURSION_LIMIT_r22 811 +#define _CHECK_RECURSION_LIMIT_r33 812 +#define _CHECK_RECURSION_REMAINING_r00 813 +#define _CHECK_RECURSION_REMAINING_r11 814 +#define _CHECK_RECURSION_REMAINING_r22 815 +#define _CHECK_RECURSION_REMAINING_r33 816 +#define _CHECK_STACK_SPACE_r00 817 +#define _CHECK_STACK_SPACE_OPERAND_r00 818 +#define _CHECK_STACK_SPACE_OPERAND_r11 819 +#define _CHECK_STACK_SPACE_OPERAND_r22 820 +#define _CHECK_STACK_SPACE_OPERAND_r33 821 +#define _CHECK_VALIDITY_r00 822 +#define _CHECK_VALIDITY_r11 823 +#define _CHECK_VALIDITY_r22 824 +#define _CHECK_VALIDITY_r33 825 +#define _COLD_DYNAMIC_EXIT_r00 826 +#define _COLD_EXIT_r00 827 +#define _COMPARE_OP_r21 828 +#define _COMPARE_OP_FLOAT_r03 829 +#define _COMPARE_OP_FLOAT_r13 830 +#define _COMPARE_OP_FLOAT_r23 831 +#define _COMPARE_OP_INT_r23 832 +#define _COMPARE_OP_STR_r23 833 +#define _CONTAINS_OP_r23 834 +#define _CONTAINS_OP_DICT_r23 835 +#define _CONTAINS_OP_SET_r23 836 +#define _CONVERT_VALUE_r11 837 +#define _COPY_r01 838 +#define _COPY_1_r02 839 +#define _COPY_1_r12 840 +#define _COPY_1_r23 841 +#define _COPY_2_r03 842 +#define _COPY_2_r13 843 +#define _COPY_2_r23 844 +#define _COPY_3_r03 845 +#define _COPY_3_r13 846 +#define _COPY_3_r23 847 +#define _COPY_3_r33 848 +#define _COPY_FREE_VARS_r00 849 +#define _COPY_FREE_VARS_r11 850 +#define _COPY_FREE_VARS_r22 851 +#define _COPY_FREE_VARS_r33 852 +#define _CREATE_INIT_FRAME_r01 853 +#define _DELETE_ATTR_r10 854 +#define _DELETE_DEREF_r00 855 +#define _DELETE_FAST_r00 856 +#define _DELETE_GLOBAL_r00 857 +#define _DELETE_NAME_r00 858 +#define _DELETE_SUBSCR_r20 859 +#define _DEOPT_r00 860 +#define _DEOPT_r10 861 +#define _DEOPT_r20 862 +#define _DEOPT_r30 863 +#define _DICT_MERGE_r11 864 +#define _DICT_UPDATE_r11 865 +#define _DO_CALL_r01 866 +#define _DO_CALL_FUNCTION_EX_r31 867 +#define _DO_CALL_KW_r11 868 +#define _DYNAMIC_EXIT_r00 869 +#define _DYNAMIC_EXIT_r10 870 +#define _DYNAMIC_EXIT_r20 871 +#define _DYNAMIC_EXIT_r30 872 +#define _END_FOR_r10 873 +#define _END_SEND_r31 874 +#define _ERROR_POP_N_r00 875 +#define _EXIT_INIT_CHECK_r10 876 +#define _EXIT_TRACE_r00 877 +#define _EXIT_TRACE_r10 878 +#define _EXIT_TRACE_r20 879 +#define _EXIT_TRACE_r30 880 +#define _EXPAND_METHOD_r00 881 +#define _EXPAND_METHOD_KW_r11 882 +#define _FATAL_ERROR_r00 883 +#define _FATAL_ERROR_r11 884 +#define _FATAL_ERROR_r22 885 +#define _FATAL_ERROR_r33 886 +#define _FORMAT_SIMPLE_r11 887 +#define _FORMAT_WITH_SPEC_r21 888 +#define _FOR_ITER_r23 889 +#define _FOR_ITER_GEN_FRAME_r03 890 +#define _FOR_ITER_GEN_FRAME_r13 891 +#define _FOR_ITER_GEN_FRAME_r23 892 +#define _FOR_ITER_TIER_TWO_r23 893 +#define _FOR_ITER_VIRTUAL_r23 894 +#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 895 +#define _GET_AITER_r11 896 +#define _GET_ANEXT_r12 897 +#define _GET_AWAITABLE_r11 898 +#define _GET_ITER_r12 899 +#define _GET_ITER_TRAD_r12 900 +#define _GET_LEN_r12 901 +#define _GUARD_BINARY_OP_EXTEND_r22 902 +#define _GUARD_BINARY_OP_EXTEND_LHS_r02 903 +#define _GUARD_BINARY_OP_EXTEND_LHS_r12 904 +#define _GUARD_BINARY_OP_EXTEND_LHS_r22 905 +#define _GUARD_BINARY_OP_EXTEND_LHS_r33 906 +#define _GUARD_BINARY_OP_EXTEND_RHS_r02 907 +#define _GUARD_BINARY_OP_EXTEND_RHS_r12 908 +#define _GUARD_BINARY_OP_EXTEND_RHS_r22 909 +#define _GUARD_BINARY_OP_EXTEND_RHS_r33 910 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 911 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 912 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 913 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 914 +#define _GUARD_BIT_IS_SET_POP_r00 915 +#define _GUARD_BIT_IS_SET_POP_r10 916 +#define _GUARD_BIT_IS_SET_POP_r21 917 +#define _GUARD_BIT_IS_SET_POP_r32 918 +#define _GUARD_BIT_IS_SET_POP_4_r00 919 +#define _GUARD_BIT_IS_SET_POP_4_r10 920 +#define _GUARD_BIT_IS_SET_POP_4_r21 921 +#define _GUARD_BIT_IS_SET_POP_4_r32 922 +#define _GUARD_BIT_IS_SET_POP_5_r00 923 +#define _GUARD_BIT_IS_SET_POP_5_r10 924 +#define _GUARD_BIT_IS_SET_POP_5_r21 925 +#define _GUARD_BIT_IS_SET_POP_5_r32 926 +#define _GUARD_BIT_IS_SET_POP_6_r00 927 +#define _GUARD_BIT_IS_SET_POP_6_r10 928 +#define _GUARD_BIT_IS_SET_POP_6_r21 929 +#define _GUARD_BIT_IS_SET_POP_6_r32 930 +#define _GUARD_BIT_IS_SET_POP_7_r00 931 +#define _GUARD_BIT_IS_SET_POP_7_r10 932 +#define _GUARD_BIT_IS_SET_POP_7_r21 933 +#define _GUARD_BIT_IS_SET_POP_7_r32 934 +#define _GUARD_BIT_IS_UNSET_POP_r00 935 +#define _GUARD_BIT_IS_UNSET_POP_r10 936 +#define _GUARD_BIT_IS_UNSET_POP_r21 937 +#define _GUARD_BIT_IS_UNSET_POP_r32 938 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 939 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 940 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 941 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 942 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 943 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 944 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 945 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 946 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 947 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 948 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 949 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 950 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 951 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 952 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 953 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 954 +#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 955 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 956 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 957 +#define _GUARD_CALLABLE_BUILTIN_O_r00 958 +#define _GUARD_CALLABLE_ISINSTANCE_r03 959 +#define _GUARD_CALLABLE_ISINSTANCE_r13 960 +#define _GUARD_CALLABLE_ISINSTANCE_r23 961 +#define _GUARD_CALLABLE_ISINSTANCE_r33 962 +#define _GUARD_CALLABLE_LEN_r03 963 +#define _GUARD_CALLABLE_LEN_r13 964 +#define _GUARD_CALLABLE_LEN_r23 965 +#define _GUARD_CALLABLE_LEN_r33 966 +#define _GUARD_CALLABLE_LIST_APPEND_r03 967 +#define _GUARD_CALLABLE_LIST_APPEND_r13 968 +#define _GUARD_CALLABLE_LIST_APPEND_r23 969 +#define _GUARD_CALLABLE_LIST_APPEND_r33 970 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 971 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 972 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 973 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 974 +#define _GUARD_CALLABLE_STR_1_r03 975 +#define _GUARD_CALLABLE_STR_1_r13 976 +#define _GUARD_CALLABLE_STR_1_r23 977 +#define _GUARD_CALLABLE_STR_1_r33 978 +#define _GUARD_CALLABLE_TUPLE_1_r03 979 +#define _GUARD_CALLABLE_TUPLE_1_r13 980 +#define _GUARD_CALLABLE_TUPLE_1_r23 981 +#define _GUARD_CALLABLE_TUPLE_1_r33 982 +#define _GUARD_CALLABLE_TYPE_1_r03 983 +#define _GUARD_CALLABLE_TYPE_1_r13 984 +#define _GUARD_CALLABLE_TYPE_1_r23 985 +#define _GUARD_CALLABLE_TYPE_1_r33 986 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 987 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 988 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 989 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 990 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 991 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 992 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 993 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 994 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 995 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 996 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 997 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 998 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 999 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 1000 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1001 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1002 +#define _GUARD_DORV_NO_DICT_r01 1003 +#define _GUARD_DORV_NO_DICT_r11 1004 +#define _GUARD_DORV_NO_DICT_r22 1005 +#define _GUARD_DORV_NO_DICT_r33 1006 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1007 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1008 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1009 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1010 +#define _GUARD_GLOBALS_VERSION_r00 1011 +#define _GUARD_GLOBALS_VERSION_r11 1012 +#define _GUARD_GLOBALS_VERSION_r22 1013 +#define _GUARD_GLOBALS_VERSION_r33 1014 +#define _GUARD_IP_RETURN_GENERATOR_r00 1015 +#define _GUARD_IP_RETURN_GENERATOR_r11 1016 +#define _GUARD_IP_RETURN_GENERATOR_r22 1017 +#define _GUARD_IP_RETURN_GENERATOR_r33 1018 +#define _GUARD_IP_RETURN_VALUE_r00 1019 +#define _GUARD_IP_RETURN_VALUE_r11 1020 +#define _GUARD_IP_RETURN_VALUE_r22 1021 +#define _GUARD_IP_RETURN_VALUE_r33 1022 +#define _GUARD_IP_YIELD_VALUE_r00 1023 +#define _GUARD_IP_YIELD_VALUE_r11 1024 +#define _GUARD_IP_YIELD_VALUE_r22 1025 +#define _GUARD_IP_YIELD_VALUE_r33 1026 +#define _GUARD_IP__PUSH_FRAME_r00 1027 +#define _GUARD_IP__PUSH_FRAME_r11 1028 +#define _GUARD_IP__PUSH_FRAME_r22 1029 +#define _GUARD_IP__PUSH_FRAME_r33 1030 +#define _GUARD_IS_FALSE_POP_r00 1031 +#define _GUARD_IS_FALSE_POP_r10 1032 +#define _GUARD_IS_FALSE_POP_r21 1033 +#define _GUARD_IS_FALSE_POP_r32 1034 +#define _GUARD_IS_NONE_POP_r00 1035 +#define _GUARD_IS_NONE_POP_r10 1036 +#define _GUARD_IS_NONE_POP_r21 1037 +#define _GUARD_IS_NONE_POP_r32 1038 +#define _GUARD_IS_NOT_NONE_POP_r10 1039 +#define _GUARD_IS_TRUE_POP_r00 1040 +#define _GUARD_IS_TRUE_POP_r10 1041 +#define _GUARD_IS_TRUE_POP_r21 1042 +#define _GUARD_IS_TRUE_POP_r32 1043 +#define _GUARD_ITERATOR_r01 1044 +#define _GUARD_ITERATOR_r11 1045 +#define _GUARD_ITERATOR_r22 1046 +#define _GUARD_ITERATOR_r33 1047 +#define _GUARD_ITER_VIRTUAL_r01 1048 +#define _GUARD_ITER_VIRTUAL_r11 1049 +#define _GUARD_ITER_VIRTUAL_r22 1050 +#define _GUARD_ITER_VIRTUAL_r33 1051 +#define _GUARD_KEYS_VERSION_r01 1052 +#define _GUARD_KEYS_VERSION_r11 1053 +#define _GUARD_KEYS_VERSION_r22 1054 +#define _GUARD_KEYS_VERSION_r33 1055 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1056 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1057 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1058 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1059 +#define _GUARD_NOS_ANY_DICT_r02 1060 +#define _GUARD_NOS_ANY_DICT_r12 1061 +#define _GUARD_NOS_ANY_DICT_r22 1062 +#define _GUARD_NOS_ANY_DICT_r33 1063 +#define _GUARD_NOS_COMPACT_ASCII_r02 1064 +#define _GUARD_NOS_COMPACT_ASCII_r12 1065 +#define _GUARD_NOS_COMPACT_ASCII_r22 1066 +#define _GUARD_NOS_COMPACT_ASCII_r33 1067 +#define _GUARD_NOS_DICT_r02 1068 +#define _GUARD_NOS_DICT_r12 1069 +#define _GUARD_NOS_DICT_r22 1070 +#define _GUARD_NOS_DICT_r33 1071 +#define _GUARD_NOS_FLOAT_r02 1072 +#define _GUARD_NOS_FLOAT_r12 1073 +#define _GUARD_NOS_FLOAT_r22 1074 +#define _GUARD_NOS_FLOAT_r33 1075 +#define _GUARD_NOS_INT_r02 1076 +#define _GUARD_NOS_INT_r12 1077 +#define _GUARD_NOS_INT_r22 1078 +#define _GUARD_NOS_INT_r33 1079 +#define _GUARD_NOS_ITER_VIRTUAL_r02 1080 +#define _GUARD_NOS_ITER_VIRTUAL_r12 1081 +#define _GUARD_NOS_ITER_VIRTUAL_r22 1082 +#define _GUARD_NOS_ITER_VIRTUAL_r33 1083 +#define _GUARD_NOS_LIST_r02 1084 +#define _GUARD_NOS_LIST_r12 1085 +#define _GUARD_NOS_LIST_r22 1086 +#define _GUARD_NOS_LIST_r33 1087 +#define _GUARD_NOS_NOT_NULL_r02 1088 +#define _GUARD_NOS_NOT_NULL_r12 1089 +#define _GUARD_NOS_NOT_NULL_r22 1090 +#define _GUARD_NOS_NOT_NULL_r33 1091 +#define _GUARD_NOS_NULL_r02 1092 +#define _GUARD_NOS_NULL_r12 1093 +#define _GUARD_NOS_NULL_r22 1094 +#define _GUARD_NOS_NULL_r33 1095 +#define _GUARD_NOS_OVERFLOWED_r02 1096 +#define _GUARD_NOS_OVERFLOWED_r12 1097 +#define _GUARD_NOS_OVERFLOWED_r22 1098 +#define _GUARD_NOS_OVERFLOWED_r33 1099 +#define _GUARD_NOS_TUPLE_r02 1100 +#define _GUARD_NOS_TUPLE_r12 1101 +#define _GUARD_NOS_TUPLE_r22 1102 +#define _GUARD_NOS_TUPLE_r33 1103 +#define _GUARD_NOS_TYPE_VERSION_r02 1104 +#define _GUARD_NOS_TYPE_VERSION_r12 1105 +#define _GUARD_NOS_TYPE_VERSION_r22 1106 +#define _GUARD_NOS_TYPE_VERSION_r33 1107 +#define _GUARD_NOS_UNICODE_r02 1108 +#define _GUARD_NOS_UNICODE_r12 1109 +#define _GUARD_NOS_UNICODE_r22 1110 +#define _GUARD_NOS_UNICODE_r33 1111 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1112 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1113 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1114 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1115 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1116 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1117 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1118 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1119 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1120 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1121 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1122 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1123 +#define _GUARD_THIRD_NULL_r03 1124 +#define _GUARD_THIRD_NULL_r13 1125 +#define _GUARD_THIRD_NULL_r23 1126 +#define _GUARD_THIRD_NULL_r33 1127 +#define _GUARD_TOS_ANY_DICT_r01 1128 +#define _GUARD_TOS_ANY_DICT_r11 1129 +#define _GUARD_TOS_ANY_DICT_r22 1130 +#define _GUARD_TOS_ANY_DICT_r33 1131 +#define _GUARD_TOS_ANY_SET_r01 1132 +#define _GUARD_TOS_ANY_SET_r11 1133 +#define _GUARD_TOS_ANY_SET_r22 1134 +#define _GUARD_TOS_ANY_SET_r33 1135 +#define _GUARD_TOS_DICT_r01 1136 +#define _GUARD_TOS_DICT_r11 1137 +#define _GUARD_TOS_DICT_r22 1138 +#define _GUARD_TOS_DICT_r33 1139 +#define _GUARD_TOS_FLOAT_r01 1140 +#define _GUARD_TOS_FLOAT_r11 1141 +#define _GUARD_TOS_FLOAT_r22 1142 +#define _GUARD_TOS_FLOAT_r33 1143 +#define _GUARD_TOS_FROZENDICT_r01 1144 +#define _GUARD_TOS_FROZENDICT_r11 1145 +#define _GUARD_TOS_FROZENDICT_r22 1146 +#define _GUARD_TOS_FROZENDICT_r33 1147 +#define _GUARD_TOS_FROZENSET_r01 1148 +#define _GUARD_TOS_FROZENSET_r11 1149 +#define _GUARD_TOS_FROZENSET_r22 1150 +#define _GUARD_TOS_FROZENSET_r33 1151 +#define _GUARD_TOS_INT_r01 1152 +#define _GUARD_TOS_INT_r11 1153 +#define _GUARD_TOS_INT_r22 1154 +#define _GUARD_TOS_INT_r33 1155 +#define _GUARD_TOS_LIST_r01 1156 +#define _GUARD_TOS_LIST_r11 1157 +#define _GUARD_TOS_LIST_r22 1158 +#define _GUARD_TOS_LIST_r33 1159 +#define _GUARD_TOS_OVERFLOWED_r01 1160 +#define _GUARD_TOS_OVERFLOWED_r11 1161 +#define _GUARD_TOS_OVERFLOWED_r22 1162 +#define _GUARD_TOS_OVERFLOWED_r33 1163 +#define _GUARD_TOS_SET_r01 1164 +#define _GUARD_TOS_SET_r11 1165 +#define _GUARD_TOS_SET_r22 1166 +#define _GUARD_TOS_SET_r33 1167 +#define _GUARD_TOS_SLICE_r01 1168 +#define _GUARD_TOS_SLICE_r11 1169 +#define _GUARD_TOS_SLICE_r22 1170 +#define _GUARD_TOS_SLICE_r33 1171 +#define _GUARD_TOS_TUPLE_r01 1172 +#define _GUARD_TOS_TUPLE_r11 1173 +#define _GUARD_TOS_TUPLE_r22 1174 +#define _GUARD_TOS_TUPLE_r33 1175 +#define _GUARD_TOS_UNICODE_r01 1176 +#define _GUARD_TOS_UNICODE_r11 1177 +#define _GUARD_TOS_UNICODE_r22 1178 +#define _GUARD_TOS_UNICODE_r33 1179 +#define _GUARD_TYPE_r01 1180 +#define _GUARD_TYPE_r11 1181 +#define _GUARD_TYPE_r22 1182 +#define _GUARD_TYPE_r33 1183 +#define _GUARD_TYPE_VERSION_r01 1184 +#define _GUARD_TYPE_VERSION_r11 1185 +#define _GUARD_TYPE_VERSION_r22 1186 +#define _GUARD_TYPE_VERSION_r33 1187 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1188 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1189 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1190 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1191 +#define _HANDLE_PENDING_AND_DEOPT_r00 1192 +#define _HANDLE_PENDING_AND_DEOPT_r10 1193 +#define _HANDLE_PENDING_AND_DEOPT_r20 1194 +#define _HANDLE_PENDING_AND_DEOPT_r30 1195 +#define _IMPORT_FROM_r12 1196 +#define _IMPORT_NAME_r21 1197 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1198 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1199 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1200 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1201 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1202 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1203 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1204 +#define _INSERT_NULL_r10 1205 +#define _INSTRUMENTED_FOR_ITER_r23 1206 +#define _INSTRUMENTED_INSTRUCTION_r00 1207 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1208 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1209 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1210 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1211 +#define _INSTRUMENTED_LINE_r00 1212 +#define _INSTRUMENTED_NOT_TAKEN_r00 1213 +#define _INSTRUMENTED_NOT_TAKEN_r11 1214 +#define _INSTRUMENTED_NOT_TAKEN_r22 1215 +#define _INSTRUMENTED_NOT_TAKEN_r33 1216 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1217 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1218 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1219 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1220 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1221 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1222 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1223 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1224 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1225 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1226 +#define _IS_NONE_r11 1227 +#define _IS_OP_r03 1228 +#define _IS_OP_r13 1229 +#define _IS_OP_r23 1230 +#define _ITER_CHECK_LIST_r02 1231 +#define _ITER_CHECK_LIST_r12 1232 +#define _ITER_CHECK_LIST_r22 1233 +#define _ITER_CHECK_LIST_r33 1234 +#define _ITER_CHECK_RANGE_r02 1235 +#define _ITER_CHECK_RANGE_r12 1236 +#define _ITER_CHECK_RANGE_r22 1237 +#define _ITER_CHECK_RANGE_r33 1238 +#define _ITER_CHECK_TUPLE_r02 1239 +#define _ITER_CHECK_TUPLE_r12 1240 +#define _ITER_CHECK_TUPLE_r22 1241 +#define _ITER_CHECK_TUPLE_r33 1242 +#define _ITER_JUMP_LIST_r02 1243 +#define _ITER_JUMP_LIST_r12 1244 +#define _ITER_JUMP_LIST_r22 1245 +#define _ITER_JUMP_LIST_r33 1246 +#define _ITER_JUMP_RANGE_r02 1247 +#define _ITER_JUMP_RANGE_r12 1248 +#define _ITER_JUMP_RANGE_r22 1249 +#define _ITER_JUMP_RANGE_r33 1250 +#define _ITER_JUMP_TUPLE_r02 1251 +#define _ITER_JUMP_TUPLE_r12 1252 +#define _ITER_JUMP_TUPLE_r22 1253 +#define _ITER_JUMP_TUPLE_r33 1254 +#define _ITER_NEXT_LIST_r23 1255 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1256 +#define _ITER_NEXT_RANGE_r03 1257 +#define _ITER_NEXT_RANGE_r13 1258 +#define _ITER_NEXT_RANGE_r23 1259 +#define _ITER_NEXT_TUPLE_r03 1260 +#define _ITER_NEXT_TUPLE_r13 1261 +#define _ITER_NEXT_TUPLE_r23 1262 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1263 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1264 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1265 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1266 +#define _JUMP_TO_TOP_r00 1267 +#define _LIST_APPEND_r10 1268 +#define _LIST_EXTEND_r11 1269 +#define _LOAD_ATTR_r10 1270 +#define _LOAD_ATTR_CLASS_r11 1271 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1272 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1273 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1274 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1275 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1276 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1277 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1278 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1279 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1280 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1281 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1282 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1283 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1284 +#define _LOAD_ATTR_MODULE_r12 1285 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1286 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1287 +#define _LOAD_ATTR_PROPERTY_FRAME_r01 1288 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1289 +#define _LOAD_ATTR_PROPERTY_FRAME_r22 1290 +#define _LOAD_ATTR_PROPERTY_FRAME_r33 1291 +#define _LOAD_ATTR_SLOT_r02 1292 +#define _LOAD_ATTR_SLOT_r12 1293 +#define _LOAD_ATTR_SLOT_r23 1294 +#define _LOAD_ATTR_WITH_HINT_r12 1295 +#define _LOAD_BUILD_CLASS_r01 1296 +#define _LOAD_BYTECODE_r00 1297 +#define _LOAD_COMMON_CONSTANT_r01 1298 +#define _LOAD_COMMON_CONSTANT_r12 1299 +#define _LOAD_COMMON_CONSTANT_r23 1300 +#define _LOAD_CONST_r01 1301 +#define _LOAD_CONST_r12 1302 +#define _LOAD_CONST_r23 1303 +#define _LOAD_CONST_INLINE_r01 1304 +#define _LOAD_CONST_INLINE_r12 1305 +#define _LOAD_CONST_INLINE_r23 1306 +#define _LOAD_CONST_INLINE_BORROW_r01 1307 +#define _LOAD_CONST_INLINE_BORROW_r12 1308 +#define _LOAD_CONST_INLINE_BORROW_r23 1309 +#define _LOAD_DEREF_r01 1310 +#define _LOAD_FAST_r01 1311 +#define _LOAD_FAST_r12 1312 +#define _LOAD_FAST_r23 1313 +#define _LOAD_FAST_0_r01 1314 +#define _LOAD_FAST_0_r12 1315 +#define _LOAD_FAST_0_r23 1316 +#define _LOAD_FAST_1_r01 1317 +#define _LOAD_FAST_1_r12 1318 +#define _LOAD_FAST_1_r23 1319 +#define _LOAD_FAST_2_r01 1320 +#define _LOAD_FAST_2_r12 1321 +#define _LOAD_FAST_2_r23 1322 +#define _LOAD_FAST_3_r01 1323 +#define _LOAD_FAST_3_r12 1324 +#define _LOAD_FAST_3_r23 1325 +#define _LOAD_FAST_4_r01 1326 +#define _LOAD_FAST_4_r12 1327 +#define _LOAD_FAST_4_r23 1328 +#define _LOAD_FAST_5_r01 1329 +#define _LOAD_FAST_5_r12 1330 +#define _LOAD_FAST_5_r23 1331 +#define _LOAD_FAST_6_r01 1332 +#define _LOAD_FAST_6_r12 1333 +#define _LOAD_FAST_6_r23 1334 +#define _LOAD_FAST_7_r01 1335 +#define _LOAD_FAST_7_r12 1336 +#define _LOAD_FAST_7_r23 1337 +#define _LOAD_FAST_AND_CLEAR_r01 1338 +#define _LOAD_FAST_AND_CLEAR_r12 1339 +#define _LOAD_FAST_AND_CLEAR_r23 1340 +#define _LOAD_FAST_BORROW_r01 1341 +#define _LOAD_FAST_BORROW_r12 1342 +#define _LOAD_FAST_BORROW_r23 1343 +#define _LOAD_FAST_BORROW_0_r01 1344 +#define _LOAD_FAST_BORROW_0_r12 1345 +#define _LOAD_FAST_BORROW_0_r23 1346 +#define _LOAD_FAST_BORROW_1_r01 1347 +#define _LOAD_FAST_BORROW_1_r12 1348 +#define _LOAD_FAST_BORROW_1_r23 1349 +#define _LOAD_FAST_BORROW_2_r01 1350 +#define _LOAD_FAST_BORROW_2_r12 1351 +#define _LOAD_FAST_BORROW_2_r23 1352 +#define _LOAD_FAST_BORROW_3_r01 1353 +#define _LOAD_FAST_BORROW_3_r12 1354 +#define _LOAD_FAST_BORROW_3_r23 1355 +#define _LOAD_FAST_BORROW_4_r01 1356 +#define _LOAD_FAST_BORROW_4_r12 1357 +#define _LOAD_FAST_BORROW_4_r23 1358 +#define _LOAD_FAST_BORROW_5_r01 1359 +#define _LOAD_FAST_BORROW_5_r12 1360 +#define _LOAD_FAST_BORROW_5_r23 1361 +#define _LOAD_FAST_BORROW_6_r01 1362 +#define _LOAD_FAST_BORROW_6_r12 1363 +#define _LOAD_FAST_BORROW_6_r23 1364 +#define _LOAD_FAST_BORROW_7_r01 1365 +#define _LOAD_FAST_BORROW_7_r12 1366 +#define _LOAD_FAST_BORROW_7_r23 1367 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1368 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1369 +#define _LOAD_FAST_CHECK_r01 1370 +#define _LOAD_FAST_CHECK_r12 1371 +#define _LOAD_FAST_CHECK_r23 1372 +#define _LOAD_FAST_LOAD_FAST_r02 1373 +#define _LOAD_FAST_LOAD_FAST_r13 1374 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1375 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1376 +#define _LOAD_GLOBAL_r00 1377 +#define _LOAD_GLOBAL_BUILTINS_r01 1378 +#define _LOAD_GLOBAL_MODULE_r01 1379 +#define _LOAD_LOCALS_r01 1380 +#define _LOAD_LOCALS_r12 1381 +#define _LOAD_LOCALS_r23 1382 +#define _LOAD_NAME_r01 1383 +#define _LOAD_SMALL_INT_r01 1384 +#define _LOAD_SMALL_INT_r12 1385 +#define _LOAD_SMALL_INT_r23 1386 +#define _LOAD_SMALL_INT_0_r01 1387 +#define _LOAD_SMALL_INT_0_r12 1388 +#define _LOAD_SMALL_INT_0_r23 1389 +#define _LOAD_SMALL_INT_1_r01 1390 +#define _LOAD_SMALL_INT_1_r12 1391 +#define _LOAD_SMALL_INT_1_r23 1392 +#define _LOAD_SMALL_INT_2_r01 1393 +#define _LOAD_SMALL_INT_2_r12 1394 +#define _LOAD_SMALL_INT_2_r23 1395 +#define _LOAD_SMALL_INT_3_r01 1396 +#define _LOAD_SMALL_INT_3_r12 1397 +#define _LOAD_SMALL_INT_3_r23 1398 +#define _LOAD_SPECIAL_r00 1399 +#define _LOAD_SUPER_ATTR_ATTR_r31 1400 +#define _LOAD_SUPER_ATTR_METHOD_r32 1401 +#define _LOCK_OBJECT_r01 1402 +#define _LOCK_OBJECT_r11 1403 +#define _LOCK_OBJECT_r22 1404 +#define _LOCK_OBJECT_r33 1405 +#define _MAKE_CALLARGS_A_TUPLE_r33 1406 +#define _MAKE_CELL_r00 1407 +#define _MAKE_FUNCTION_r12 1408 +#define _MAKE_HEAP_SAFE_r01 1409 +#define _MAKE_HEAP_SAFE_r11 1410 +#define _MAKE_HEAP_SAFE_r22 1411 +#define _MAKE_HEAP_SAFE_r33 1412 +#define _MAKE_WARM_r00 1413 +#define _MAKE_WARM_r11 1414 +#define _MAKE_WARM_r22 1415 +#define _MAKE_WARM_r33 1416 +#define _MAP_ADD_r20 1417 +#define _MATCH_CLASS_r33 1418 +#define _MATCH_KEYS_r23 1419 +#define _MATCH_MAPPING_r02 1420 +#define _MATCH_MAPPING_r12 1421 +#define _MATCH_MAPPING_r23 1422 +#define _MATCH_SEQUENCE_r02 1423 +#define _MATCH_SEQUENCE_r12 1424 +#define _MATCH_SEQUENCE_r23 1425 +#define _MAYBE_EXPAND_METHOD_r00 1426 +#define _MAYBE_EXPAND_METHOD_KW_r11 1427 +#define _MONITOR_CALL_r00 1428 +#define _MONITOR_CALL_KW_r11 1429 +#define _MONITOR_JUMP_BACKWARD_r00 1430 +#define _MONITOR_JUMP_BACKWARD_r11 1431 +#define _MONITOR_JUMP_BACKWARD_r22 1432 +#define _MONITOR_JUMP_BACKWARD_r33 1433 +#define _MONITOR_RESUME_r00 1434 +#define _NOP_r00 1435 +#define _NOP_r11 1436 +#define _NOP_r22 1437 +#define _NOP_r33 1438 +#define _POP_EXCEPT_r10 1439 +#define _POP_ITER_r20 1440 +#define _POP_JUMP_IF_FALSE_r00 1441 +#define _POP_JUMP_IF_FALSE_r10 1442 +#define _POP_JUMP_IF_FALSE_r21 1443 +#define _POP_JUMP_IF_FALSE_r32 1444 +#define _POP_JUMP_IF_TRUE_r00 1445 +#define _POP_JUMP_IF_TRUE_r10 1446 +#define _POP_JUMP_IF_TRUE_r21 1447 +#define _POP_JUMP_IF_TRUE_r32 1448 +#define _POP_TOP_r10 1449 +#define _POP_TOP_FLOAT_r00 1450 +#define _POP_TOP_FLOAT_r10 1451 +#define _POP_TOP_FLOAT_r21 1452 +#define _POP_TOP_FLOAT_r32 1453 +#define _POP_TOP_INT_r00 1454 +#define _POP_TOP_INT_r10 1455 +#define _POP_TOP_INT_r21 1456 +#define _POP_TOP_INT_r32 1457 +#define _POP_TOP_NOP_r00 1458 +#define _POP_TOP_NOP_r10 1459 +#define _POP_TOP_NOP_r21 1460 +#define _POP_TOP_NOP_r32 1461 +#define _POP_TOP_OPARG_r00 1462 +#define _POP_TOP_UNICODE_r00 1463 +#define _POP_TOP_UNICODE_r10 1464 +#define _POP_TOP_UNICODE_r21 1465 +#define _POP_TOP_UNICODE_r32 1466 +#define _PUSH_EXC_INFO_r02 1467 +#define _PUSH_EXC_INFO_r12 1468 +#define _PUSH_EXC_INFO_r23 1469 +#define _PUSH_FRAME_r10 1470 +#define _PUSH_NULL_r01 1471 +#define _PUSH_NULL_r12 1472 +#define _PUSH_NULL_r23 1473 +#define _PUSH_NULL_CONDITIONAL_r00 1474 +#define _PUSH_TAGGED_ZERO_r01 1475 +#define _PUSH_TAGGED_ZERO_r12 1476 +#define _PUSH_TAGGED_ZERO_r23 1477 +#define _PY_FRAME_EX_r31 1478 +#define _PY_FRAME_GENERAL_r01 1479 +#define _PY_FRAME_KW_r11 1480 +#define _REPLACE_WITH_TRUE_r02 1481 +#define _REPLACE_WITH_TRUE_r12 1482 +#define _REPLACE_WITH_TRUE_r23 1483 +#define _RESUME_CHECK_r00 1484 +#define _RESUME_CHECK_r11 1485 +#define _RESUME_CHECK_r22 1486 +#define _RESUME_CHECK_r33 1487 +#define _RETURN_GENERATOR_r01 1488 +#define _RETURN_VALUE_r11 1489 +#define _SAVE_RETURN_OFFSET_r00 1490 +#define _SAVE_RETURN_OFFSET_r11 1491 +#define _SAVE_RETURN_OFFSET_r22 1492 +#define _SAVE_RETURN_OFFSET_r33 1493 +#define _SEND_r33 1494 +#define _SEND_GEN_FRAME_r33 1495 +#define _SETUP_ANNOTATIONS_r00 1496 +#define _SET_ADD_r10 1497 +#define _SET_FUNCTION_ATTRIBUTE_r01 1498 +#define _SET_FUNCTION_ATTRIBUTE_r11 1499 +#define _SET_FUNCTION_ATTRIBUTE_r21 1500 +#define _SET_FUNCTION_ATTRIBUTE_r32 1501 +#define _SET_IP_r00 1502 +#define _SET_IP_r11 1503 +#define _SET_IP_r22 1504 +#define _SET_IP_r33 1505 +#define _SET_UPDATE_r11 1506 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1507 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1508 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1509 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1510 +#define _SPILL_OR_RELOAD_r01 1511 +#define _SPILL_OR_RELOAD_r02 1512 +#define _SPILL_OR_RELOAD_r03 1513 +#define _SPILL_OR_RELOAD_r10 1514 +#define _SPILL_OR_RELOAD_r12 1515 +#define _SPILL_OR_RELOAD_r13 1516 +#define _SPILL_OR_RELOAD_r20 1517 +#define _SPILL_OR_RELOAD_r21 1518 +#define _SPILL_OR_RELOAD_r23 1519 +#define _SPILL_OR_RELOAD_r30 1520 +#define _SPILL_OR_RELOAD_r31 1521 +#define _SPILL_OR_RELOAD_r32 1522 +#define _START_EXECUTOR_r00 1523 +#define _STORE_ATTR_r20 1524 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1525 +#define _STORE_ATTR_SLOT_r21 1526 +#define _STORE_ATTR_WITH_HINT_r21 1527 +#define _STORE_DEREF_r10 1528 +#define _STORE_FAST_LOAD_FAST_r11 1529 +#define _STORE_FAST_STORE_FAST_r20 1530 +#define _STORE_GLOBAL_r10 1531 +#define _STORE_NAME_r10 1532 +#define _STORE_SLICE_r30 1533 +#define _STORE_SUBSCR_r30 1534 +#define _STORE_SUBSCR_DICT_r31 1535 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1536 +#define _STORE_SUBSCR_LIST_INT_r32 1537 +#define _SWAP_r11 1538 +#define _SWAP_2_r02 1539 +#define _SWAP_2_r12 1540 +#define _SWAP_2_r22 1541 +#define _SWAP_2_r33 1542 +#define _SWAP_3_r03 1543 +#define _SWAP_3_r13 1544 +#define _SWAP_3_r23 1545 +#define _SWAP_3_r33 1546 +#define _SWAP_FAST_r01 1547 +#define _SWAP_FAST_r11 1548 +#define _SWAP_FAST_r22 1549 +#define _SWAP_FAST_r33 1550 +#define _SWAP_FAST_0_r01 1551 +#define _SWAP_FAST_0_r11 1552 +#define _SWAP_FAST_0_r22 1553 +#define _SWAP_FAST_0_r33 1554 +#define _SWAP_FAST_1_r01 1555 +#define _SWAP_FAST_1_r11 1556 +#define _SWAP_FAST_1_r22 1557 +#define _SWAP_FAST_1_r33 1558 +#define _SWAP_FAST_2_r01 1559 +#define _SWAP_FAST_2_r11 1560 +#define _SWAP_FAST_2_r22 1561 +#define _SWAP_FAST_2_r33 1562 +#define _SWAP_FAST_3_r01 1563 +#define _SWAP_FAST_3_r11 1564 +#define _SWAP_FAST_3_r22 1565 +#define _SWAP_FAST_3_r33 1566 +#define _SWAP_FAST_4_r01 1567 +#define _SWAP_FAST_4_r11 1568 +#define _SWAP_FAST_4_r22 1569 +#define _SWAP_FAST_4_r33 1570 +#define _SWAP_FAST_5_r01 1571 +#define _SWAP_FAST_5_r11 1572 +#define _SWAP_FAST_5_r22 1573 +#define _SWAP_FAST_5_r33 1574 +#define _SWAP_FAST_6_r01 1575 +#define _SWAP_FAST_6_r11 1576 +#define _SWAP_FAST_6_r22 1577 +#define _SWAP_FAST_6_r33 1578 +#define _SWAP_FAST_7_r01 1579 +#define _SWAP_FAST_7_r11 1580 +#define _SWAP_FAST_7_r22 1581 +#define _SWAP_FAST_7_r33 1582 +#define _TIER2_RESUME_CHECK_r00 1583 +#define _TIER2_RESUME_CHECK_r11 1584 +#define _TIER2_RESUME_CHECK_r22 1585 +#define _TIER2_RESUME_CHECK_r33 1586 +#define _TO_BOOL_r11 1587 +#define _TO_BOOL_BOOL_r01 1588 +#define _TO_BOOL_BOOL_r11 1589 +#define _TO_BOOL_BOOL_r22 1590 +#define _TO_BOOL_BOOL_r33 1591 +#define _TO_BOOL_INT_r02 1592 +#define _TO_BOOL_INT_r12 1593 +#define _TO_BOOL_INT_r23 1594 +#define _TO_BOOL_LIST_r02 1595 +#define _TO_BOOL_LIST_r12 1596 +#define _TO_BOOL_LIST_r23 1597 +#define _TO_BOOL_NONE_r01 1598 +#define _TO_BOOL_NONE_r11 1599 +#define _TO_BOOL_NONE_r22 1600 +#define _TO_BOOL_NONE_r33 1601 +#define _TO_BOOL_STR_r02 1602 +#define _TO_BOOL_STR_r12 1603 +#define _TO_BOOL_STR_r23 1604 +#define _TRACE_RECORD_r00 1605 +#define _UNARY_INVERT_r12 1606 +#define _UNARY_NEGATIVE_r12 1607 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1608 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1609 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1610 +#define _UNARY_NOT_r01 1611 +#define _UNARY_NOT_r11 1612 +#define _UNARY_NOT_r22 1613 +#define _UNARY_NOT_r33 1614 +#define _UNPACK_EX_r10 1615 +#define _UNPACK_SEQUENCE_r10 1616 +#define _UNPACK_SEQUENCE_LIST_r10 1617 +#define _UNPACK_SEQUENCE_TUPLE_r10 1618 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1619 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1620 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1621 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1622 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1623 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1624 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1625 +#define _WITH_EXCEPT_START_r33 1626 +#define _YIELD_VALUE_r11 1627 +#define MAX_UOP_REGS_ID 1627 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index e29ce36e91e..8465fd4345e 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -79,7 +79,6 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_POP_TOP_INT] = 0, [_POP_TOP_FLOAT] = 0, [_POP_TOP_UNICODE] = 0, - [_POP_TWO] = HAS_ESCAPES_FLAG, [_POP_TOP_OPARG] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PUSH_NULL] = HAS_PURE_FLAG, [_END_FOR] = HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG, @@ -126,8 +125,13 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT] = 0, [_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT] = 0, [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT] = 0, + [_BINARY_OP_TRUEDIV_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_BINARY_OP_EXTEND_LHS] = HAS_EXIT_FLAG, + [_GUARD_BINARY_OP_EXTEND_RHS] = HAS_EXIT_FLAG, [_GUARD_BINARY_OP_EXTEND] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_EXTEND] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -216,6 +220,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG, [_GUARD_TYPE_VERSION_LOCKED] = HAS_EXIT_FLAG, + [_GUARD_TYPE] = HAS_EXIT_FLAG, [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_EXIT_FLAG, [_LOAD_ATTR_INSTANCE_VALUE] = HAS_DEOPT_FLAG, [_LOAD_ATTR_MODULE] = HAS_EXIT_FLAG, @@ -224,6 +229,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG, [_LOAD_ATTR_CLASS] = HAS_ESCAPES_FLAG, [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG, [_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG, [_STORE_ATTR_INSTANCE_VALUE] = HAS_ESCAPES_FLAG, [_LOCK_OBJECT] = HAS_DEOPT_FLAG, @@ -251,7 +257,13 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_MATCH_SEQUENCE] = 0, [_MATCH_KEYS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_ITER] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_ITERATOR] = HAS_EXIT_FLAG, + [_GUARD_ITER_VIRTUAL] = HAS_EXIT_FLAG, + [_PUSH_TAGGED_ZERO] = 0, + [_GET_ITER_TRAD] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_NOS_ITER_VIRTUAL] = HAS_EXIT_FLAG, + [_FOR_ITER_VIRTUAL_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_ITER_CHECK_LIST] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG, [_ITER_NEXT_LIST_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, @@ -304,16 +316,18 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CALL_STR_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_TUPLE_1] = HAS_EXIT_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, + [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_LEN] = HAS_EXIT_FLAG, [_CALL_LEN] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_ISINSTANCE] = HAS_EXIT_FLAG, @@ -325,14 +339,14 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_RECURSION_LIMIT] = HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_O_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_MAYBE_EXPAND_METHOD_KW] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PY_FRAME_KW] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_CHECK_FUNCTION_VERSION_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, @@ -382,14 +396,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG, [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, [_LOAD_CONST_INLINE] = HAS_PURE_FLAG, - [_POP_TOP_LOAD_CONST_INLINE] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_LOAD_CONST_INLINE_BORROW] = HAS_PURE_FLAG, - [_POP_CALL] = HAS_ESCAPES_FLAG, - [_POP_CALL_ONE] = HAS_ESCAPES_FLAG, - [_POP_CALL_TWO] = HAS_ESCAPES_FLAG, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = 0, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = 0, [_START_EXECUTOR] = HAS_DEOPT_FLAG, [_MAKE_WARM] = 0, @@ -412,10 +419,12 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_RECORD_TOS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_TOS_TYPE] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS] = HAS_RECORDS_VALUE_FLAG, + [_RECORD_NOS_TYPE] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, [_RECORD_3OS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, [_RECORD_4OS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_CALLABLE] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, + [_RECORD_CALLABLE_KW] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, [_RECORD_BOUND_METHOD] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, [_RECORD_CODE] = HAS_RECORDS_VALUE_FLAG, }; @@ -829,15 +838,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 2, 3, _POP_TOP_UNICODE_r32 }, }, }, - [_POP_TWO] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 2, _POP_TWO_r20 }, - { -1, -1, -1 }, - }, - }, [_POP_TOP_OPARG] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -1252,6 +1252,33 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_BINARY_OP_TRUEDIV_FLOAT] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, [_BINARY_OP_ADD_UNICODE] = { .best = { 0, 1, 2, 2 }, .entries = { @@ -1270,6 +1297,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_BINARY_OP_EXTEND_LHS] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_BINARY_OP_EXTEND_LHS_r02 }, + { 2, 1, _GUARD_BINARY_OP_EXTEND_LHS_r12 }, + { 2, 2, _GUARD_BINARY_OP_EXTEND_LHS_r22 }, + { 3, 3, _GUARD_BINARY_OP_EXTEND_LHS_r33 }, + }, + }, + [_GUARD_BINARY_OP_EXTEND_RHS] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_BINARY_OP_EXTEND_RHS_r02 }, + { 2, 1, _GUARD_BINARY_OP_EXTEND_RHS_r12 }, + { 2, 2, _GUARD_BINARY_OP_EXTEND_RHS_r22 }, + { 3, 3, _GUARD_BINARY_OP_EXTEND_RHS_r33 }, + }, + }, [_GUARD_BINARY_OP_EXTEND] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -2062,6 +2107,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TYPE_VERSION_LOCKED_r33 }, }, }, + [_GUARD_TYPE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TYPE_r01 }, + { 1, 1, _GUARD_TYPE_r11 }, + { 2, 2, _GUARD_TYPE_r22 }, + { 3, 3, _GUARD_TYPE_r33 }, + }, + }, [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -2126,10 +2180,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_LOAD_ATTR_PROPERTY_FRAME] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _LOAD_ATTR_PROPERTY_FRAME_r01 }, + { 1, 1, _LOAD_ATTR_PROPERTY_FRAME_r11 }, + { 2, 2, _LOAD_ATTR_PROPERTY_FRAME_r22 }, + { 3, 3, _LOAD_ATTR_PROPERTY_FRAME_r33 }, + }, + }, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _LOAD_ATTR_PROPERTY_FRAME_r11 }, + { 1, 1, _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -2377,6 +2440,42 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_ITERATOR] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_ITERATOR_r01 }, + { 1, 1, _GUARD_ITERATOR_r11 }, + { 2, 2, _GUARD_ITERATOR_r22 }, + { 3, 3, _GUARD_ITERATOR_r33 }, + }, + }, + [_GUARD_ITER_VIRTUAL] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_ITER_VIRTUAL_r01 }, + { 1, 1, _GUARD_ITER_VIRTUAL_r11 }, + { 2, 2, _GUARD_ITER_VIRTUAL_r22 }, + { 3, 3, _GUARD_ITER_VIRTUAL_r33 }, + }, + }, + [_PUSH_TAGGED_ZERO] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 1, 0, _PUSH_TAGGED_ZERO_r01 }, + { 2, 1, _PUSH_TAGGED_ZERO_r12 }, + { 3, 2, _PUSH_TAGGED_ZERO_r23 }, + { -1, -1, -1 }, + }, + }, + [_GET_ITER_TRAD] = { + .best = { 1, 1, 1, 1 }, + .entries = { + { -1, -1, -1 }, + { 2, 1, _GET_ITER_TRAD_r12 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_FOR_ITER_TIER_TWO] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -2386,6 +2485,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_NOS_ITER_VIRTUAL] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 2, 0, _GUARD_NOS_ITER_VIRTUAL_r02 }, + { 2, 1, _GUARD_NOS_ITER_VIRTUAL_r12 }, + { 2, 2, _GUARD_NOS_ITER_VIRTUAL_r22 }, + { 3, 3, _GUARD_NOS_ITER_VIRTUAL_r33 }, + }, + }, + [_FOR_ITER_VIRTUAL_TIER_TWO] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _FOR_ITER_VIRTUAL_TIER_TWO_r23 }, + { -1, -1, -1 }, + }, + }, [_ITER_CHECK_LIST] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -2854,10 +2971,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 2, 3, _CALL_TUPLE_1_r32 }, }, }, - [_CHECK_AND_ALLOCATE_OBJECT] = { + [_CHECK_OBJECT] = { .best = { 0, 0, 0, 0 }, .entries = { - { 0, 0, _CHECK_AND_ALLOCATE_OBJECT_r00 }, + { 0, 0, _CHECK_OBJECT_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, + [_ALLOCATE_OBJECT] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _ALLOCATE_OBJECT_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2881,10 +3007,19 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_GUARD_CALLABLE_BUILTIN_CLASS] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 0, 0, _GUARD_CALLABLE_BUILTIN_CLASS_r00 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_CALL_BUILTIN_CLASS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_BUILTIN_CLASS_r01 }, + { 0, 0, _CALL_BUILTIN_CLASS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -2938,7 +3073,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 }, + { 0, 0, _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -3046,7 +3181,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -3055,7 +3190,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -3100,7 +3235,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -3109,7 +3244,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = { .best = { 0, 0, 0, 0 }, .entries = { - { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 }, + { 0, 0, _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 }, { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, @@ -3556,15 +3691,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_POP_TOP_LOAD_CONST_INLINE] = { - .best = { 1, 1, 1, 1 }, - .entries = { - { -1, -1, -1 }, - { 1, 1, _POP_TOP_LOAD_CONST_INLINE_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - }, - }, [_LOAD_CONST_INLINE_BORROW] = { .best = { 0, 1, 2, 2 }, .entries = { @@ -3574,60 +3700,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_POP_CALL] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 2, _POP_CALL_r20 }, - { -1, -1, -1 }, - }, - }, - [_POP_CALL_ONE] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 3, _POP_CALL_ONE_r30 }, - }, - }, - [_POP_CALL_TWO] = { - .best = { 3, 3, 3, 3 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - { 0, 3, _POP_CALL_TWO_r30 }, - }, - }, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = { - .best = { 1, 1, 1, 1 }, - .entries = { - { -1, -1, -1 }, - { 1, 1, _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, - }, - }, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 1, 2, _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 }, - { -1, -1, -1 }, - }, - }, - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = { - .best = { 0, 1, 2, 2 }, - .entries = { - { 3, 0, _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 }, - { 3, 1, _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 }, - { 3, 2, _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 }, - { -1, -1, -1 }, - }, - }, [_SHUFFLE_3_LOAD_CONST_INLINE_BORROW] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -3934,7 +4006,6 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_POP_TOP_UNICODE_r10] = _POP_TOP_UNICODE, [_POP_TOP_UNICODE_r21] = _POP_TOP_UNICODE, [_POP_TOP_UNICODE_r32] = _POP_TOP_UNICODE, - [_POP_TWO_r20] = _POP_TWO, [_POP_TOP_OPARG_r00] = _POP_TOP_OPARG, [_PUSH_NULL_r01] = _PUSH_NULL, [_PUSH_NULL_r12] = _PUSH_NULL, @@ -4074,10 +4145,25 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, [_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_r23] = _BINARY_OP_TRUEDIV_FLOAT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23] = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, [_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_LHS_r02] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r12] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r22] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_LHS_r33] = _GUARD_BINARY_OP_EXTEND_LHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r02] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r12] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r22] = _GUARD_BINARY_OP_EXTEND_RHS, + [_GUARD_BINARY_OP_EXTEND_RHS_r33] = _GUARD_BINARY_OP_EXTEND_RHS, [_GUARD_BINARY_OP_EXTEND_r22] = _GUARD_BINARY_OP_EXTEND, [_BINARY_OP_EXTEND_r23] = _BINARY_OP_EXTEND, [_BINARY_SLICE_r31] = _BINARY_SLICE, @@ -4223,6 +4309,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TYPE_VERSION_LOCKED_r11] = _GUARD_TYPE_VERSION_LOCKED, [_GUARD_TYPE_VERSION_LOCKED_r22] = _GUARD_TYPE_VERSION_LOCKED, [_GUARD_TYPE_VERSION_LOCKED_r33] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_r01] = _GUARD_TYPE, + [_GUARD_TYPE_r11] = _GUARD_TYPE, + [_GUARD_TYPE_r22] = _GUARD_TYPE, + [_GUARD_TYPE_r33] = _GUARD_TYPE, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r01] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r11] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r22] = _CHECK_MANAGED_OBJECT_HAS_VALUES, @@ -4240,7 +4330,11 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CHECK_ATTR_CLASS_r22] = _CHECK_ATTR_CLASS, [_CHECK_ATTR_CLASS_r33] = _CHECK_ATTR_CLASS, [_LOAD_ATTR_CLASS_r11] = _LOAD_ATTR_CLASS, + [_LOAD_ATTR_PROPERTY_FRAME_r01] = _LOAD_ATTR_PROPERTY_FRAME, [_LOAD_ATTR_PROPERTY_FRAME_r11] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r22] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r33] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11] = _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, [_GUARD_DORV_NO_DICT_r01] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r11] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r22] = _GUARD_DORV_NO_DICT, @@ -4291,7 +4385,24 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_MATCH_SEQUENCE_r23] = _MATCH_SEQUENCE, [_MATCH_KEYS_r23] = _MATCH_KEYS, [_GET_ITER_r12] = _GET_ITER, + [_GUARD_ITERATOR_r01] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r11] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r22] = _GUARD_ITERATOR, + [_GUARD_ITERATOR_r33] = _GUARD_ITERATOR, + [_GUARD_ITER_VIRTUAL_r01] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r11] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r22] = _GUARD_ITER_VIRTUAL, + [_GUARD_ITER_VIRTUAL_r33] = _GUARD_ITER_VIRTUAL, + [_PUSH_TAGGED_ZERO_r01] = _PUSH_TAGGED_ZERO, + [_PUSH_TAGGED_ZERO_r12] = _PUSH_TAGGED_ZERO, + [_PUSH_TAGGED_ZERO_r23] = _PUSH_TAGGED_ZERO, + [_GET_ITER_TRAD_r12] = _GET_ITER_TRAD, [_FOR_ITER_TIER_TWO_r23] = _FOR_ITER_TIER_TWO, + [_GUARD_NOS_ITER_VIRTUAL_r02] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r12] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r22] = _GUARD_NOS_ITER_VIRTUAL, + [_GUARD_NOS_ITER_VIRTUAL_r33] = _GUARD_NOS_ITER_VIRTUAL, + [_FOR_ITER_VIRTUAL_TIER_TWO_r23] = _FOR_ITER_VIRTUAL_TIER_TWO, [_ITER_CHECK_LIST_r02] = _ITER_CHECK_LIST, [_ITER_CHECK_LIST_r12] = _ITER_CHECK_LIST, [_ITER_CHECK_LIST_r22] = _ITER_CHECK_LIST, @@ -4415,16 +4526,18 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_CALLABLE_TUPLE_1_r23] = _GUARD_CALLABLE_TUPLE_1, [_GUARD_CALLABLE_TUPLE_1_r33] = _GUARD_CALLABLE_TUPLE_1, [_CALL_TUPLE_1_r32] = _CALL_TUPLE_1, - [_CHECK_AND_ALLOCATE_OBJECT_r00] = _CHECK_AND_ALLOCATE_OBJECT, + [_CHECK_OBJECT_r00] = _CHECK_OBJECT, + [_ALLOCATE_OBJECT_r00] = _ALLOCATE_OBJECT, [_CREATE_INIT_FRAME_r01] = _CREATE_INIT_FRAME, [_EXIT_INIT_CHECK_r10] = _EXIT_INIT_CHECK, - [_CALL_BUILTIN_CLASS_r01] = _CALL_BUILTIN_CLASS, + [_GUARD_CALLABLE_BUILTIN_CLASS_r00] = _GUARD_CALLABLE_BUILTIN_CLASS, + [_CALL_BUILTIN_CLASS_r00] = _CALL_BUILTIN_CLASS, [_GUARD_CALLABLE_BUILTIN_O_r00] = _GUARD_CALLABLE_BUILTIN_O, [_CALL_BUILTIN_O_r03] = _CALL_BUILTIN_O, [_GUARD_CALLABLE_BUILTIN_FAST_r00] = _GUARD_CALLABLE_BUILTIN_FAST, [_CALL_BUILTIN_FAST_r00] = _CALL_BUILTIN_FAST, [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS, - [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01] = _CALL_BUILTIN_FAST_WITH_KEYWORDS, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00] = _CALL_BUILTIN_FAST_WITH_KEYWORDS, [_GUARD_CALLABLE_LEN_r03] = _GUARD_CALLABLE_LEN, [_GUARD_CALLABLE_LEN_r13] = _GUARD_CALLABLE_LEN, [_GUARD_CALLABLE_LEN_r23] = _GUARD_CALLABLE_LEN, @@ -4451,14 +4564,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CHECK_RECURSION_LIMIT_r33] = _CHECK_RECURSION_LIMIT, [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_O_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, [_CALL_METHOD_DESCRIPTOR_NOARGS_r03] = _CALL_METHOD_DESCRIPTOR_NOARGS, [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, - [_CALL_METHOD_DESCRIPTOR_FAST_r01] = _CALL_METHOD_DESCRIPTOR_FAST, - [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01] = _CALL_METHOD_DESCRIPTOR_FAST_INLINE, + [_CALL_METHOD_DESCRIPTOR_FAST_r00] = _CALL_METHOD_DESCRIPTOR_FAST, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00] = _CALL_METHOD_DESCRIPTOR_FAST_INLINE, [_MAYBE_EXPAND_METHOD_KW_r11] = _MAYBE_EXPAND_METHOD_KW, [_PY_FRAME_KW_r11] = _PY_FRAME_KW, [_CHECK_FUNCTION_VERSION_KW_r11] = _CHECK_FUNCTION_VERSION_KW, @@ -4589,18 +4702,9 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_LOAD_CONST_INLINE_r01] = _LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_r12] = _LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_r23] = _LOAD_CONST_INLINE, - [_POP_TOP_LOAD_CONST_INLINE_r11] = _POP_TOP_LOAD_CONST_INLINE, [_LOAD_CONST_INLINE_BORROW_r01] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r12] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r23] = _LOAD_CONST_INLINE_BORROW, - [_POP_CALL_r20] = _POP_CALL, - [_POP_CALL_ONE_r30] = _POP_CALL_ONE, - [_POP_CALL_TWO_r30] = _POP_CALL_TWO, - [_POP_TOP_LOAD_CONST_INLINE_BORROW_r11] = _POP_TOP_LOAD_CONST_INLINE_BORROW, - [_POP_TWO_LOAD_CONST_INLINE_BORROW_r21] = _POP_TWO_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r03] = _INSERT_2_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r13] = _INSERT_2_LOAD_CONST_INLINE_BORROW, - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r23] = _INSERT_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, @@ -4691,6 +4795,8 @@ const uint16_t _PyUop_SpillsAndReloads[4][4] = { }; const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { + [_ALLOCATE_OBJECT] = "_ALLOCATE_OBJECT", + [_ALLOCATE_OBJECT_r00] = "_ALLOCATE_OBJECT_r00", [_BINARY_OP] = "_BINARY_OP", [_BINARY_OP_r23] = "_BINARY_OP_r23", [_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT", @@ -4796,6 +4902,16 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03", [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13", [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23", + [_BINARY_OP_TRUEDIV_FLOAT] = "_BINARY_OP_TRUEDIV_FLOAT", + [_BINARY_OP_TRUEDIV_FLOAT_r23] = "_BINARY_OP_TRUEDIV_FLOAT_r23", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13", + [_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23] = "_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23", [_BINARY_SLICE] = "_BINARY_SLICE", [_BINARY_SLICE_r31] = "_BINARY_SLICE_r31", [_BUILD_INTERPOLATION] = "_BUILD_INTERPOLATION", @@ -4815,11 +4931,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BUILD_TUPLE] = "_BUILD_TUPLE", [_BUILD_TUPLE_r01] = "_BUILD_TUPLE_r01", [_CALL_BUILTIN_CLASS] = "_CALL_BUILTIN_CLASS", - [_CALL_BUILTIN_CLASS_r01] = "_CALL_BUILTIN_CLASS_r01", + [_CALL_BUILTIN_CLASS_r00] = "_CALL_BUILTIN_CLASS_r00", [_CALL_BUILTIN_FAST] = "_CALL_BUILTIN_FAST", [_CALL_BUILTIN_FAST_r00] = "_CALL_BUILTIN_FAST_r00", [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS", - [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS_r01", + [_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00] = "_CALL_BUILTIN_FAST_WITH_KEYWORDS_r00", [_CALL_BUILTIN_O] = "_CALL_BUILTIN_O", [_CALL_BUILTIN_O_r03] = "_CALL_BUILTIN_O_r03", [_CALL_FUNCTION_EX_NON_PY_GENERAL] = "_CALL_FUNCTION_EX_NON_PY_GENERAL", @@ -4840,13 +4956,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_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_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_r00", [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE", - [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE", - [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00", [_CALL_METHOD_DESCRIPTOR_NOARGS] = "_CALL_METHOD_DESCRIPTOR_NOARGS", [_CALL_METHOD_DESCRIPTOR_NOARGS_r03] = "_CALL_METHOD_DESCRIPTOR_NOARGS_r03", [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = "_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", @@ -4866,8 +4982,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_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", [_CHECK_ATTR_CLASS_r01] = "_CHECK_ATTR_CLASS_r01", [_CHECK_ATTR_CLASS_r11] = "_CHECK_ATTR_CLASS_r11", @@ -4918,6 +5032,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CHECK_METHOD_VERSION_r00] = "_CHECK_METHOD_VERSION_r00", [_CHECK_METHOD_VERSION_KW] = "_CHECK_METHOD_VERSION_KW", [_CHECK_METHOD_VERSION_KW_r11] = "_CHECK_METHOD_VERSION_KW_r11", + [_CHECK_OBJECT] = "_CHECK_OBJECT", + [_CHECK_OBJECT_r00] = "_CHECK_OBJECT_r00", [_CHECK_PEP_523] = "_CHECK_PEP_523", [_CHECK_PEP_523_r00] = "_CHECK_PEP_523_r00", [_CHECK_PEP_523_r11] = "_CHECK_PEP_523_r11", @@ -5051,6 +5167,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_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", + [_FOR_ITER_VIRTUAL_TIER_TWO] = "_FOR_ITER_VIRTUAL_TIER_TWO", + [_FOR_ITER_VIRTUAL_TIER_TWO_r23] = "_FOR_ITER_VIRTUAL_TIER_TWO_r23", [_GET_AITER] = "_GET_AITER", [_GET_AITER_r11] = "_GET_AITER_r11", [_GET_ANEXT] = "_GET_ANEXT", @@ -5059,10 +5177,22 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GET_AWAITABLE_r11] = "_GET_AWAITABLE_r11", [_GET_ITER] = "_GET_ITER", [_GET_ITER_r12] = "_GET_ITER_r12", + [_GET_ITER_TRAD] = "_GET_ITER_TRAD", + [_GET_ITER_TRAD_r12] = "_GET_ITER_TRAD_r12", [_GET_LEN] = "_GET_LEN", [_GET_LEN_r12] = "_GET_LEN_r12", [_GUARD_BINARY_OP_EXTEND] = "_GUARD_BINARY_OP_EXTEND", [_GUARD_BINARY_OP_EXTEND_r22] = "_GUARD_BINARY_OP_EXTEND_r22", + [_GUARD_BINARY_OP_EXTEND_LHS] = "_GUARD_BINARY_OP_EXTEND_LHS", + [_GUARD_BINARY_OP_EXTEND_LHS_r02] = "_GUARD_BINARY_OP_EXTEND_LHS_r02", + [_GUARD_BINARY_OP_EXTEND_LHS_r12] = "_GUARD_BINARY_OP_EXTEND_LHS_r12", + [_GUARD_BINARY_OP_EXTEND_LHS_r22] = "_GUARD_BINARY_OP_EXTEND_LHS_r22", + [_GUARD_BINARY_OP_EXTEND_LHS_r33] = "_GUARD_BINARY_OP_EXTEND_LHS_r33", + [_GUARD_BINARY_OP_EXTEND_RHS] = "_GUARD_BINARY_OP_EXTEND_RHS", + [_GUARD_BINARY_OP_EXTEND_RHS_r02] = "_GUARD_BINARY_OP_EXTEND_RHS_r02", + [_GUARD_BINARY_OP_EXTEND_RHS_r12] = "_GUARD_BINARY_OP_EXTEND_RHS_r12", + [_GUARD_BINARY_OP_EXTEND_RHS_r22] = "_GUARD_BINARY_OP_EXTEND_RHS_r22", + [_GUARD_BINARY_OP_EXTEND_RHS_r33] = "_GUARD_BINARY_OP_EXTEND_RHS_r33", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02", [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12] = "_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12", @@ -5118,6 +5248,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_BIT_IS_UNSET_POP_7_r10] = "_GUARD_BIT_IS_UNSET_POP_7_r10", [_GUARD_BIT_IS_UNSET_POP_7_r21] = "_GUARD_BIT_IS_UNSET_POP_7_r21", [_GUARD_BIT_IS_UNSET_POP_7_r32] = "_GUARD_BIT_IS_UNSET_POP_7_r32", + [_GUARD_CALLABLE_BUILTIN_CLASS] = "_GUARD_CALLABLE_BUILTIN_CLASS", + [_GUARD_CALLABLE_BUILTIN_CLASS_r00] = "_GUARD_CALLABLE_BUILTIN_CLASS_r00", [_GUARD_CALLABLE_BUILTIN_FAST] = "_GUARD_CALLABLE_BUILTIN_FAST", [_GUARD_CALLABLE_BUILTIN_FAST_r00] = "_GUARD_CALLABLE_BUILTIN_FAST_r00", [_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS] = "_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS", @@ -5234,6 +5366,16 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_IS_TRUE_POP_r10] = "_GUARD_IS_TRUE_POP_r10", [_GUARD_IS_TRUE_POP_r21] = "_GUARD_IS_TRUE_POP_r21", [_GUARD_IS_TRUE_POP_r32] = "_GUARD_IS_TRUE_POP_r32", + [_GUARD_ITERATOR] = "_GUARD_ITERATOR", + [_GUARD_ITERATOR_r01] = "_GUARD_ITERATOR_r01", + [_GUARD_ITERATOR_r11] = "_GUARD_ITERATOR_r11", + [_GUARD_ITERATOR_r22] = "_GUARD_ITERATOR_r22", + [_GUARD_ITERATOR_r33] = "_GUARD_ITERATOR_r33", + [_GUARD_ITER_VIRTUAL] = "_GUARD_ITER_VIRTUAL", + [_GUARD_ITER_VIRTUAL_r01] = "_GUARD_ITER_VIRTUAL_r01", + [_GUARD_ITER_VIRTUAL_r11] = "_GUARD_ITER_VIRTUAL_r11", + [_GUARD_ITER_VIRTUAL_r22] = "_GUARD_ITER_VIRTUAL_r22", + [_GUARD_ITER_VIRTUAL_r33] = "_GUARD_ITER_VIRTUAL_r33", [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", [_GUARD_KEYS_VERSION_r01] = "_GUARD_KEYS_VERSION_r01", [_GUARD_KEYS_VERSION_r11] = "_GUARD_KEYS_VERSION_r11", @@ -5269,6 +5411,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_NOS_INT_r12] = "_GUARD_NOS_INT_r12", [_GUARD_NOS_INT_r22] = "_GUARD_NOS_INT_r22", [_GUARD_NOS_INT_r33] = "_GUARD_NOS_INT_r33", + [_GUARD_NOS_ITER_VIRTUAL] = "_GUARD_NOS_ITER_VIRTUAL", + [_GUARD_NOS_ITER_VIRTUAL_r02] = "_GUARD_NOS_ITER_VIRTUAL_r02", + [_GUARD_NOS_ITER_VIRTUAL_r12] = "_GUARD_NOS_ITER_VIRTUAL_r12", + [_GUARD_NOS_ITER_VIRTUAL_r22] = "_GUARD_NOS_ITER_VIRTUAL_r22", + [_GUARD_NOS_ITER_VIRTUAL_r33] = "_GUARD_NOS_ITER_VIRTUAL_r33", [_GUARD_NOS_LIST] = "_GUARD_NOS_LIST", [_GUARD_NOS_LIST_r02] = "_GUARD_NOS_LIST_r02", [_GUARD_NOS_LIST_r12] = "_GUARD_NOS_LIST_r12", @@ -5389,6 +5536,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_UNICODE_r11] = "_GUARD_TOS_UNICODE_r11", [_GUARD_TOS_UNICODE_r22] = "_GUARD_TOS_UNICODE_r22", [_GUARD_TOS_UNICODE_r33] = "_GUARD_TOS_UNICODE_r33", + [_GUARD_TYPE] = "_GUARD_TYPE", + [_GUARD_TYPE_r01] = "_GUARD_TYPE_r01", + [_GUARD_TYPE_r11] = "_GUARD_TYPE_r11", + [_GUARD_TYPE_r22] = "_GUARD_TYPE_r22", + [_GUARD_TYPE_r33] = "_GUARD_TYPE_r33", [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION", [_GUARD_TYPE_VERSION_r01] = "_GUARD_TYPE_VERSION_r01", [_GUARD_TYPE_VERSION_r11] = "_GUARD_TYPE_VERSION_r11", @@ -5422,10 +5574,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_INIT_CALL_PY_EXACT_ARGS_3_r01] = "_INIT_CALL_PY_EXACT_ARGS_3_r01", [_INIT_CALL_PY_EXACT_ARGS_4] = "_INIT_CALL_PY_EXACT_ARGS_4", [_INIT_CALL_PY_EXACT_ARGS_4_r01] = "_INIT_CALL_PY_EXACT_ARGS_4_r01", - [_INSERT_2_LOAD_CONST_INLINE_BORROW] = "_INSERT_2_LOAD_CONST_INLINE_BORROW", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r03] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r03", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r13] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r13", - [_INSERT_2_LOAD_CONST_INLINE_BORROW_r23] = "_INSERT_2_LOAD_CONST_INLINE_BORROW_r23", [_INSERT_NULL] = "_INSERT_NULL", [_INSERT_NULL_r10] = "_INSERT_NULL_r10", [_IS_NONE] = "_IS_NONE", @@ -5469,6 +5617,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_r10] = "_LOAD_ATTR_r10", [_LOAD_ATTR_CLASS] = "_LOAD_ATTR_CLASS", [_LOAD_ATTR_CLASS_r11] = "_LOAD_ATTR_CLASS_r11", + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = "_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME", + [_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11] = "_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11", [_LOAD_ATTR_INSTANCE_VALUE] = "_LOAD_ATTR_INSTANCE_VALUE", [_LOAD_ATTR_INSTANCE_VALUE_r02] = "_LOAD_ATTR_INSTANCE_VALUE_r02", [_LOAD_ATTR_INSTANCE_VALUE_r12] = "_LOAD_ATTR_INSTANCE_VALUE_r12", @@ -5492,7 +5642,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11", [_LOAD_ATTR_PROPERTY_FRAME] = "_LOAD_ATTR_PROPERTY_FRAME", + [_LOAD_ATTR_PROPERTY_FRAME_r01] = "_LOAD_ATTR_PROPERTY_FRAME_r01", [_LOAD_ATTR_PROPERTY_FRAME_r11] = "_LOAD_ATTR_PROPERTY_FRAME_r11", + [_LOAD_ATTR_PROPERTY_FRAME_r22] = "_LOAD_ATTR_PROPERTY_FRAME_r22", + [_LOAD_ATTR_PROPERTY_FRAME_r33] = "_LOAD_ATTR_PROPERTY_FRAME_r33", [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT", [_LOAD_ATTR_SLOT_r02] = "_LOAD_ATTR_SLOT_r02", [_LOAD_ATTR_SLOT_r12] = "_LOAD_ATTR_SLOT_r12", @@ -5683,12 +5836,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_NOP_r11] = "_NOP_r11", [_NOP_r22] = "_NOP_r22", [_NOP_r33] = "_NOP_r33", - [_POP_CALL] = "_POP_CALL", - [_POP_CALL_r20] = "_POP_CALL_r20", - [_POP_CALL_ONE] = "_POP_CALL_ONE", - [_POP_CALL_ONE_r30] = "_POP_CALL_ONE_r30", - [_POP_CALL_TWO] = "_POP_CALL_TWO", - [_POP_CALL_TWO_r30] = "_POP_CALL_TWO_r30", [_POP_EXCEPT] = "_POP_EXCEPT", [_POP_EXCEPT_r10] = "_POP_EXCEPT_r10", [_POP_ITER] = "_POP_ITER", @@ -5705,10 +5852,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_POP_TOP_INT_r10] = "_POP_TOP_INT_r10", [_POP_TOP_INT_r21] = "_POP_TOP_INT_r21", [_POP_TOP_INT_r32] = "_POP_TOP_INT_r32", - [_POP_TOP_LOAD_CONST_INLINE] = "_POP_TOP_LOAD_CONST_INLINE", - [_POP_TOP_LOAD_CONST_INLINE_r11] = "_POP_TOP_LOAD_CONST_INLINE_r11", - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = "_POP_TOP_LOAD_CONST_INLINE_BORROW", - [_POP_TOP_LOAD_CONST_INLINE_BORROW_r11] = "_POP_TOP_LOAD_CONST_INLINE_BORROW_r11", [_POP_TOP_NOP] = "_POP_TOP_NOP", [_POP_TOP_NOP_r00] = "_POP_TOP_NOP_r00", [_POP_TOP_NOP_r10] = "_POP_TOP_NOP_r10", @@ -5721,10 +5864,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_POP_TOP_UNICODE_r10] = "_POP_TOP_UNICODE_r10", [_POP_TOP_UNICODE_r21] = "_POP_TOP_UNICODE_r21", [_POP_TOP_UNICODE_r32] = "_POP_TOP_UNICODE_r32", - [_POP_TWO] = "_POP_TWO", - [_POP_TWO_r20] = "_POP_TWO_r20", - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = "_POP_TWO_LOAD_CONST_INLINE_BORROW", - [_POP_TWO_LOAD_CONST_INLINE_BORROW_r21] = "_POP_TWO_LOAD_CONST_INLINE_BORROW_r21", [_PUSH_EXC_INFO] = "_PUSH_EXC_INFO", [_PUSH_EXC_INFO_r02] = "_PUSH_EXC_INFO_r02", [_PUSH_EXC_INFO_r12] = "_PUSH_EXC_INFO_r12", @@ -5737,6 +5876,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_PUSH_NULL_r23] = "_PUSH_NULL_r23", [_PUSH_NULL_CONDITIONAL] = "_PUSH_NULL_CONDITIONAL", [_PUSH_NULL_CONDITIONAL_r00] = "_PUSH_NULL_CONDITIONAL_r00", + [_PUSH_TAGGED_ZERO] = "_PUSH_TAGGED_ZERO", + [_PUSH_TAGGED_ZERO_r01] = "_PUSH_TAGGED_ZERO_r01", + [_PUSH_TAGGED_ZERO_r12] = "_PUSH_TAGGED_ZERO_r12", + [_PUSH_TAGGED_ZERO_r23] = "_PUSH_TAGGED_ZERO_r23", [_PY_FRAME_EX] = "_PY_FRAME_EX", [_PY_FRAME_EX_r31] = "_PY_FRAME_EX_r31", [_PY_FRAME_GENERAL] = "_PY_FRAME_GENERAL", @@ -5747,9 +5890,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_RECORD_4OS] = "_RECORD_4OS", [_RECORD_BOUND_METHOD] = "_RECORD_BOUND_METHOD", [_RECORD_CALLABLE] = "_RECORD_CALLABLE", + [_RECORD_CALLABLE_KW] = "_RECORD_CALLABLE_KW", [_RECORD_CODE] = "_RECORD_CODE", [_RECORD_NOS] = "_RECORD_NOS", [_RECORD_NOS_GEN_FUNC] = "_RECORD_NOS_GEN_FUNC", + [_RECORD_NOS_TYPE] = "_RECORD_NOS_TYPE", [_RECORD_TOS] = "_RECORD_TOS", [_RECORD_TOS_TYPE] = "_RECORD_TOS_TYPE", [_REPLACE_WITH_TRUE] = "_REPLACE_WITH_TRUE", @@ -6046,8 +6191,6 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _POP_TOP_UNICODE: return 1; - case _POP_TWO: - return 2; case _POP_TOP_OPARG: return oparg; case _PUSH_NULL: @@ -6140,10 +6283,20 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT: return 2; + case _BINARY_OP_TRUEDIV_FLOAT: + return 2; + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE: + return 2; + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT: + return 2; case _BINARY_OP_ADD_UNICODE: return 2; case _BINARY_OP_INPLACE_ADD_UNICODE: return 2; + case _GUARD_BINARY_OP_EXTEND_LHS: + return 0; + case _GUARD_BINARY_OP_EXTEND_RHS: + return 0; case _GUARD_BINARY_OP_EXTEND: return 0; case _BINARY_OP_EXTEND: @@ -6320,6 +6473,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GUARD_TYPE_VERSION_LOCKED: return 0; + case _GUARD_TYPE: + return 0; case _CHECK_MANAGED_OBJECT_HAS_VALUES: return 0; case _LOAD_ATTR_INSTANCE_VALUE: @@ -6336,6 +6491,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _LOAD_ATTR_PROPERTY_FRAME: return 1; + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME: + return 1; case _GUARD_DORV_NO_DICT: return 0; case _STORE_ATTR_INSTANCE_VALUE: @@ -6390,8 +6547,20 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GET_ITER: return 1; + case _GUARD_ITERATOR: + return 0; + case _GUARD_ITER_VIRTUAL: + return 0; + case _PUSH_TAGGED_ZERO: + return 0; + case _GET_ITER_TRAD: + return 1; case _FOR_ITER_TIER_TWO: return 0; + case _GUARD_NOS_ITER_VIRTUAL: + return 0; + case _FOR_ITER_VIRTUAL_TIER_TWO: + return 0; case _ITER_CHECK_LIST: return 0; case _GUARD_NOT_EXHAUSTED_LIST: @@ -6496,14 +6665,18 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CALL_TUPLE_1: return 3; - case _CHECK_AND_ALLOCATE_OBJECT: + case _CHECK_OBJECT: + return 0; + case _ALLOCATE_OBJECT: return 0; case _CREATE_INIT_FRAME: return 2 + oparg; case _EXIT_INIT_CHECK: return 1; + case _GUARD_CALLABLE_BUILTIN_CLASS: + return 0; case _CALL_BUILTIN_CLASS: - return 2 + oparg; + return 0; case _GUARD_CALLABLE_BUILTIN_O: return 0; case _CALL_BUILTIN_O: @@ -6515,7 +6688,7 @@ int _PyUop_num_popped(int opcode, int oparg) case _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS: return 0; case _CALL_BUILTIN_FAST_WITH_KEYWORDS: - return 2 + oparg; + return 0; case _GUARD_CALLABLE_LEN: return 0; case _CALL_LEN: @@ -6539,9 +6712,9 @@ int _PyUop_num_popped(int opcode, int oparg) case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: return 0; case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: - return 2 + oparg; + return 0; case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: - return 1 + oparg; + return 0; case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS: return 0; case _CALL_METHOD_DESCRIPTOR_NOARGS: @@ -6551,9 +6724,9 @@ int _PyUop_num_popped(int opcode, int oparg) case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST: return 0; case _CALL_METHOD_DESCRIPTOR_FAST: - return 2 + oparg; + return 0; case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: - return 1 + oparg; + return 0; case _MAYBE_EXPAND_METHOD_KW: return 0; case _PY_FRAME_KW: @@ -6652,22 +6825,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _LOAD_CONST_INLINE: return 0; - case _POP_TOP_LOAD_CONST_INLINE: - return 1; case _LOAD_CONST_INLINE_BORROW: return 0; - case _POP_CALL: - return 2; - case _POP_CALL_ONE: - return 3; - case _POP_CALL_TWO: - return 4; - case _POP_TOP_LOAD_CONST_INLINE_BORROW: - return 1; - case _POP_TWO_LOAD_CONST_INLINE_BORROW: - return 2; - case _INSERT_2_LOAD_CONST_INLINE_BORROW: - return 2; case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW: return 3; case _START_EXECUTOR: @@ -6712,6 +6871,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _RECORD_NOS: return 0; + case _RECORD_NOS_TYPE: + return 0; case _RECORD_NOS_GEN_FUNC: return 0; case _RECORD_3OS_GEN_FUNC: @@ -6720,6 +6881,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _RECORD_CALLABLE: return 0; + case _RECORD_CALLABLE_KW: + return 0; case _RECORD_BOUND_METHOD: return 0; case _RECORD_CODE: diff --git a/Include/object.h b/Include/object.h index e33f92295fb..d51132be1a6 100644 --- a/Include/object.h +++ b/Include/object.h @@ -306,6 +306,11 @@ typedef Py_hash_t (*hashfunc)(PyObject *); typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); typedef PyObject *(*getiterfunc) (PyObject *); typedef PyObject *(*iternextfunc) (PyObject *); +typedef struct { + PyObject *object; + Py_ssize_t index; +} _PyObjectIndexPair; +typedef _PyObjectIndexPair (*_Py_iteritemfunc) (PyObject *, Py_ssize_t index); typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*initproc)(PyObject *, PyObject *, PyObject *); diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index ac6d4d964d3..53a7eaf0de5 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -180,42 +180,45 @@ extern "C" { #define FOR_ITER_LIST 175 #define FOR_ITER_RANGE 176 #define FOR_ITER_TUPLE 177 -#define JUMP_BACKWARD_JIT 178 -#define JUMP_BACKWARD_NO_JIT 179 -#define LOAD_ATTR_CLASS 180 -#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 181 -#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 182 -#define LOAD_ATTR_INSTANCE_VALUE 183 -#define LOAD_ATTR_METHOD_LAZY_DICT 184 -#define LOAD_ATTR_METHOD_NO_DICT 185 -#define LOAD_ATTR_METHOD_WITH_VALUES 186 -#define LOAD_ATTR_MODULE 187 -#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 188 -#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 189 -#define LOAD_ATTR_PROPERTY 190 -#define LOAD_ATTR_SLOT 191 -#define LOAD_ATTR_WITH_HINT 192 -#define LOAD_GLOBAL_BUILTIN 193 -#define LOAD_GLOBAL_MODULE 194 -#define LOAD_SUPER_ATTR_ATTR 195 -#define LOAD_SUPER_ATTR_METHOD 196 -#define RESUME_CHECK 197 -#define RESUME_CHECK_JIT 198 -#define SEND_GEN 199 -#define STORE_ATTR_INSTANCE_VALUE 200 -#define STORE_ATTR_SLOT 201 -#define STORE_ATTR_WITH_HINT 202 -#define STORE_SUBSCR_DICT 203 -#define STORE_SUBSCR_LIST_INT 204 -#define TO_BOOL_ALWAYS_TRUE 205 -#define TO_BOOL_BOOL 206 -#define TO_BOOL_INT 207 -#define TO_BOOL_LIST 208 -#define TO_BOOL_NONE 209 -#define TO_BOOL_STR 210 -#define UNPACK_SEQUENCE_LIST 211 -#define UNPACK_SEQUENCE_TUPLE 212 -#define UNPACK_SEQUENCE_TWO_TUPLE 213 +#define FOR_ITER_VIRTUAL 178 +#define GET_ITER_SELF 179 +#define GET_ITER_VIRTUAL 180 +#define JUMP_BACKWARD_JIT 181 +#define JUMP_BACKWARD_NO_JIT 182 +#define LOAD_ATTR_CLASS 183 +#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 184 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 185 +#define LOAD_ATTR_INSTANCE_VALUE 186 +#define LOAD_ATTR_METHOD_LAZY_DICT 187 +#define LOAD_ATTR_METHOD_NO_DICT 188 +#define LOAD_ATTR_METHOD_WITH_VALUES 189 +#define LOAD_ATTR_MODULE 190 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 191 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 192 +#define LOAD_ATTR_PROPERTY 193 +#define LOAD_ATTR_SLOT 194 +#define LOAD_ATTR_WITH_HINT 195 +#define LOAD_GLOBAL_BUILTIN 196 +#define LOAD_GLOBAL_MODULE 197 +#define LOAD_SUPER_ATTR_ATTR 198 +#define LOAD_SUPER_ATTR_METHOD 199 +#define RESUME_CHECK 200 +#define RESUME_CHECK_JIT 201 +#define SEND_GEN 202 +#define STORE_ATTR_INSTANCE_VALUE 203 +#define STORE_ATTR_SLOT 204 +#define STORE_ATTR_WITH_HINT 205 +#define STORE_SUBSCR_DICT 206 +#define STORE_SUBSCR_LIST_INT 207 +#define TO_BOOL_ALWAYS_TRUE 208 +#define TO_BOOL_BOOL 209 +#define TO_BOOL_INT 210 +#define TO_BOOL_LIST 211 +#define TO_BOOL_NONE 212 +#define TO_BOOL_STR 213 +#define UNPACK_SEQUENCE_LIST 214 +#define UNPACK_SEQUENCE_TUPLE 215 +#define UNPACK_SEQUENCE_TWO_TUPLE 216 #define INSTRUMENTED_END_FOR 233 #define INSTRUMENTED_POP_ITER 234 #define INSTRUMENTED_END_SEND 235 diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 9f5c36230a7..974246f896e 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -61,32 +61,4 @@ #define PYTHON_ABI_VERSION 3 #define PYTHON_ABI_STRING "3" - -/* Stable ABI for free-threaded builds (introduced in PEP 803) - is enabled by one of: - - Py_TARGET_ABI3T, or - - Py_LIMITED_API and Py_GIL_DISABLED. - "Output" macros to be used internally: - - Py_LIMITED_API (defines the subset of API we expose) - - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between - free-threaded & GIL) - (Don't use Py_TARGET_ABI3T directly: it's currently only used to set these - 2 macros. It's also available for users' convenience.) - */ -#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \ - && !defined(Py_TARGET_ABI3T) -# define Py_TARGET_ABI3T Py_LIMITED_API -#endif -#if defined(Py_TARGET_ABI3T) -# define _Py_OPAQUE_PYOBJECT -# if !defined(Py_LIMITED_API) -# define Py_LIMITED_API Py_TARGET_ABI3T -# elif Py_LIMITED_API > Py_TARGET_ABI3T - // if both are defined, use the *lower* version, - // i.e. maximum compatibility -# undef Py_LIMITED_API -# define Py_LIMITED_API Py_TARGET_ABI3T -# endif -#endif - #endif //_Py_PATCHLEVEL_H diff --git a/Include/pyabi.h b/Include/pyabi.h new file mode 100644 index 00000000000..8c4ae281a43 --- /dev/null +++ b/Include/pyabi.h @@ -0,0 +1,121 @@ +/* Macros that restrict available definitions and select implementations + * to match an ABI stability promise: + * + * - internal API/ABI (may change at any time) -- Py_BUILD_CORE* + * - general CPython API/ABI (may change in 3.x.0) -- default + * - Stable ABI: abi3, abi3t (long-term stable) -- Py_LIMITED_API, + * Py_TARGET_ABI3T, _Py_OPAQUE_PYOBJECT + * - Free-threading (incompatible with non-free-threading builds) + * -- Py_GIL_DISABLED + */ + +#ifndef _Py_PYABI_H +#define _Py_PYABI_H + +/* Defines to build Python and its standard library: + * + * - Py_BUILD_CORE: Build Python core. Gives access to Python internals; should + * not be used by third-party modules. + * - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module. + * - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library. + * + * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE. + * + * On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas + * Py_BUILD_CORE_BUILTIN does not. + */ +#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif +#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif + +/* Check valid values for target ABI macros. + */ +#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 3 + // Empty Py_LIMITED_API used to work; redefine to + // Python 3.2 to be explicit. +# undef Py_LIMITED_API +# define Py_LIMITED_API 0x03020000 +#endif +#if defined(Py_TARGET_ABI3T) && Py_TARGET_ABI3T+0 < 0x030f0000 +# error "Py_TARGET_ABI3T must be 0x030f0000 (3.15) or above" +#endif + +/* Stable ABI for free-threaded builds (abi3t, introduced in PEP 803) + * is enabled by one of: + * - Py_TARGET_ABI3T, or + * - Py_LIMITED_API and Py_GIL_DISABLED. + * + * These affect set the following, which Python.h should use internally: + * - Py_LIMITED_API (defines the subset of API we expose) + * - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between + * free-threaded & GIL) + * + * (Don't use Py_TARGET_ABI3T directly. It's currently only used to set these + * 2 macros, and defined for users' convenience.) + */ +#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \ + && !defined(Py_TARGET_ABI3T) +# define Py_TARGET_ABI3T Py_LIMITED_API +#endif +#if defined(Py_TARGET_ABI3T) +# define _Py_OPAQUE_PYOBJECT +# if !defined(Py_LIMITED_API) +# define Py_LIMITED_API Py_TARGET_ABI3T +# elif Py_LIMITED_API > Py_TARGET_ABI3T + // if both are defined, use the *lower* version, + // i.e. maximum compatibility +# undef Py_LIMITED_API +# define Py_LIMITED_API Py_TARGET_ABI3T +# endif +#else +# ifdef _Py_OPAQUE_PYOBJECT + // _Py_OPAQUE_PYOBJECT is a private macro; do not define it directly. +# error "Define Py_TARGET_ABI3T to target abi3t." +# endif +#endif + +#if defined(Py_TARGET_ABI3T) +# if !defined(Py_GIL_DISABLED) + // Define Py_GIL_DISABLED for users' needs. Users check this macro to see + // whether they need extra synchronization. +# define Py_GIL_DISABLED +# endif +# if defined(_Py_IS_TESTCEXT) + // When compiling for abi3t, contents of Python.h should not depend + // on Py_GIL_DISABLED. + // We ask GCC to error if it sees the macro from this point on. + // Since users are free to the macro, and there's no way to undo the + // poisoning at the end of Python.h, we only do this in a test module + // (test_cext). + // + // Clang's poisoning is stricter than GCC's: it looks in `#elif` + // expressions after matching `#if`s. We disable it for now. + // We also provide an undocumented, unsupported opt-out macro to help + // porting to other compilers. Consider reaching out if you use it. +# if defined(__GNUC__) && !defined(__clang__) && !defined(_Py_NO_GCC_POISON) +# undef Py_GIL_DISABLED +# pragma GCC poison Py_GIL_DISABLED +# endif +# endif +#endif + +/* The internal C API must not be used with the limited C API: make sure + * that Py_BUILD_CORE* macros are not defined in this case. + * But, keep the "original" values, under different names, for "exports.h" + */ +#ifdef Py_BUILD_CORE +# define _PyEXPORTS_CORE +#endif +#ifdef Py_BUILD_CORE_MODULE +# define _PyEXPORTS_CORE_MODULE +#endif +#ifdef Py_LIMITED_API +# undef Py_BUILD_CORE +# undef Py_BUILD_CORE_BUILTIN +# undef Py_BUILD_CORE_MODULE +#endif + +#endif // _Py_PYABI_H diff --git a/Include/pyport.h b/Include/pyport.h index 62cba4c1421..c975921beaf 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -58,34 +58,6 @@ #endif -/* Defines to build Python and its standard library: - * - * - Py_BUILD_CORE: Build Python core. Give access to Python internals, but - * should not be used by third-party modules. - * - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module. - * - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library. - * - * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE. - * - * On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas - * Py_BUILD_CORE_BUILTIN does not. - */ -#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE) -# define Py_BUILD_CORE -#endif -#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE) -# define Py_BUILD_CORE -#endif - -#if defined(Py_TARGET_ABI3T) -# if !defined(Py_GIL_DISABLED) -// Define Py_GIL_DISABLED for users' needs. This macro is used to enable -// locking needed in for free-threaded interpreters builds. -# define Py_GIL_DISABLED -# endif -#endif - - /************************************************************************** Symbols and macros to supply platform-independent interfaces to basic C language & library operations whose spellings vary across platforms. @@ -393,17 +365,6 @@ extern "C" { # define Py_NO_INLINE #endif -#include "exports.h" - -#ifdef Py_LIMITED_API - // The internal C API must not be used with the limited C API: make sure - // that Py_BUILD_CORE macro is not defined in this case. These 3 macros are - // used by exports.h, so only undefine them afterwards. -# undef Py_BUILD_CORE -# undef Py_BUILD_CORE_BUILTIN -# undef Py_BUILD_CORE_MODULE -#endif - /* limits.h constants that may be missing */ #ifndef INT_MAX diff --git a/InternalDocs/code_objects.md b/InternalDocs/code_objects.md index a91a7043c1b..cccbe715886 100644 --- a/InternalDocs/code_objects.md +++ b/InternalDocs/code_objects.md @@ -70,14 +70,6 @@ ### Format of the locations table representation of the source code positions of instructions, which are returned by the `co_positions()` iterator. -> [!NOTE] -> `co_linetable` is not to be confused with `co_lnotab`. -> For backwards compatibility, `co_lnotab` exposes the format -> as it existed in Python 3.10 and lower: this older format -> stores only the start line for each instruction. -> It is lazily created from `co_linetable` when accessed. -> See [`Objects/lnotab_notes.txt`](../Objects/lnotab_notes.txt) for more details. - `co_linetable` consists of a sequence of location entries. Each entry starts with a byte with the most significant bit set, followed by zero or more bytes with the most significant bit unset. diff --git a/InternalDocs/string_interning.md b/InternalDocs/string_interning.md index 0913b1a3471..829a27654a3 100644 --- a/InternalDocs/string_interning.md +++ b/InternalDocs/string_interning.md @@ -16,8 +16,8 @@ ## Singletons The 256 possible one-character latin-1 strings, which can be retrieved with `_Py_LATIN1_CHR(c)`, are stored in statically allocated arrays, -`_PyRuntime.static_objects.strings.ascii` and -`_PyRuntime.static_objects.strings.latin1`. +`_PyRuntime.static_objects.singletons.strings.ascii` and +`_PyRuntime.static_objects.singletons.strings.latin1`. Longer singleton strings are marked in C source with `_Py_ID` (if the string is a valid C identifier fragment) or `_Py_STR` (if it needs a separate diff --git a/Lib/_colorize.py b/Lib/_colorize.py index 6849a75ce47..bb0cde63dea 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -1,3 +1,4 @@ +import builtins import os import sys @@ -188,6 +189,17 @@ class Argparse(ThemeSection): message: str = ANSIColors.MAGENTA +@dataclass(frozen=True, kw_only=True) +class Ast(ThemeSection): + node: str = ANSIColors.CYAN + field: str = ANSIColors.BLUE + attribute: str = ANSIColors.GREY + string: str = ANSIColors.GREEN + number: str = ANSIColors.YELLOW + keyword: str = ANSIColors.BOLD_BLUE + reset: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class Calendar(ThemeSection): header: str = ANSIColors.BOLD @@ -210,25 +222,25 @@ class Difflib(ThemeSection): @dataclass(frozen=True, kw_only=True) class FancyCompleter(ThemeSection): # functions and methods - function: str = ANSIColors.BOLD_BLUE - builtin_function_or_method: str = ANSIColors.BOLD_BLUE - method: str = ANSIColors.BOLD_CYAN - method_wrapper: str = ANSIColors.BOLD_CYAN - wrapper_descriptor: str = ANSIColors.BOLD_CYAN - method_descriptor: str = ANSIColors.BOLD_CYAN + function: builtins.str = ANSIColors.BOLD_BLUE + builtin_function_or_method: builtins.str = ANSIColors.BOLD_BLUE + method: builtins.str = ANSIColors.BOLD_CYAN + method_wrapper: builtins.str = ANSIColors.BOLD_CYAN + wrapper_descriptor: builtins.str = ANSIColors.BOLD_CYAN + method_descriptor: builtins.str = ANSIColors.BOLD_CYAN # numbers - int: str = ANSIColors.BOLD_YELLOW - float: str = ANSIColors.BOLD_YELLOW - complex: str = ANSIColors.BOLD_YELLOW - bool: str = ANSIColors.BOLD_YELLOW + int: builtins.str = ANSIColors.BOLD_YELLOW + float: builtins.str = ANSIColors.BOLD_YELLOW + complex: builtins.str = ANSIColors.BOLD_YELLOW + bool: builtins.str = ANSIColors.BOLD_YELLOW # others - type: str = ANSIColors.BOLD_MAGENTA - module: str = ANSIColors.CYAN - NoneType: str = ANSIColors.GREY - bytes: str = ANSIColors.BOLD_GREEN - str: str = ANSIColors.BOLD_GREEN + type: builtins.str = ANSIColors.BOLD_MAGENTA + module: builtins.str = ANSIColors.CYAN + NoneType: builtins.str = ANSIColors.GREY + bytes: builtins.str = ANSIColors.BOLD_GREEN + str: builtins.str = ANSIColors.BOLD_GREEN @dataclass(frozen=True, kw_only=True) @@ -382,6 +394,14 @@ class Timeit(ThemeSection): reset: str = ANSIColors.RESET +@dataclass(frozen=True, kw_only=True) +class Tokenize(ThemeSection): + whitespace: str = ANSIColors.GREY + error: str = ANSIColors.BOLD_RED + position: str = ANSIColors.GREY + delimiter: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class Traceback(ThemeSection): type: str = ANSIColors.BOLD_MAGENTA @@ -412,6 +432,7 @@ class Theme: below. """ argparse: Argparse = field(default_factory=Argparse) + ast: Ast = field(default_factory=Ast) calendar: Calendar = field(default_factory=Calendar) difflib: Difflib = field(default_factory=Difflib) fancycompleter: FancyCompleter = field(default_factory=FancyCompleter) @@ -419,6 +440,7 @@ class Theme: live_profiler: LiveProfiler = field(default_factory=LiveProfiler) syntax: Syntax = field(default_factory=Syntax) timeit: Timeit = field(default_factory=Timeit) + tokenize: Tokenize = field(default_factory=Tokenize) traceback: Traceback = field(default_factory=Traceback) unittest: Unittest = field(default_factory=Unittest) @@ -426,6 +448,7 @@ def copy_with( self, *, argparse: Argparse | None = None, + ast: Ast | None = None, calendar: Calendar | None = None, difflib: Difflib | None = None, fancycompleter: FancyCompleter | None = None, @@ -433,6 +456,7 @@ def copy_with( live_profiler: LiveProfiler | None = None, syntax: Syntax | None = None, timeit: Timeit | None = None, + tokenize: Tokenize | None = None, traceback: Traceback | None = None, unittest: Unittest | None = None, ) -> Self: @@ -443,6 +467,7 @@ def copy_with( """ return type(self)( argparse=argparse or self.argparse, + ast=ast or self.ast, calendar=calendar or self.calendar, difflib=difflib or self.difflib, fancycompleter=fancycompleter or self.fancycompleter, @@ -450,6 +475,7 @@ def copy_with( live_profiler=live_profiler or self.live_profiler, syntax=syntax or self.syntax, timeit=timeit or self.timeit, + tokenize=tokenize or self.tokenize, traceback=traceback or self.traceback, unittest=unittest or self.unittest, ) @@ -464,6 +490,7 @@ def no_colors(cls) -> Self: """ return cls( argparse=Argparse.no_colors(), + ast=Ast.no_colors(), calendar=Calendar.no_colors(), difflib=Difflib.no_colors(), fancycompleter=FancyCompleter.no_colors(), @@ -471,6 +498,7 @@ def no_colors(cls) -> Self: live_profiler=LiveProfiler.no_colors(), syntax=Syntax.no_colors(), timeit=Timeit.no_colors(), + tokenize=Tokenize.no_colors(), traceback=Traceback.no_colors(), unittest=Unittest.no_colors(), ) diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index f5954e4372a..6b5357a3151 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -86,11 +86,16 @@ _specializations = frozendict( "JUMP_BACKWARD_NO_JIT", "JUMP_BACKWARD_JIT", ), + GET_ITER=( + "GET_ITER_SELF", + "GET_ITER_VIRTUAL", + ), FOR_ITER=( "FOR_ITER_LIST", "FOR_ITER_TUPLE", "FOR_ITER_RANGE", "FOR_ITER_GEN", + "FOR_ITER_VIRTUAL", ), CALL=( "CALL_BOUND_METHOD_EXACT_ARGS", @@ -176,42 +181,45 @@ _specialized_opmap = frozendict( FOR_ITER_LIST=175, FOR_ITER_RANGE=176, FOR_ITER_TUPLE=177, - JUMP_BACKWARD_JIT=178, - JUMP_BACKWARD_NO_JIT=179, - LOAD_ATTR_CLASS=180, - LOAD_ATTR_CLASS_WITH_METACLASS_CHECK=181, - LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN=182, - LOAD_ATTR_INSTANCE_VALUE=183, - LOAD_ATTR_METHOD_LAZY_DICT=184, - LOAD_ATTR_METHOD_NO_DICT=185, - LOAD_ATTR_METHOD_WITH_VALUES=186, - LOAD_ATTR_MODULE=187, - LOAD_ATTR_NONDESCRIPTOR_NO_DICT=188, - LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES=189, - LOAD_ATTR_PROPERTY=190, - LOAD_ATTR_SLOT=191, - LOAD_ATTR_WITH_HINT=192, - LOAD_GLOBAL_BUILTIN=193, - LOAD_GLOBAL_MODULE=194, - LOAD_SUPER_ATTR_ATTR=195, - LOAD_SUPER_ATTR_METHOD=196, - RESUME_CHECK=197, - RESUME_CHECK_JIT=198, - SEND_GEN=199, - STORE_ATTR_INSTANCE_VALUE=200, - STORE_ATTR_SLOT=201, - STORE_ATTR_WITH_HINT=202, - STORE_SUBSCR_DICT=203, - STORE_SUBSCR_LIST_INT=204, - TO_BOOL_ALWAYS_TRUE=205, - TO_BOOL_BOOL=206, - TO_BOOL_INT=207, - TO_BOOL_LIST=208, - TO_BOOL_NONE=209, - TO_BOOL_STR=210, - UNPACK_SEQUENCE_LIST=211, - UNPACK_SEQUENCE_TUPLE=212, - UNPACK_SEQUENCE_TWO_TUPLE=213, + FOR_ITER_VIRTUAL=178, + GET_ITER_SELF=179, + GET_ITER_VIRTUAL=180, + JUMP_BACKWARD_JIT=181, + JUMP_BACKWARD_NO_JIT=182, + LOAD_ATTR_CLASS=183, + LOAD_ATTR_CLASS_WITH_METACLASS_CHECK=184, + LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN=185, + LOAD_ATTR_INSTANCE_VALUE=186, + LOAD_ATTR_METHOD_LAZY_DICT=187, + LOAD_ATTR_METHOD_NO_DICT=188, + LOAD_ATTR_METHOD_WITH_VALUES=189, + LOAD_ATTR_MODULE=190, + LOAD_ATTR_NONDESCRIPTOR_NO_DICT=191, + LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES=192, + LOAD_ATTR_PROPERTY=193, + LOAD_ATTR_SLOT=194, + LOAD_ATTR_WITH_HINT=195, + LOAD_GLOBAL_BUILTIN=196, + LOAD_GLOBAL_MODULE=197, + LOAD_SUPER_ATTR_ATTR=198, + LOAD_SUPER_ATTR_METHOD=199, + RESUME_CHECK=200, + RESUME_CHECK_JIT=201, + SEND_GEN=202, + STORE_ATTR_INSTANCE_VALUE=203, + STORE_ATTR_SLOT=204, + STORE_ATTR_WITH_HINT=205, + STORE_SUBSCR_DICT=206, + STORE_SUBSCR_LIST_INT=207, + TO_BOOL_ALWAYS_TRUE=208, + TO_BOOL_BOOL=209, + TO_BOOL_INT=210, + TO_BOOL_LIST=211, + TO_BOOL_NONE=212, + TO_BOOL_STR=213, + UNPACK_SEQUENCE_LIST=214, + UNPACK_SEQUENCE_TUPLE=215, + UNPACK_SEQUENCE_TWO_TUPLE=216, ) opmap = frozendict( diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 3367ac485a5..746b0907c1d 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -464,7 +464,8 @@ def pattern(self, format): format = re_sub(r'\s+', r'\\s+', format) format = re_sub(r"'", "['\u02bc]", format) # needed for br_FR year_in_format = False - day_of_month_in_format = False + day_d_in_format = False + day_e_in_format = False def repl(m): directive = m.group()[1:] # exclude `%` symbol match directive: @@ -472,20 +473,30 @@ def repl(m): nonlocal year_in_format year_in_format = True case 'd': - nonlocal day_of_month_in_format - day_of_month_in_format = True + nonlocal day_d_in_format + day_d_in_format = True + case 'e': + nonlocal day_e_in_format + day_e_in_format = True return self[directive] format = re_sub(r'%[-_0^#]*[0-9]*([OE]?[:\\]?.?)', repl, format) - if day_of_month_in_format and not year_in_format: - import warnings - warnings.warn("""\ + if not year_in_format: + if day_d_in_format: + raise ValueError( + "Day of month directive '%d' may not be used without " + "a year directive. Parsing dates involving a day of " + "month without a year is ambiguous and fails to parse " + "leap day. Add a year to the input and format. " + "See https://github.com/python/cpython/issues/70647.") + if day_e_in_format: + import warnings + warnings.warn("""\ Parsing dates involving a day of month without a year specified is ambiguous -and fails to parse leap day. The default behavior will change in Python 3.15 -to either always raise an exception or to use a different default year (TBD). -To avoid trouble, add a specific year to the input & format. +and fails to parse leap day. '%e' without a year will become an error in Python 3.17. +To avoid trouble, add a specific year to the input and format. See https://github.com/python/cpython/issues/70647.""", - DeprecationWarning, - skip_file_prefixes=(os.path.dirname(__file__),)) + DeprecationWarning, + skip_file_prefixes=(os.path.dirname(__file__),)) return format def compile(self, format): diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py index 9fee2564114..5c9a0812646 100644 --- a/Lib/annotationlib.py +++ b/Lib/annotationlib.py @@ -47,6 +47,7 @@ class Format(enum.IntEnum): "__cell__", "__owner__", "__stringifier_dict__", + "__resolved_str_cache__", ) @@ -94,6 +95,7 @@ def __init__( # value later. self.__code__ = None self.__ast_node__ = None + self.__resolved_str_cache__ = None def __init_subclass__(cls, /, *args, **kwds): raise TypeError("Cannot subclass ForwardRef") @@ -113,7 +115,7 @@ def evaluate( """ match format: case Format.STRING: - return self.__forward_arg__ + return self.__resolved_str__ case Format.VALUE: is_forwardref_format = False case Format.FORWARDREF: @@ -258,6 +260,24 @@ def __forward_arg__(self): "Attempted to access '__forward_arg__' on an uninitialized ForwardRef" ) + @property + def __resolved_str__(self): + # __forward_arg__ with any names from __extra_names__ replaced + # with the type_repr of the value they represent + if self.__resolved_str_cache__ is None: + resolved_str = self.__forward_arg__ + names = self.__extra_names__ + + if names: + visitor = _ExtraNameFixer(names) + ast_expr = ast.parse(resolved_str, mode="eval").body + node = visitor.visit(ast_expr) + resolved_str = ast.unparse(node) + + self.__resolved_str_cache__ = resolved_str + + return self.__resolved_str_cache__ + @property def __forward_code__(self): if self.__code__ is not None: @@ -321,7 +341,7 @@ def __repr__(self): extra.append(", is_class=True") if self.__owner__ is not None: extra.append(f", owner={self.__owner__!r}") - return f"ForwardRef({self.__forward_arg__!r}{''.join(extra)})" + return f"ForwardRef({self.__resolved_str__!r}{''.join(extra)})" _Template = type(t"") @@ -357,6 +377,7 @@ def __init__( self.__cell__ = cell self.__owner__ = owner self.__stringifier_dict__ = stringifier_dict + self.__resolved_str_cache__ = None # Needed for ForwardRef def __convert_to_ast(self, other): if isinstance(other, _Stringifier): @@ -1163,3 +1184,14 @@ def _get_dunder_annotations(obj): if not isinstance(ann, dict): raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") return ann + + +class _ExtraNameFixer(ast.NodeTransformer): + """Fixer for __extra_names__ items in ForwardRef __repr__ and string evaluation""" + def __init__(self, extra_names): + self.extra_names = extra_names + + def visit_Name(self, node: ast.Name): + if (new_name := self.extra_names.get(node.id, _sentinel)) is not _sentinel: + node = ast.Name(id=type_repr(new_name)) + return node diff --git a/Lib/ast.py b/Lib/ast.py index d9743ba7ab4..ba4ee0197b8 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -21,6 +21,7 @@ :license: Python License. """ from _ast import * +lazy from _colorize import can_colorize, get_theme def parse(source, filename='', mode='exec', *, @@ -117,21 +118,32 @@ def _convert_literal(node): def dump( node, annotate_fields=True, include_attributes=False, *, - indent=None, show_empty=False, + color=False, indent=None, show_empty=False, ): """ Return a formatted dump of the tree in node. This is mainly useful for - debugging purposes. If annotate_fields is true (by default), - the returned string will show the names and the values for fields. - If annotate_fields is false, the result string will be more compact by - omitting unambiguous field names. Attributes such as line - numbers and column offsets are not dumped by default. If this is wanted, - include_attributes can be set to true. If indent is a non-negative - integer or string, then the tree will be pretty-printed with that indent - level. None (the default) selects the single line representation. + debugging purposes. + + If annotate_fields is true (by default), the returned string will show the + names and the values for fields. If annotate_fields is false, the result + string will be more compact by omitting unambiguous field names. + + Attributes such as line numbers and column offsets are not dumped by default. + If this is wanted, include_attributes can be set to true. + + If color is true, the returned string is syntax highlighted using ANSI + escape sequences. If color is false (the default), colored output is always + disabled. + + If indent is a non-negative integer or string, then the tree will be + pretty-printed with that indent level. If indent is None (the default), + the tree is dumped on a single line. + If show_empty is False, then empty lists and fields that are None will be omitted from the output for better readability. """ + t = get_theme(force_color=color, force_no_color=not color).ast + def _format(node, level=0): if indent is not None: level += 1 @@ -166,7 +178,9 @@ def _format(node, level=0): field_type = cls._field_types.get(name, object) if field_type is expr_context: if not keywords: - args_buffer.append(repr(value)) + args_buffer.append( + f'{t.node}{type(value).__name__}' + f'{t.reset}()') continue if not keywords: args.extend(args_buffer) @@ -174,7 +188,7 @@ def _format(node, level=0): value, simple = _format(value, level) allsimple = allsimple and simple if keywords: - args.append('%s=%s' % (name, value)) + args.append(f'{t.field}{name}{t.reset}={value}') else: args.append(value) if include_attributes and node._attributes: @@ -187,14 +201,21 @@ def _format(node, level=0): continue value, simple = _format(value, level) allsimple = allsimple and simple - args.append('%s=%s' % (name, value)) + args.append(f'{t.attribute}{name}{t.reset}={value}') + cls_name = f'{t.node}{cls.__name__}{t.reset}' if allsimple and len(args) <= 3: - return '%s(%s)' % (node.__class__.__name__, ', '.join(args)), not args - return '%s(%s%s)' % (node.__class__.__name__, prefix, sep.join(args)), False + return f'{cls_name}({", ".join(args)})', not args + return f'{cls_name}({prefix}{sep.join(args)})', False elif isinstance(node, list): if not node: return '[]', True return '[%s%s]' % (prefix, sep.join(_format(x, level)[0] for x in node)), False + if isinstance(node, bool) or node is None or node is Ellipsis: + return f'{t.keyword}{node!r}{t.reset}', True + if isinstance(node, (int, float, complex)): + return f'{t.number}{node!r}{t.reset}', True + if isinstance(node, (str, bytes)): + return f'{t.string}{node!r}{t.reset}', True return repr(node), True if not isinstance(node, AST): @@ -642,7 +663,7 @@ def main(args=None): import argparse import sys - parser = argparse.ArgumentParser(color=True) + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('infile', nargs='?', default='-', help='the file to parse; defaults to stdin') parser.add_argument('-m', '--mode', default='exec', @@ -661,7 +682,7 @@ def main(args=None): '(for example, 3.10)') parser.add_argument('-O', '--optimize', type=int, default=-1, metavar='LEVEL', - help='optimization level for parser (default -1)') + help='optimization level for parser') parser.add_argument('--show-empty', default=False, action='store_true', help='show empty lists and fields in dump output') args = parser.parse_args(args) @@ -688,6 +709,7 @@ def main(args=None): tree = parse(source, name, args.mode, type_comments=args.no_type_comments, feature_version=feature_version, optimize=args.optimize) print(dump(tree, include_attributes=args.include_attributes, + color=can_colorize(file=sys.stdout), indent=args.indent, show_empty=args.show_empty)) if __name__ == '__main__': diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py index 0bf3bdded40..37eba9657ac 100644 --- a/Lib/asyncio/__main__.py +++ b/Lib/asyncio/__main__.py @@ -101,11 +101,15 @@ def run(self): if not sys.flags.isolated and (startup_path := os.getenv("PYTHONSTARTUP")): sys.audit("cpython.run_startup", startup_path) - - import tokenize - with tokenize.open(startup_path) as f: - startup_code = compile(f.read(), startup_path, "exec") + try: + import tokenize + with tokenize.open(startup_path) as f: + startup_code = compile(f.read(), startup_path, "exec") exec(startup_code, console.locals) + except SystemExit: + raise + except BaseException: + console.showtraceback() ps1 = getattr(sys, "ps1", ">>> ") if CAN_USE_PYREPL: @@ -162,17 +166,29 @@ def interrupt(self) -> None: "ps", help="Display a table of all pending tasks in a process" ) ps.add_argument("pid", type=int, help="Process ID to inspect") + ps.add_argument( + "--retries", + type=int, + default=3, + help="Number of retries on transient attach errors", + ) pstree = subparsers.add_parser( "pstree", help="Display a tree of all pending tasks in a process" ) pstree.add_argument("pid", type=int, help="Process ID to inspect") + pstree.add_argument( + "--retries", + type=int, + default=3, + help="Number of retries on transient attach errors", + ) args = parser.parse_args() match args.command: case "ps": - asyncio.tools.display_awaited_by_tasks_table(args.pid) + asyncio.tools.display_awaited_by_tasks_table(args.pid, retries=args.retries) sys.exit(0) case "pstree": - asyncio.tools.display_awaited_by_tasks_tree(args.pid) + asyncio.tools.display_awaited_by_tasks_tree(args.pid, retries=args.retries) sys.exit(0) case None: pass # continue to the interactive shell diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index 00e8f6d5d1a..45dfebc6590 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -37,6 +37,7 @@ def __init__(self): self._errors = [] self._base_error = None self._on_completed_fut = None + self._cancel_on_enter = False def __repr__(self): info = [''] @@ -63,6 +64,8 @@ async def __aenter__(self): raise RuntimeError( f'TaskGroup {self!r} cannot determine the parent task') self._entered = True + if self._cancel_on_enter: + self.cancel() return self @@ -178,6 +181,9 @@ async def _aexit(self, et, exc): finally: exc = None + # Suppress any remaining exception (exceptions deserving to be raised + # were raised above). + return True def create_task(self, coro, **kwargs): """Create a new task in this group and return it. @@ -278,3 +284,30 @@ def _on_task_done(self, task): self._abort() self._parent_cancel_requested = True self._parent_task.cancel() + + def cancel(self): + """Cancel the task group + + `cancel()` will be called on any tasks in the group that aren't yet + done, as well as the parent (body) of the group. This will cause the + task group context manager to exit *without* `asyncio.CancelledError` + being raised. + + If `cancel()` is called before entering the task group, the group will be + cancelled upon entry. This is useful for patterns where one piece of + code passes an unused TaskGroup instance to another in order to have + the ability to cancel anything run within the group. + + `cancel()` is idempotent and may be called after the task group has + already exited. + """ + if not self._entered: + self._cancel_on_enter = True + return + if self._exiting and not self._tasks: + return + if not self._aborting: + self._abort() + if self._parent_task and not self._parent_cancel_requested: + self._parent_cancel_requested = True + self._parent_task.cancel() diff --git a/Lib/asyncio/tools.py b/Lib/asyncio/tools.py index 62d6a71557f..2ac1738d15c 100644 --- a/Lib/asyncio/tools.py +++ b/Lib/asyncio/tools.py @@ -231,27 +231,38 @@ def exit_with_permission_help_text(): print( "Error: The specified process cannot be attached to due to insufficient permissions.\n" "See the Python documentation for details on required privileges and troubleshooting:\n" - "https://docs.python.org/3.14/howto/remote_debugging.html#permission-requirements\n" + "https://docs.python.org/3/howto/remote_debugging.html#permission-requirements\n", + file=sys.stderr, ) sys.exit(1) -def _get_awaited_by_tasks(pid: int) -> list: - try: - return get_all_awaited_by(pid) - except RuntimeError as e: - while e.__context__ is not None: - e = e.__context__ - print(f"Error retrieving tasks: {e}") - sys.exit(1) - except PermissionError: - exit_with_permission_help_text() +_TRANSIENT_ERRORS = (RuntimeError, OSError, UnicodeDecodeError, MemoryError) -def display_awaited_by_tasks_table(pid: int) -> None: +def _get_awaited_by_tasks(pid: int, retries: int = 3) -> list: + for attempt in range(retries + 1): + try: + return get_all_awaited_by(pid) + except PermissionError: + exit_with_permission_help_text() + except ProcessLookupError: + print(f"Error: process {pid} not found.", file=sys.stderr) + sys.exit(1) + except _TRANSIENT_ERRORS as e: + if attempt < retries: + continue + if isinstance(e, RuntimeError): + while e.__context__ is not None: + e = e.__context__ + print(f"Error retrieving tasks: {e}", file=sys.stderr) + sys.exit(1) + + +def display_awaited_by_tasks_table(pid: int, retries: int = 3) -> None: """Build and print a table of all pending tasks under `pid`.""" - tasks = _get_awaited_by_tasks(pid) + tasks = _get_awaited_by_tasks(pid, retries=retries) table = build_task_table(tasks) # Print the table in a simple tabular format print( @@ -262,10 +273,10 @@ def display_awaited_by_tasks_table(pid: int) -> None: print(f"{row[0]:<10} {row[1]:<20} {row[2]:<20} {row[3]:<50} {row[4]:<50} {row[5]:<15} {row[6]:<15}") -def display_awaited_by_tasks_tree(pid: int) -> None: +def display_awaited_by_tasks_tree(pid: int, retries: int = 3) -> None: """Build and print a tree of all pending tasks under `pid`.""" - tasks = _get_awaited_by_tasks(pid) + tasks = _get_awaited_by_tasks(pid, retries=retries) try: result = build_async_tree(tasks) except CycleFoundException as e: diff --git a/Lib/base64.py b/Lib/base64.py index 7f39c68070b..4b810e08569 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -68,7 +68,7 @@ def b64encode(s, altchars=None, *, padded=True, wrapcol=0): def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, - *, padded=True, ignorechars=_NOT_SPECIFIED): + *, padded=True, ignorechars=_NOT_SPECIFIED, canonical=False): """Decode the Base64 encoded bytes-like object or ASCII string s. Optional altchars must be a bytes-like object or ASCII string of length 2 @@ -110,11 +110,13 @@ def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, alphabet = binascii.BASE64_ALPHABET[:-2] + altchars return binascii.a2b_base64(s, strict_mode=validate, alphabet=alphabet, - padded=padded, ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars, + canonical=canonical) if ignorechars is _NOT_SPECIFIED: ignorechars = b'' result = binascii.a2b_base64(s, strict_mode=validate, - padded=padded, ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars, + canonical=canonical) if badchar is not None: import warnings if validate: @@ -230,7 +232,8 @@ def b32encode(s, *, padded=True, wrapcol=0): return binascii.b2a_base32(s, padded=padded, wrapcol=wrapcol) b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32') -def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b''): +def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'', + canonical=False): s = _bytes_from_decode_data(s) # Handle section 2.4 zero and one mapping. The flag map01 will be either # False, or the character to map the digit 1 (one) to. It should be @@ -240,7 +243,8 @@ def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b''): s = s.translate(bytes.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() - return binascii.a2b_base32(s, padded=padded, ignorechars=ignorechars) + return binascii.a2b_base32(s, padded=padded, ignorechars=ignorechars, + canonical=canonical) b32decode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32', extra_args=_B32_DECODE_MAP01_DOCSTRING) @@ -249,13 +253,15 @@ def b32hexencode(s, *, padded=True, wrapcol=0): alphabet=binascii.BASE32HEX_ALPHABET) b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex') -def b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b''): +def b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'', + canonical=False): s = _bytes_from_decode_data(s) # base32hex does not have the 01 mapping if casefold: s = s.upper() return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET, - padded=padded, ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars, + canonical=canonical) b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex', extra_args='') @@ -323,7 +329,8 @@ def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False): return binascii.b2a_ascii85(b, foldspaces=foldspaces, adobe=adobe, wrapcol=wrapcol, pad=pad) -def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): +def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v', + canonical=False): """Decode the Ascii85 encoded bytes-like object or ASCII string b. foldspaces is a flag that specifies whether the 'y' short sequence should be @@ -337,10 +344,13 @@ def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): input. This should only contain whitespace characters, and by default contains all whitespace characters in ASCII. + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ return binascii.a2b_ascii85(b, foldspaces=foldspaces, - adobe=adobe, ignorechars=ignorechars) + adobe=adobe, ignorechars=ignorechars, + canonical=canonical) def b85encode(b, pad=False, *, wrapcol=0): """Encode bytes-like object b in base85 format and return a bytes object. @@ -353,12 +363,15 @@ def b85encode(b, pad=False, *, wrapcol=0): """ return binascii.b2a_base85(b, wrapcol=wrapcol, pad=pad) -def b85decode(b, *, ignorechars=b''): +def b85decode(b, *, ignorechars=b'', canonical=False): """Decode the base85-encoded bytes-like object or ASCII string b + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ - return binascii.a2b_base85(b, ignorechars=ignorechars) + return binascii.a2b_base85(b, ignorechars=ignorechars, + canonical=canonical) def z85encode(s, pad=False, *, wrapcol=0): """Encode bytes-like object b in z85 format and return a bytes object. @@ -372,12 +385,15 @@ def z85encode(s, pad=False, *, wrapcol=0): return binascii.b2a_base85(s, wrapcol=wrapcol, pad=pad, alphabet=binascii.Z85_ALPHABET) -def z85decode(s, *, ignorechars=b''): +def z85decode(s, *, ignorechars=b'', canonical=False): """Decode the z85-encoded bytes-like object or ASCII string b + If canonical is true, non-canonical encodings are rejected. + The result is returned as a bytes object. """ - return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET, ignorechars=ignorechars) + return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET, + ignorechars=ignorechars, canonical=canonical) # Legacy interface. This code could be cleaned up since I don't believe # binascii has any line length limitations. It just doesn't seem worth it diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index febab521629..20f1e728733 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1253,6 +1253,20 @@ def copy(self): c.update(self) return c + + # This method has a default implementation in MutableMapping, but dict's + # equivalent is last-in, first-out instead of first-in, first-out. + def popitem(self): + """Remove and return a (key, value) pair as a 2-tuple. + + Removes pairs in the same order as the wrapped mapping's popitem() + method. For dict objects (the default), that order is last-in, + first-out (LIFO). + Raises KeyError if the UserDict is empty. + """ + return self.data.popitem() + + @classmethod def fromkeys(cls, iterable, value=None): d = cls() diff --git a/Lib/configparser.py b/Lib/configparser.py index e76647d339e..a53ac872764 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -315,12 +315,15 @@ def __init__(self, source, *args): def append(self, lineno, line): self.errors.append((lineno, line)) - self.message += '\n\t[line %2d]: %s' % (lineno, repr(line)) + self.message += f'\n\t[line {lineno:2d}]: {line!r}' def combine(self, others): + messages = [self.message] for other in others: - for error in other.errors: - self.append(*error) + for lineno, line in other.errors: + self.errors.append((lineno, line)) + messages.append(f'\n\t[line {lineno:2d}]: {line!r}') + self.message = "".join(messages) return self @staticmethod diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 482a4c61039..df192763c5b 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1,13 +1,13 @@ -import re import sys -import copy import types -import inspect import keyword import itertools import annotationlib import abc from reprlib import recursive_repr +lazy import copy +lazy import inspect +lazy import re __all__ = ['dataclass', @@ -217,9 +217,8 @@ def __repr__(self): _POST_INIT_NAME = '__post_init__' # String regex that string annotations for ClassVar or InitVar must match. -# Allows "identifier.identifier[" or "identifier[". -# https://bugs.python.org/issue33453 for details. -_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') +# This regular expression is compiled on demand so that 're' module can be imported lazily +_MODULE_IDENTIFIER_RE = None # Atomic immutable types which don't require any recursive handling and for which deepcopy # returns the same object. We can provide a fast-path for these types in asdict and astuple. @@ -725,10 +724,10 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, annotation_fields=annotation_fields) -def _frozen_get_del_attr(cls, fields, func_builder): - locals = {'cls': cls, +def _frozen_set_del_attr(cls, fields, func_builder): + locals = {'__class__': cls, 'FrozenInstanceError': FrozenInstanceError} - condition = 'type(self) is cls' + condition = 'type(self) is __class__' if fields: condition += ' or name in {' + ', '.join(repr(f.name) for f in fields) + '}' @@ -736,14 +735,14 @@ def _frozen_get_del_attr(cls, fields, func_builder): ('self', 'name', 'value'), (f' if {condition}:', ' raise FrozenInstanceError(f"cannot assign to field {name!r}")', - f' super(cls, self).__setattr__(name, value)'), + f' super(__class__, self).__setattr__(name, value)'), locals=locals, overwrite_error=True) func_builder.add_fn('__delattr__', ('self', 'name'), (f' if {condition}:', ' raise FrozenInstanceError(f"cannot delete field {name!r}")', - f' super(cls, self).__delattr__(name)'), + f' super(__class__, self).__delattr__(name)'), locals=locals, overwrite_error=True) @@ -804,10 +803,17 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): # a eval() penalty for every single field of every dataclass # that's defined. It was judged not worth it. - match = _MODULE_IDENTIFIER_RE.match(annotation) + # String regex that string annotations for ClassVar or InitVar must match. + # Allows "identifier.identifier[" or "identifier[". + # https://github.com/python/cpython/issues/77634 for details. + global _MODULE_IDENTIFIER_RE + if _MODULE_IDENTIFIER_RE is None: + _MODULE_IDENTIFIER_RE = re.compile(r'(?:\s*(\w+)\s*\.)?\s*(\w+)') + + match = _MODULE_IDENTIFIER_RE.prefixmatch(annotation) if match: ns = None - module_name = match.group(1) + module_name = match[1] if not module_name: # No module name, assume the class's module did # "from dataclasses import InitVar". @@ -817,7 +823,7 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): module = sys.modules.get(cls.__module__) if module and module.__dict__.get(module_name) is a_module: ns = sys.modules.get(a_type.__module__).__dict__ - if ns and is_type_predicate(ns.get(match.group(2)), a_module): + if ns and is_type_predicate(ns.get(match[2]), a_module): return True return False @@ -982,6 +988,28 @@ def _hash_exception(cls, fields, func_builder): # See https://bugs.python.org/issue32929#msg312829 for an if-statement # version of this table. +# A non-data descriptor to autogenerate class docstring +# from the signature of its __init__ method on demand. +# The primary reason is to be able to lazy import `inspect` module. +class _AutoDocstring: + + def __get__(self, _obj, cls): + try: + # In some cases fetching a signature is not possible. + # But, we surely should not fail in this case. + text_sig = str(inspect.signature( + cls, + annotation_format=annotationlib.Format.FORWARDREF, + )).replace(' -> None', '') + except TypeError, ValueError: + text_sig = '' + + doc = cls.__name__ + text_sig + setattr(cls, '__doc__', doc) + return doc + +_auto_docstring = _AutoDocstring() + def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, match_args, kw_only, slots, weakref_slot): @@ -1199,7 +1227,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, overwrite_error='Consider using functools.total_ordering') if frozen: - _frozen_get_del_attr(cls, field_list, func_builder) + _frozen_set_del_attr(cls, field_list, func_builder) # Decide if/how we're going to create a hash function. hash_action = _hash_action[bool(unsafe_hash), @@ -1209,23 +1237,13 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, if hash_action: cls.__hash__ = hash_action(cls, field_list, func_builder) - # Generate the methods and add them to the class. This needs to be done - # before the __doc__ logic below, since inspect will look at the __init__ - # signature. + # Generate the methods and add them to the class. func_builder.add_fns_to_class(cls) if not getattr(cls, '__doc__'): - # Create a class doc-string. - try: - # In some cases fetching a signature is not possible. - # But, we surely should not fail in this case. - text_sig = str(inspect.signature( - cls, - annotation_format=annotationlib.Format.FORWARDREF, - )).replace(' -> None', '') - except (TypeError, ValueError): - text_sig = '' - cls.__doc__ = (cls.__name__ + text_sig) + # Create a class doc-string lazily via descriptor protocol + # to avoid importing `inspect` module. + cls.__doc__ = _auto_docstring if match_args: # I could probably compute this once. @@ -1292,10 +1310,18 @@ def _update_func_cell_for__class__(f, oldcls, newcls): # This function doesn't reference __class__, so nothing to do. return False # Fix the cell to point to the new class, if it's already pointing - # at the old class. I'm not convinced that the "is oldcls" test - # is needed, but other than performance can't hurt. + # at the old class. closure = f.__closure__[idx] - if closure.cell_contents is oldcls: + + try: + contents = closure.cell_contents + except ValueError: + # Cell is empty + return False + + # This check makes it so we avoid updating an incorrect cell if the + # class body contains a function that was defined in a different class. + if contents is oldcls: closure.cell_contents = newcls return True return False @@ -1377,8 +1403,10 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields): # make an update, since all closures for a class will share a # given cell. for member in newcls.__dict__.values(): + # If this is a wrapped function, unwrap it. - member = inspect.unwrap(member) + if not isinstance(member, type) and hasattr(member, '__wrapped__'): + member = inspect.unwrap(member) if isinstance(member, types.FunctionType): if _update_func_cell_for__class__(member, cls, newcls): @@ -1490,7 +1518,8 @@ class C: If given, 'dict_factory' will be used instead of built-in dict. The function applies recursively to field values that are dataclass instances. This will also look into built-in containers: - tuples, lists, and dicts. Other objects are copied with 'copy.deepcopy()'. + tuples, lists, dicts, and frozendicts. Other objects are copied + with 'copy.deepcopy()'. """ if not _is_dataclass_instance(obj): raise TypeError("asdict() should be called on dataclass instances") @@ -1546,7 +1575,7 @@ def _asdict_inner(obj, dict_factory): return obj_type(*[_asdict_inner(v, dict_factory) for v in obj]) else: return obj_type(_asdict_inner(v, dict_factory) for v in obj) - elif issubclass(obj_type, dict): + elif issubclass(obj_type, (dict, frozendict)): if hasattr(obj_type, 'default_factory'): # obj is a defaultdict, which has a different constructor from # dict as it requires the default_factory as its first arg. @@ -1581,7 +1610,8 @@ class C: If given, 'tuple_factory' will be used instead of built-in tuple. The function applies recursively to field values that are dataclass instances. This will also look into built-in containers: - tuples, lists, and dicts. Other objects are copied with 'copy.deepcopy()'. + tuples, lists, dicts, and frozendicts. Other objects are copied + with 'copy.deepcopy()'. """ if not _is_dataclass_instance(obj): @@ -1610,7 +1640,7 @@ def _astuple_inner(obj, tuple_factory): # generator (which is not true for namedtuples, handled # above). return type(obj)(_astuple_inner(v, tuple_factory) for v in obj) - elif isinstance(obj, dict): + elif isinstance(obj, (dict, frozendict)): obj_type = type(obj) if hasattr(obj_type, 'default_factory'): # obj is a defaultdict, which has a different constructor from diff --git a/Lib/email/generator.py b/Lib/email/generator.py index cebbc416087..ba11d63fba6 100644 --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -392,7 +392,7 @@ def _make_boundary(cls, text=None): b = boundary counter = 0 while True: - cre = cls._compile_re('^--' + re.escape(b) + '(--)?$', re.MULTILINE) + cre = cls._compile_re('^--' + re.escape(b) + '(--)?\r?$', re.MULTILINE) if not cre.search(text): break b = boundary + '.' + str(counter) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 76954111699..660fec4f1be 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -391,17 +391,21 @@ def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self.OutputString()) def js_output(self, attrs=None): + import base64 # Print javascript output_string = self.OutputString(attrs) if _has_control_character(output_string): raise CookieError("Control characters are not allowed in cookies") + # Base64-encode value to avoid template + # injection in cookie values. + output_encoded = base64.b64encode(output_string.encode('utf-8')).decode("ascii") return """ - """ % (output_string.replace('"', r'\"')) + """ % (output_encoded,) def OutputString(self, attrs=None): # Build up our result diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index d10c88a43f9..1cabe479450 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -476,34 +476,58 @@ def GetExtensionKeys(self, extensionName): Keybindings come from GetCurrentKeySet() active key dict, where previously used bindings are disabled. """ - keysName = extensionName + '_cfgBindings' - activeKeys = self.GetCurrentKeySet() - extKeys = {} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames = self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - event = '<<' + eventName + '>>' - binding = activeKeys[event] - extKeys[event] = binding - return extKeys + bindings_section = f'{extensionName}_cfgBindings' + current_keyset = self.GetCurrentKeySet() + extension_keys = {} - def __GetRawExtensionKeys(self,extensionName): + event_names = set() + if self.userCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.userCfg['extensions'].GetOptionList(bindings_section) + ) + if self.defaultCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.defaultCfg['extensions'].GetOptionList(bindings_section) + ) + + for event_name in event_names: + event = f'<<{event_name}>>' + binding = current_keyset.get(event, None) + if binding is None: + continue + extension_keys[event] = binding + return extension_keys + + def __GetRawExtensionKeys(self, extension_name): """Return dict {configurable extensionName event : keybinding list}. Events come from default config extension_cfgBindings section. Keybindings list come from the splitting of GetOption, which tries user config before default config. """ - keysName = extensionName+'_cfgBindings' - extKeys = {} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames = self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - binding = self.GetOption( - 'extensions', keysName, eventName, default='').split() - event = '<<' + eventName + '>>' - extKeys[event] = binding - return extKeys + bindings_section = f'{extension_name}_cfgBindings' + extension_keys = {} + + event_names = set() + if self.userCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.userCfg['extensions'].GetOptionList(bindings_section) + ) + if self.defaultCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.defaultCfg['extensions'].GetOptionList(bindings_section) + ) + + for event_name in event_names: + binding = self.GetOption( + 'extensions', + bindings_section, + event_name, + default='', + ).split() + event = f'<<{event_name}>>' + extension_keys[event] = binding + return extension_keys def GetExtensionBindings(self, extensionName): """Return dict {extensionName event : active or defined keybinding}. @@ -512,18 +536,30 @@ def GetExtensionBindings(self, extensionName): configurable events (from default config) to GetOption splits, as in self.__GetRawExtensionKeys. """ - bindsName = extensionName + '_bindings' - extBinds = self.GetExtensionKeys(extensionName) - #add the non-configurable bindings - if self.defaultCfg['extensions'].has_section(bindsName): - eventNames = self.defaultCfg['extensions'].GetOptionList(bindsName) - for eventName in eventNames: - binding = self.GetOption( - 'extensions', bindsName, eventName, default='').split() - event = '<<' + eventName + '>>' - extBinds[event] = binding + bindings_section = f'{extensionName}_bindings' + extension_keys = self.GetExtensionKeys(extensionName) - return extBinds + # add the non-configurable bindings + event_names = set() + if self.userCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.userCfg['extensions'].GetOptionList(bindings_section) + ) + if self.defaultCfg['extensions'].has_section(bindings_section): + event_names |= set( + self.defaultCfg['extensions'].GetOptionList(bindings_section) + ) + + for event_name in event_names: + binding = self.GetOption( + 'extensions', + bindings_section, + event_name, + default='' + ).split() + event = f'<<{event_name}>>' + extension_keys[event] = binding + return extension_keys def GetKeyBinding(self, keySetName, eventStr): """Return the keybinding list for keySetName eventStr. diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index e618ef07a90..10bd3c23450 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1960,12 +1960,15 @@ def create_page_extensions(self): def load_extensions(self): "Fill self.extensions with data from the default and user configs." self.extensions = {} + for ext_name in idleConf.GetExtensions(active_only=False): # Former built-in extensions are already filtered out. self.extensions[ext_name] = [] for ext_name in self.extensions: - opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) + default = set(self.ext_defaultCfg.GetOptionList(ext_name)) + user = set(self.ext_userCfg.GetOptionList(ext_name)) + opt_list = sorted(default | user) # Bring 'enable' options to the beginning of the list. enables = [opt_name for opt_name in opt_list @@ -1975,8 +1978,12 @@ def load_extensions(self): opt_list = enables + opt_list for opt_name in opt_list: - def_str = self.ext_defaultCfg.Get( - ext_name, opt_name, raw=True) + if opt_name in default: + def_str = self.ext_defaultCfg.Get( + ext_name, opt_name, raw=True) + else: + def_str = self.ext_userCfg.Get( + ext_name, opt_name, raw=True) try: def_obj = {'True':True, 'False':False}[def_str] opt_type = 'bool' @@ -2054,10 +2061,11 @@ def set_extension_value(self, section, opt): default = opt['default'] value = opt['var'].get().strip() or default opt['var'].set(value) - # if self.defaultCfg.has_section(section): - # Currently, always true; if not, indent to return. - if (value == default): + + # Only save option in user config if it differs from the default + if self.ext_defaultCfg.has_section(section) and value == default: return self.ext_userCfg.RemoveOption(section, name) + # Set the option. return self.ext_userCfg.SetOption(section, name, value) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 3128934763a..239bf5af470 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -312,6 +312,9 @@ def __init__(self, flist=None, filename=None, key=None, root=None): else: self.update_menu_state('options', '*ine*umbers', 'disabled') + self.mtime = self.last_mtime() + text_frame.bind('', self.focus_in_event) + def handle_winconfig(self, event=None): self.set_width() @@ -857,9 +860,8 @@ def RemoveKeybindings(self): self.text.event_delete(event, *keylist) for extensionName in self.get_standard_extension_names(): xkeydefs = idleConf.GetExtensionBindings(extensionName) - if xkeydefs: - for event, keylist in xkeydefs.items(): - self.text.event_delete(event, *keylist) + for event, keylist in xkeydefs.items(): + self.text.event_delete(event, *keylist) def ApplyKeybindings(self): """Apply the virtual, configurable keybindings. @@ -1027,6 +1029,8 @@ def get_saved(self): def set_saved(self, flag): self.undo.set_saved(flag) + if flag: + self.mtime = self.last_mtime() def reset_undo(self): self.undo.reset_undo() @@ -1112,6 +1116,21 @@ def _close(self): # unless override: unregister from flist, terminate if last window self.close_hook() + def last_mtime(self): + file = self.io.filename + return os.path.getmtime(file) if file else 0 + + def focus_in_event(self, event): + mtime = self.last_mtime() + if self.mtime != mtime: + self.mtime = mtime + if self. askyesno( + 'Reload', '"%s"\n\nThis script has been modified by another program.' + '\nDo you want to reload it?' % self.io.filename, parent=self.text): + self.io.loadfile(self.io.filename) + else: + self.set_saved(False) + def load_extensions(self): self.extensions = {} self.load_standard_extensions() diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index 9a9d3b7b4e2..57bf5559c0f 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -82,6 +82,99 @@ def test_get_multiple_message(self, mock): subtests += 1 self.assertEqual(subtests, len(data2)) # All subtests ran? + def _capture_exception(self): + """Call run.print_exception() and return its stderr output.""" + with captured_stderr() as output: + with mock.patch.object(run, 'cleanup_traceback') as ct: + ct.side_effect = lambda t, e: t + run.print_exception() + return output.getvalue() + + @force_not_colorized + def test_print_exception_group_nested(self): + try: + try: + raise ExceptionGroup('inner', [ValueError('v1')]) + except ExceptionGroup as inner: + raise ExceptionGroup('outer', [inner, TypeError('t1')]) + except ExceptionGroup: + tb = self._capture_exception() + + self.assertIn('ExceptionGroup: outer (2 sub-exceptions)', tb) + self.assertIn('ExceptionGroup: inner', tb) + self.assertIn('ValueError: v1', tb) + self.assertIn('TypeError: t1', tb) + # Verify tree structure characters. + self.assertIn('+-+---------------- 1 ----------------', tb) + self.assertIn('+---------------- 2 ----------------', tb) + self.assertIn('+------------------------------------', tb) + + @force_not_colorized + def test_print_exception_group_chaining(self): + # __cause__ on a sub-exception exercises the prefixed + # chaining-message path (margin chars on separator lines). + sub = TypeError('t1') + sub.__cause__ = ValueError('original') + try: + raise ExceptionGroup('eg1', [sub]) + except ExceptionGroup: + tb = self._capture_exception() + self.assertIn('ValueError: original', tb) + self.assertIn('| The above exception was the direct cause', tb) + self.assertIn('ExceptionGroup: eg1', tb) + + # __context__ (implicit chaining) on a sub-exception. + sub = TypeError('t2') + sub.__context__ = ValueError('first') + try: + raise ExceptionGroup('eg2', [sub]) + except ExceptionGroup: + tb = self._capture_exception() + self.assertIn('ValueError: first', tb) + self.assertIn('| During handling of the above exception', tb) + self.assertIn('ExceptionGroup: eg2', tb) + + @force_not_colorized + def test_print_exception_group_seen(self): + shared = ValueError('shared') + try: + raise ExceptionGroup('eg', [shared, shared]) + except ExceptionGroup: + tb = self._capture_exception() + + self.assertIn('ValueError: shared', tb) + self.assertIn('', tb) + + @force_not_colorized + def test_print_exception_group_max_width(self): + excs = [ValueError(f'v{i}') for i in range(20)] + try: + raise ExceptionGroup('eg', excs) + except ExceptionGroup: + tb = self._capture_exception() + + self.assertIn('+---------------- 15 ----------------', tb) + self.assertIn('+---------------- ... ----------------', tb) + self.assertIn('and 5 more exceptions', tb) + self.assertNotIn('+---------------- 16 ----------------', tb) + + @force_not_colorized + def test_print_exception_group_max_depth(self): + def make_nested(depth): + if depth == 0: + return ValueError('leaf') + return ExceptionGroup(f'level{depth}', + [make_nested(depth - 1)]) + + try: + raise make_nested(15) + except ExceptionGroup: + tb = self._capture_exception() + + self.assertIn('... (max_group_depth is 10)', tb) + self.assertIn('ExceptionGroup: level15', tb) + self.assertNotIn('ValueError: leaf', tb) + # StdioFile tests. class S(str): diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py index 86c5d41b629..86c21f00bb8 100644 --- a/Lib/idlelib/idle_test/test_squeezer.py +++ b/Lib/idlelib/idle_test/test_squeezer.py @@ -170,6 +170,7 @@ def test_write_not_stdout(self): def test_write_stdout(self): """Test Squeezer's overriding of the EditorWindow's write() method.""" + requires('gui') editwin = self.make_mock_editor_window() for text in ['', 'TEXT']: diff --git a/Lib/idlelib/idle_test/test_zzdummy.py b/Lib/idlelib/idle_test/test_zzdummy.py index 209d8564da0..14c343cf9b3 100644 --- a/Lib/idlelib/idle_test/test_zzdummy.py +++ b/Lib/idlelib/idle_test/test_zzdummy.py @@ -38,38 +38,8 @@ def __init__(self, root, text): self.text.undo_block_stop = mock.Mock() -class ZZDummyTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - requires('gui') - root = cls.root = Tk() - root.withdraw() - text = cls.text = Text(cls.root) - cls.editor = DummyEditwin(root, text) - zzdummy.idleConf.userCfg = testcfg - - @classmethod - def tearDownClass(cls): - zzdummy.idleConf.userCfg = usercfg - del cls.editor, cls.text - cls.root.update_idletasks() - for id in cls.root.tk.call('after', 'info'): - cls.root.after_cancel(id) # Need for EditorWindow. - cls.root.destroy() - del cls.root - - def setUp(self): - text = self.text - text.insert('1.0', code_sample) - text.undo_block_start.reset_mock() - text.undo_block_stop.reset_mock() - zz = self.zz = zzdummy.ZzDummy(self.editor) - zzdummy.ZzDummy.ztext = '# ignore #' - - def tearDown(self): - self.text.delete('1.0', 'end') - del self.zz +class ZZDummyMixin: + """Shared tests for ZzDummy with default and user configs.""" def checklines(self, text, value): # Verify that there are lines being checked. @@ -89,7 +59,8 @@ def test_init(self): def test_reload(self): self.assertEqual(self.zz.ztext, '# ignore #') - testcfg['extensions'].SetOption('ZzDummy', 'z-text', 'spam') + zzdummy.idleConf.userCfg['extensions'].SetOption( + 'ZzDummy', 'z-text', 'spam') zzdummy.ZzDummy.reload() self.assertEqual(self.zz.ztext, 'spam') @@ -148,5 +119,75 @@ def test_roundtrip(self): self.assertEqual(text.get('1.0', 'end-1c'), code_sample) +class ZZDummyTest(ZZDummyMixin, unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + root = cls.root = Tk() + root.withdraw() + text = cls.text = Text(cls.root) + cls.editor = DummyEditwin(root, text) + zzdummy.idleConf.userCfg = testcfg + + @classmethod + def tearDownClass(cls): + zzdummy.idleConf.userCfg = usercfg + del cls.editor, cls.text + cls.root.update_idletasks() + for id in cls.root.tk.call('after', 'info'): + cls.root.after_cancel(id) # Need for EditorWindow. + cls.root.destroy() + del cls.root + + def setUp(self): + text = self.text + text.insert('1.0', code_sample) + text.undo_block_start.reset_mock() + text.undo_block_stop.reset_mock() + zz = self.zz = zzdummy.ZzDummy(self.editor) + zzdummy.ZzDummy.ztext = '# ignore #' + + def tearDown(self): + self.text.delete('1.0', 'end') + del self.zz + + def test_exists(self): + conf = zzdummy.idleConf + self.assertEqual( + conf.GetSectionList('user', 'extensions'), []) + self.assertEqual( + conf.GetSectionList('default', 'extensions'), + ['AutoComplete', 'CodeContext', 'FormatParagraph', + 'ParenMatch', 'ZzDummy', 'ZzDummy_cfgBindings', + 'ZzDummy_bindings']) + self.assertIn("ZzDummy", conf.GetExtensions(False)) + self.assertNotIn("ZzDummy", conf.GetExtensions()) + self.assertEqual( + conf.GetExtensionKeys("ZzDummy"), {}) + self.assertEqual( + conf.GetExtensionBindings("ZzDummy"), + {'<>': ['']}) + + def test_exists_user(self): + conf = zzdummy.idleConf + conf.userCfg["extensions"].read_dict({ + "ZzDummy": {'enable': 'True'} + }) + self.assertEqual( + conf.GetSectionList('user', 'extensions'), + ["ZzDummy"]) + self.assertIn("ZzDummy", conf.GetExtensions()) + self.assertEqual( + conf.GetExtensionKeys("ZzDummy"), + {'<>': ['']}) + self.assertEqual( + conf.GetExtensionBindings("ZzDummy"), + {'<>': [''], + '<>': ['']}) + # Restore + conf.userCfg["extensions"].remove_section("ZzDummy") + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_zzdummy_user.py b/Lib/idlelib/idle_test/test_zzdummy_user.py new file mode 100644 index 00000000000..1d3f2ac3096 --- /dev/null +++ b/Lib/idlelib/idle_test/test_zzdummy_user.py @@ -0,0 +1,108 @@ +"Test zzdummy with user config, coverage 100%." + +from idlelib import zzdummy +import unittest +from test.support import requires +from tkinter import Tk, Text +from idlelib import config + +from idlelib.idle_test.test_zzdummy import ( + ZZDummyMixin, DummyEditwin, code_sample, +) + + +real_usercfg = zzdummy.idleConf.userCfg +test_usercfg = { + 'main': config.IdleUserConfParser(''), + 'highlight': config.IdleUserConfParser(''), + 'keys': config.IdleUserConfParser(''), + 'extensions': config.IdleUserConfParser(''), +} +test_usercfg["extensions"].read_dict({ + "ZzDummy": {'enable': 'True', 'enable_shell': 'False', + 'enable_editor': 'True', 'z-text': 'Z'}, + "ZzDummy_cfgBindings": { + 'z-in': ''}, + "ZzDummy_bindings": { + 'z-out': ''}, +}) +real_defaultcfg = zzdummy.idleConf.defaultCfg +test_defaultcfg = { + 'main': config.IdleUserConfParser(''), + 'highlight': config.IdleUserConfParser(''), + 'keys': config.IdleUserConfParser(''), + 'extensions': config.IdleUserConfParser(''), +} +test_defaultcfg["extensions"].read_dict({ + "AutoComplete": {'popupwait': '2000'}, + "CodeContext": {'maxlines': '15'}, + "FormatParagraph": {'max-width': '72'}, + "ParenMatch": {'style': 'expression', + 'flash-delay': '500', 'bell': 'True'}, +}) +test_defaultcfg["main"].read_dict({ + "Theme": {"default": 1, "name": "IDLE Classic", "name2": ""}, + "Keys": {"default": 1, "name": "IDLE Classic", "name2": ""}, +}) +for key in ("keys",): + real_default = real_defaultcfg[key] + value = {name: dict(real_default[name]) for name in real_default} + test_defaultcfg[key].read_dict(value) + + +class ZZDummyTest(ZZDummyMixin, unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + root = cls.root = Tk() + root.withdraw() + text = cls.text = Text(cls.root) + cls.editor = DummyEditwin(root, text) + zzdummy.idleConf.userCfg = test_usercfg + zzdummy.idleConf.defaultCfg = test_defaultcfg + + @classmethod + def tearDownClass(cls): + zzdummy.idleConf.defaultCfg = real_defaultcfg + zzdummy.idleConf.userCfg = real_usercfg + del cls.editor, cls.text + cls.root.update_idletasks() + for id in cls.root.tk.call('after', 'info'): + cls.root.after_cancel(id) # Need for EditorWindow. + cls.root.destroy() + del cls.root + + def setUp(self): + text = self.text + text.insert('1.0', code_sample) + text.undo_block_start.reset_mock() + text.undo_block_stop.reset_mock() + zz = self.zz = zzdummy.ZzDummy(self.editor) + zzdummy.ZzDummy.ztext = '# ignore #' + + def tearDown(self): + self.text.delete('1.0', 'end') + del self.zz + + def test_exists(self): + self.assertEqual( + zzdummy.idleConf.GetSectionList('user', 'extensions'), + ['ZzDummy', 'ZzDummy_cfgBindings', 'ZzDummy_bindings']) + self.assertEqual( + zzdummy.idleConf.GetSectionList('default', 'extensions'), + ['AutoComplete', 'CodeContext', 'FormatParagraph', + 'ParenMatch']) + self.assertIn("ZzDummy", + zzdummy.idleConf.GetExtensions()) + self.assertEqual( + zzdummy.idleConf.GetExtensionKeys("ZzDummy"), + {'<>': ['']}) + self.assertEqual( + zzdummy.idleConf.GetExtensionBindings("ZzDummy"), + {'<>': [''], + '<>': ['']}) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index a30db99a619..e1c40fee8f4 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -249,31 +249,94 @@ def print_exception(): sys.last_type, sys.last_value, sys.last_traceback = excinfo sys.last_exc = val seen = set() + exclude = ("run.py", "rpc.py", "threading.py", "queue.py", + "debugger_r.py", "bdb.py") + max_group_width = 15 + max_group_depth = 10 + group_depth = 0 - def print_exc(typ, exc, tb): + def print_exc_group(typ, exc, tb, prefix=""): + nonlocal group_depth + group_depth += 1 + prefix2 = prefix or " " + if group_depth > max_group_depth: + print(f"{prefix2}| ... (max_group_depth is {max_group_depth})", + file=efile) + group_depth -= 1 + return + if tb: + if not prefix: + print(" + Exception Group Traceback (most recent call last):", file=efile) + else: + print(f"{prefix}| Exception Group Traceback (most recent call last):", file=efile) + tbe = traceback.extract_tb(tb) + cleanup_traceback(tbe, exclude) + for line in traceback.format_list(tbe): + for subline in line.rstrip().splitlines(): + print(f"{prefix2}| {subline}", file=efile) + lines = get_message_lines(typ, exc, tb) + for line in lines: + print(f"{prefix2}| {line}", end="", file=efile) + num_excs = len(exc.exceptions) + if num_excs <= max_group_width: + n = num_excs + else: + n = max_group_width + 1 + for i, sub in enumerate(exc.exceptions[:n], 1): + truncated = (i > max_group_width) + first_line_pre = "+-" if i == 1 else " " + title = str(i) if not truncated else '...' + print(f"{prefix2}{first_line_pre}+---------------- {title} ----------------", file=efile) + if truncated: + remaining = num_excs - max_group_width + plural = 's' if remaining > 1 else '' + print(f"{prefix2} | and {remaining} more exception{plural}", + file=efile) + need_print_underline = True + elif id(sub) not in seen: + if not prefix: + print_exc(type(sub), sub, sub.__traceback__, " ") + else: + print_exc(type(sub), sub, sub.__traceback__, prefix + " ") + need_print_underline = not isinstance(sub, BaseExceptionGroup) + else: + print(f"{prefix2} | ", file=efile) + need_print_underline = True + if need_print_underline and i == n: + print(f"{prefix2} +------------------------------------", file=efile) + group_depth -= 1 + + def print_exc(typ, exc, tb, prefix=""): seen.add(id(exc)) context = exc.__context__ cause = exc.__cause__ + prefix2 = f"{prefix}| " if prefix else "" if cause is not None and id(cause) not in seen: - print_exc(type(cause), cause, cause.__traceback__) - print("\nThe above exception was the direct cause " - "of the following exception:\n", file=efile) + print_exc(type(cause), cause, cause.__traceback__, prefix) + print(f"{prefix2}\n{prefix2}The above exception was the direct cause " + f"of the following exception:\n{prefix2}", file=efile) elif (context is not None and not exc.__suppress_context__ and id(context) not in seen): - print_exc(type(context), context, context.__traceback__) - print("\nDuring handling of the above exception, " - "another exception occurred:\n", file=efile) - if tb: - tbe = traceback.extract_tb(tb) - print('Traceback (most recent call last):', file=efile) - exclude = ("run.py", "rpc.py", "threading.py", "queue.py", - "debugger_r.py", "bdb.py") - cleanup_traceback(tbe, exclude) - traceback.print_list(tbe, file=efile) - lines = get_message_lines(typ, exc, tb) - for line in lines: - print(line, end='', file=efile) + print_exc(type(context), context, context.__traceback__, prefix) + print(f"{prefix2}\n{prefix2}During handling of the above exception, " + f"another exception occurred:\n{prefix2}", file=efile) + if isinstance(exc, BaseExceptionGroup): + print_exc_group(typ, exc, tb, prefix=prefix) + else: + if tb: + print(f"{prefix2}Traceback (most recent call last):", file=efile) + tbe = traceback.extract_tb(tb) + cleanup_traceback(tbe, exclude) + if prefix: + for line in traceback.format_list(tbe): + for subline in line.rstrip().splitlines(): + print(f"{prefix}| {subline}", file=efile) + else: + traceback.print_list(tbe, file=efile) + lines = get_message_lines(typ, exc, tb) + for line in lines: + print(f"{prefix2}{line}", end="", file=efile) print_exc(typ, val, tb) diff --git a/Lib/importlib/resources/__init__.py b/Lib/importlib/resources/__init__.py index 723c9f9eb33..27d6c7f8930 100644 --- a/Lib/importlib/resources/__init__.py +++ b/Lib/importlib/resources/__init__.py @@ -8,12 +8,11 @@ """ from ._common import ( + Anchor, + Package, as_file, files, - Package, - Anchor, ) - from ._functional import ( contents, is_resource, @@ -23,10 +22,8 @@ read_binary, read_text, ) - from .abc import ResourceReader - __all__ = [ 'Package', 'Anchor', diff --git a/Lib/importlib/resources/_common.py b/Lib/importlib/resources/_common.py index d16ebe4520f..6f87d77492f 100644 --- a/Lib/importlib/resources/_common.py +++ b/Lib/importlib/resources/_common.py @@ -1,17 +1,17 @@ -import os -import pathlib -import tempfile -import functools import contextlib -import types +import functools import importlib import inspect import itertools +import os +import pathlib +import tempfile +import types +from typing import Optional, cast -from typing import Union, Optional, cast from .abc import ResourceReader, Traversable -Package = Union[types.ModuleType, str] +Package = types.ModuleType | str Anchor = Package @@ -71,6 +71,19 @@ def is_wrapper(frame_info): return next(callers).frame +def _assert_spec(package: types.ModuleType) -> None: + """ + Provide a nicer error message when package is ``__main__`` + and its ``__spec__`` is ``None`` + (https://docs.python.org/3/reference/import.html#main-spec). + """ + if package.__spec__ is None: + raise TypeError( + f"Cannot access resources for '{package.__name__}' " + "as it does not appear to correspond to an importable module (its __spec__ is None)." + ) + + def from_package(package: types.ModuleType): """ Return a Traversable object for the given package. @@ -79,6 +92,7 @@ def from_package(package: types.ModuleType): # deferred for performance (python/cpython#109829) from ._adapters import wrap_spec + _assert_spec(package) spec = wrap_spec(package) reader = spec.loader.get_resource_reader(spec.name) return reader.files() diff --git a/Lib/importlib/resources/_functional.py b/Lib/importlib/resources/_functional.py index f59416f2dd6..b08a5c6efe2 100644 --- a/Lib/importlib/resources/_functional.py +++ b/Lib/importlib/resources/_functional.py @@ -2,8 +2,8 @@ import warnings -from ._common import files, as_file - +from ._common import as_file, files +from .abc import TraversalError _MISSING = object() @@ -42,7 +42,10 @@ def is_resource(anchor, *path_names): Otherwise returns ``False``. """ - return _get_resource(anchor, path_names).is_file() + try: + return _get_resource(anchor, path_names).is_file() + except TraversalError: + return False def contents(anchor, *path_names): diff --git a/Lib/importlib/resources/abc.py b/Lib/importlib/resources/abc.py index 6750a7aaf14..0b5fdee80e8 100644 --- a/Lib/importlib/resources/abc.py +++ b/Lib/importlib/resources/abc.py @@ -1,14 +1,22 @@ import abc -import io import itertools import os import pathlib -from typing import Any, BinaryIO, Iterable, Iterator, NoReturn, Text, Optional -from typing import runtime_checkable, Protocol -from typing import Union +from collections.abc import Iterable, Iterator +from typing import ( + Any, + BinaryIO, + Literal, + NoReturn, + Optional, + Protocol, + Text, + TextIO, + overload, + runtime_checkable, +) - -StrPath = Union[str, os.PathLike[str]] +StrPath = str | os.PathLike[str] __all__ = ["ResourceReader", "Traversable", "TraversableResources"] @@ -82,11 +90,13 @@ def read_bytes(self) -> bytes: with self.open('rb') as strm: return strm.read() - def read_text(self, encoding: Optional[str] = None) -> str: + def read_text( + self, encoding: Optional[str] = None, errors: Optional[str] = None + ) -> str: """ Read contents of self as text """ - with self.open(encoding=encoding) as strm: + with self.open(encoding=encoding, errors=errors) as strm: return strm.read() @abc.abstractmethod @@ -132,8 +142,14 @@ def __truediv__(self, child: StrPath) -> "Traversable": """ return self.joinpath(child) + @overload + def open(self, mode: Literal['r'] = 'r', *args: Any, **kwargs: Any) -> TextIO: ... + + @overload + def open(self, mode: Literal['rb'], *args: Any, **kwargs: Any) -> BinaryIO: ... + @abc.abstractmethod - def open(self, mode='r', *args, **kwargs): + def open(self, mode: str = 'r', *args: Any, **kwargs: Any) -> TextIO | BinaryIO: """ mode may be 'r' or 'rb' to open as text or binary. Return a handle suitable for reading (same as pathlib.Path.open). @@ -160,7 +176,7 @@ class TraversableResources(ResourceReader): def files(self) -> "Traversable": """Return a Traversable object for the loaded package.""" - def open_resource(self, resource: StrPath) -> io.BufferedReader: + def open_resource(self, resource: StrPath) -> BinaryIO: return self.files().joinpath(resource).open('rb') def resource_path(self, resource: Any) -> NoReturn: diff --git a/Lib/importlib/resources/readers.py b/Lib/importlib/resources/readers.py index 70fc7e2b9c0..5d0ae46d672 100644 --- a/Lib/importlib/resources/readers.py +++ b/Lib/importlib/resources/readers.py @@ -3,15 +3,14 @@ import collections import contextlib import itertools -import pathlib import operator +import pathlib import re import warnings import zipfile from collections.abc import Iterator from . import abc - from ._itertools import only diff --git a/Lib/importlib/resources/simple.py b/Lib/importlib/resources/simple.py index 2e75299b13a..5e182d12607 100644 --- a/Lib/importlib/resources/simple.py +++ b/Lib/importlib/resources/simple.py @@ -5,7 +5,7 @@ import abc import io import itertools -from typing import BinaryIO, List +from typing import BinaryIO from .abc import Traversable, TraversableResources @@ -24,14 +24,14 @@ def package(self) -> str: """ @abc.abstractmethod - def children(self) -> List['SimpleReader']: + def children(self) -> list['SimpleReader']: """ Obtain an iterable of SimpleReader for available child containers (e.g. directories). """ @abc.abstractmethod - def resources(self) -> List[str]: + def resources(self) -> list[str]: """ Obtain available named resources for this virtual package. """ diff --git a/Lib/inspect.py b/Lib/inspect.py index dfc5503dee5..d3af61b26e2 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -416,7 +416,6 @@ def iscode(object): co_freevars tuple of names of free variables co_posonlyargcount number of positional only arguments co_kwonlyargcount number of keyword only arguments (not including ** arg) - co_lnotab encoded mapping of line numbers to bytecode indices co_name name with which this code object was defined co_names tuple of names other than arguments and function locals co_nlocals number of local variables @@ -1634,7 +1633,6 @@ def getframeinfo(frame, context=1): def getlineno(frame): """Get the line number from a frame object, allowing for optimization.""" - # FrameType.f_lineno is now a descriptor that grovels co_lnotab return frame.f_lineno _FrameInfo = namedtuple('_FrameInfo', ('frame',) + Traceback._fields) diff --git a/Lib/json/tool.py b/Lib/json/tool.py index e0b944b197d..e56a601c581 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -89,7 +89,8 @@ def main(): infile = open(options.infile, encoding='utf-8') try: if options.json_lines: - objs = (json.loads(line) for line in infile) + lines = infile.readlines() + objs = (json.loads(line) for line in lines) else: objs = (json.load(infile),) finally: diff --git a/Lib/locale.py b/Lib/locale.py index e7382796905..4ff6f8c0f0a 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -1505,8 +1505,8 @@ def getpreferredencoding(do_setlocale=True): # This maps Windows language identifiers to locale strings. # # This list has been updated from -# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_238z.asp -# to include every locale up to Windows Vista. +# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/70feba9f-294e-491e-b6eb-56532684c37f +# to include every locale up to protocol revision 16.0 (2024-04-23). # # NOTE: this mapping is incomplete. If your language is missing, please # submit a bug report as detailed in the Python devguide at: @@ -1516,10 +1516,15 @@ def getpreferredencoding(do_setlocale=True): # windows_locale = { - 0x0436: "af_ZA", # Afrikaans - 0x041c: "sq_AL", # Albanian - 0x0484: "gsw_FR",# Alsatian - France + 0x0036: "af", # Afrikaans + 0x0436: "af_ZA", # Afrikaans - South Africa + 0x001c: "sq", # Albanian + 0x041c: "sq_AL", # Albanian - Albania + 0x0084: "gsw", # Alsatian + 0x0484: "gsw_FR", # Alsatian - France + 0x005e: "am", # Amharic 0x045e: "am_ET", # Amharic - Ethiopia + 0x0001: "ar", # Arabic 0x0401: "ar_SA", # Arabic - Saudi Arabia 0x0801: "ar_IQ", # Arabic - Iraq 0x0c01: "ar_EG", # Arabic - Egypt @@ -1533,39 +1538,72 @@ def getpreferredencoding(do_setlocale=True): 0x2c01: "ar_JO", # Arabic - Jordan 0x3001: "ar_LB", # Arabic - Lebanon 0x3401: "ar_KW", # Arabic - Kuwait - 0x3801: "ar_AE", # Arabic - United Arab Emirates + 0x3801: "ar_AE", # Arabic - U.A.E. 0x3c01: "ar_BH", # Arabic - Bahrain 0x4001: "ar_QA", # Arabic - Qatar - 0x042b: "hy_AM", # Armenian + 0x002b: "hy", # Armenian + 0x042b: "hy_AM", # Armenian - Armenia + 0x004d: "as", # Assamese 0x044d: "as_IN", # Assamese - India - 0x042c: "az_AZ", # Azeri - Latin - 0x082c: "az_AZ", # Azeri - Cyrillic - 0x046d: "ba_RU", # Bashkir - 0x042d: "eu_ES", # Basque - Russia - 0x0423: "be_BY", # Belarusian - 0x0445: "bn_IN", # Begali - 0x201a: "bs_BA", # Bosnian - Cyrillic - 0x141a: "bs_BA", # Bosnian - Latin + 0x002c: "az", # Azerbaijani (Latin) + 0x742c: "az", # Azerbaijani (Cyrillic) + 0x782c: "az", # Azerbaijani (Latin) + 0x042c: "az_AZ", # Azerbaijani (Latin) - Azerbaijan + 0x0045: "bn", # Bangla + 0x0445: "bn_IN", # Bangla - India + 0x0845: "bn_BD", # Bangla - Bangladesh + 0x006d: "ba", # Bashkir + 0x046d: "ba_RU", # Bashkir - Russia + 0x002d: "eu", # Basque + 0x042d: "eu_ES", # Basque - Spain + 0x0023: "be", # Belarusian + 0x0423: "be_BY", # Belarusian - Belarus + 0x641a: "bs", # Bosnian (Cyrillic) + 0x681a: "bs", # Bosnian (Latin) + 0x141a: "bs_BA", # Bosnian (Latin) - Bosnia and Herzegovina + 0x201a: "bs_BA", # Bosnian (Cyrillic) - Bosnia and Herzegovina + 0x781a: "bs", # Bosnian (Latin) + 0x007e: "br", # Breton 0x047e: "br_FR", # Breton - France - 0x0402: "bg_BG", # Bulgarian -# 0x0455: "my_MM", # Burmese - Not supported - 0x0403: "ca_ES", # Catalan - 0x0004: "zh_CHS",# Chinese - Simplified - 0x0404: "zh_TW", # Chinese - Taiwan - 0x0804: "zh_CN", # Chinese - PRC - 0x0c04: "zh_HK", # Chinese - Hong Kong S.A.R. - 0x1004: "zh_SG", # Chinese - Singapore - 0x1404: "zh_MO", # Chinese - Macao S.A.R. - 0x7c04: "zh_CHT",# Chinese - Traditional + 0x0002: "bg", # Bulgarian + 0x0402: "bg_BG", # Bulgarian - Bulgaria + 0x0055: "my", # Burmese + 0x0455: "my_MM", # Burmese - Myanmar + 0x0003: "ca", # Catalan + 0x0403: "ca_ES", # Catalan - Spain + 0x0803: "ca_ES", # Valencian - Spain + 0x0092: "ku", # Central Kurdish + 0x7c92: "ku", # Central Kurdish + 0x0492: "ku_IQ", # Central Kurdish - Iraq + 0x005c: "chr", # Cherokee + 0x7c5c: "chr", # Cherokee + 0x045c: "chr_US", # Cherokee - United States + 0x0004: "zh", # Chinese (Simplified) + 0x7804: "zh", # Chinese (Simplified) + 0x7c04: "zh", # Chinese (Traditional) + 0x0404: "zh_TW", # Chinese (Traditional) - Taiwan + 0x0804: "zh_CN", # Chinese (Simplified) - People's Republic of China + 0x0c04: "zh_HK", # Chinese (Traditional) - Hong Kong S.A.R. + 0x1004: "zh_SG", # Chinese (Simplified) - Singapore + 0x1404: "zh_MO", # Chinese (Traditional) - Macao S.A.R. + 0x0083: "co", # Corsican 0x0483: "co_FR", # Corsican - France - 0x041a: "hr_HR", # Croatian - 0x101a: "hr_BA", # Croatian - Bosnia - 0x0405: "cs_CZ", # Czech - 0x0406: "da_DK", # Danish - 0x048c: "gbz_AF",# Dari - Afghanistan - 0x0465: "div_MV",# Divehi - Maldives - 0x0413: "nl_NL", # Dutch - The Netherlands + 0x001a: "hr", # Croatian + 0x041a: "hr_HR", # Croatian - Croatia + 0x101a: "hr_BA", # Croatian (Latin) - Bosnia and Herzegovina + 0x0005: "cs", # Czech + 0x0405: "cs_CZ", # Czech - Czech Republic + 0x0006: "da", # Danish + 0x0406: "da_DK", # Danish - Denmark + 0x008c: "prs", # Dari + 0x048c: "prs_AF", # Dari - Afghanistan + 0x0065: "dv", # Divehi + 0x0465: "dv_MV", # Divehi - Maldives + 0x0013: "nl", # Dutch + 0x0413: "nl_NL", # Dutch - Netherlands 0x0813: "nl_BE", # Dutch - Belgium + 0x0c51: "dz_BT", # Dzongkha - Bhutan + 0x0009: "en", # English 0x0409: "en_US", # English - United States 0x0809: "en_GB", # English - United Kingdom 0x0c09: "en_AU", # English - Australia @@ -1573,122 +1611,248 @@ def getpreferredencoding(do_setlocale=True): 0x1409: "en_NZ", # English - New Zealand 0x1809: "en_IE", # English - Ireland 0x1c09: "en_ZA", # English - South Africa - 0x2009: "en_JA", # English - Jamaica - 0x2409: "en_CB", # English - Caribbean + 0x2009: "en_JM", # English - Jamaica 0x2809: "en_BZ", # English - Belize - 0x2c09: "en_TT", # English - Trinidad + 0x2c09: "en_TT", # English - Trinidad and Tobago 0x3009: "en_ZW", # English - Zimbabwe - 0x3409: "en_PH", # English - Philippines + 0x3409: "en_PH", # English - Republic of the Philippines + 0x3c09: "en_HK", # English - Hong Kong 0x4009: "en_IN", # English - India 0x4409: "en_MY", # English - Malaysia - 0x4809: "en_IN", # English - Singapore - 0x0425: "et_EE", # Estonian - 0x0438: "fo_FO", # Faroese - 0x0464: "fil_PH",# Filipino - 0x040b: "fi_FI", # Finnish + 0x4809: "en_SG", # English - Singapore + 0x4c09: "en_AE", # English - United Arab Emirates + 0x0025: "et", # Estonian + 0x0425: "et_EE", # Estonian - Estonia + 0x0038: "fo", # Faroese + 0x0438: "fo_FO", # Faroese - Faroe Islands + 0x0064: "fil", # Filipino + 0x0464: "fil_PH", # Filipino - Philippines + 0x000b: "fi", # Finnish + 0x040b: "fi_FI", # Finnish - Finland + 0x000c: "fr", # French 0x040c: "fr_FR", # French - France 0x080c: "fr_BE", # French - Belgium 0x0c0c: "fr_CA", # French - Canada 0x100c: "fr_CH", # French - Switzerland 0x140c: "fr_LU", # French - Luxembourg - 0x180c: "fr_MC", # French - Monaco + 0x180c: "fr_MC", # French - Principality of Monaco + 0x1c0c: "fr_029", # French - Caribbean + 0x200c: "fr_RE", # French - Reunion + 0x240c: "fr_CD", # French - Congo, DRC + 0x280c: "fr_SN", # French - Senegal + 0x2c0c: "fr_CM", # French - Cameroon + 0x300c: "fr_CI", # French - Côte d'Ivoire + 0x340c: "fr_ML", # French - Mali + 0x380c: "fr_MA", # French - Morocco + 0x3c0c: "fr_HT", # French - Haiti + 0x0062: "fy", # Frisian 0x0462: "fy_NL", # Frisian - Netherlands - 0x0456: "gl_ES", # Galician - 0x0437: "ka_GE", # Georgian + 0x0067: "ff", # Fulah + 0x7c67: "ff", # Fulah (Latin) + 0x0467: "ff_NG", + 0x0867: "ff_SN", # Fulah - Senegal + 0x0056: "gl", # Galician + 0x0456: "gl_ES", # Galician - Spain + 0x0037: "ka", # Georgian + 0x0437: "ka_GE", # Georgian - Georgia + 0x0007: "de", # German 0x0407: "de_DE", # German - Germany 0x0807: "de_CH", # German - Switzerland 0x0c07: "de_AT", # German - Austria 0x1007: "de_LU", # German - Luxembourg 0x1407: "de_LI", # German - Liechtenstein - 0x0408: "el_GR", # Greek + 0x0008: "el", # Greek + 0x0408: "el_GR", # Greek - Greece + 0x006f: "kl", # Greenlandic 0x046f: "kl_GL", # Greenlandic - Greenland - 0x0447: "gu_IN", # Gujarati - 0x0468: "ha_NG", # Hausa - Latin - 0x040d: "he_IL", # Hebrew - 0x0439: "hi_IN", # Hindi - 0x040e: "hu_HU", # Hungarian - 0x040f: "is_IS", # Icelandic - 0x0421: "id_ID", # Indonesian - 0x045d: "iu_CA", # Inuktitut - Syllabics - 0x085d: "iu_CA", # Inuktitut - Latin + 0x0074: "gn", # Guarani + 0x0474: "gn_PY", # Guarani - Paraguay + 0x0047: "gu", # Gujarati + 0x0447: "gu_IN", # Gujarati - India + 0x0068: "ha", # Hausa (Latin) + 0x7c68: "ha", # Hausa (Latin) + 0x0468: "ha_NG", # Hausa (Latin) - Nigeria + 0x0075: "haw", # Hawaiian + 0x0475: "haw_US", # Hawaiian - United States + 0x000d: "he", # Hebrew + 0x040d: "he_IL", # Hebrew - Israel + 0x0039: "hi", # Hindi + 0x0439: "hi_IN", # Hindi - India + 0x000e: "hu", # Hungarian + 0x040e: "hu_HU", # Hungarian - Hungary + 0x000f: "is", # Icelandic + 0x040f: "is_IS", # Icelandic - Iceland + 0x0070: "ig", # Igbo + 0x0470: "ig_NG", # Igbo - Nigeria + 0x0021: "id", # Indonesian + 0x0421: "id_ID", # Indonesian - Indonesia + 0x005d: "iu", # Inuktitut (Latin) + 0x785d: "iu", # Inuktitut (Syllabics) + 0x7c5d: "iu", # Inuktitut (Latin) + 0x045d: "iu_CA", # Inuktitut (Syllabics) - Canada + 0x085d: "iu_CA", # Inuktitut (Latin) - Canada + 0x003c: "ga", # Irish 0x083c: "ga_IE", # Irish - Ireland + 0x0010: "it", # Italian 0x0410: "it_IT", # Italian - Italy 0x0810: "it_CH", # Italian - Switzerland - 0x0411: "ja_JP", # Japanese + 0x0011: "ja", # Japanese + 0x0411: "ja_JP", # Japanese - Japan + 0x004b: "kn", # Kannada 0x044b: "kn_IN", # Kannada - India - 0x043f: "kk_KZ", # Kazakh - 0x0453: "kh_KH", # Khmer - Cambodia - 0x0486: "qut_GT",# K'iche - Guatemala + 0x0471: "kr_NG", # Kanuri (Latin) - Nigeria + 0x0060: "ks", # Kashmiri + 0x0460: "ks", # Kashmiri - Perso_Arabic + 0x0860: "ks_IN", # Kashmiri (Devanagari) - India + 0x003f: "kk", # Kazakh + 0x043f: "kk_KZ", # Kazakh - Kazakhstan + 0x0053: "km", # Khmer + 0x0453: "km_KH", # Khmer - Cambodia + 0x0087: "rw", # Kinyarwanda 0x0487: "rw_RW", # Kinyarwanda - Rwanda - 0x0457: "kok_IN",# Konkani - 0x0412: "ko_KR", # Korean - 0x0440: "ky_KG", # Kyrgyz - 0x0454: "lo_LA", # Lao - Lao PDR - 0x0426: "lv_LV", # Latvian - 0x0427: "lt_LT", # Lithuanian - 0x082e: "dsb_DE",# Lower Sorbian - Germany - 0x046e: "lb_LU", # Luxembourgish - 0x042f: "mk_MK", # FYROM Macedonian + 0x0041: "sw", # Kiswahili + 0x0441: "sw_KE", # Kiswahili - Kenya + 0x0057: "kok", # Konkani + 0x0457: "kok_IN", # Konkani - India + 0x0012: "ko", # Korean + 0x0412: "ko_KR", # Korean - Korea + 0x0040: "ky", # Kyrgyz + 0x0440: "ky_KG", # Kyrgyz - Kyrgyzstan + 0x0054: "lo", # Lao + 0x0454: "lo_LA", # Lao - Lao P.D.R. + 0x0476: "la_VA", # Latin - Vatican City + 0x0026: "lv", # Latvian + 0x0426: "lv_LV", # Latvian - Latvia + 0x0027: "lt", # Lithuanian + 0x0427: "lt_LT", # Lithuanian - Lithuania + 0x7c2e: "dsb", # Lower Sorbian + 0x082e: "dsb_DE", # Lower Sorbian - Germany + 0x006e: "lb", # Luxembourgish + 0x046e: "lb_LU", # Luxembourgish - Luxembourg + 0x002f: "mk", # Macedonian + 0x042f: "mk_MK", # Macedonian - North Macedonia + 0x003e: "ms", # Malay 0x043e: "ms_MY", # Malay - Malaysia 0x083e: "ms_BN", # Malay - Brunei Darussalam + 0x004c: "ml", # Malayalam 0x044c: "ml_IN", # Malayalam - India - 0x043a: "mt_MT", # Maltese - 0x0481: "mi_NZ", # Maori - 0x047a: "arn_CL",# Mapudungun - 0x044e: "mr_IN", # Marathi - 0x047c: "moh_CA",# Mohawk - Canada - 0x0450: "mn_MN", # Mongolian - Cyrillic - 0x0850: "mn_CN", # Mongolian - PRC - 0x0461: "ne_NP", # Nepali - 0x0414: "nb_NO", # Norwegian - Bokmal - 0x0814: "nn_NO", # Norwegian - Nynorsk + 0x003a: "mt", # Maltese + 0x043a: "mt_MT", # Maltese - Malta + 0x0081: "mi", # Maori + 0x0481: "mi_NZ", # Maori - New Zealand + 0x007a: "arn", # Mapudungun + 0x047a: "arn_CL", # Mapudungun - Chile + 0x004e: "mr", # Marathi + 0x044e: "mr_IN", # Marathi - India + 0x007c: "moh", # Mohawk + 0x047c: "moh_CA", # Mohawk - Canada + 0x0050: "mn", # Mongolian (Cyrillic) + 0x7850: "mn", # Mongolian (Cyrillic) + 0x7c50: "mn", # Mongolian (Traditional Mongolian) + 0x0450: "mn_MN", # Mongolian (Cyrillic) - Mongolia + 0x0c50: "mn_MN", # Mongolian (Traditional Mongolian) - Mongolia + 0x0061: "ne", # Nepali + 0x0461: "ne_NP", # Nepali - Nepal + 0x0861: "ne_IN", # Nepali - India + 0x0014: "no", # Norwegian (Bokmal) + 0x0414: "nb_NO", # Norwegian (Bokmal) - Norway + 0x0814: "nn_NO", # Norwegian (Nynorsk) - Norway + 0x7814: "nn", # Norwegian (Nynorsk) + 0x7c14: "nb", # Norwegian (Bokmal) + 0x0082: "oc", # Occitan 0x0482: "oc_FR", # Occitan - France - 0x0448: "or_IN", # Oriya - India + 0x0048: "or", # Odia + 0x0448: "or_IN", # Odia - India + 0x0072: "om", # Oromo + 0x0472: "om_ET", # Oromo - Ethiopia + 0x0063: "ps", # Pashto 0x0463: "ps_AF", # Pashto - Afghanistan - 0x0429: "fa_IR", # Persian - 0x0415: "pl_PL", # Polish + 0x0029: "fa", # Persian + 0x0429: "fa_IR", # Persian - Iran + 0x0015: "pl", # Polish + 0x0415: "pl_PL", # Polish - Poland + 0x0016: "pt", # Portuguese 0x0416: "pt_BR", # Portuguese - Brazil 0x0816: "pt_PT", # Portuguese - Portugal - 0x0446: "pa_IN", # Punjabi - 0x046b: "quz_BO",# Quechua (Bolivia) - 0x086b: "quz_EC",# Quechua (Ecuador) - 0x0c6b: "quz_PE",# Quechua (Peru) + 0x0046: "pa", # Punjabi + 0x7c46: "pa", # Punjabi + 0x0446: "pa_IN", # Punjabi - India + 0x0846: "pa_PK", # Punjabi - Islamic Republic of Pakistan + 0x006b: "quz", # Quechua + 0x046b: "quz_BO", # Quechua - Bolivia + 0x086b: "quz_EC", # Quechua - Ecuador + 0x0c6b: "quz_PE", # Quechua - Peru + 0x0018: "ro", # Romanian 0x0418: "ro_RO", # Romanian - Romania - 0x0417: "rm_CH", # Romansh - 0x0419: "ru_RU", # Russian - 0x243b: "smn_FI",# Sami Finland - 0x103b: "smj_NO",# Sami Norway - 0x143b: "smj_SE",# Sami Sweden - 0x043b: "se_NO", # Sami Northern Norway - 0x083b: "se_SE", # Sami Northern Sweden - 0x0c3b: "se_FI", # Sami Northern Finland - 0x203b: "sms_FI",# Sami Skolt - 0x183b: "sma_NO",# Sami Southern Norway - 0x1c3b: "sma_SE",# Sami Southern Sweden - 0x044f: "sa_IN", # Sanskrit - 0x0c1a: "sr_SP", # Serbian - Cyrillic - 0x1c1a: "sr_BA", # Serbian - Bosnia Cyrillic - 0x081a: "sr_SP", # Serbian - Latin - 0x181a: "sr_BA", # Serbian - Bosnia Latin + 0x0818: "ro_MD", # Romanian - Moldova + 0x0017: "rm", # Romansh + 0x0417: "rm_CH", # Romansh - Switzerland + 0x0019: "ru", # Russian + 0x0419: "ru_RU", # Russian - Russia + 0x0819: "ru_MD", # Russian - Moldova + 0x0085: "sah", # Sakha + 0x0485: "sah_RU", # Sakha - Russia + 0x003b: "se", # Sami (Northern) + 0x043b: "se_NO", # Sami (Northern) - Norway + 0x083b: "se_SE", # Sami (Northern) - Sweden + 0x0c3b: "se_FI", # Sami (Northern) - Finland + 0x7c3b: "smj", # Sami (Lule) + 0x103b: "smj_NO", # Sami (Lule) - Norway + 0x143b: "smj_SE", # Sami (Lule) - Sweden + 0x783b: "sma", # Sami (Southern) + 0x183b: "sma_NO", # Sami (Southern) - Norway + 0x1c3b: "sma_SE", # Sami (Southern) - Sweden + 0x743b: "sms", # Sami (Skolt) + 0x203b: "sms_FI", # Sami (Skolt) - Finland + 0x703b: "smn", # Sami (Inari) + 0x243b: "smn_FI", # Sami (Inari) - Finland + 0x004f: "sa", # Sanskrit + 0x044f: "sa_IN", # Sanskrit - India + 0x0091: "gd", # Scottish Gaelic + 0x0491: "gd_GB", # Scottish Gaelic - United Kingdom + 0x6c1a: "sr", # Serbian (Cyrillic) + 0x701a: "sr", # Serbian (Latin) + 0x7c1a: "sr", # Serbian (Latin) + 0x081a: "sr_CS", # Serbian (Latin) - Serbia and Montenegro (Former) + 0x0c1a: "sr_CS", # Serbian (Cyrillic) - Serbia and Montenegro (Former) + 0x181a: "sr_BA", # Serbian (Latin) - Bosnia and Herzegovina + 0x1c1a: "sr_BA", # Serbian (Cyrillic) - Bosnia and Herzegovina + 0x241a: "sr_RS", # Serbian (Latin) - Serbia + 0x281a: "sr_RS", # Serbian (Cyrillic) - Serbia + 0x2c1a: "sr_ME", # Serbian (Latin) - Montenegro + 0x301a: "sr_ME", # Serbian (Cyrillic) - Montenegro + 0x006c: "nso", # Sesotho sa Leboa + 0x046c: "nso_ZA", # Sesotho sa Leboa - South Africa + 0x0032: "tn", # Setswana + 0x0432: "tn_ZA", # Setswana - South Africa + 0x0832: "tn_BW", # Setswana - Botswana + 0x0059: "sd", # Sindhi + 0x7c59: "sd", # Sindhi + 0x0859: "sd_PK", # Sindhi - Islamic Republic of Pakistan + 0x005b: "si", # Sinhala 0x045b: "si_LK", # Sinhala - Sri Lanka - 0x046c: "ns_ZA", # Northern Sotho - 0x0432: "tn_ZA", # Setswana - Southern Africa - 0x041b: "sk_SK", # Slovak - 0x0424: "sl_SI", # Slovenian + 0x001b: "sk", # Slovak + 0x041b: "sk_SK", # Slovak - Slovakia + 0x0024: "sl", # Slovenian + 0x0424: "sl_SI", # Slovenian - Slovenia + 0x0477: "so_SO", # Somali - Somalia + 0x0030: "st", # Sotho + 0x0430: "st_ZA", # Sotho - South Africa + 0x000a: "es", # Spanish 0x040a: "es_ES", # Spanish - Spain 0x080a: "es_MX", # Spanish - Mexico - 0x0c0a: "es_ES", # Spanish - Spain (Modern) + 0x0c0a: "es_ES", # Spanish - Spain 0x100a: "es_GT", # Spanish - Guatemala 0x140a: "es_CR", # Spanish - Costa Rica 0x180a: "es_PA", # Spanish - Panama 0x1c0a: "es_DO", # Spanish - Dominican Republic - 0x200a: "es_VE", # Spanish - Venezuela + 0x200a: "es_VE", # Spanish - Bolivarian Republic of Venezuela 0x240a: "es_CO", # Spanish - Colombia 0x280a: "es_PE", # Spanish - Peru 0x2c0a: "es_AR", # Spanish - Argentina 0x300a: "es_EC", # Spanish - Ecuador 0x340a: "es_CL", # Spanish - Chile - 0x380a: "es_UR", # Spanish - Uruguay + 0x380a: "es_UY", # Spanish - Uruguay 0x3c0a: "es_PY", # Spanish - Paraguay 0x400a: "es_BO", # Spanish - Bolivia 0x440a: "es_SV", # Spanish - El Salvador @@ -1696,36 +1860,87 @@ def getpreferredencoding(do_setlocale=True): 0x4c0a: "es_NI", # Spanish - Nicaragua 0x500a: "es_PR", # Spanish - Puerto Rico 0x540a: "es_US", # Spanish - United States -# 0x0430: "", # Sutu - Not supported - 0x0441: "sw_KE", # Swahili + 0x5c0a: "es_CU", # Spanish - Cuba + 0x001d: "sv", # Swedish 0x041d: "sv_SE", # Swedish - Sweden 0x081d: "sv_FI", # Swedish - Finland - 0x045a: "syr_SY",# Syriac - 0x0428: "tg_TJ", # Tajik - Cyrillic - 0x085f: "tmz_DZ",# Tamazight - Latin - 0x0449: "ta_IN", # Tamil - 0x0444: "tt_RU", # Tatar - 0x044a: "te_IN", # Telugu - 0x041e: "th_TH", # Thai - 0x0851: "bo_BT", # Tibetan - Bhutan - 0x0451: "bo_CN", # Tibetan - PRC - 0x041f: "tr_TR", # Turkish - 0x0442: "tk_TM", # Turkmen - Cyrillic - 0x0480: "ug_CN", # Uighur - Arabic - 0x0422: "uk_UA", # Ukrainian - 0x042e: "wen_DE",# Upper Sorbian - Germany - 0x0420: "ur_PK", # Urdu + 0x005a: "syr", # Syriac + 0x045a: "syr_SY", # Syriac - Syria + 0x0028: "tg", # Tajik (Cyrillic) + 0x7c28: "tg", # Tajik (Cyrillic) + 0x0428: "tg_TJ", # Tajik (Cyrillic) - Tajikistan + 0x005f: "tzm", # Tamazight (Latin) + 0x785f: "tzm", + 0x7c5f: "tzm", # Tamazight (Latin) + 0x085f: "tzm_DZ", # Tamazight (Latin) - Algeria + 0x045f: "tzm_MA", # Central Atlas Tamazight (Arabic) - Morocco + 0x105f: "tzm_MA", + 0x0049: "ta", # Tamil + 0x0449: "ta_IN", # Tamil - India + 0x0849: "ta_LK", # Tamil - Sri Lanka + 0x0044: "tt", # Tatar + 0x0444: "tt_RU", # Tatar - Russia + 0x004a: "te", # Telugu + 0x044a: "te_IN", # Telugu - India + 0x001e: "th", # Thai + 0x041e: "th_TH", # Thai - Thailand + 0x0051: "bo", # Tibetan + 0x0451: "bo_CN", # Tibetan - People's Republic of China + 0x0073: "ti", # Tigrinya + 0x0473: "ti_ET", # Tigrinya - Ethiopia + 0x0873: "ti_ER", # Tigrinya - Eritrea + 0x0031: "ts", # Tsonga + 0x0431: "ts_ZA", # Tsonga - South Africa + 0x001f: "tr", # Turkish + 0x041f: "tr_TR", # Turkish - Turkey + 0x0042: "tk", # Turkmen + 0x0442: "tk_TM", # Turkmen - Turkmenistan + 0x0022: "uk", # Ukrainian + 0x0422: "uk_UA", # Ukrainian - Ukraine + 0x002e: "hsb", # Upper Sorbian + 0x042e: "hsb_DE", # Upper Sorbian - Germany + 0x0020: "ur", # Urdu + 0x0420: "ur_PK", # Urdu - Islamic Republic of Pakistan 0x0820: "ur_IN", # Urdu - India - 0x0443: "uz_UZ", # Uzbek - Latin - 0x0843: "uz_UZ", # Uzbek - Cyrillic - 0x042a: "vi_VN", # Vietnamese - 0x0452: "cy_GB", # Welsh + 0x0080: "ug", # Uyghur + 0x0480: "ug_CN", # Uyghur - People's Republic of China + 0x0043: "uz", # Uzbek (Latin) + 0x7843: "uz", # Uzbek (Cyrillic) + 0x7c43: "uz", # Uzbek (Latin) + 0x0443: "uz_UZ", # Uzbek (Latin) - Uzbekistan + 0x0033: "ve", # Venda + 0x0433: "ve_ZA", # Venda - South Africa + 0x002a: "vi", # Vietnamese + 0x042a: "vi_VN", # Vietnamese - Vietnam + 0x0052: "cy", # Welsh + 0x0452: "cy_GB", # Welsh - United Kingdom + 0x0088: "wo", # Wolof 0x0488: "wo_SN", # Wolof - Senegal + 0x0034: "xh", # Xhosa 0x0434: "xh_ZA", # Xhosa - South Africa - 0x0485: "sah_RU",# Yakut - Cyrillic - 0x0478: "ii_CN", # Yi - PRC + 0x0078: "ii", # Yi + 0x0478: "ii_CN", # Yi - People's Republic of China + 0x043d: "yi_001", # Yiddish - World + 0x006a: "yo", # Yoruba 0x046a: "yo_NG", # Yoruba - Nigeria - 0x0435: "zu_ZA", # Zulu + 0x0035: "zu", # Zulu + 0x0435: "zu_ZA", # Zulu - South Africa + 0x0086: "qut", + +# 0x0001007f: "x-IV-mathan", # math alphanumeric sorting + 0x00010407: "de_DE", + 0x0001040e: "hu_HU", + 0x00010437: "ka_GE", + 0x00020804: "zh_CN", + 0x00021004: "zh_SG", + 0x00021404: "zh_MO", + 0x00030404: "zh_TW", + 0x00040404: "zh_TW", + 0x00040411: "ja_JP", + 0x00040c04: "zh_HK", + 0x00041404: "zh_MO", + 0x00050804: "zh_CN", + 0x00051004: "zh_SG", } def _print_locale(): diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 9ce996c9ccd..e37ec07d722 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -16,7 +16,6 @@ import sys import socket import struct -import tempfile import time @@ -77,7 +76,11 @@ def arbitrary_address(family): if family == 'AF_INET': return ('localhost', 0) elif family == 'AF_UNIX': - return tempfile.mktemp(prefix='sock-', dir=util.get_temp_dir()) + # NOTE: util.get_temp_dir() is a 0o700 per-process directory. A + # mktemp-style ToC vs ToU concern is not important; bind() surfaces + # the extremely unlikely collision as EADDRINUSE. + return os.path.join(util.get_temp_dir(), + f'sock-{os.urandom(6).hex()}') elif family == 'AF_PIPE': return (r'\\.\pipe\pyc-%d-%d-%s' % (os.getpid(), next(_mmap_counter), os.urandom(8).hex())) diff --git a/Lib/multiprocessing/popen_fork.py b/Lib/multiprocessing/popen_fork.py index 7affa1b985f..a02a53b6a17 100644 --- a/Lib/multiprocessing/popen_fork.py +++ b/Lib/multiprocessing/popen_fork.py @@ -67,7 +67,17 @@ def _launch(self, process_obj): code = 1 parent_r, child_w = os.pipe() child_r, parent_w = os.pipe() - self.pid = os.fork() + # gh-146313: Tell the resource tracker's at-fork handler to keep + # the inherited pipe fd so this child reuses the parent's tracker + # (gh-80849) rather than closing it and launching its own. + from .resource_tracker import _fork_intent + _fork_intent.preserve_fd = True + try: + self.pid = os.fork() + finally: + # Reset in both parent and child so the flag does not leak + # into a subsequent raw os.fork() or nested Process launch. + _fork_intent.preserve_fd = False if self.pid == 0: try: atexit._clear() diff --git a/Lib/multiprocessing/resource_tracker.py b/Lib/multiprocessing/resource_tracker.py index 3606d1effb4..d3328a8c617 100644 --- a/Lib/multiprocessing/resource_tracker.py +++ b/Lib/multiprocessing/resource_tracker.py @@ -20,6 +20,7 @@ import signal import sys import threading +import time import warnings from collections import deque @@ -75,6 +76,10 @@ def __init__(self): # The reader should understand all formats. self._use_simple_format = False + # Set to True by _stop_locked() if the waitpid polling loop ran to + # its timeout without reaping the tracker. Exposed for tests. + self._waitpid_timed_out = False + def _reentrant_call_error(self): # gh-109629: this happens if an explicit call to the ResourceTracker # gets interrupted by a garbage collection, invoking a finalizer (*) @@ -87,16 +92,51 @@ def __del__(self): # making sure child processess are cleaned before ResourceTracker # gets destructed. # see https://github.com/python/cpython/issues/88887 - self._stop(use_blocking_lock=False) + # gh-146313: use a timeout to avoid deadlocking if a forked child + # still holds the pipe's write end open. + self._stop(use_blocking_lock=False, wait_timeout=1.0) - def _stop(self, use_blocking_lock=True): + def _after_fork_in_child(self): + # gh-146313: Called in the child right after os.fork(). + # + # The tracker process is a child of the *parent*, not of us, so we + # could never waitpid() it anyway. Clearing _pid means our __del__ + # becomes a no-op (the early return for _pid is None). + # + # Whether we keep the inherited _fd depends on who forked us: + # + # - multiprocessing.Process with the 'fork' start method sets + # _fork_intent.preserve_fd before forking. The child keeps the + # fd and reuses the parent's tracker (gh-80849). This is safe + # because multiprocessing's atexit handler joins all children + # before the parent's __del__ runs, so by then the fd copies + # are gone and the parent can reap the tracker promptly. + # + # - A raw os.fork() leaves the flag unset. We close the fd in the child after forking so + # the parent's __del__ can reap the tracker without waiting + # for the child to exit. If we later need a tracker, ensure_running() + # will launch a fresh one. + self._lock._at_fork_reinit() + self._reentrant_messages.clear() + self._pid = None + self._exitcode = None + if (self._fd is not None and + not getattr(_fork_intent, 'preserve_fd', False)): + fd = self._fd + self._fd = None + try: + os.close(fd) + except OSError: + pass + + def _stop(self, use_blocking_lock=True, wait_timeout=None): if use_blocking_lock: with self._lock: - self._stop_locked() + self._stop_locked(wait_timeout=wait_timeout) else: acquired = self._lock.acquire(blocking=False) try: - self._stop_locked() + self._stop_locked(wait_timeout=wait_timeout) finally: if acquired: self._lock.release() @@ -106,6 +146,10 @@ def _stop_locked( close=os.close, waitpid=os.waitpid, waitstatus_to_exitcode=os.waitstatus_to_exitcode, + monotonic=time.monotonic, + sleep=time.sleep, + WNOHANG=getattr(os, 'WNOHANG', None), + wait_timeout=None, ): # This shouldn't happen (it might when called by a finalizer) # so we check for it anyway. @@ -122,7 +166,30 @@ def _stop_locked( self._fd = None try: - _, status = waitpid(self._pid, 0) + if wait_timeout is None: + _, status = waitpid(self._pid, 0) + else: + # gh-146313: A forked child may still hold the pipe's write + # end open, preventing the tracker from seeing EOF and + # exiting. Poll with WNOHANG to avoid blocking forever. + deadline = monotonic() + wait_timeout + delay = 0.001 + while True: + result_pid, status = waitpid(self._pid, WNOHANG) + if result_pid != 0: + break + remaining = deadline - monotonic() + if remaining <= 0: + # The tracker is still running; it will be + # reparented to PID 1 (or the nearest subreaper) + # when we exit, and reaped there once all pipe + # holders release their fd. + self._pid = None + self._exitcode = None + self._waitpid_timed_out = True + return + delay = min(delay * 2, remaining, 0.1) + sleep(delay) except ChildProcessError: self._pid = None self._exitcode = None @@ -308,12 +375,24 @@ def _send(self, cmd, name, rtype): self._ensure_running_and_write(msg) +# gh-146313: Per-thread flag set by .popen_fork.Popen._launch() just before +# os.fork(), telling _after_fork_in_child() to keep the inherited pipe fd so +# the child can reuse this tracker (gh-80849). Unset for raw os.fork() calls, +# where the child instead closes the fd so the parent's __del__ can reap the +# tracker. Using threading.local() keeps multiple threads calling +# popen_fork.Popen._launch() at once from clobbering eachothers intent. +_fork_intent = threading.local() + _resource_tracker = ResourceTracker() ensure_running = _resource_tracker.ensure_running register = _resource_tracker.register unregister = _resource_tracker.unregister getfd = _resource_tracker.getfd +# gh-146313: See _after_fork_in_child docstring. +if hasattr(os, 'register_at_fork'): + os.register_at_fork(after_in_child=_resource_tracker._after_fork_in_child) + def _decode_message(line): if line.startswith(b'{'): diff --git a/Lib/opcode.py b/Lib/opcode.py index d53b94d89b4..8466814d225 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -69,6 +69,9 @@ FOR_ITER=frozendict( counter=1, ), + GET_ITER=frozendict( + counter=1, + ), LOAD_SUPER_ATTR=frozendict( counter=1, ), diff --git a/Lib/pprint.py b/Lib/pprint.py index f197d7d17cd..73550219980 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -735,6 +735,61 @@ def _pprint_user_string(self, object, stream, indent, allowance, context, level) _dispatch[_collections.UserString.__repr__] = _pprint_user_string + def _pprint_template(self, object, stream, indent, allowance, context, level): + cls_name = object.__class__.__name__ + if self._expand: + indent += self._indent_per_level + else: + indent += len(cls_name) + 1 + + items = ( + ("strings", object.strings), + ("interpolations", object.interpolations), + ) + stream.write(self._format_block_start(cls_name + "(", indent)) + self._format_namespace_items( + items, stream, indent, allowance, context, level + ) + stream.write( + self._format_block_end(")", indent - self._indent_per_level) + ) + + def _pprint_interpolation(self, object, stream, indent, allowance, context, level): + cls_name = object.__class__.__name__ + if self._expand: + indent += self._indent_per_level + items = ( + ("value", object.value), + ("expression", object.expression), + ("conversion", object.conversion), + ("format_spec", object.format_spec), + ) + stream.write(self._format_block_start(cls_name + "(", indent)) + self._format_namespace_items( + items, stream, indent, allowance, context, level + ) + stream.write( + self._format_block_end(")", indent - self._indent_per_level) + ) + else: + indent += len(cls_name) + items = ( + object.value, + object.expression, + object.conversion, + object.format_spec, + ) + stream.write(cls_name + "(") + self._format_items( + items, stream, indent, allowance, context, level + ) + stream.write(")") + + t = t"{0}" + _dispatch[type(t).__repr__] = _pprint_template + _dispatch[type(t.interpolations[0]).__repr__] = _pprint_interpolation + del t + def _safe_repr(self, object, context, maxlevels, level): # Return triple (repr_string, isreadable, isrecursive). typ = type(object) diff --git a/Lib/profiling/sampling/_assets/tachyon-logo.png b/Lib/profiling/sampling/_assets/tachyon-logo.png index f87e006b14f..03e67823d5a 100644 Binary files a/Lib/profiling/sampling/_assets/tachyon-logo.png and b/Lib/profiling/sampling/_assets/tachyon-logo.png differ diff --git a/Lib/socket.py b/Lib/socket.py index 3073c012b19..34d897a82ed 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -649,18 +649,22 @@ def _fallback_socketpair(family=AF_INET, type=SOCK_STREAM, proto=0): # Authenticating avoids using a connection from something else # able to connect to {host}:{port} instead of us. # We expect only AF_INET and AF_INET6 families. - try: - if ( - ssock.getsockname() != csock.getpeername() - or csock.getsockname() != ssock.getpeername() - ): - raise ConnectionError("Unexpected peer connection") - except: - # getsockname() and getpeername() can fail - # if either socket isn't connected. - ssock.close() - csock.close() - raise + # + # Note that we skip this on WASI because on that platorm the client socket + # may not have finished connecting by the time we've reached this point (gh-146139). + if sys.platform != "wasi": + try: + if ( + ssock.getsockname() != csock.getpeername() + or csock.getsockname() != ssock.getpeername() + ): + raise ConnectionError("Unexpected peer connection") + except: + # getsockname() and getpeername() can fail + # if either socket isn't connected. + ssock.close() + csock.close() + raise return (ssock, csock) diff --git a/Lib/statistics.py b/Lib/statistics.py index 26cf925529e..32fcf2313a8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -136,7 +136,7 @@ from fractions import Fraction from decimal import Decimal -from itertools import count, groupby, repeat +from itertools import compress, count, groupby, repeat from bisect import bisect_left, bisect_right from math import hypot, sqrt, fabs, exp, erfc, tau, log, fsum, sumprod from math import isfinite, isinf, pi, cos, sin, tan, cosh, asin, atan, acos @@ -145,6 +145,7 @@ from collections import Counter, namedtuple, defaultdict _SQRT2 = sqrt(2.0) +_SQRT2PI = sqrt(tau) _random = random ## Exceptions ############################################################## @@ -194,9 +195,9 @@ def fmean(data, weights=None): n = len(data) except TypeError: # Handle iterators that do not define __len__(). - counter = count() - total = fsum(map(itemgetter(0), zip(data, counter))) - n = next(counter) + counter = count(1) + total = fsum(compress(data, counter)) + n = next(counter) - 1 else: total = fsum(data) @@ -1257,11 +1258,11 @@ def samples(self, n, *, seed=None): def pdf(self, x): "Probability density function. P(x <= X < x+dx) / dx" - variance = self._sigma * self._sigma - if not variance: + sigma = self._sigma + if not sigma: raise StatisticsError('pdf() not defined when sigma is zero') - diff = x - self._mu - return exp(diff * diff / (-2.0 * variance)) / sqrt(tau * variance) + z = (x - self._mu) / sigma + return exp(-0.5 * z * z) / (_SQRT2PI * sigma) def cdf(self, x): "Cumulative distribution function. P(X <= x)" diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml index a960543f277..dca74eb6e14 100644 --- a/Lib/test/.ruff.toml +++ b/Lib/test/.ruff.toml @@ -18,6 +18,8 @@ extend-exclude = [ "test_lazy_import/__init__.py", "test_lazy_import/data/*.py", "test_lazy_import/data/**/*.py", + # Unary plus literal pattern is not yet supported by Ruff (GH-145239) + "test_patma.py", ] [lint] diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 69174cff699..580d9f2b325 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -6321,8 +6321,9 @@ def test_resource_tracker_sigkill(self): def _is_resource_tracker_reused(conn, pid): from multiprocessing.resource_tracker import _resource_tracker _resource_tracker.ensure_running() - # The pid should be None in the child process, expect for the fork - # context. It should not be a new value. + # The pid should be None in the child (the at-fork handler clears + # it for fork; spawn/forkserver children never had it set). It + # should not be a new value. reused = _resource_tracker._pid in (None, pid) reused &= _resource_tracker._check_alive() conn.send(reused) @@ -6408,6 +6409,183 @@ def test_resource_tracker_blocked_signals(self): # restore sigmask to what it was before executing test signal.pthread_sigmask(signal.SIG_SETMASK, orig_sigmask) + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_fork_deadlock(self): + # gh-146313: ResourceTracker.__del__ used to deadlock if a forked + # child still held the pipe's write end open when the parent + # exited, because the parent would block in waitpid() waiting for + # the tracker to exit, but the tracker would never see EOF. + cmd = '''if 1: + import os, signal + from multiprocessing.resource_tracker import ensure_running + ensure_running() + if os.fork() == 0: + signal.pause() + os._exit(0) + # parent falls through and exits, triggering __del__ + ''' + proc = subprocess.Popen([sys.executable, '-c', cmd], + start_new_session=True) + try: + try: + proc.wait(timeout=support.SHORT_TIMEOUT) + except subprocess.TimeoutExpired: + self.fail( + "Parent process deadlocked in ResourceTracker.__del__" + ) + self.assertEqual(proc.returncode, 0) + finally: + try: + os.killpg(proc.pid, signal.SIGKILL) + except ProcessLookupError: + pass + proc.wait() + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_mp_fork_reuse_and_prompt_reap(self): + # gh-146313 / gh-80849: A child started via multiprocessing.Process + # with the 'fork' start method should reuse the parent's resource + # tracker (the at-fork handler preserves the inherited pipe fd), + # *and* the parent should be able to reap the tracker promptly + # after joining the child, without hitting the waitpid timeout. + cmd = textwrap.dedent(''' + import multiprocessing as mp + from multiprocessing.resource_tracker import _resource_tracker + + def child(conn): + # Prove we can talk to the parent's tracker by registering + # and unregistering a dummy resource over the inherited fd. + # If the fd were closed, ensure_running would launch a new + # tracker and _pid would be non-None. + _resource_tracker.register("x", "dummy") + _resource_tracker.unregister("x", "dummy") + conn.send((_resource_tracker._fd is not None, + _resource_tracker._pid is None, + _resource_tracker._check_alive())) + + if __name__ == "__main__": + mp.set_start_method("fork") + _resource_tracker.ensure_running() + r, w = mp.Pipe(duplex=False) + p = mp.Process(target=child, args=(w,)) + p.start() + child_has_fd, child_pid_none, child_alive = r.recv() + p.join() + w.close(); r.close() + + # Now simulate __del__: the child has exited and released + # its fd copy, so the tracker should see EOF and exit + # promptly -- no timeout. + _resource_tracker._stop(wait_timeout=5.0) + print(child_has_fd, child_pid_none, child_alive, + _resource_tracker._waitpid_timed_out, + _resource_tracker._exitcode) + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + parts = out.decode().split() + self.assertEqual(parts, ['True', 'True', 'True', 'False', '0'], + f"unexpected: {parts!r} stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_raw_fork_prompt_reap(self): + # gh-146313: After a raw os.fork() the at-fork handler closes the + # child's inherited fd, so the parent can reap the tracker + # immediately -- even while the child is still alive -- rather + # than waiting out the 1s timeout. + cmd = textwrap.dedent(''' + import os, signal + from multiprocessing.resource_tracker import _resource_tracker + + _resource_tracker.ensure_running() + r, w = os.pipe() + pid = os.fork() + if pid == 0: + os.close(r) + # Report whether our fd was closed by the at-fork handler. + os.write(w, b"1" if _resource_tracker._fd is None else b"0") + os.close(w) + signal.pause() # stay alive so parent's reap is meaningful + os._exit(0) + os.close(w) + child_fd_closed = os.read(r, 1) == b"1" + os.close(r) + + # Child is still alive and paused. Because it closed its fd + # copy, our close below is the last one and the tracker exits. + _resource_tracker._stop(wait_timeout=5.0) + + os.kill(pid, signal.SIGKILL) + os.waitpid(pid, 0) + print(child_fd_closed, + _resource_tracker._waitpid_timed_out, + _resource_tracker._exitcode) + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + parts = out.decode().split() + self.assertEqual(parts, ['True', 'False', '0'], + f"unexpected: {parts!r} stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_lock_reinit_after_fork(self): + # gh-146313: If a parent thread held the tracker's lock at fork + # time, the child would inherit the held lock and deadlock on + # its next ensure_running(). The at-fork handler reinits it. + cmd = textwrap.dedent(''' + import os, threading + from multiprocessing.resource_tracker import _resource_tracker + + held = threading.Event() + release = threading.Event() + def hold(): + with _resource_tracker._lock: + held.set() + release.wait() + t = threading.Thread(target=hold) + t.start() + held.wait() + + pid = os.fork() + if pid == 0: + ok = _resource_tracker._lock.acquire(timeout=5.0) + os._exit(0 if ok else 1) + + release.set() + t.join() + _, status = os.waitpid(pid, 0) + print(os.waitstatus_to_exitcode(status)) + ''') + rc, out, err = script_helper.assert_python_ok( + '-W', 'ignore::DeprecationWarning', '-c', cmd) + self.assertEqual(out.strip(), b'0', + f"child failed to acquire lock: stderr={err!r}") + + @only_run_in_forkserver_testsuite("avoids redundant testing.") + def test_resource_tracker_safety_net_timeout(self): + # gh-146313: When an mp.Process(fork) child holds the preserved + # fd and the parent calls _stop() without joining (simulating + # abnormal shutdown), the safety-net timeout should fire rather + # than deadlocking. + cmd = textwrap.dedent(''' + import multiprocessing as mp + import signal + from multiprocessing.resource_tracker import _resource_tracker + + if __name__ == "__main__": + mp.set_start_method("fork") + _resource_tracker.ensure_running() + p = mp.Process(target=signal.pause) + p.start() + # Stop WITHOUT joining -- child still holds preserved fd + _resource_tracker._stop(wait_timeout=0.5) + print(_resource_tracker._waitpid_timed_out) + p.terminate() + p.join() + ''') + rc, out, err = script_helper.assert_python_ok('-c', cmd) + self.assertEqual(out.strip(), b'True', + f"safety-net timeout did not fire: stderr={err!r}") + + class TestSimpleQueue(unittest.TestCase): @classmethod diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index bb8695541ac..5d5b8e415f3 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -22,7 +22,7 @@ from test import support from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST -from test.support import os_helper, script_helper, warnings_helper +from test.support import os_helper, script_helper import datetime as datetime_module from datetime import MINYEAR, MAXYEAR @@ -1206,15 +1206,20 @@ def test_strptime_single_digit(self): newdate = strptime(string, format) self.assertEqual(newdate, target, msg=reason) - @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. with self.assertRaises(ValueError): # The existing behavior that GH-70647 seeks to change. date.strptime('02-29', '%m-%d') + # %e without a year is deprecated, scheduled for removal in 3.17. + _strptime._regex_cache.clear() + with self.assertWarnsRegex(DeprecationWarning, + r'.*day of month without a year.*'): + date.strptime('02-01', '%m-%e') with self._assertNotWarns(DeprecationWarning): date.strptime('20-03-14', '%y-%m-%d') date.strptime('02-29,2024', '%m-%d,%Y') + date.strptime('02-29,2024', '%m-%e,%Y') class SubclassDate(date): sub_var = 1 @@ -3119,19 +3124,24 @@ def test_strptime_single_digit(self): newdate = strptime(string, format) self.assertEqual(newdate, target, msg=reason) - @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. with self.assertRaises(ValueError): # The existing behavior that GH-70647 seeks to change. self.theclass.strptime('02-29', '%m-%d') + with self.assertRaises(ValueError): + self.theclass.strptime('03-14.159265', '%m-%d.%f') + # %e without a year is deprecated, scheduled for removal in 3.17. + _strptime._regex_cache.clear() with self.assertWarnsRegex(DeprecationWarning, r'.*day of month without a year.*'): - self.theclass.strptime('03-14.159265', '%m-%d.%f') + self.theclass.strptime('03-14.159265', '%m-%e.%f') with self._assertNotWarns(DeprecationWarning): self.theclass.strptime('20-03-14.159265', '%y-%m-%d.%f') with self._assertNotWarns(DeprecationWarning): self.theclass.strptime('02-29,2024', '%m-%d,%Y') + with self._assertNotWarns(DeprecationWarning): + self.theclass.strptime('02-29,2024', '%m-%e,%Y') def test_strptime_z_empty(self): for directive in ('z', ':z'): diff --git a/Lib/test/support/strace_helper.py b/Lib/test/support/strace_helper.py index cf95f7bdc7d..bf15283d302 100644 --- a/Lib/test/support/strace_helper.py +++ b/Lib/test/support/strace_helper.py @@ -74,7 +74,7 @@ def sections(self): def _filter_memory_call(call): # mmap can operate on a fd or "MAP_ANONYMOUS" which gives a block of memory. # Ignore "MAP_ANONYMOUS + the "MAP_ANON" alias. - if call.syscall == "mmap" and "MAP_ANON" in call.args[3]: + if call.syscall in ("mmap", "mmap2") and "MAP_ANON" in call.args[3]: return True if call.syscall in ("munmap", "mprotect"): diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py index 67e0595943d..48fa52bfd56 100644 --- a/Lib/test/test__colorize.py +++ b/Lib/test/test__colorize.py @@ -5,6 +5,7 @@ import unittest import unittest.mock import _colorize +from test.support import cpython_only, import_helper from test.support.os_helper import EnvironmentVarGuard @@ -22,6 +23,15 @@ def supports_virtual_terminal(): return contextlib.nullcontext() +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "_colorize", {"copy", "re", "inspect"} + ) + + class TestTheme(unittest.TestCase): def test_attributes(self): diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index 50cf8fcb6b4..77f2a77882f 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -1961,6 +1961,15 @@ def test_forward_repr(self): "typing.List[ForwardRef('int', owner='class')]", ) + def test_forward_repr_extra_names(self): + def f(a: undefined | str): ... + + annos = get_annotations(f, format=Format.FORWARDREF) + + self.assertRegex( + repr(annos['a']), r"ForwardRef\('undefined \| str'.*\)" + ) + def test_forward_recursion_actually(self): def namespace1(): a = ForwardRef("A") @@ -2037,6 +2046,17 @@ def test_evaluate_string_format(self): fr = ForwardRef("set[Any]") self.assertEqual(fr.evaluate(format=Format.STRING), "set[Any]") + def test_evaluate_string_format_extra_names(self): + # Test that internal extra_names are replaced when evaluating as strings + def f(a: unknown | str | int | list[str] | tuple[int, ...]): ... + + fr = get_annotations(f, format=Format.FORWARDREF)['a'] + # Test the cache is not populated before access + self.assertIsNone(fr.__resolved_str_cache__) + + self.assertEqual(fr.evaluate(format=Format.STRING), "unknown | str | int | list[str] | tuple[int, ...]") + self.assertEqual(fr.__resolved_str_cache__, "unknown | str | int | list[str] | tuple[int, ...]") + def test_evaluate_forwardref_format(self): fr = ForwardRef("undef") evaluated = fr.evaluate(format=Format.FORWARDREF) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index f29f98beb2d..75d553e6f77 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -1705,6 +1705,16 @@ def check_text(code, empty, full, **kwargs): full="Module(body=[Import(names=[alias(name='_ast', asname='ast')], is_lazy=0), ImportFrom(module='module', names=[alias(name='sub')], level=0, is_lazy=0)], type_ignores=[])", ) + def test_dump_with_color(self): + node = ast.parse("x = 1") + self.assertNotIn("\x1b[", ast.dump(node)) + self.assertNotIn("\x1b[", ast.dump(node, color=False)) + self.assertIn("\x1b[", ast.dump(node, color=True)) + + node = ast.Constant(value="\x1b[31m") + self.assertEqual(ast.dump(node), "Constant(value='\\x1b[31m')") + self.assertIn("'\\x1b[31m'", ast.dump(node, color=True)) + def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Constant(2), src.body.right) @@ -3415,6 +3425,7 @@ def test_subinterpreter(self): self.assertEqual(res, 0) +@support.force_not_colorized_test_class class CommandLineTests(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index df4ec794897..f32dcd589e2 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -427,6 +427,27 @@ def test_recvfrom_into(self): self.loop.run_until_complete( self._basetest_datagram_recvfrom_into(server_address)) + async def _basetest_datagram_recvfrom_into_wrong_size(self, server_address): + # Call sock_sendto() with a size larger than the buffer + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: + sock.setblocking(False) + + buf = bytearray(5000) + data = b'\x01' * 4096 + wrong_size = len(buf) + 1 + await self.loop.sock_sendto(sock, data, server_address) + with self.assertRaises(ValueError): + await self.loop.sock_recvfrom_into( + sock, buf, wrong_size) + + size, addr = await self.loop.sock_recvfrom_into(sock, buf) + self.assertEqual(buf[:size], data) + + def test_recvfrom_into_wrong_size(self): + with test_utils.run_udp_echo_server() as server_address: + self.loop.run_until_complete( + self._basetest_datagram_recvfrom_into_wrong_size(server_address)) + async def _basetest_datagram_sendto_blocking(self, server_address): # Sad path, sock.sendto() raises BlockingIOError # This involves patching sock.sendto() to raise BlockingIOError but diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py index 91f6b03b459..8925884b9dc 100644 --- a/Lib/test/test_asyncio/test_taskgroups.py +++ b/Lib/test/test_asyncio/test_taskgroups.py @@ -1102,6 +1102,131 @@ async def throw_error(): # cancellation happens here and error is more understandable await asyncio.sleep(0) + async def test_taskgroup_cancel_children(self): + # (asserting that TimeoutError is not raised) + async with asyncio.timeout(1): + async with asyncio.TaskGroup() as tg: + tg.create_task(asyncio.sleep(10)) + tg.create_task(asyncio.sleep(10)) + await asyncio.sleep(0) + tg.cancel() + + async def test_taskgroup_cancel_body(self): + count = 0 + async with asyncio.TaskGroup() as tg: + tg.cancel() + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_idempotent(self): + count = 0 + async with asyncio.TaskGroup() as tg: + tg.cancel() + tg.cancel() + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_after_exit(self): + async with asyncio.TaskGroup() as tg: + await asyncio.sleep(0) + # (asserting that exception is not raised) + tg.cancel() + + async def test_taskgroup_cancel_before_enter(self): + tg = asyncio.TaskGroup() + tg.cancel() + count = 0 + async with tg: + count += 1 + await asyncio.sleep(0) + count += 1 + self.assertEqual(count, 1) + + async def test_taskgroup_cancel_before_create_task(self): + async with asyncio.TaskGroup() as tg: + tg.cancel() + # TODO: This behavior is not ideal. We'd rather have no exception + # raised, and the child task run until the first await. + with self.assertRaises(RuntimeError): + tg.create_task(asyncio.sleep(1)) + + async def test_taskgroup_cancel_before_exception(self): + async def raise_exc(parent_tg: asyncio.TaskGroup): + parent_tg.cancel() + raise RuntimeError + + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.create_task(raise_exc(tg)) + await asyncio.sleep(1) + + async def test_taskgroup_cancel_after_exception(self): + async def raise_exc(parent_tg: asyncio.TaskGroup): + try: + raise RuntimeError + finally: + parent_tg.cancel() + + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.create_task(raise_exc(tg)) + await asyncio.sleep(1) + + async def test_taskgroup_body_cancel_before_exception(self): + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + tg.cancel() + raise RuntimeError + + async def test_taskgroup_body_cancel_after_exception(self): + with self.assertRaises(ExceptionGroup): + async with asyncio.TaskGroup() as tg: + try: + raise RuntimeError + finally: + tg.cancel() + + async def test_taskgroup_cancel_one_winner(self): + async def race(*fns): + outcome = None + async def run(fn): + nonlocal outcome + outcome = await fn() + tg.cancel() + + async with asyncio.TaskGroup() as tg: + for fn in fns: + tg.create_task(run(fn)) + return outcome + + event = asyncio.Event() + record = [] + async def fn_1(): + record.append("1 started") + await event.wait() + record.append("1 finished") + return 1 + + async def fn_2(): + record.append("2 started") + await event.wait() + record.append("2 finished") + return 2 + + async def fn_3(): + record.append("3 started") + event.set() + await asyncio.sleep(10) + record.append("3 finished") + return 3 + + self.assertEqual(await race(fn_1, fn_2, fn_3), 1) + self.assertListEqual(record, ["1 started", "2 started", "3 started", "1 finished"]) + class TestTaskGroup(BaseTestTaskGroup, unittest.IsolatedAsyncioTestCase): loop_factory = asyncio.EventLoop diff --git a/Lib/test/test_asyncio/test_tools.py b/Lib/test/test_asyncio/test_tools.py index 1ab51a6ca3e..df934164eb9 100644 --- a/Lib/test/test_asyncio/test_tools.py +++ b/Lib/test/test_asyncio/test_tools.py @@ -2,13 +2,27 @@ from asyncio import tools -from collections import namedtuple +import _remote_debugging -LocationInfo = namedtuple('LocationInfo', ['lineno', 'end_lineno', 'col_offset', 'end_col_offset'], defaults=[None]*4) -FrameInfo = namedtuple('FrameInfo', ['funcname', 'filename', 'location']) -CoroInfo = namedtuple('CoroInfo', ['call_stack', 'task_name']) -TaskInfo = namedtuple('TaskInfo', ['task_id', 'task_name', 'coroutine_stack', 'awaited_by']) -AwaitedInfo = namedtuple('AwaitedInfo', ['thread_id', 'awaited_by']) + +def LocationInfo(lineno, end_lineno=None, col_offset=None, end_col_offset=None): + return _remote_debugging.LocationInfo((lineno, end_lineno, col_offset, end_col_offset)) + + +def FrameInfo(funcname, filename, location, opcode=None): + return _remote_debugging.FrameInfo((filename, location, funcname, opcode)) + + +def CoroInfo(call_stack, task_name): + return _remote_debugging.CoroInfo((call_stack, task_name)) + + +def TaskInfo(task_id, task_name, coroutine_stack, awaited_by): + return _remote_debugging.TaskInfo((task_id, task_name, coroutine_stack, awaited_by)) + + +def AwaitedInfo(thread_id, awaited_by): + return _remote_debugging.AwaitedInfo((thread_id, awaited_by)) # mock output of get_all_awaited_by function. diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 81cdacb9624..6991e2ef681 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -383,6 +383,49 @@ def assertInvalidLength(data, strict_mode=True): assertInvalidLength(b'A\tB\nC ??DE', # only 5 valid characters strict_mode=False) + def test_base64_canonical(self): + # https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + # Decoders MAY reject encoded data if the pad bits are not zero. + + # Without canonical=True, non-zero padding bits are accepted + self.assertEqual(binascii.a2b_base64(self.type2test(b'AB==')), b'\x00') + self.assertEqual(binascii.a2b_base64(self.type2test(b'AB=='), + strict_mode=True), b'\x00') + + # 2 data chars + "==": last char has 4 padding bits + # 'A' = 0, 'B' = 1 -> leftover 0001 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AB=='), canonical=True) + # 'A' = 0, 'P' = 15 -> leftover 1111 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AP=='), canonical=True) + + # 3 data chars + "=": last char has 2 padding bits + # 'A' = 0, 'A' = 0, 'B' = 1 -> leftover 01 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AAB='), canonical=True) + # 'A' = 0, 'A' = 0, 'D' = 3 -> leftover 11 (non-zero) + with self.assertRaises(binascii.Error): + binascii.a2b_base64(self.type2test(b'AAD='), canonical=True) + + # Verify that zero padding bits are accepted + binascii.a2b_base64(self.type2test(b'AA=='), canonical=True) + binascii.a2b_base64(self.type2test(b'AAA='), canonical=True) + + # Full quads with no padding have no leftover bits -- always valid + binascii.a2b_base64(self.type2test(b'AAAA'), canonical=True) + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base64_canonical_roundtrip(self, payload): + # The encoder must always produce canonical output. + encoded = binascii.b2a_base64(payload, newline=False) + decoded = binascii.a2b_base64(encoded, canonical=True) + self.assertEqual(decoded, payload) + def test_base64_alphabet(self): alphabet = (b'!"#$%&\'()*+,-012345689@' b'ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr') @@ -443,20 +486,22 @@ def test_ascii85_valid(self): res += b self.assertEqual(res, rawdata) - # Test decoding inputs with length 1 mod 5 - params = [ - (b"a", False, False, b"", b""), - (b"xbw", False, False, b"wx", b""), - (b"<~c~>", False, True, b"", b""), - (b"{d ~>", False, True, b" {", b""), - (b"ye", True, False, b"", b" "), - (b"z\x01y\x00f", True, False, b"\x00\x01", b"\x00\x00\x00\x00 "), - (b"<~FCfN8yg~>", True, True, b"", b"test "), - (b"FE;\x03#8zFCf\x02N8yh~>", True, True, b"\x02\x03", b"tset\x00\x00\x00\x00test "), + # Inputs with length 1 mod 5 end with a 1-char group, which is + # an encoding violation per the PLRM spec. + error_params = [ + (b"a", False, False, b""), + (b"xbw", False, False, b"wx"), + (b"<~c~>", False, True, b""), + (b"{d ~>", False, True, b" {"), + (b"ye", True, False, b""), + (b"z\x01y\x00f", True, False, b"\x00\x01"), + (b"<~FCfN8yg~>", True, True, b""), + (b"FE;\x03#8zFCf\x02N8yh~>", True, True, b"\x02\x03"), ] - for a, foldspaces, adobe, ignorechars, b in params: + for a, foldspaces, adobe, ignorechars in error_params: kwargs = {"foldspaces": foldspaces, "adobe": adobe, "ignorechars": ignorechars} - self.assertEqual(binascii.a2b_ascii85(self.type2test(a), **kwargs), b) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(self.type2test(a), **kwargs) def test_ascii85_invalid(self): # Test Ascii85 with invalid characters interleaved @@ -670,16 +715,18 @@ def test_base85_valid(self): self.assertEqual(res, self.rawdata) # Test decoding inputs with different length - self.assertEqual(binascii.a2b_base85(self.type2test(b'a')), b'') - self.assertEqual(binascii.a2b_base85(self.type2test(b'a')), b'') + # 1-char groups are rejected (encoding violation) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(self.type2test(b'a')) self.assertEqual(binascii.a2b_base85(self.type2test(b'ab')), b'q') self.assertEqual(binascii.a2b_base85(self.type2test(b'abc')), b'qa') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcd')), b'qa\x9e') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcde')), b'qa\x9e\xb6') - self.assertEqual(binascii.a2b_base85(self.type2test(b'abcdef')), - b'qa\x9e\xb6') + # 6-char input = full 5-char group + trailing 1-char group (rejected) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(self.type2test(b'abcdef')) self.assertEqual(binascii.a2b_base85(self.type2test(b'abcdefg')), b'qa\x9e\xb6\x81') @@ -767,6 +814,169 @@ def test_base85_alphabet(self): with self.assertRaises(TypeError): binascii.a2b_base64(data, alphabet=bytearray(alphabet)) + def test_base85_canonical(self): + # Non-canonical encodings are accepted without canonical=True + self.assertEqual(binascii.a2b_base85(b'VF'), b'a') + + # 1-char partial groups are always rejected (encoding violation: + # no conforming encoder produces them) + with self.assertRaises(binascii.Error): + binascii.a2b_base85(b'V') + with self.assertRaises(binascii.Error): + binascii.a2b_base85(b'0') + + # Verify round-trip: encode then decode with canonical=True works + for data in [b'a', b'ab', b'abc', b'abcd', b'abcde', + b'\x00', b'\xff', b'\x00\x00', b'\xff\xff\xff']: + encoded = binascii.b2a_base85(data) + decoded = binascii.a2b_base85(encoded, canonical=True) + self.assertEqual(decoded, data) + + # Test non-canonical rejection for each partial group size + # (2-char/1-byte, 3-char/2-byte, 4-char/3-byte). + # Incrementing the last digit by 1 produces a non-canonical + # encoding. For 4-char groups (n_pad=1) a +1 can change the + # output byte, so we use b'ab\x00' whose canonical form allows + # a +1 that still decodes to the same 3 bytes. + for data in [b'a', b'ab', b'ab\x00']: + canonical_enc = binascii.b2a_base85(data) + non_canonical = (canonical_enc[:-1] + + bytes([canonical_enc[-1] + 1])) + # Same decoded output without canonical check + self.assertEqual(binascii.a2b_base85(non_canonical), data) + # Rejected with canonical=True + with self.assertRaises(binascii.Error): + binascii.a2b_base85(non_canonical, canonical=True) + + # Boundary bytes: \x00 and \xff for each partial group size + for data in [b'\x00', b'\x00\x00', b'\x00\x00\x00', + b'\xff', b'\xff\xff', b'\xff\xff\xff']: + canonical_enc = binascii.b2a_base85(data) + binascii.a2b_base85(canonical_enc, canonical=True) + + # Full 5-char groups are always canonical (no padding bits) + self.assertEqual( + binascii.a2b_base85(b'VPa!s', canonical=True), b'abcd') + + # Empty input is valid + self.assertEqual(binascii.a2b_base85(b'', canonical=True), b'') + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base85_canonical_roundtrip(self, payload): + encoded = binascii.b2a_base85(payload) + decoded = binascii.a2b_base85(encoded, canonical=True) + self.assertEqual(decoded, payload) + + @hypothesis.given(payload=hypothesis.strategies.binary(min_size=1, max_size=3)) + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff') + @hypothesis.example(b'ab\x00') + def test_base85_canonical_unique(self, payload): + # For a partial group, sweeping all 85 last-digit values should + # yield exactly one encoding that both decodes to the original + # payload AND passes canonical=True. + hypothesis.assume(len(payload) % 4 != 0) + canonical_enc = binascii.b2a_base85(payload) + table = binascii.BASE85_ALPHABET + accepted = [] + for digit in table: + candidate = canonical_enc[:-1] + bytes([digit]) + try: + result = binascii.a2b_base85(candidate, canonical=True) + if result == payload: + accepted.append(candidate) + except binascii.Error: + pass + self.assertEqual(accepted, [canonical_enc]) + + def test_ascii85_canonical(self): + # Non-canonical encodings are accepted without canonical=True + self.assertEqual(binascii.a2b_ascii85(b'@0'), b'a') + + # 1-char partial groups are always rejected (PLRM encoding violation) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'@') + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'!') + + # Verify round-trip: encode then decode with canonical=True works + for data in [b'a', b'ab', b'abc', b'abcd', b'abcde', + b'\x00', b'\xff', b'\x00\x00', b'\xff\xff\xff']: + encoded = binascii.b2a_ascii85(data) + decoded = binascii.a2b_ascii85(encoded, canonical=True) + self.assertEqual(decoded, data) + + # Test non-canonical rejection for each partial group size. + # See test_base85_canonical for why b'ab\x00' is used for 3 bytes. + for data in [b'a', b'ab', b'ab\x00']: + canonical_enc = binascii.b2a_ascii85(data) + non_canonical = (canonical_enc[:-1] + + bytes([canonical_enc[-1] + 1])) + self.assertEqual(binascii.a2b_ascii85(non_canonical), data) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(non_canonical, canonical=True) + + # Full 5-char groups are always canonical + self.assertEqual( + binascii.a2b_ascii85(b'@:E_W', canonical=True), b'abcd') + + # 'z' is the canonical form for all-zero groups per the PLRM. + # '!!!!!' decodes identically but is non-canonical. + self.assertEqual(binascii.a2b_ascii85(b'!!!!!'), b'\x00' * 4) + self.assertEqual(binascii.a2b_ascii85(b'z'), b'\x00' * 4) + self.assertEqual( + binascii.a2b_ascii85(b'z', canonical=True), b'\x00' * 4) + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'!!!!!', canonical=True) + # Multiple groups: z + !!!!! should fail + with self.assertRaises(binascii.Error): + binascii.a2b_ascii85(b'z!!!!!', canonical=True) + # Multiple z groups are fine + self.assertEqual( + binascii.a2b_ascii85(b'zz', canonical=True), b'\x00' * 8) + + # Empty input is valid + self.assertEqual(binascii.a2b_ascii85(b'', canonical=True), b'') + + # Adobe-wrapped with canonical + self.assertEqual( + binascii.a2b_ascii85(b'<~@:E_W~>', canonical=True, adobe=True), + b'abcd') + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\x00\x00\x00\x00') # triggers z abbreviation + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_ascii85_canonical_roundtrip(self, payload): + encoded = binascii.b2a_ascii85(payload) + decoded = binascii.a2b_ascii85(encoded, canonical=True) + self.assertEqual(decoded, payload) + + @hypothesis.given(payload=hypothesis.strategies.binary(min_size=1, max_size=3)) + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff') + @hypothesis.example(b'ab\x00') + def test_ascii85_canonical_unique(self, payload): + hypothesis.assume(len(payload) % 4 != 0) + canonical_enc = binascii.b2a_ascii85(payload) + # Ascii85 alphabet: '!' (33) through 'u' (117) + accepted = [] + for digit in range(33, 118): + candidate = canonical_enc[:-1] + bytes([digit]) + try: + result = binascii.a2b_ascii85(candidate, canonical=True) + if result == payload: + accepted.append(candidate) + except binascii.Error: + pass + self.assertEqual(accepted, [canonical_enc]) + def test_base32_valid(self): # Test base32 with valid data lines = [] @@ -935,6 +1145,55 @@ def assertInvalidLength(data, *args, length=None, **kwargs): assertInvalidLength(b" ABC=====", ignorechars=b' ') assertInvalidLength(b" ABCDEF==", ignorechars=b' ') + def test_base32_canonical(self): + # https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + # Decoders MAY reject encoded data if the pad bits are not zero. + + # Without canonical=True, non-zero padding bits are accepted + self.assertEqual(binascii.a2b_base32(self.type2test(b'AB======')), + b'\x00') + + # 2 data chars + "======": last char has 2 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AB======'), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AD======'), canonical=True) + + # 4 data chars + "====": last char has 4 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAB===='), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAP===='), canonical=True) + + # 5 data chars + "===": last char has 1 padding bit + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAB==='), canonical=True) + + # 7 data chars + "=": last char has 3 padding bits + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAAAB='), canonical=True) + with self.assertRaises(binascii.Error): + binascii.a2b_base32(self.type2test(b'AAAAAAH='), canonical=True) + + # Verify that zero padding bits are accepted + binascii.a2b_base32(self.type2test(b'AA======'), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAA===='), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAAA==='), canonical=True) + binascii.a2b_base32(self.type2test(b'AAAAAAA='), canonical=True) + + # Full octet with no padding -- always valid + binascii.a2b_base32(self.type2test(b'AAAAAAAA'), canonical=True) + + @hypothesis.given(payload=hypothesis.strategies.binary()) + @hypothesis.example(b'') + @hypothesis.example(b'\x00') + @hypothesis.example(b'\xff\xff') + @hypothesis.example(b'abc') + def test_base32_canonical_roundtrip(self, payload): + encoded = binascii.b2a_base32(payload) + decoded = binascii.a2b_base32(encoded, canonical=True) + self.assertEqual(decoded, payload) + def test_a2b_base32_padded(self): a2b_base32 = binascii.a2b_base32 t = self.type2test diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index 57c1a787d82..1aabde6811a 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -495,12 +495,17 @@ def test_formatmonth(self): calendar.TextCalendar().formatmonth(0, 2), result_0_02_text ) + def test_formatmonth_with_invalid_month(self): with self.assertRaises(calendar.IllegalMonthError): calendar.TextCalendar().formatmonth(2017, 13) with self.assertRaises(calendar.IllegalMonthError): calendar.TextCalendar().formatmonth(2017, -1) + def test_illegal_month_error_bases(self): + self.assertIsSubclass(calendar.IllegalMonthError, ValueError) + self.assertIsSubclass(calendar.IllegalMonthError, IndexError) + def test_formatmonthname_with_year(self): self.assertEqual( calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=True), diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index db067199195..4c16bbd4cb0 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2870,6 +2870,88 @@ def func(): self.do_test(func, names) +class Test_Pep523AllowSpecialization(unittest.TestCase): + """Tests for _PyInterpreterState_SetEvalFrameFunc with + allow_specialization=1.""" + + def test_is_specialization_enabled_default(self): + # With no custom eval frame, specialization should be enabled + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + + def test_is_specialization_enabled_with_eval_frame(self): + # Setting eval frame with allow_specialization=0 disables specialization + try: + _testinternalcapi.set_eval_frame_record([]) + self.assertFalse(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + + def test_is_specialization_enabled_after_restore(self): + # Restoring the default eval frame re-enables specialization + try: + _testinternalcapi.set_eval_frame_record([]) + self.assertFalse(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + + def test_is_specialization_enabled_with_allow(self): + # Setting eval frame with allow_specialization=1 keeps it enabled + try: + _testinternalcapi.set_eval_frame_interp([]) + self.assertTrue(_testinternalcapi.is_specialization_enabled()) + finally: + _testinternalcapi.set_eval_frame_default() + + def test_allow_specialization_call(self): + def func(): + pass + + def func_outer(): + func() + + actual_calls = [] + try: + _testinternalcapi.set_eval_frame_interp( + actual_calls) + for i in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE * 2): + func_outer() + finally: + _testinternalcapi.set_eval_frame_default() + + # With specialization enabled, calls to inner() will dispatch + # through the installed frame evaluator + self.assertEqual(actual_calls.count("func"), 0) + + # But the normal interpreter loop still shouldn't be inlining things + self.assertNotEqual(actual_calls.count("func_outer"), 0) + + def test_no_specialization_call(self): + # Without allow_specialization, ALL calls go through the eval frame. + # This is the existing PEP 523 behavior. + def inner(x=42): + pass + def func(): + inner() + + # Pre-specialize + for _ in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE): + func() + + actual_calls = [] + try: + _testinternalcapi.set_eval_frame_record(actual_calls) + for _ in range(SUFFICIENT_TO_DEOPT_AND_SPECIALIZE): + func() + finally: + _testinternalcapi.set_eval_frame_default() + + # Without allow_specialization, every call including inner() goes + # through the eval frame + expected = ["func", "inner"] * SUFFICIENT_TO_DEOPT_AND_SPECIALIZE + self.assertEqual(actual_calls, expected) + + @unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED') class TestPyThreadId(unittest.TestCase): def test_py_thread_id(self): diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 097a3ac4baf..39075fc64cf 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -371,6 +371,75 @@ def testfunc(n): # look for indirect evidence: the += operator self.assertIn("_BINARY_OP_ADD_INT", uops) + def test_get_iter_list(self): + l = list(range(10)) + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in l: + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_TAGGED_ZERO", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_get_iter_gen(self): + def gen(): + while True: + yield 1 + + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in gen(): + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_NULL", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_get_iter_trad(self): + d = {v:v for v in range(10)} + def testfunc(n): + total = 0 + while n: + n -= 1 + total += n + for i in d: + break + return total + + total = testfunc(TIER2_THRESHOLD) + self.assertEqual(total, sum(range(TIER2_THRESHOLD))) + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GET_ITER_TRAD", uops) + self.assertNotIn("_GET_ITER", uops) + self.assertNotIn("_GET_ITER_VIRTUAL", uops) + self.assertNotIn("_GET_ITER_SELF", uops) + + def test_for_iter_range(self): def testfunc(n): total = 0 @@ -1358,9 +1427,13 @@ def testfunc(n): for _ in gen(n): pass testfunc(TIER2_THRESHOLD * 2) + # The generator may be inlined into testfunc's trace, + # so check whichever executor contains _YIELD_VALUE. gen_ex = get_first_executor(gen) - self.assertIsNotNone(gen_ex) - uops = get_opnames(gen_ex) + testfunc_ex = get_first_executor(testfunc) + ex = gen_ex or testfunc_ex + self.assertIsNotNone(ex) + uops = get_opnames(ex) self.assertNotIn("_MAKE_HEAP_SAFE", uops) self.assertIn("_YIELD_VALUE", uops) @@ -1521,6 +1594,29 @@ class Foo: Foo.attr = 0 self.assertFalse(ex.is_valid()) + def test_guard_type_version_locked_removed(self): + """ + Verify that redundant _GUARD_TYPE_VERSION_LOCKED guards are + eliminated for sequential STORE_ATTR_INSTANCE_VALUE in __init__. + """ + + class Foo: + def __init__(self): + self.a = 1 + self.b = 2 + self.c = 3 + + def thing(n): + for _ in range(n): + Foo() + + res, ex = self._run_with_optimizer(thing, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + opnames = list(iter_opnames(ex)) + guard_locked_count = opnames.count("_GUARD_TYPE_VERSION_LOCKED") + # Only the first store needs the guard; the rest should be NOPed. + self.assertEqual(guard_locked_count, 1) + def test_type_version_doesnt_segfault(self): """ Tests that setting a type version doesn't cause a segfault when later looking at the stack. @@ -1542,6 +1638,133 @@ def fn(a): fn(A()) + def test_init_resolves_callable(self): + """ + _CHECK_AND_ALLOCATE_OBJECT should resolve __init__ to a constant, + enabling the optimizer to propagate type information through the frame + and eliminate redundant function version and arg count checks. + """ + class MyPoint: + def __init__(self, x, y): + # If __init__ callable is propagated through, then + # These will get promoted from globals to constants. + self.x = range(1) + self.y = range(1) + + def testfunc(n): + for _ in range(n): + p = MyPoint(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # The __init__ call should be traced through via _PUSH_FRAME + self.assertIn("_PUSH_FRAME", uops) + # __init__ resolution allows promotion of range to constant + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + + def test_init_guards_removed(self): + class MyPoint: + def __init__(self, x, y): + return None + + def testfunc(n): + point_local = MyPoint + for _ in range(n): + p = point_local(1.0, 2.0) + p = point_local(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + # The __init__ call should be traced through via _PUSH_FRAME + count = count_ops(ex, "_CREATE_INIT_FRAME") + self.assertEqual(count, 2) + # __init__ resolution allows promotion of range to constant + count = count_ops(ex, "_CHECK_OBJECT") + self.assertEqual(count, 1) + + def test_init_guards_removed_global(self): + + def testfunc(n): + for _ in range(n): + p = MyGlobalPoint(1.0, 2.0) + p = MyGlobalPoint(1.0, 2.0) + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + # The __init__ call should be traced through via _PUSH_FRAME + count = count_ops(ex, "_CREATE_INIT_FRAME") + self.assertEqual(count, 2) + # __init__ resolution allows promotion of range to constant + count = count_ops(ex, "_CHECK_OBJECT") + self.assertEqual(count, 0) + + def test_guard_type_version_locked_propagates(self): + """ + _GUARD_TYPE_VERSION_LOCKED should set the type version on the + symbol so repeated accesses to the same type can benefit. + """ + class Item: + def __init__(self, val): + self.val = val + + def get(self): + return self.val + + def get2(self): + return self.val + 1 + + def testfunc(n): + item = Item(42) + total = 0 + for _ in range(n): + # Two method calls on the same object — the second + # should benefit from type info set by the first. + total += item.get() + item.get2() + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * (42 + 43)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both methods should be traced through + self.assertEqual(uops.count("_PUSH_FRAME"), 2) + # Type version propagation: one guard covers both method lookups + self.assertEqual(uops.count("_GUARD_TYPE_VERSION"), 1) + # Function checks cannot be eliminated for safety reasons. + self.assertIn("_CHECK_FUNCTION_VERSION", uops) + + def test_method_chain_guard_elimination(self): + """ + Calling two methods on the same object should share the outer + type guard — only one _GUARD_TYPE_VERSION for the two lookups. + """ + class Calc: + def __init__(self, val): + self.val = val + + def add(self, x): + self.val += x + return self + + def testfunc(n): + c = Calc(0) + for _ in range(n): + c.add(1).add(2) + return c.val + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 3) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both add() calls should be inlined + push_count = uops.count("_PUSH_FRAME") + self.assertEqual(push_count, 2) + # Only one outer type version guard for the two method lookups + # on the same object c (the second lookup reuses type info) + guard_version_count = uops.count("_GUARD_TYPE_VERSION") + self.assertEqual(guard_version_count, 1) + def test_func_guards_removed_or_reduced(self): def testfunc(n): for i in range(n): @@ -1554,10 +1777,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertIn("_PUSH_FRAME", uops) - # Both should be not present, as this is a call - # to a simple function with a known function version. - self.assertNotIn("_CHECK_FUNCTION_VERSION_INLINE", uops) - self.assertNotIn("_CHECK_FUNCTION_VERSION", uops) + self.assertIn("_CHECK_FUNCTION_VERSION", uops) # Removed guard self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops) @@ -1576,6 +1796,49 @@ def testfunc(n): self.assertIn("_CHECK_FUNCTION_VERSION_INLINE", uops) self.assertNotIn("_CHECK_METHOD_VERSION", uops) + def test_record_bound_method_general(self): + class MyClass: + def method(self, *args): + return args[0] + 1 + + def testfunc(n): + obj = MyClass() + bound = obj.method + result = 0 + for i in range(n): + result += bound(i) + return result + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual( + res, sum(i + 1 for i in range(TIER2_THRESHOLD)) + ) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + + def test_record_bound_method_exact_args(self): + class MyClass: + def method(self, x): + return x + 1 + + def testfunc(n): + obj = MyClass() + bound = obj.method + result = 0 + for i in range(n): + result += bound(i) + return result + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual( + res, sum(i + 1 for i in range(TIER2_THRESHOLD)) + ) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops) + def test_jit_error_pops(self): """ Tests that the correct number of pops are inserted into the @@ -1643,7 +1906,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_BINARY_OP_ADD_INT", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_GUARD_NOS_INT", uops) self.assertNotIn("_GUARD_TOS_INT", uops) @@ -1808,7 +2070,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_UNARY_NEGATIVE", uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_unary_not_pop_top_load_const_inline_borrow(self): def testfunc(n): @@ -1827,9 +2088,9 @@ def testfunc(n): self.assertNotIn("_UNARY_NOT", uops) # TODO (gh-143723): After refactoring TO_BOOL_INT to eliminate redundant # refcounts, 'not a' is now constant-folded and currently lowered to - # _POP_TOP_LOAD_CONST_INLINE_BORROW. Re-enable once constant folding - # avoids this fused pop+const uop. - # self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) + # _POP_TOP + _LOAD_CONST_INLINE_BORROW. Re-enable once constant folding + # avoids emitting these. + # self.assertNotIn("_LOAD_CONST_INLINE_BORROW", uops) def test_unary_invert_insert_1_load_const_inline_borrow(self): def testfunc(n): @@ -1863,7 +2124,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_int_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1880,7 +2140,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_INT", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_str_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1897,7 +2157,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_STR", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_compare_op_float_insert_two_load_const_inline_borrow(self): def testfunc(n): @@ -1914,7 +2174,7 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_COMPARE_OP_FLOAT", uops) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_contains_op_pop_two_load_const_inline_borrow(self): def testfunc(n): @@ -1931,7 +2191,6 @@ def testfunc(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_CONTAINS_OP", uops) - self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops) def test_to_bool_bool_contains_op_set(self): """ @@ -2173,7 +2432,7 @@ def f(n): uops = get_opnames(ex) self.assertNotIn("_GUARD_TOS_ANY_SET", uops) # _CONTAINS_OP_SET is constant-folded away for frozenset literals - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) def test_remove_guard_for_known_type_tuple(self): def f(n): @@ -2456,6 +2715,9 @@ def testfunc(n): uops = get_opnames(ex) # When the result of type(...) is known, _CALL_TYPE_1 is decomposed. self.assertNotIn("_CALL_TYPE_1", uops) + # _CALL_TYPE_1 produces 2 _POP_TOP_NOP (callable and null) + # type(42) is int produces 4 _POP_TOP_NOP + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 6) def test_call_type_1_result_is_const(self): def testfunc(n): @@ -2644,6 +2906,50 @@ def testfunc(n): self.assertNotIn("_GUARD_TOS_INT", uops) self.assertIn("_POP_TOP_NOP", uops) + def test_check_is_not_py_callable(self): + def testfunc(n): + total = 0 + f = len + xs = (1, 2, 3) + for _ in range(n): + total += f(xs) + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE", uops) + + def test_check_is_not_py_callable_ex(self): + def testfunc(n): + total = 0 + xs = (1, 2, 3) + args = (xs,) + for _ in range(n): + total += len(*args) + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_EX", uops) + + def test_check_is_not_py_callable_kw(self): + def testfunc(n): + total = 0 + xs = (3, 1, 2) + for _ in range(n): + total += sorted(xs, reverse=False)[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_KW", uops) + def test_call_len_string(self): def testfunc(n): for _ in range(n): @@ -2707,6 +3013,21 @@ class C: self.assertNotIn("_COMPARE_OP_INT", uops) self.assertNotIn(self.guard_is_true, uops) + def test_call_builtin_class(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = int("42") + x += y + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 42) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + self.assertNotIn("_GUARD_CALLABLE_BUILTIN_CLASS", uops) + def test_call_builtin_o(self): def testfunc(n): x = 0 @@ -2995,7 +3316,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_true, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_is_false(self): def testfunc(n): @@ -3013,7 +3333,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_false, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_subclass(self): def testfunc(n): @@ -3031,7 +3350,6 @@ def testfunc(n): self.assertNotIn("_CALL_ISINSTANCE", uops) self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertNotIn(self.guard_is_true, uops) - self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) def test_call_isinstance_unknown_object(self): def testfunc(n): @@ -3193,6 +3511,29 @@ def f(n): self.assertNotIn("_LOAD_ATTR_METHOD_NO_DICT", uops) self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) + def test_cached_load_special(self): + class CM: + def __enter__(self): + return self + def __exit__(self, *args): + pass + def f(n): + cm = CM() + x = 0 + for _ in range(n): + with cm: + x += 1 + return x + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_SPECIAL", uops) + # __enter__/__exit__ produce 2 _POP_TOP_NOP + # x += 1 produces 2 _POP_TOP_NOP + # __exit__()'s None return produces 1 _POP_TOP_NOP + self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 5) + def test_store_fast_refcount_elimination(self): def foo(x): # Since x is known to be @@ -3413,6 +3754,171 @@ def testfunc(args): uops = get_opnames(ex) self.assertNotIn("_UNARY_NEGATIVE_FLOAT_INPLACE", uops) + def test_float_truediv_inplace_unique_lhs(self): + # (a + b) / (c + d): LHS is unique float from add, RHS is unique + # float from add. The division reuses the LHS in place. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / (c + d) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 1.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 1.25) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE", uops) + + def test_float_truediv_inplace_unique_rhs(self): + # x = c + d stores to a local (not unique when reloaded). + # (a + b) is unique. The division should use inplace on the RHS. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + x = c + d + total += x / (a + b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, 4.0, 5.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (9.0 / 5.0)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT", uops) + + def test_float_truediv_speculative_guards_from_tracing(self): + # a, b are locals with no statically known type. _RECORD_TOS_TYPE / + # _RECORD_NOS_TYPE (added to the BINARY_OP macro) capture the observed + # operand types during tracing, and the optimizer then speculatively + # emits _GUARD_{TOS,NOS}_FLOAT and specializes the division. + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += a / b + return total + + res, ex = self._run_with_optimizer(testfunc, (10.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (10.0 / 3.0)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GUARD_TOS_FLOAT", uops) + self.assertIn("_GUARD_NOS_FLOAT", uops) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT", uops) + + def test_float_remainder_speculative_guards_from_tracing(self): + # a, b are locals with no statically known type. Tracing records + # them as floats; the optimizer then speculatively emits + # _GUARD_{TOS,NOS}_FLOAT for NB_REMAINDER. That narrows both + # operands to float, and the _BINARY_OP handler marks the result + # as a unique float. Downstream, `* 2.0` therefore specializes + # to _BINARY_OP_MULTIPLY_FLOAT_INPLACE. + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + total += (a % b) * 2.0 + return total + + res, ex = self._run_with_optimizer(testfunc, (10.0, 3.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * (10.0 % 3.0) * 2.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_GUARD_TOS_FLOAT", uops) + self.assertIn("_GUARD_NOS_FLOAT", uops) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE", uops) + + def test_float_truediv_type_propagation(self): + # Test the _BINARY_OP_TRUEDIV_FLOAT propagates type information + def testfunc(args): + a, b, n = args + total = 0.0 + for _ in range(n): + x = (a + b) # type of x will specialize to float + total += x / x - x / x + return total + + res, ex = self._run_with_optimizer(testfunc, + (2.0, 3.0, TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * ((2.0 + 3.0) / (2.0 + 3.0) - (2.0 + 3.0) / (2.0 + 3.0)) + self.assertAlmostEqual(res, expected) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT", uops) + self.assertIn("_BINARY_OP_SUBTRACT_FLOAT_INPLACE", uops) + + def test_float_truediv_unique_result_enables_inplace(self): + # (a+b) / (c+d) / (e+f): chained divisions where each result + # is unique, enabling inplace for subsequent divisions. + def testfunc(args): + a, b, c, d, e, f, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / (c + d) / (e + f) + return total + + res, ex = self._run_with_optimizer(testfunc, + (2.0, 3.0, 1.0, 1.0, 1.0, 1.0, TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * ((2.0 + 3.0) / (1.0 + 1.0) / (1.0 + 1.0)) + self.assertAlmostEqual(res, expected) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE", uops) + + def test_float_add_chain_both_unique(self): + # (a+b) + (c+d): both sub-additions produce unique floats. + # The outer + should use inplace on one of them. + def testfunc(args): + a, b, c, d, n = args + total = 0.0 + for _ in range(n): + total += (a + b) + (c + d) + return total + + res, ex = self._run_with_optimizer(testfunc, (1.0, 2.0, 3.0, 4.0, TIER2_THRESHOLD)) + self.assertAlmostEqual(res, TIER2_THRESHOLD * 10.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # The outer + should use inplace (at least one operand is unique) + inplace = ( + "_BINARY_OP_ADD_FLOAT_INPLACE" in uops + or "_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT" in uops + ) + self.assertTrue(inplace, "Expected inplace add for unique sub-results") + + def test_float_truediv_non_float_type_no_crash(self): + # Fraction / Fraction goes through _BINARY_OP with NB_TRUE_DIVIDE + # but returns Fraction, not float. The optimizer must not assume + # the result is float for non-int/float operands. See gh-146306. + from fractions import Fraction + def testfunc(args): + a, b, n = args + total = Fraction(0) + for _ in range(n): + total += a / b + return float(total) + + res, ex = self._run_with_optimizer(testfunc, (Fraction(10), Fraction(3), TIER2_THRESHOLD)) + expected = float(TIER2_THRESHOLD * Fraction(10, 3)) + self.assertAlmostEqual(res, expected) + + def test_float_truediv_mixed_float_fraction_no_crash(self): + # float / Fraction: lhs is known float from a prior guard, + # but rhs is Fraction. The guard insertion for rhs should + # deopt cleanly at runtime, not crash. + from fractions import Fraction + def testfunc(args): + a, b, c, n = args + total = 0.0 + for _ in range(n): + total += (a + b) / c # (a+b) is float, c is Fraction + return total + + res, ex = self._run_with_optimizer(testfunc, (2.0, 3.0, Fraction(4), TIER2_THRESHOLD)) + expected = TIER2_THRESHOLD * (5.0 / Fraction(4)) + self.assertAlmostEqual(res, float(expected)) + def test_int_add_inplace_unique_lhs(self): # a * b produces a unique compact int; adding c reuses it in place def testfunc(args): @@ -3834,6 +4340,118 @@ def testfunc(n): # propagates PyFloat_Type. self.assertNotIn("_GUARD_NOS_FLOAT", uops) + def test_binary_op_extend_list_concat_type_propagation(self): + # list + list is specialized via BINARY_OP_EXTEND. The tier 2 optimizer + # should learn that the result is a list and eliminate subsequent + # list-type guards. + def testfunc(n): + a = [1, 2] + b = [3, 4] + x = True + for _ in range(n): + c = a + b + if c[0]: + x = False + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, False) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + # The c[0] subscript emits _GUARD_NOS_LIST before _BINARY_OP_SUBSCR_LIST_INT; + # since _BINARY_OP_EXTEND now propagates PyList_Type, that guard is gone. + self.assertIn("_BINARY_OP_SUBSCR_LIST_INT", uops) + self.assertNotIn("_GUARD_NOS_LIST", uops) + + def test_binary_op_extend_tuple_concat_type_propagation(self): + # tuple + tuple is specialized via BINARY_OP_EXTEND. The tier 2 optimizer + # should learn the result is a tuple and eliminate subsequent tuple guards. + def testfunc(n): + t1 = (1, 2) + t2 = (3, 4) + for _ in range(n): + a, b, c, d = t1 + t2 + return a + b + c + d + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 10) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_UNPACK_SEQUENCE_TUPLE", uops) + self.assertNotIn("_GUARD_TOS_TUPLE", uops) + + def test_binary_op_extend_guard_elimination(self): + # When both operands have known types (e.g., from a prior + # _BINARY_OP_EXTEND result), the _GUARD_BINARY_OP_EXTEND + # should be eliminated. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # first: guard stays, result type = list + d = c + c # second: both operands are list -> guard eliminated + total += d[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Both list additions use _BINARY_OP_EXTEND + self.assertEqual(uops.count("_BINARY_OP_EXTEND"), 2) + # But the second guard is eliminated because both operands + # are known to be lists from the first _BINARY_OP_EXTEND. + self.assertEqual(uops.count("_GUARD_BINARY_OP_EXTEND"), 1) + + def test_binary_op_extend_partial_guard_lhs_known(self): + # When the lhs type is already known (from a prior _BINARY_OP_EXTEND + # result) but the rhs type is not, the optimizer should emit + # _GUARD_BINARY_OP_EXTEND_RHS (checking only the rhs) instead of + # the full _GUARD_BINARY_OP_EXTEND. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # result type is list (known) + d = c + b # lhs (c) is known list, rhs (b) is not -> _GUARD_BINARY_OP_EXTEND_RHS + total += d[0] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_GUARD_BINARY_OP_EXTEND_RHS", uops) + self.assertNotIn("_GUARD_BINARY_OP_EXTEND_LHS", uops) + + def test_binary_op_extend_partial_guard_rhs_known(self): + # When the rhs type is already known (from a prior _BINARY_OP_EXTEND + # result) but the lhs type is not, the optimizer should emit + # _GUARD_BINARY_OP_EXTEND_LHS (checking only the lhs) instead of + # the full _GUARD_BINARY_OP_EXTEND. + def testfunc(n): + a = [1, 2] + b = [3, 4] + total = 0 + for _ in range(n): + c = a + b # result type is list (known) + d = b + c # rhs (c) is known list, lhs (b) is not -> _GUARD_BINARY_OP_EXTEND_LHS + total += d[2] + return total + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_GUARD_BINARY_OP_EXTEND_LHS", uops) + self.assertNotIn("_GUARD_BINARY_OP_EXTEND_RHS", uops) + def test_unary_invert_long_type(self): def testfunc(n): for _ in range(n): @@ -4404,7 +5022,7 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 2) self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) def test_binary_subscr_frozendict_const_fold(self): @@ -4419,6 +5037,7 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) # lookup result is folded to constant 1, so comparison is optimized away self.assertNotIn("_COMPARE_OP_INT", uops) @@ -4434,8 +5053,39 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) self.assertNotIn("_CONTAINS_OP_SET", uops) + def test_contains_op_frozendict_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 'x' in FROZEN_DICT_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + self.assertNotIn("_CONTAINS_OP_DICT", uops) + + def test_not_contains_op_frozendict_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 'z' not in FROZEN_DICT_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertGreaterEqual(count_ops(ex, "_LOAD_CONST_INLINE_BORROW"), 3) + self.assertNotIn("_CONTAINS_OP_DICT", uops) + def test_binary_subscr_list_slice(self): def testfunc(n): x = 0 @@ -4539,6 +5189,24 @@ def return_true(): # v + 1 should be constant folded self.assertNotIn("_BINARY_OP", uops) + def test_is_none_narrows_to_constant(self): + def testfunc(n): + value = None + hits = 0 + for _ in range(n): + if value is None: + hits += 1 + return hits + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertNotIn("_IS_NONE", uops) + self.assertIn("_GUARD_IS_NONE_POP", uops) + self.assertIn("_POP_TOP_NOP", uops) + def test_is_false_narrows_to_constant(self): def f(n): def return_false(): @@ -4634,7 +5302,58 @@ def testfunc(*args): self.assertIn("_LOAD_ATTR_PROPERTY_FRAME", uops) # This is a sign the optimizer ran and didn't hit contradiction. - self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) + + def test_load_attr_getattribute_frame(self): + class B: + def __getattribute__(self, name): + return len(name) + + def testfunc(n): + b = B() + y = 0 + for _ in range(n): + y += b.x + b.y + return y + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, 2 * TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertIn("_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME", uops) + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + + def test_load_attr_property_frame_invalidates_on_code_change(self): + class C: + @property + def val(self): + return int(1) + + fget = C.val.fget + + def testfunc(*args): + n, c = args[0] + total = 0 + for _ in range(n): + total += c.val + return total + + testfunc((3, C())) + res, ex = self._run_with_optimizer(testfunc, (TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_LOAD_ATTR_PROPERTY_FRAME", uops) + # Check the optimizer traced through the property call. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + fget.__code__ = (lambda self: 2).__code__ + _testinternalcapi.clear_executor_deletion_list() + ex = get_first_executor(testfunc) + self.assertIsNone(ex) + res = testfunc((TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD * 2) def test_unary_negative(self): def testfunc(n): @@ -5022,6 +5741,72 @@ def g(): PYTHON_JIT="1", PYTHON_JIT_STRESS="1") self.assertEqual(result[0].rc, 0, result) + def test_call_kw(self): + def func(a): + return int(a) * 42 + + def testfunc(n): + x = 0 + for _ in range(n): + x += func(a=1) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 42 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_FUNCTION_VERSION_KW", uops) + # Check the optimizer has optmized through the function call + # by promoting global `int` to a constant. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + def test_call_kw_bound_method(self): + class C: + def method(self, a, b): + return int(a) + int(b) + + def testfunc(n): + obj = C() + x = 0 + meth = obj.method + for _ in range(n): + x += meth(a=1, b=2) + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 3 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_METHOD_VERSION_KW", uops) + # Check the optimizer has optmized through the function call + # by promoting global `int` to a constant. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + def test_func_version_guarded_on_change(self): + def testfunc(n): + for i in range(n): + # Only works on functions promoted to constants + global_identity_code_will_be_modified(i) + + testfunc(TIER2_THRESHOLD) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_PUSH_FRAME", uops) + self.assertIn("_CHECK_FUNCTION_VERSION", uops) + + global_identity_code_will_be_modified.__code__ = (lambda a: 0xdeadead).__code__ + _testinternalcapi.clear_executor_deletion_list() + ex = get_first_executor(testfunc) + self.assertIsNone(ex) + # JItted code should've deopted. + self.assertEqual(global_identity_code_will_be_modified(None), 0xdeadead) + def test_call_super(self): class A: def method1(self): @@ -5068,6 +5853,9 @@ def testfunc(n): def global_identity(x): return x +def global_identity_code_will_be_modified(x): + return x + class TestObject: def test(self, *args, **kwargs): return args[0] @@ -5075,5 +5863,9 @@ def test(self, *args, **kwargs): test_object = TestObject() test_bound_method = TestObject.test.__get__(test_object) +class MyGlobalPoint: + def __init__(self, x, y): + return None + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_cext/setup.py b/Lib/test/test_cext/setup.py index 7262a110d83..25fe50df603 100644 --- a/Lib/test/test_cext/setup.py +++ b/Lib/test/test_cext/setup.py @@ -18,6 +18,11 @@ # The purpose of test_cext extension is to check that building a C # extension using the Python C API does not emit C compiler warnings. '-Werror', + # Enable extra checks for header files, which: + # - need to be enabled somewhere inside Python headers (rather than + # before including Python.h) + # - should not be checked for user code + '-D_Py_IS_TESTCEXT', ] # C compiler flags for GCC and clang diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index fac7e9148f1..5e802a929b1 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -424,13 +424,6 @@ def func(): new_code = code = func.__code__.replace(co_linetable=b'') self.assertEqual(list(new_code.co_lines()), []) - def test_co_lnotab_is_deprecated(self): # TODO: remove in 3.14 - def func(): - pass - - with self.assertWarns(DeprecationWarning): - func.__code__.co_lnotab - @unittest.skipIf(_testinternalcapi is None, '_testinternalcapi is missing') def test_returns_only_none(self): value = True diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index d7c4f19c1a5..8d8dd2a2bf2 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1729,6 +1729,19 @@ def test_error(self): self.assertEqual(e1.message, e2.message) self.assertEqual(repr(e1), repr(e2)) + def test_combine_error_linear_complexity(self): + # Ensure that ParsingError.combine() has linear complexity. + # See https://github.com/python/cpython/issues/148370. + n = 50000 + s = '[*]\n' + (err_line := '=\n') * n + p = configparser.ConfigParser(strict=False) + with self.assertRaises(configparser.ParsingError) as cm: + p.read_string(s) + errlines = cm.exception.message.splitlines() + self.assertEqual(len(errlines), n + 1) + self.assertStartsWith(errlines[0], "Source contains parsing errors: ") + self.assertEqual(errlines[42], f"\t[line {43:2d}]: {err_line!r}") + def test_nosectionerror(self): import pickle e1 = configparser.NoSectionError('section') diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 2e5b72742c3..7327c1bd5f5 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -553,6 +553,33 @@ def test_roundtrip_escaped_unquoted_newlines(self): self.assertEqual(row, rows[i]) + def test_reader_reentrant_iterator(self): + # gh-145105: re-entering the reader from the iterator must not crash. + class ReentrantIter: + def __init__(self): + self.reader = None + self.n = 0 + def __iter__(self): + return self + def __next__(self): + self.n += 1 + if self.n == 1: + try: + next(self.reader) + except StopIteration: + pass + return "a,b" + if self.n == 2: + return "x" + raise StopIteration + + it = ReentrantIter() + reader = csv.reader(it) + it.reader = reader + with self.assertRaises(csv.Error): + next(reader) + + class TestDialectRegistry(unittest.TestCase): def test_registry_badargs(self): self.assertRaises(TypeError, csv.list_dialects, None) diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index f14e1aa32e1..6a1bae14773 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -1,4 +1,5 @@ import binascii +import ctypes import math import struct import sys @@ -165,6 +166,48 @@ def test_endian_double(self): self.assertEqual(s.value, math.pi) self.assertEqual(bin(struct.pack(">d", math.pi)), bin(s)) + @unittest.skipUnless(hasattr(ctypes, 'c_float_complex'), "No complex types") + def test_endian_float_complex(self): + c_float_complex = ctypes.c_float_complex + if sys.byteorder == "little": + self.assertIs(c_float_complex.__ctype_le__, c_float_complex) + self.assertIs(c_float_complex.__ctype_be__.__ctype_le__, + c_float_complex) + else: + self.assertIs(c_float_complex.__ctype_be__, c_float_complex) + self.assertIs(c_float_complex.__ctype_le__.__ctype_be__, + c_float_complex) + s = c_float_complex(math.pi+1j) + self.assertEqual(bin(struct.pack("F", math.pi+1j)), bin(s)) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + s = c_float_complex.__ctype_le__(math.pi+1j) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + self.assertEqual(bin(struct.pack("F", math.pi+1j)), bin(s)) + + @unittest.skipUnless(hasattr(ctypes, 'c_double_complex'), "No complex types") + def test_endian_double_complex(self): + c_double_complex = ctypes.c_double_complex + if sys.byteorder == "little": + self.assertIs(c_double_complex.__ctype_le__, c_double_complex) + self.assertIs(c_double_complex.__ctype_be__.__ctype_le__, + c_double_complex) + else: + self.assertIs(c_double_complex.__ctype_be__, c_double_complex) + self.assertIs(c_double_complex.__ctype_le__.__ctype_be__, + c_double_complex) + s = c_double_complex(math.pi+1j) + self.assertEqual(bin(struct.pack("D", math.pi+1j)), bin(s)) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + s = c_double_complex.__ctype_le__(math.pi+1j) + self.assertAlmostEqual(s.value, math.pi+1j, places=6) + self.assertEqual(bin(struct.pack("D", math.pi+1j)), bin(s)) + def test_endian_other(self): self.assertIs(c_byte.__ctype_le__, c_byte) self.assertIs(c_byte.__ctype_be__, c_byte) diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 8b5e0cf7806..5eec9e23cd4 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -27,11 +27,21 @@ import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. from test import support -from test.support import import_helper +from test.support import cpython_only, import_helper # Just any custom exception we can catch. class CustomError(Exception): pass + +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "dataclasses", {"inspect", "re", "copy"} + ) + + class TestCase(unittest.TestCase): def test_no_fields(self): @dataclass @@ -1693,17 +1703,24 @@ class GroupTuple: class GroupDict: id: int users: Dict[str, User] + @dataclass + class GroupFrozenDict: + id: int + users: frozendict[str, User] a = User('Alice', 1) b = User('Bob', 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) gd = GroupDict(0, {'first': a, 'second': b}) + gfd = GroupFrozenDict(0, frozendict({'first': a, 'second': b})) self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2}]}) self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2})}) - self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, - 'second': {'name': 'Bob', 'id': 2}}}) + expected_dict = {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, + 'second': {'name': 'Bob', 'id': 2}}} + self.assertEqual(asdict(gd), expected_dict) + self.assertEqual(asdict(gfd), expected_dict) def test_helper_asdict_builtin_object_containers(self): @dataclass @@ -1884,14 +1901,21 @@ class GroupTuple: class GroupDict: id: int users: Dict[str, User] + @dataclass + class GroupFrozenDict: + id: int + users: frozendict[str, User] a = User('Alice', 1) b = User('Bob', 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) gd = GroupDict(0, {'first': a, 'second': b}) + gfd = GroupFrozenDict(0, frozendict({'first': a, 'second': b})) self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) - self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) + d = {'first': ('Alice', 1), 'second': ('Bob', 2)} + self.assertEqual(astuple(gd), (0, d)) + self.assertEqual(astuple(gfd), (0, frozendict(d))) def test_helper_astuple_builtin_object_containers(self): @dataclass @@ -2295,6 +2319,20 @@ class C: self.assertDocStrEqual(C.__doc__, "C()") + def test_docstring_slotted(self): + @dataclass(slots=True) + class C: + x: int + + self.assertDocStrEqual(C.__doc__, "C(x:int)") + + def test_docstring_recursive(self): + @dataclass() + class C: + x: list[C] + + self.assertDocStrEqual(C.__doc__, "C(x:list[test.test_dataclasses.TestDocString.test_docstring_recursive..C])") + def test_docstring_one_field(self): @dataclass class C: @@ -3052,29 +3090,41 @@ class C(base): class TestFrozen(unittest.TestCase): - def test_frozen(self): - @dataclass(frozen=True) - class C: - i: int + # Some tests have a subtest with a slotted dataclass. + # See https://github.com/python/cpython/issues/105936 for the reasons. - c = C(10) - self.assertEqual(c.i, 10) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertEqual(c.i, 10) + def test_frozen(self): + for slots in (False, True): + with self.subTest(slots=slots): + + @dataclass(frozen=True, slots=slots) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + del c.i + self.assertEqual(c.i, 10) def test_frozen_empty(self): - @dataclass(frozen=True) - class C: - pass + for slots in (False, True): + with self.subTest(slots=slots): - c = C() - self.assertNotHasAttr(c, 'i') - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertNotHasAttr(c, 'i') - with self.assertRaises(FrozenInstanceError): - del c.i + @dataclass(frozen=True, slots=slots) + class C: + pass + + c = C() + self.assertNotHasAttr(c, 'i') + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertNotHasAttr(c, 'i') + with self.assertRaises(FrozenInstanceError): + del c.i def test_inherit(self): @dataclass(frozen=True) @@ -3270,41 +3320,43 @@ class D(I): d.i = 5 def test_non_frozen_normal_derived(self): - # See bpo-32953. + # See bpo-32953 and https://github.com/python/cpython/issues/105936 + for slots in (False, True): + with self.subTest(slots=slots): - @dataclass(frozen=True) - class D: - x: int - y: int = 10 + @dataclass(frozen=True, slots=slots) + class D: + x: int + y: int = 10 - class S(D): - pass + class S(D): + pass - s = S(3) - self.assertEqual(s.x, 3) - self.assertEqual(s.y, 10) - s.cached = True + s = S(3) + self.assertEqual(s.x, 3) + self.assertEqual(s.y, 10) + s.cached = True - # But can't change the frozen attributes. - with self.assertRaises(FrozenInstanceError): - s.x = 5 - with self.assertRaises(FrozenInstanceError): - s.y = 5 - self.assertEqual(s.x, 3) - self.assertEqual(s.y, 10) - self.assertEqual(s.cached, True) + # But can't change the frozen attributes. + with self.assertRaises(FrozenInstanceError): + s.x = 5 + with self.assertRaises(FrozenInstanceError): + s.y = 5 + self.assertEqual(s.x, 3) + self.assertEqual(s.y, 10) + self.assertEqual(s.cached, True) - with self.assertRaises(FrozenInstanceError): - del s.x - self.assertEqual(s.x, 3) - with self.assertRaises(FrozenInstanceError): - del s.y - self.assertEqual(s.y, 10) - del s.cached - self.assertNotHasAttr(s, 'cached') - with self.assertRaises(AttributeError) as cm: - del s.cached - self.assertNotIsInstance(cm.exception, FrozenInstanceError) + with self.assertRaises(FrozenInstanceError): + del s.x + self.assertEqual(s.x, 3) + with self.assertRaises(FrozenInstanceError): + del s.y + self.assertEqual(s.y, 10) + del s.cached + self.assertNotHasAttr(s, 'cached') + with self.assertRaises(AttributeError) as cm: + del s.cached + self.assertNotIsInstance(cm.exception, FrozenInstanceError) def test_non_frozen_normal_derived_from_empty_frozen(self): @dataclass(frozen=True) @@ -3971,6 +4023,14 @@ class SlotsTest: return SlotsTest + # See https://github.com/python/cpython/issues/135228#issuecomment-3755979059 + def make_frozen(): + @dataclass(frozen=True, slots=True) + class SlotsTest: + pass + + return SlotsTest + def make_with_annotations(): @dataclass(slots=True) class SlotsTest: @@ -3996,7 +4056,7 @@ class SlotsTest: return SlotsTest - for make in (make_simple, make_with_annotations, make_with_annotations_and_method, make_with_forwardref): + for make in (make_simple, make_frozen, make_with_annotations, make_with_annotations_and_method, make_with_forwardref): with self.subTest(make=make): C = make() support.gc_collect() @@ -5339,5 +5399,51 @@ def cls(self): # one will be keeping a reference to the underlying class A. self.assertIs(A().cls(), B) + def test_empty_class_cell(self): + # gh-148947: Make sure that we explicitly handle the empty class cell. + def maker(): + if False: + __class__ = 42 + + def method(self): + return __class__ + return method + + from dataclasses import dataclass + + @dataclass(slots=True) + class X: + a: int + + meth = maker() + + with self.assertRaisesRegex(NameError, '__class__'): + X(1).meth() + + def test_class_cell_from_other_class(self): + # This test fails without the "is oldcls" check in + # _update_func_cell_for__class__. + class Base: + def meth(self): + return "Base" + + class Child(Base): + def meth(self): + return super().meth() + " Child" + + @dataclass(slots=True) + class DC(Child): + a: int + + meth = Child.meth + + closure = DC.meth.__closure__ + self.assertEqual(len(closure), 1) + self.assertIs(closure[0].cell_contents, Child) + + self.assertEqual(DC(1).meth(), "Base Child") + + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index f8bbcd35ca7..cc9bc918b61 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -877,6 +877,7 @@ def foo(x): dis_nested_2 = """%s Disassembly of at 0x..., file "%s", line %d>: -- COPY_FREE_VARS 1 + RESUME 4 %4d LOAD_FAST 0 (.0) GET_ITER 0 @@ -889,7 +890,7 @@ def foo(x): LOAD_FAST_BORROW 1 (z) BINARY_OP 0 (+) YIELD_VALUE 0 - RESUME 5 + RESUME 9 POP_TOP JUMP_BACKWARD 17 (to L2) L3: END_FOR @@ -936,7 +937,7 @@ def loop_test(): LIST_EXTEND 1 LOAD_SMALL_INT 3 BINARY_OP 5 (*) - GET_ITER 0 + GET_ITER_VIRTUAL 0 L1: FOR_ITER_LIST 14 (to L2) STORE_FAST 0 (i) @@ -1443,7 +1444,7 @@ def test_show_caches(self): caches = list(self.get_cached_values(quickened, adaptive)) for cache in caches: self.assertRegex(cache, pattern) - total_caches = 22 + total_caches = 23 empty_caches = 7 self.assertEqual(caches.count(""), empty_caches) self.assertEqual(len(caches), total_caches) @@ -1859,131 +1860,131 @@ def _prepare_test_cases(): make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=4, start_offset=4, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3), make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='GET_ITER', arg=0, argval=0, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), - make_inst(opname='FOR_ITER', arg=33, argval=96, argrepr='to L4', offset=26, start_offset=26, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=42, start_offset=42, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=52, start_offset=52, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=54, start_offset=54, starts_line=True, line_number=5), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=58, start_offset=58, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=72, argrepr='to L2', offset=62, start_offset=62, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=66, start_offset=66, starts_line=False, line_number=5), - make_inst(opname='JUMP_BACKWARD', arg=23, argval=26, argrepr='to L1', offset=68, start_offset=68, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=72, start_offset=72, starts_line=True, line_number=7, label=2), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=74, start_offset=74, starts_line=False, line_number=7), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=76, start_offset=76, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=90, argrepr='to L3', offset=80, start_offset=80, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=False, line_number=7), - make_inst(opname='JUMP_BACKWARD', arg=32, argval=26, argrepr='to L1', offset=86, start_offset=86, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=True, line_number=8, label=3), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=False, line_number=8), - make_inst(opname='JUMP_FORWARD', arg=13, argval=122, argrepr='to L5', offset=94, start_offset=94, starts_line=False, line_number=8), - make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=True, line_number=3, label=4), - make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=100, start_offset=100, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, start_offset=110, starts_line=False, line_number=10), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=10), - make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=122, start_offset=122, starts_line=True, line_number=11, label=5), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=124, start_offset=124, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=216, argrepr='to L8', offset=132, start_offset=132, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=136, start_offset=136, starts_line=False, line_number=11), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=138, start_offset=138, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=148, start_offset=148, starts_line=False, line_number=12), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=150, start_offset=150, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=12), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=160, start_offset=160, starts_line=True, line_number=13), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=13), - make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=164, start_offset=164, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=False, line_number=13), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=True, line_number=14), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=180, start_offset=180, starts_line=False, line_number=14), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=182, start_offset=182, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=196, argrepr='to L6', offset=186, start_offset=186, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=190, start_offset=190, starts_line=False, line_number=14), - make_inst(opname='JUMP_BACKWARD', arg=37, argval=122, argrepr='to L5', offset=192, start_offset=192, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=196, start_offset=196, starts_line=True, line_number=16, label=6), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=198, start_offset=198, starts_line=False, line_number=16), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=200, start_offset=200, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=214, argrepr='to L7', offset=204, start_offset=204, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=208, start_offset=208, starts_line=False, line_number=16), - make_inst(opname='JUMP_BACKWARD', arg=46, argval=122, argrepr='to L5', offset=210, start_offset=210, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='JUMP_FORWARD', arg=11, argval=238, argrepr='to L9', offset=214, start_offset=214, starts_line=True, line_number=17, label=7), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=216, start_offset=216, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=226, start_offset=226, starts_line=False, line_number=19), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=228, start_offset=228, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=19), - make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=20, label=9), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=240, start_offset=240, starts_line=True, line_number=21), - make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=21), - make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=244, start_offset=244, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=21), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=258, start_offset=258, starts_line=True, line_number=25), - make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=262, start_offset=262, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=268, start_offset=268, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=278, start_offset=278, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=280, start_offset=280, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=290, start_offset=290, starts_line=False, line_number=26), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=292, start_offset=292, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=26), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=True, line_number=25), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=False, line_number=25), + make_inst(opname='GET_ITER', arg=0, argval=0, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='FOR_ITER', arg=33, argval=98, argrepr='to L4', offset=28, start_offset=28, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=32, start_offset=32, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=34, start_offset=34, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=44, start_offset=44, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=56, start_offset=56, starts_line=True, line_number=5), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=60, start_offset=60, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=74, argrepr='to L2', offset=64, start_offset=64, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=68, start_offset=68, starts_line=False, line_number=5), + make_inst(opname='JUMP_BACKWARD', arg=23, argval=28, argrepr='to L1', offset=70, start_offset=70, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=74, start_offset=74, starts_line=True, line_number=7, label=2), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=76, start_offset=76, starts_line=False, line_number=7), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=78, start_offset=78, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=92, argrepr='to L3', offset=82, start_offset=82, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=86, start_offset=86, starts_line=False, line_number=7), + make_inst(opname='JUMP_BACKWARD', arg=32, argval=28, argrepr='to L1', offset=88, start_offset=88, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=8, label=3), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=False, line_number=8), + make_inst(opname='JUMP_FORWARD', arg=13, argval=124, argrepr='to L5', offset=96, start_offset=96, starts_line=False, line_number=8), + make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=True, line_number=3, label=4), + make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=100, start_offset=100, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=102, start_offset=102, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=112, start_offset=112, starts_line=False, line_number=10), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=114, start_offset=114, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=10), + make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=124, start_offset=124, starts_line=True, line_number=11, label=5), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=126, start_offset=126, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=218, argrepr='to L8', offset=134, start_offset=134, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=138, start_offset=138, starts_line=False, line_number=11), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=140, start_offset=140, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=150, start_offset=150, starts_line=False, line_number=12), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=152, start_offset=152, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=12), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=162, start_offset=162, starts_line=True, line_number=13), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=164, start_offset=164, starts_line=False, line_number=13), + make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=166, start_offset=166, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=False, line_number=13), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=180, start_offset=180, starts_line=True, line_number=14), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=182, start_offset=182, starts_line=False, line_number=14), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=198, argrepr='to L6', offset=188, start_offset=188, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=192, start_offset=192, starts_line=False, line_number=14), + make_inst(opname='JUMP_BACKWARD', arg=37, argval=124, argrepr='to L5', offset=194, start_offset=194, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=198, start_offset=198, starts_line=True, line_number=16, label=6), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=200, start_offset=200, starts_line=False, line_number=16), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=216, argrepr='to L7', offset=206, start_offset=206, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=210, start_offset=210, starts_line=False, line_number=16), + make_inst(opname='JUMP_BACKWARD', arg=46, argval=124, argrepr='to L5', offset=212, start_offset=212, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='JUMP_FORWARD', arg=11, argval=240, argrepr='to L9', offset=216, start_offset=216, starts_line=True, line_number=17, label=7), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=218, start_offset=218, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=228, start_offset=228, starts_line=False, line_number=19), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=19), + make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=240, start_offset=240, starts_line=True, line_number=20, label=9), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=242, start_offset=242, starts_line=True, line_number=21), + make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=244, start_offset=244, starts_line=False, line_number=21), + make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=246, start_offset=246, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=21), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=260, start_offset=260, starts_line=True, line_number=25), + make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=264, start_offset=264, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=270, start_offset=270, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=272, start_offset=272, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=280, start_offset=280, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=282, start_offset=282, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=292, start_offset=292, starts_line=False, line_number=26), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=294, start_offset=294, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=302, start_offset=302, starts_line=False, line_number=26), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=True, line_number=25), make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=306, start_offset=306, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=318, start_offset=318, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=328, start_offset=328, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=330, start_offset=330, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=340, start_offset=340, starts_line=False, line_number=28), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=28), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=True, line_number=25), - make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=364, argrepr='to L11', offset=356, start_offset=356, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), - make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25, label=11), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=308, start_offset=308, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=310, start_offset=310, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=320, start_offset=320, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=330, start_offset=330, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=332, start_offset=332, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=342, start_offset=342, starts_line=False, line_number=28), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=28), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=True, line_number=25), + make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=350, start_offset=350, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=366, argrepr='to L11', offset=358, start_offset=358, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25), + make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25, label=11), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=372, start_offset=372, starts_line=False, line_number=25), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=318, argrepr='to L10', offset=374, start_offset=374, starts_line=False, line_number=25), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=376, start_offset=376, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=384, start_offset=384, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=394, start_offset=394, starts_line=False, line_number=22), - make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=430, argrepr='to L12', offset=396, start_offset=396, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=22), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=404, start_offset=404, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=414, start_offset=414, starts_line=False, line_number=23), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=416, start_offset=416, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=23), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=318, argrepr='to L10', offset=428, start_offset=428, starts_line=False, line_number=23), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=22, label=12), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=432, start_offset=432, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=440, start_offset=440, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=450, start_offset=450, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=452, start_offset=452, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=464, start_offset=464, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=468, start_offset=468, starts_line=False, line_number=None), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=25), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=320, argrepr='to L10', offset=376, start_offset=376, starts_line=False, line_number=25), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=378, start_offset=378, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=384, start_offset=384, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=386, start_offset=386, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=396, start_offset=396, starts_line=False, line_number=22), + make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=432, argrepr='to L12', offset=398, start_offset=398, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=22), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=404, start_offset=404, starts_line=False, line_number=22), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=406, start_offset=406, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=416, start_offset=416, starts_line=False, line_number=23), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=418, start_offset=418, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=23), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=428, start_offset=428, starts_line=False, line_number=23), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=320, argrepr='to L10', offset=430, start_offset=430, starts_line=False, line_number=23), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=432, start_offset=432, starts_line=True, line_number=22, label=12), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=434, start_offset=434, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=440, start_offset=440, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=442, start_offset=442, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=452, start_offset=452, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=454, start_offset=454, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=28), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=466, start_offset=466, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=468, start_offset=468, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=470, start_offset=470, starts_line=False, line_number=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index c2d7d09d591..3c9a86f3e8c 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -1,13 +1,20 @@ import io import textwrap import unittest +import random +import sys from email import message_from_string, message_from_bytes from email.message import EmailMessage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText from email.generator import Generator, BytesGenerator +import email.generator from email.headerregistry import Address from email import policy import email.errors from test.test_email import TestEmailBase, parameterize +import test.support + @parameterize @@ -288,6 +295,36 @@ def test_keep_long_encoded_newlines(self): g.flatten(msg) self.assertEqual(s.getvalue(), self.typ(expected)) + def _test_boundary_detection(self, linesep): + # Generate a boundary token in the same way as _make_boundary + token = random.randrange(sys.maxsize) + + def _patch_random_randrange(*args, **kwargs): + return token + + with test.support.swap_attr( + random, "randrange", _patch_random_randrange + ): + boundary = self.genclass._make_boundary(text=None) + boundary_in_part = ( + "this goes before the boundary\n--" + + boundary + + "\nthis goes after\n" + ) + msg = MIMEMultipart() + msg.attach(MIMEText(boundary_in_part)) + self.genclass(self.ioclass()).flatten(msg, linesep=linesep) + # Generator checks the message content for the string it is about + # to use as a boundary ('token' in this test) and when it finds it + # in our attachment appends .0 to make the boundary it uses unique. + self.assertEqual(msg.get_boundary(), boundary + ".0") + + def test_lf_boundary_detection(self): + self._test_boundary_detection("\n") + + def test_crlf_boundary_detection(self): + self._test_boundary_detection("\r\n") + class TestGenerator(TestGeneratorBase, TestEmailBase): diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index a2de58c2926..1087cbd0836 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1930,6 +1930,12 @@ def test_init_in_background_thread(self): out, err = self.run_embedded_interpreter("test_init_in_background_thread") self.assertEqual(err, "") + def test_isinitialized_false_during_site_import(self): + # gh-146302: Py_IsInitialized() must not return true during site import. + out, err = self.run_embedded_interpreter( + "test_isinitialized_false_during_site_import") + self.assertEqual(err, "") + class AuditingTests(EmbeddingTestsMixin, unittest.TestCase): def test_open_code_hook(self): diff --git a/Lib/test/test_free_threading/test_dict.py b/Lib/test/test_free_threading/test_dict.py index 1ffd924e9f4..55272a00c3a 100644 --- a/Lib/test/test_free_threading/test_dict.py +++ b/Lib/test/test_free_threading/test_dict.py @@ -245,6 +245,29 @@ def reader(): with threading_helper.start_threads([t1, t2]): pass + @unittest.skipIf(_testcapi is None, "requires _testcapi") + def test_racing_watch_unwatch_dict(self): + # gh-148393: race between PyDict_Watch / PyDict_Unwatch + # and concurrent dict mutation reading _ma_watcher_tag. + wid = _testcapi.add_dict_watcher(0) + try: + d = {} + ITERS = 1000 + + def writer(): + for i in range(ITERS): + d[i] = i + del d[i] + + def watcher(): + for _ in range(ITERS): + _testcapi.watch_dict(wid, d) + _testcapi.unwatch_dict(wid, d) + + threading_helper.run_concurrently([writer, watcher]) + finally: + _testcapi.clear_dict_watcher(wid) + def test_racing_dict_update_and_method_lookup(self): # gh-144295: test race between dict modifications and method lookups. # Uses BytesIO because the race requires a type without Py_TPFLAGS_INLINE_VALUES diff --git a/Lib/test/test_free_threading/test_str.py b/Lib/test/test_free_threading/test_str.py index 9a1ce3620ac..11e04009956 100644 --- a/Lib/test/test_free_threading/test_str.py +++ b/Lib/test/test_free_threading/test_str.py @@ -1,7 +1,9 @@ +import sys +import threading import unittest from itertools import cycle -from threading import Event, Thread +from threading import Barrier, Event, Thread from unittest import TestCase from test.support import threading_helper @@ -69,6 +71,24 @@ def reader_func(): for reader in readers: reader.join() + def test_intern_unowned_string(self): + # Test interning strings owned by various threads. + strings = [f"intern_race_owner_{i}" for i in range(50)] + + NUM_THREADS = 5 + b = Barrier(NUM_THREADS) + + def interner(): + tid = threading.get_ident() + for i in range(20): + strings.append(f"intern_{tid}_{i}") + b.wait() + for s in strings: + r = sys.intern(s) + self.assertTrue(sys._is_interned(r)) + + threading_helper.run_concurrently(interner, nthreads=NUM_THREADS) + def test_maketrans_dict_concurrent_modification(self): for _ in range(5): d = {2000: 'a'} diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index efa85b564f7..a8ee7d119e4 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -3358,6 +3358,21 @@ def t(self, *args, **kwargs): with self.assertRaisesRegex(TypeError, msg): A().t(a=1) + def test_positional_only_argument(self): + @functools.singledispatch + def f(arg, /, extra): + return "base" + @f.register + def f_int(arg: int, /, extra: str): + return "int" + @f.register + def f_str(arg: str, /, extra: int): + return "str" + + self.assertEqual(f(None, "extra"), "base") + self.assertEqual(f(1, "extra"), "int") + self.assertEqual(f("s", "extra"), "str") + def test_union(self): @functools.singledispatch def f(arg): diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 57991b5b6b8..62cf0c0c6af 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -29,12 +29,13 @@ def skip_if_different_mount_drives(): test_tools.skip_if_missing("cases_generator") with test_tools.imports_under_tool("cases_generator"): - from analyzer import StackItem + from analyzer import StackItem, analyze_files from cwriter import CWriter import parser from stack import Local, Stack import tier1_generator import optimizer_generator + import record_function_generator def handle_stderr(): @@ -1890,6 +1891,260 @@ def test_reassigning_dead_inputs(self): """ self.run_cases_test(input, output) + def test_recording_after_specializing_with_cache(self): + input = """ + specializing op(SPEC, (counter/1 --)) { + spam; + } + + tier2 op(REC, (--)) { + RECORD_VALUE(0); + } + + op(BODY, (--)) { + ham; + } + + macro(OP) = SPEC + unused/2 + REC + BODY; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); + // SPEC + { + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + spam; + } + /* Skip 2 cache entries */ + // BODY + { + ham; + } + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_recording_after_non_specializing(self): + input = """ + op(REGULAR, (--)) { + spam; + } + + tier2 op(REC, (--)) { + RECORD_VALUE(0); + } + + macro(OP) = REGULAR + REC; + """ + with self.assertRaisesRegex(SyntaxError, "Recording uop"): + self.run_cases_test(input, "") + + def test_multiple_consecutive_recording_uops(self): + """Multiple consecutive recording uops at the start of a macro are legal.""" + input = """ + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + op(_DO_STUFF, (a, b -- res)) { + res = a; + INPUTS_DEAD(); + } + macro(OP) = _RECORD_A + _RECORD_B + _DO_STUFF; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); + _PyStackRef a; + _PyStackRef res; + // _DO_STUFF + { + a = stack_pointer[-2]; + res = a; + } + stack_pointer[-2] = res; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_multiple_recording_uops_after_specializing(self): + """Multiple recording uops after a specializing uop are legal.""" + input = """ + specializing op(_SPECIALIZE_OP, (counter/1, a, b -- a, b)) { + SPAM(); + } + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + op(_DO_STUFF, (a, b -- res)) { + res = a; + INPUTS_DEAD(); + } + macro(OP) = _SPECIALIZE_OP + _RECORD_A + _RECORD_B + unused/2 + _DO_STUFF; + """ + output = """ + TARGET(OP) { + #if _Py_TAIL_CALL_INTERP + int opcode = OP; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 4; + INSTRUCTION_STATS(OP); + _PyStackRef a; + _PyStackRef res; + // _SPECIALIZE_OP + { + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + SPAM(); + } + /* Skip 2 cache entries */ + // _DO_STUFF + { + a = stack_pointer[-2]; + res = a; + } + stack_pointer[-2] = res; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_recording_uop_between_real_uops_rejected(self): + """A recording uop sandwiched between real uops is rejected.""" + input = """ + tier2 op(_RECORD_A, (a, b -- a, b)) { + RECORD_VALUE(a); + } + op(_FIRST, (a, b -- a, b)) { + first(a); + } + tier2 op(_RECORD_B, (a, b -- a, b)) { + RECORD_VALUE(b); + } + macro(OP) = _RECORD_A + _FIRST + _RECORD_B; + """ + with self.assertRaisesRegex(SyntaxError, + "must precede all " + "non-recording, non-specializing uops"): + self.run_cases_test(input, "") + + +class TestRecorderTableGeneration(unittest.TestCase): + + def setUp(self) -> None: + super().setUp() + self.maxDiff = None + self.temp_dir = tempfile.gettempdir() + self.temp_input_filename = os.path.join(self.temp_dir, "input.txt") + + def tearDown(self) -> None: + try: + os.remove(self.temp_input_filename) + except FileNotFoundError: + pass + super().tearDown() + + def generate_tables(self, input: str) -> str: + import io + with open(self.temp_input_filename, "w+") as f: + f.write(parser.BEGIN_MARKER) + f.write(input) + f.write(parser.END_MARKER) + with handle_stderr(): + analysis = analyze_files([self.temp_input_filename]) + buf = io.StringIO() + out = CWriter(buf, 0, False) + record_function_generator.generate_recorder_tables(analysis, out) + return buf.getvalue() + + def test_single_recording_uop_generates_count(self): + input = """ + tier2 op(_RECORD_TOS, (value -- value)) { + RECORD_VALUE(value); + } + op(_DO_STUFF, (value -- res)) { + res = value; + } + macro(OP) = _RECORD_TOS + _DO_STUFF; + """ + output = self.generate_tables(input) + self.assertIn("_RECORD_TOS_INDEX", output) + self.assertIn("[OP] = {1, {_RECORD_TOS_INDEX}}", output) + + def test_three_recording_uops_generate_count_3_in_order(self): + input = """ + tier2 op(_RECORD_X, (a, b, c -- a, b, c)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_Y, (a, b, c -- a, b, c)) { + RECORD_VALUE(b); + } + tier2 op(_RECORD_Z, (a, b, c -- a, b, c)) { + RECORD_VALUE(c); + } + op(_DO_STUFF, (a, b, c -- res)) { + res = a; + } + macro(OP) = _RECORD_X + _RECORD_Y + _RECORD_Z + _DO_STUFF; + """ + output = self.generate_tables(input) + self.assertIn( + "[OP] = {3, {_RECORD_X_INDEX, _RECORD_Y_INDEX, _RECORD_Z_INDEX}}", + output, + ) + + def test_four_recording_uops_rejected(self): + input = """ + tier2 op(_RECORD_A, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(a); + } + tier2 op(_RECORD_B, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(b); + } + tier2 op(_RECORD_C, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(c); + } + tier2 op(_RECORD_D, (a, b, c, d -- a, b, c, d)) { + RECORD_VALUE(d); + } + op(_DO_STUFF, (a, b, c, d -- res)) { + res = a; + } + macro(OP) = _RECORD_A + _RECORD_B + _RECORD_C + _RECORD_D + _DO_STUFF; + """ + with self.assertRaisesRegex(ValueError, "exceeds MAX_RECORDED_VALUES"): + self.generate_tables(input) + class TestGeneratedAbstractCases(unittest.TestCase): def setUp(self) -> None: @@ -2638,5 +2893,30 @@ def test_replace_opocode_uop_reject_array_effects(self): "Pure evaluation cannot take array-like inputs"): self.run_cases_test(input, input2, output) + def test_overridden_abstract_with_multiple_caches(self): + input = """ + op(OP, (version/1, unused/1, index/1, value -- res)) { + res = SPAM(version, index, value); + } + """ + input2 = """ + op(OP, (value -- res)) { + res = eggs(version, index, value); + } + """ + output = """ + case OP: { + JitOptRef value; + JitOptRef res; + value = stack_pointer[-1]; + uint16_t version = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; + res = eggs(version, index, value); + stack_pointer[-1] = res; + break; + } + """ + self.run_cases_test(input, input2, output) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index de4d200374b..1ea182fec4f 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -24,6 +24,7 @@ import unittest import warnings from _operator import _compare_digest as operator_compare_digest +from test import support from test.support import _4G, bigmemtest from test.support import check_disallow_instantiation from test.support import hashlib_helper, import_helper @@ -1024,6 +1025,13 @@ def test_hmac_digest_digestmod_parameter(self): ): self.hmac_digest(b'key', b'msg', value) + @support.subTests("xof_name", ("shake_128", "shake_256")) + def test_hmac_new_xof_digestmod(self, xof_name): + # gh-145200: XOF digests (SHAKE) are not supported by HMAC. + # Verify that the error path does not leak the EVP_MAC_CTX. + with self.assertRaises(_hashlib.UnsupportedDigestmodError): + self.hmac_new(b'key', digestmod=xof_name) + class BuiltinConstructorTestCase(ThroughBuiltinAPIMixin, ExtensionConstructorTestCaseMixin, diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index e2c7551c0b3..cfcbc17bd6d 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -1,5 +1,5 @@ # Simple test suite for http/cookies.py - +import base64 import copy import unittest import doctest @@ -175,17 +175,19 @@ def test_load(self): self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" """) - self.assertEqual(C.js_output(['path']), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" """) @@ -290,17 +292,19 @@ def test_quoted_meta(self): self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" """) - self.assertEqual(C.js_output(['path']), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" """) @@ -391,13 +395,16 @@ def test_setter(self): self.assertEqual( M.output(), "Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i)) + expected_encoded_cookie = base64.b64encode( + ("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii") + ).decode('ascii') expected_js_output = """ - """ % (i, "%s_coded_val" % i) + """ % (expected_encoded_cookie,) self.assertEqual(M.js_output(), expected_js_output) for i in ["foo bar", "foo@bar"]: # Try some illegal characters diff --git a/Lib/test/test_importlib/resources/_path.py b/Lib/test/test_importlib/resources/_path.py index b144628cb73..3720af7c508 100644 --- a/Lib/test/test_importlib/resources/_path.py +++ b/Lib/test/test_importlib/resources/_path.py @@ -1,10 +1,6 @@ -import pathlib import functools - -from typing import Dict, Union -from typing import runtime_checkable -from typing import Protocol - +import pathlib +from typing import Protocol, Union, runtime_checkable #### # from jaraco.path 3.7.1 @@ -16,7 +12,7 @@ class Symlink(str): """ -FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']] +FilesSpec = dict[str, Union[str, bytes, Symlink, 'FilesSpec']] @runtime_checkable @@ -32,13 +28,13 @@ def write_bytes(self, content): ... # pragma: no cover def symlink_to(self, target): ... # pragma: no cover -def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker: +def _ensure_tree_maker(obj: str | TreeMaker) -> TreeMaker: return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore[return-value] def build( spec: FilesSpec, - prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment] + prefix: str | TreeMaker = pathlib.Path(), # type: ignore[assignment] ): """ Build a set of files/directories, as described by the spec. @@ -70,7 +66,7 @@ def build( @functools.singledispatch -def create(content: Union[str, bytes, FilesSpec], path): +def create(content: str | bytes | FilesSpec, path): path.mkdir(exist_ok=True) build(content, prefix=path) # type: ignore[arg-type] diff --git a/Lib/test/test_importlib/resources/test_compatibilty_files.py b/Lib/test/test_importlib/resources/test_compatibilty_files.py index bcf608d9e2c..2fd39bedf25 100644 --- a/Lib/test/test_importlib/resources/test_compatibilty_files.py +++ b/Lib/test/test_importlib/resources/test_compatibilty_files.py @@ -1,8 +1,6 @@ +import importlib.resources as resources import io import unittest - -from importlib import resources - from importlib.resources._adapters import ( CompatibilityFiles, wrap_spec, @@ -26,51 +24,46 @@ def files(self): return resources.files(self.package) def test_spec_path_iter(self): - self.assertEqual( - sorted(path.name for path in self.files.iterdir()), - ['a', 'b', 'c'], - ) + assert sorted(path.name for path in self.files.iterdir()) == ['a', 'b', 'c'] def test_child_path_iter(self): - self.assertEqual(list((self.files / 'a').iterdir()), []) + assert list((self.files / 'a').iterdir()) == [] def test_orphan_path_iter(self): - self.assertEqual(list((self.files / 'a' / 'a').iterdir()), []) - self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), []) + assert list((self.files / 'a' / 'a').iterdir()) == [] + assert list((self.files / 'a' / 'a' / 'a').iterdir()) == [] def test_spec_path_is(self): - self.assertFalse(self.files.is_file()) - self.assertFalse(self.files.is_dir()) + assert not self.files.is_file() + assert not self.files.is_dir() def test_child_path_is(self): - self.assertTrue((self.files / 'a').is_file()) - self.assertFalse((self.files / 'a').is_dir()) + assert (self.files / 'a').is_file() + assert not (self.files / 'a').is_dir() def test_orphan_path_is(self): - self.assertFalse((self.files / 'a' / 'a').is_file()) - self.assertFalse((self.files / 'a' / 'a').is_dir()) - self.assertFalse((self.files / 'a' / 'a' / 'a').is_file()) - self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir()) + assert not (self.files / 'a' / 'a').is_file() + assert not (self.files / 'a' / 'a').is_dir() + assert not (self.files / 'a' / 'a' / 'a').is_file() + assert not (self.files / 'a' / 'a' / 'a').is_dir() def test_spec_path_name(self): - self.assertEqual(self.files.name, 'testingpackage') + assert self.files.name == 'testingpackage' def test_child_path_name(self): - self.assertEqual((self.files / 'a').name, 'a') + assert (self.files / 'a').name == 'a' def test_orphan_path_name(self): - self.assertEqual((self.files / 'a' / 'b').name, 'b') - self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c') + assert (self.files / 'a' / 'b').name == 'b' + assert (self.files / 'a' / 'b' / 'c').name == 'c' def test_spec_path_open(self): - self.assertEqual(self.files.read_bytes(), b'Hello, world!') - self.assertEqual(self.files.read_text(encoding='utf-8'), 'Hello, world!') + assert self.files.read_bytes() == b'Hello, world!' + assert self.files.read_text(encoding='utf-8') == 'Hello, world!' def test_child_path_open(self): - self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!') - self.assertEqual( - (self.files / 'a').read_text(encoding='utf-8'), 'Hello, world!' - ) + assert (self.files / 'a').read_bytes() == b'Hello, world!' + assert (self.files / 'a').read_text(encoding='utf-8') == 'Hello, world!' def test_orphan_path_open(self): with self.assertRaises(FileNotFoundError): @@ -88,7 +81,7 @@ def test_orphan_path_invalid(self): def test_wrap_spec(self): spec = wrap_spec(self.package) - self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles) + assert isinstance(spec.loader.get_resource_reader(None), CompatibilityFiles) class CompatibilityFilesNoReaderTests(unittest.TestCase): @@ -101,4 +94,4 @@ def files(self): return resources.files(self.package) def test_spec_path_joinpath(self): - self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath) + assert isinstance(self.files / 'a', CompatibilityFiles.OrphanPath) diff --git a/Lib/test/test_importlib/resources/test_contents.py b/Lib/test/test_importlib/resources/test_contents.py index 4e4e0e9c337..bdc158d85a2 100644 --- a/Lib/test/test_importlib/resources/test_contents.py +++ b/Lib/test/test_importlib/resources/test_contents.py @@ -1,5 +1,5 @@ +import importlib.resources as resources import unittest -from importlib import resources from . import util diff --git a/Lib/test/test_importlib/resources/test_custom.py b/Lib/test/test_importlib/resources/test_custom.py index 640f90fc0dd..a7fc6bc35c5 100644 --- a/Lib/test/test_importlib/resources/test_custom.py +++ b/Lib/test/test_importlib/resources/test_custom.py @@ -1,12 +1,12 @@ -import unittest import contextlib +import importlib.resources as resources import pathlib +import unittest +from importlib.resources import abc +from importlib.resources.abc import ResourceReader, TraversableResources from test.support import os_helper -from importlib import resources -from importlib.resources import abc -from importlib.resources.abc import TraversableResources, ResourceReader from . import util diff --git a/Lib/test/test_importlib/resources/test_files.py b/Lib/test/test_importlib/resources/test_files.py index c935b1e10ac..c922d32cedc 100644 --- a/Lib/test/test_importlib/resources/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -1,15 +1,16 @@ +import contextlib +import importlib +import importlib.resources as resources import pathlib import py_compile import textwrap import unittest import warnings -import importlib -import contextlib - -from importlib import resources from importlib.resources.abc import Traversable + +from test.support import import_helper, os_helper + from . import util -from test.support import os_helper, import_helper @contextlib.contextmanager @@ -36,7 +37,7 @@ def test_traversable(self): def test_joinpath_with_multiple_args(self): files = resources.files(self.data) binfile = files.joinpath('subdirectory', 'binary.file') - self.assertTrue(binfile.is_file()) + assert binfile.is_file() class OpenDiskTests(FilesTests, util.DiskSetup, unittest.TestCase): @@ -62,7 +63,7 @@ def test_non_paths_in_dunder_path(self): to cause the ``PathEntryFinder`` to be called when searching for packages. In that case, resources should still be loadable. """ - import namespacedata01 + import namespacedata01 # type: ignore[import-not-found] namespacedata01.__path__.append( '__editable__.sample_namespace-1.0.finder.__path_hook__' @@ -153,7 +154,9 @@ def _compile_importlib(self): sources = pathlib.Path(resources.__file__).parent for source_path in sources.glob('**/*.py'): - c_path = c_resources.joinpath(source_path.relative_to(sources)).with_suffix('.pyc') + c_path = c_resources.joinpath(source_path.relative_to(sources)).with_suffix( + '.pyc' + ) py_compile.compile(source_path, c_path) self.fixtures.enter_context(import_helper.DirsOnSysPath(bin_site)) diff --git a/Lib/test/test_importlib/resources/test_functional.py b/Lib/test/test_importlib/resources/test_functional.py index e8d25fa4d9f..9cec6af9a5d 100644 --- a/Lib/test/test_importlib/resources/test_functional.py +++ b/Lib/test/test_importlib/resources/test_functional.py @@ -1,17 +1,12 @@ -import unittest -import os import importlib +import importlib.resources as resources +import os +import unittest from test.support import warnings_helper -from importlib import resources - from . import util -# Since the functional API forwards to Traversable, we only test -# filesystem resources here -- not zip files, namespace packages etc. -# We do test for two kinds of Anchor, though. - class StringAnchorMixin: anchor01 = 'data01' @@ -28,7 +23,7 @@ def anchor02(self): return importlib.import_module('data02') -class FunctionalAPIBase(util.DiskSetup): +class FunctionalAPIBase: def setUp(self): super().setUp() self.load_fixture('data02') @@ -43,83 +38,90 @@ def _gen_resourcetxt_path_parts(self): with self.subTest(path_parts=path_parts): yield path_parts + @staticmethod + def remove_utf16_bom(string): + """Remove an architecture-specific UTF-16 BOM prefix when present. + + Some platforms surface UTF-16 BOM bytes as escaped text when the + fixture is intentionally decoded as UTF-8 with ``errors='backslashreplace'``. + Strip that prefix so assertions validate content consistently.""" + for bom in ('\\xff\\xfe', '\\xfe\\xff', '\ufeff'): + if string.startswith(bom): + return string[len(bom) :] + return string + def test_read_text(self): - self.assertEqual( - resources.read_text(self.anchor01, 'utf-8.file'), - 'Hello, UTF-8 world!\n', + assert ( + resources.read_text(self.anchor01, 'utf-8.file') == 'Hello, UTF-8 world!\n' ) - self.assertEqual( + assert ( resources.read_text( self.anchor02, 'subdirectory', 'subsubdir', 'resource.txt', encoding='utf-8', - ), - 'a resource', + ) + == 'a resource' ) for path_parts in self._gen_resourcetxt_path_parts(): - self.assertEqual( + assert ( resources.read_text( self.anchor02, *path_parts, encoding='utf-8', - ), - 'a resource', + ) + == 'a resource' ) # Use generic OSError, since e.g. attempting to read a directory can # fail with PermissionError rather than IsADirectoryError with self.assertRaises(OSError): resources.read_text(self.anchor01) - with self.assertRaises(OSError): + with self.assertRaises((OSError, resources.abc.TraversalError)): resources.read_text(self.anchor01, 'no-such-file') with self.assertRaises(UnicodeDecodeError): resources.read_text(self.anchor01, 'utf-16.file') - self.assertEqual( + assert ( resources.read_text( self.anchor01, 'binary.file', encoding='latin1', - ), - '\x00\x01\x02\x03', + ) + == '\x00\x01\x02\x03' ) - self.assertEndsWith( # ignore the BOM + assert self.remove_utf16_bom( resources.read_text( self.anchor01, 'utf-16.file', errors='backslashreplace', ), - 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( - errors='backslashreplace', - ), + ) == 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( + errors='backslashreplace', ) def test_read_binary(self): - self.assertEqual( - resources.read_binary(self.anchor01, 'utf-8.file'), - b'Hello, UTF-8 world!\n', + assert ( + resources.read_binary(self.anchor01, 'utf-8.file') + == b'Hello, UTF-8 world!\n' ) for path_parts in self._gen_resourcetxt_path_parts(): - self.assertEqual( - resources.read_binary(self.anchor02, *path_parts), - b'a resource', - ) + assert resources.read_binary(self.anchor02, *path_parts) == b'a resource' def test_open_text(self): with resources.open_text(self.anchor01, 'utf-8.file') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' for path_parts in self._gen_resourcetxt_path_parts(): with resources.open_text( self.anchor02, *path_parts, encoding='utf-8', ) as f: - self.assertEqual(f.read(), 'a resource') + assert f.read() == 'a resource' # Use generic OSError, since e.g. attempting to read a directory can # fail with PermissionError rather than IsADirectoryError with self.assertRaises(OSError): resources.open_text(self.anchor01) - with self.assertRaises(OSError): + with self.assertRaises((OSError, resources.abc.TraversalError)): resources.open_text(self.anchor01, 'no-such-file') with resources.open_text(self.anchor01, 'utf-16.file') as f: with self.assertRaises(UnicodeDecodeError): @@ -129,71 +131,70 @@ def test_open_text(self): 'binary.file', encoding='latin1', ) as f: - self.assertEqual(f.read(), '\x00\x01\x02\x03') + assert f.read() == '\x00\x01\x02\x03' with resources.open_text( self.anchor01, 'utf-16.file', errors='backslashreplace', ) as f: - self.assertEndsWith( # ignore the BOM - f.read(), - 'Hello, UTF-16 world!\n'.encode('utf-16-le').decode( - errors='backslashreplace', - ), + assert self.remove_utf16_bom(f.read()) == 'Hello, UTF-16 world!\n'.encode( + 'utf-16-le' + ).decode( + errors='backslashreplace', ) def test_open_binary(self): with resources.open_binary(self.anchor01, 'utf-8.file') as f: - self.assertEqual(f.read(), b'Hello, UTF-8 world!\n') + assert f.read() == b'Hello, UTF-8 world!\n' for path_parts in self._gen_resourcetxt_path_parts(): with resources.open_binary( self.anchor02, *path_parts, ) as f: - self.assertEqual(f.read(), b'a resource') + assert f.read() == b'a resource' def test_path(self): with resources.path(self.anchor01, 'utf-8.file') as path: with open(str(path), encoding='utf-8') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' with resources.path(self.anchor01) as path: with open(os.path.join(path, 'utf-8.file'), encoding='utf-8') as f: - self.assertEqual(f.read(), 'Hello, UTF-8 world!\n') + assert f.read() == 'Hello, UTF-8 world!\n' def test_is_resource(self): is_resource = resources.is_resource - self.assertTrue(is_resource(self.anchor01, 'utf-8.file')) - self.assertFalse(is_resource(self.anchor01, 'no_such_file')) - self.assertFalse(is_resource(self.anchor01)) - self.assertFalse(is_resource(self.anchor01, 'subdirectory')) + assert is_resource(self.anchor01, 'utf-8.file') + assert not is_resource(self.anchor01, 'no_such_file') + assert not is_resource(self.anchor01) + assert not is_resource(self.anchor01, 'subdirectory') for path_parts in self._gen_resourcetxt_path_parts(): - self.assertTrue(is_resource(self.anchor02, *path_parts)) + assert is_resource(self.anchor02, *path_parts) def test_contents(self): with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)): c = resources.contents(self.anchor01) - self.assertGreaterEqual( - set(c), - {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'}, - ) - with self.assertRaises(OSError), warnings_helper.check_warnings(( - ".*contents.*", - DeprecationWarning, - )): + assert set(c) >= {'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'} + with ( + self.assertRaises(OSError), + warnings_helper.check_warnings(( + ".*contents.*", + DeprecationWarning, + )), + ): list(resources.contents(self.anchor01, 'utf-8.file')) for path_parts in self._gen_resourcetxt_path_parts(): - with self.assertRaises(OSError), warnings_helper.check_warnings(( - ".*contents.*", - DeprecationWarning, - )): + with ( + self.assertRaises((OSError, resources.abc.TraversalError)), + warnings_helper.check_warnings(( + ".*contents.*", + DeprecationWarning, + )), + ): list(resources.contents(self.anchor01, *path_parts)) with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)): c = resources.contents(self.anchor01, 'subdirectory') - self.assertGreaterEqual( - set(c), - {'binary.file'}, - ) + assert set(c) >= {'binary.file'} @warnings_helper.ignore_warnings(category=DeprecationWarning) def test_common_errors(self): @@ -233,17 +234,28 @@ def test_text_errors(self): ) -class FunctionalAPITest_StringAnchor( +class FunctionalAPITest_StringAnchor_Disk( StringAnchorMixin, FunctionalAPIBase, + util.DiskSetup, unittest.TestCase, ): pass -class FunctionalAPITest_ModuleAnchor( +class FunctionalAPITest_ModuleAnchor_Disk( ModuleAnchorMixin, FunctionalAPIBase, + util.DiskSetup, + unittest.TestCase, +): + pass + + +class FunctionalAPITest_StringAnchor_Memory( + StringAnchorMixin, + FunctionalAPIBase, + util.MemorySetup, unittest.TestCase, ): pass diff --git a/Lib/test/test_importlib/resources/test_open.py b/Lib/test/test_importlib/resources/test_open.py index 8c00378ad3c..950f71db05a 100644 --- a/Lib/test/test_importlib/resources/test_open.py +++ b/Lib/test/test_importlib/resources/test_open.py @@ -1,6 +1,6 @@ +import importlib.resources as resources import unittest -from importlib import resources from . import util @@ -23,19 +23,19 @@ def test_open_binary(self): target = resources.files(self.data) / 'binary.file' with target.open('rb') as fp: result = fp.read() - self.assertEqual(result, bytes(range(4))) + assert result == bytes(range(4)) def test_open_text_default_encoding(self): target = resources.files(self.data) / 'utf-8.file' with target.open(encoding='utf-8') as fp: result = fp.read() - self.assertEqual(result, 'Hello, UTF-8 world!\n') + assert result == 'Hello, UTF-8 world!\n' def test_open_text_given_encoding(self): target = resources.files(self.data) / 'utf-16.file' with target.open(encoding='utf-16', errors='strict') as fp: result = fp.read() - self.assertEqual(result, 'Hello, UTF-16 world!\n') + assert result == 'Hello, UTF-16 world!\n' def test_open_text_with_errors(self): """ @@ -46,11 +46,10 @@ def test_open_text_with_errors(self): self.assertRaises(UnicodeError, fp.read) with target.open(encoding='utf-8', errors='ignore') as fp: result = fp.read() - self.assertEqual( - result, + assert result == ( 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00' ) def test_open_binary_FileNotFoundError(self): diff --git a/Lib/test/test_importlib/resources/test_path.py b/Lib/test/test_importlib/resources/test_path.py index 903911f57b3..162344e5d83 100644 --- a/Lib/test/test_importlib/resources/test_path.py +++ b/Lib/test/test_importlib/resources/test_path.py @@ -1,8 +1,8 @@ +import importlib.resources as resources import io import pathlib import unittest -from importlib import resources from . import util @@ -19,9 +19,9 @@ def test_reading(self): """ target = resources.files(self.data) / 'utf-8.file' with resources.as_file(target) as path: - self.assertIsInstance(path, pathlib.Path) - self.assertEndsWith(path.name, "utf-8.file") - self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8')) + assert isinstance(path, pathlib.Path) + assert path.name.endswith("utf-8.file"), repr(path) + assert 'Hello, UTF-8 world!\n' == path.read_text(encoding='utf-8') class PathDiskTests(PathTests, util.DiskSetup, unittest.TestCase): diff --git a/Lib/test/test_importlib/resources/test_read.py b/Lib/test/test_importlib/resources/test_read.py index 59c237d9641..4085a64b0ee 100644 --- a/Lib/test/test_importlib/resources/test_read.py +++ b/Lib/test/test_importlib/resources/test_read.py @@ -1,6 +1,6 @@ +import importlib.resources as resources import unittest - -from importlib import import_module, resources +from importlib import import_module from . import util @@ -18,23 +18,25 @@ def execute(self, package, path): class ReadTests: def test_read_bytes(self): result = resources.files(self.data).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(4))) + assert result == bytes(range(4)) def test_read_text_default_encoding(self): result = ( - resources.files(self.data) + resources + .files(self.data) .joinpath('utf-8.file') .read_text(encoding='utf-8') ) - self.assertEqual(result, 'Hello, UTF-8 world!\n') + assert result == 'Hello, UTF-8 world!\n' def test_read_text_given_encoding(self): result = ( - resources.files(self.data) + resources + .files(self.data) .joinpath('utf-16.file') .read_text(encoding='utf-16') ) - self.assertEqual(result, 'Hello, UTF-16 world!\n') + assert result == 'Hello, UTF-16 world!\n' def test_read_text_with_errors(self): """ @@ -43,11 +45,10 @@ def test_read_text_with_errors(self): target = resources.files(self.data) / 'utf-16.file' self.assertRaises(UnicodeError, target.read_text, encoding='utf-8') result = target.read_text(encoding='utf-8', errors='ignore') - self.assertEqual( - result, + assert result == ( 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00' ) @@ -59,13 +60,13 @@ class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('data01.subdirectory') result = resources.files(submodule).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(4, 8))) + assert result == bytes(range(4, 8)) def test_read_submodule_resource_by_name(self): result = ( resources.files('data01.subdirectory').joinpath('binary.file').read_bytes() ) - self.assertEqual(result, bytes(range(4, 8))) + assert result == bytes(range(4, 8)) class ReadNamespaceTests(ReadTests, util.DiskSetup, unittest.TestCase): @@ -78,15 +79,16 @@ class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('namespacedata01.subdirectory') result = resources.files(submodule).joinpath('binary.file').read_bytes() - self.assertEqual(result, bytes(range(12, 16))) + assert result == bytes(range(12, 16)) def test_read_submodule_resource_by_name(self): result = ( - resources.files('namespacedata01.subdirectory') + resources + .files('namespacedata01.subdirectory') .joinpath('binary.file') .read_bytes() ) - self.assertEqual(result, bytes(range(12, 16))) + assert result == bytes(range(12, 16)) if __name__ == '__main__': diff --git a/Lib/test/test_importlib/resources/test_reader.py b/Lib/test/test_importlib/resources/test_reader.py index ed5693ab416..691a78bb060 100644 --- a/Lib/test/test_importlib/resources/test_reader.py +++ b/Lib/test/test_importlib/resources/test_reader.py @@ -1,9 +1,8 @@ import os.path import pathlib import unittest - from importlib import import_module -from importlib.readers import MultiplexedPath, NamespaceReader +from importlib.resources.readers import MultiplexedPath, NamespaceReader from . import util @@ -31,9 +30,7 @@ def test_iterdir(self): contents.remove('__pycache__') except (KeyError, ValueError): pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'} def test_iterdir_duplicate(self): contents = { @@ -44,16 +41,19 @@ def test_iterdir_duplicate(self): contents.remove(remove) except (KeyError, ValueError): pass - self.assertEqual( - contents, - {'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'}, - ) + assert contents == { + '__init__.py', + 'binary.file', + 'subdirectory', + 'utf-16.file', + 'utf-8.file', + } def test_is_dir(self): - self.assertEqual(MultiplexedPath(self.folder).is_dir(), True) + assert MultiplexedPath(self.folder).is_dir() def test_is_file(self): - self.assertEqual(MultiplexedPath(self.folder).is_file(), False) + assert not MultiplexedPath(self.folder).is_file() def test_open_file(self): path = MultiplexedPath(self.folder) @@ -67,19 +67,17 @@ def test_open_file(self): def test_join_path(self): prefix = str(self.folder.parent) path = MultiplexedPath(self.folder, self.data01) - self.assertEqual( - str(path.joinpath('binary.file'))[len(prefix) + 1 :], - os.path.join('namespacedata01', 'binary.file'), + assert str(path.joinpath('binary.file'))[len(prefix) + 1 :] == os.path.join( + 'namespacedata01', 'binary.file' ) sub = path.joinpath('subdirectory') assert isinstance(sub, MultiplexedPath) assert 'namespacedata01' in str(sub) assert 'data01' in str(sub) - self.assertEqual( - str(path.joinpath('imaginary'))[len(prefix) + 1 :], - os.path.join('namespacedata01', 'imaginary'), + assert str(path.joinpath('imaginary'))[len(prefix) + 1 :] == os.path.join( + 'namespacedata01', 'imaginary' ) - self.assertEqual(path.joinpath(), path) + assert path.joinpath() == path def test_join_path_compound(self): path = MultiplexedPath(self.folder) @@ -88,23 +86,16 @@ def test_join_path_compound(self): def test_join_path_common_subdir(self): prefix = str(self.data02.parent) path = MultiplexedPath(self.data01, self.data02) - self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath) - self.assertEqual( - str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :], - os.path.join('data02', 'subdirectory', 'subsubdir'), + assert isinstance(path.joinpath('subdirectory'), MultiplexedPath) + assert str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :] == ( + os.path.join('data02', 'subdirectory', 'subsubdir') ) def test_repr(self): - self.assertEqual( - repr(MultiplexedPath(self.folder)), - f"MultiplexedPath('{self.folder}')", - ) + assert repr(MultiplexedPath(self.folder)) == f"MultiplexedPath('{self.folder}')" def test_name(self): - self.assertEqual( - MultiplexedPath(self.folder).name, - os.path.basename(self.folder), - ) + assert MultiplexedPath(self.folder).name == os.path.basename(self.folder) class NamespaceReaderTest(util.DiskSetup, unittest.TestCase): @@ -119,18 +110,14 @@ def test_resource_path(self): reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) root = self.data.__path__[0] - self.assertEqual( - reader.resource_path('binary.file'), os.path.join(root, 'binary.file') - ) - self.assertEqual( - reader.resource_path('imaginary'), os.path.join(root, 'imaginary') - ) + assert reader.resource_path('binary.file') == os.path.join(root, 'binary.file') + assert reader.resource_path('imaginary') == os.path.join(root, 'imaginary') def test_files(self): reader = NamespaceReader(self.data.__spec__.submodule_search_locations) root = self.data.__path__[0] - self.assertIsInstance(reader.files(), MultiplexedPath) - self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')") + assert isinstance(reader.files(), MultiplexedPath) + assert repr(reader.files()) == f"MultiplexedPath('{root}')" if __name__ == '__main__': diff --git a/Lib/test/test_importlib/resources/test_resource.py b/Lib/test/test_importlib/resources/test_resource.py index fcede14b891..b114b1f0d80 100644 --- a/Lib/test/test_importlib/resources/test_resource.py +++ b/Lib/test/test_importlib/resources/test_resource.py @@ -1,7 +1,9 @@ +import importlib.resources as resources +import types import unittest +from importlib import import_module from . import util -from importlib import resources, import_module class ResourceTests: @@ -9,16 +11,16 @@ class ResourceTests: def test_is_file_exists(self): target = resources.files(self.data) / 'binary.file' - self.assertTrue(target.is_file()) + assert target.is_file() def test_is_file_missing(self): target = resources.files(self.data) / 'not-a-file' - self.assertFalse(target.is_file()) + assert not target.is_file() def test_is_dir(self): target = resources.files(self.data) / 'subdirectory' - self.assertFalse(target.is_file()) - self.assertTrue(target.is_dir()) + assert not target.is_file() + assert target.is_dir() class ResourceDiskTests(ResourceTests, util.DiskSetup, unittest.TestCase): @@ -38,7 +40,7 @@ def test_resource_contents(self): package = util.create_package( file=self.data, path=self.data.__file__, contents=['A', 'B', 'C'] ) - self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'}) + assert names(resources.files(package)) == {'A', 'B', 'C'} def test_is_file(self): package = util.create_package( @@ -46,7 +48,7 @@ def test_is_file(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertTrue(resources.files(package).joinpath('B').is_file()) + assert resources.files(package).joinpath('B').is_file() def test_is_dir(self): package = util.create_package( @@ -54,7 +56,7 @@ def test_is_dir(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertTrue(resources.files(package).joinpath('D').is_dir()) + assert resources.files(package).joinpath('D').is_dir() def test_resource_missing(self): package = util.create_package( @@ -62,7 +64,7 @@ def test_resource_missing(self): path=self.data.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'], ) - self.assertFalse(resources.files(package).joinpath('Z').is_file()) + assert not resources.files(package).joinpath('Z').is_file() class ResourceCornerCaseTests(util.DiskSetup, unittest.TestCase): @@ -82,30 +84,26 @@ def test_package_has_no_reader_fallback(self): module.__file__ = '/path/which/shall/not/be/named' module.__spec__.loader = module.__loader__ module.__spec__.origin = module.__file__ - self.assertFalse(resources.files(module).joinpath('A').is_file()) + assert not resources.files(module).joinpath('A').is_file() class ResourceFromZipsTest01(util.ZipSetup, unittest.TestCase): def test_is_submodule_resource(self): submodule = import_module('data01.subdirectory') - self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file()) + assert resources.files(submodule).joinpath('binary.file').is_file() def test_read_submodule_resource_by_name(self): - self.assertTrue( - resources.files('data01.subdirectory').joinpath('binary.file').is_file() - ) + assert resources.files('data01.subdirectory').joinpath('binary.file').is_file() def test_submodule_contents(self): submodule = import_module('data01.subdirectory') - self.assertEqual( - names(resources.files(submodule)), {'__init__.py', 'binary.file'} - ) + assert names(resources.files(submodule)) == {'__init__.py', 'binary.file'} def test_submodule_contents_by_name(self): - self.assertEqual( - names(resources.files('data01.subdirectory')), - {'__init__.py', 'binary.file'}, - ) + assert names(resources.files('data01.subdirectory')) == { + '__init__.py', + 'binary.file', + } def test_as_file_directory(self): with resources.as_file(resources.files('data01')) as data: @@ -124,14 +122,8 @@ def test_unrelated_contents(self): Test thata zip with two unrelated subpackages return distinct resources. Ref python/importlib_resources#44. """ - self.assertEqual( - names(resources.files('data02.one')), - {'__init__.py', 'resource1.txt'}, - ) - self.assertEqual( - names(resources.files('data02.two')), - {'__init__.py', 'resource2.txt'}, - ) + assert names(resources.files('data02.one')) == {'__init__.py', 'resource1.txt'} + assert names(resources.files('data02.two')) == {'__init__.py', 'resource2.txt'} class DeletingZipsTest(util.ZipSetup, unittest.TestCase): @@ -168,16 +160,15 @@ def test_read_text_does_not_keep_open(self): class ResourceFromNamespaceTests: def test_is_submodule_resource(self): - self.assertTrue( - resources.files(import_module('namespacedata01')) + assert ( + resources + .files(import_module('namespacedata01')) .joinpath('binary.file') .is_file() ) def test_read_submodule_resource_by_name(self): - self.assertTrue( - resources.files('namespacedata01').joinpath('binary.file').is_file() - ) + assert resources.files('namespacedata01').joinpath('binary.file').is_file() def test_submodule_contents(self): contents = names(resources.files(import_module('namespacedata01'))) @@ -185,9 +176,7 @@ def test_submodule_contents(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} def test_submodule_contents_by_name(self): contents = names(resources.files('namespacedata01')) @@ -195,9 +184,7 @@ def test_submodule_contents_by_name(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual( - contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} - ) + assert contents == {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'} def test_submodule_sub_contents(self): contents = names(resources.files(import_module('namespacedata01.subdirectory'))) @@ -205,7 +192,7 @@ def test_submodule_sub_contents(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual(contents, {'binary.file'}) + assert contents == {'binary.file'} def test_submodule_sub_contents_by_name(self): contents = names(resources.files('namespacedata01.subdirectory')) @@ -213,7 +200,7 @@ def test_submodule_sub_contents_by_name(self): contents.remove('__pycache__') except KeyError: pass - self.assertEqual(contents, {'binary.file'}) + assert contents == {'binary.file'} class ResourceFromNamespaceDiskTests( @@ -232,5 +219,24 @@ class ResourceFromNamespaceZipTests( MODULE = 'namespacedata01' +class MainModuleTests(unittest.TestCase): + def test_main_module_with_none_spec(self): + """ + __main__ module with no spec should raise TypeError (for clarity). + + See python/cpython#138531 for details. + """ + # construct a __main__ module with no __spec__. + mainmodule = types.ModuleType("__main__") + + assert mainmodule.__spec__ is None + + with self.assertRaises( + TypeError, + msg="Cannot access resources for '__main__' as it does not appear to correspond to an importable module (its __spec__ is None).", + ): + resources.files(mainmodule) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_importlib/resources/test_util.py b/Lib/test/test_importlib/resources/test_util.py new file mode 100644 index 00000000000..de304b6f351 --- /dev/null +++ b/Lib/test/test_importlib/resources/test_util.py @@ -0,0 +1,29 @@ +import unittest + +from .util import MemorySetup, Traversable + + +class TestMemoryTraversableImplementation(unittest.TestCase): + def test_concrete_methods_are_not_overridden(self): + """`MemoryTraversable` must not override `Traversable` concrete methods. + + This test is not an attempt to enforce a particular `Traversable` protocol; + it merely catches changes in the `Traversable` abstract/concrete methods + that have not been mirrored in the `MemoryTraversable` subclass. + """ + + traversable_concrete_methods = { + method + for method, value in Traversable.__dict__.items() + if callable(value) and method not in Traversable.__abstractmethods__ + } + memory_traversable_concrete_methods = { + method + for method, value in MemorySetup.MemoryTraversable.__dict__.items() + if callable(value) and not method.startswith("__") + } + overridden_methods = ( + memory_traversable_concrete_methods & traversable_concrete_methods + ) + + assert not overridden_methods diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py index e2d995f5963..85b5c61518d 100644 --- a/Lib/test/test_importlib/resources/util.py +++ b/Lib/test/test_importlib/resources/util.py @@ -1,18 +1,18 @@ import abc +import contextlib +import functools import importlib import io +import pathlib import sys import types -import pathlib -import contextlib - -from importlib.resources.abc import ResourceReader -from test.support import import_helper, os_helper -from . import zip as zip_ -from . import _path - - from importlib.machinery import ModuleSpec +from importlib.resources.abc import ResourceReader, Traversable, TraversableResources + +from test.support import import_helper, os_helper + +from . import _path +from . import zip as zip_ class Reader(ResourceReader): @@ -122,7 +122,7 @@ def test_missing_path(self): bytes_data = io.BytesIO(b'Hello, world!') package = create_package(file=bytes_data, path=FileNotFoundError()) self.execute(package, 'utf-8.file') - self.assertEqual(package.__loader__._path, 'utf-8.file') + assert package.__loader__._path == 'utf-8.file' def test_extant_path(self): # Attempting to open or read or request the path when the @@ -133,7 +133,7 @@ def test_extant_path(self): path = __file__ package = create_package(file=bytes_data, path=path) self.execute(package, 'utf-8.file') - self.assertEqual(package.__loader__._path, 'utf-8.file') + assert package.__loader__._path == 'utf-8.file' def test_useless_loader(self): package = create_package(file=FileNotFoundError(), path=FileNotFoundError()) @@ -202,5 +202,108 @@ def tree_on_path(self, spec): self.fixtures.enter_context(import_helper.DirsOnSysPath(temp_dir)) +class MemorySetup(ModuleSetup): + """Support loading a module in memory.""" + + MODULE = 'data01' + + def load_fixture(self, module): + self.fixtures.enter_context(self.augment_sys_metapath(module)) + return importlib.import_module(module) + + @contextlib.contextmanager + def augment_sys_metapath(self, module): + finder_instance = self.MemoryFinder(module) + sys.meta_path.append(finder_instance) + yield + sys.meta_path.remove(finder_instance) + + class MemoryFinder(importlib.abc.MetaPathFinder): + def __init__(self, module): + self._module = module + + def find_spec(self, fullname, path, target=None): + if fullname != self._module: + return None + + return importlib.machinery.ModuleSpec( + name=fullname, + loader=MemorySetup.MemoryLoader(self._module), + is_package=True, + ) + + class MemoryLoader(importlib.abc.Loader): + def __init__(self, module): + self._module = module + + def exec_module(self, module): + pass + + def get_resource_reader(self, fullname): + return MemorySetup.MemoryTraversableResources(self._module, fullname) + + class MemoryTraversableResources(TraversableResources): + def __init__(self, module, fullname): + self._module = module + self._fullname = fullname + + def files(self): + return MemorySetup.MemoryTraversable(self._module, self._fullname) + + class MemoryTraversable(Traversable): + """Implement only the abstract methods of `Traversable`. + + Besides `.__init__()`, no other methods may be implemented or overridden. + This is critical for validating the concrete `Traversable` implementations. + """ + + def __init__(self, module, fullname): + self._module = module + self._fullname = fullname + + def _resolve(self): + """ + Fully traverse the `fixtures` dictionary. + + This should be wrapped in a `try/except KeyError` + but it is not currently needed and lowers the code coverage numbers. + """ + path = pathlib.PurePosixPath(self._fullname) + return functools.reduce(lambda d, p: d[p], path.parts, fixtures) + + def iterdir(self): + directory = self._resolve() + if not isinstance(directory, dict): + # Filesystem openers raise OSError, and that exception is mirrored here. + raise OSError(f"{self._fullname} is not a directory") + for path in directory: + yield MemorySetup.MemoryTraversable( + self._module, f"{self._fullname}/{path}" + ) + + def is_dir(self) -> bool: + return isinstance(self._resolve(), dict) + + def is_file(self) -> bool: + return not self.is_dir() + + def open(self, mode='r', encoding=None, errors=None, *_, **__): + contents = self._resolve() + if isinstance(contents, dict): + # Filesystem openers raise OSError when attempting to open a directory, + # and that exception is mirrored here. + raise OSError(f"{self._fullname} is a directory") + if isinstance(contents, str): + contents = contents.encode("utf-8") + result = io.BytesIO(contents) + if "b" in mode: + return result + return io.TextIOWrapper(result, encoding=encoding, errors=errors) + + @property + def name(self): + return pathlib.PurePosixPath(self._fullname).name + + class CommonTests(DiskSetup, CommonTestsBase): pass diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py index ae09aa457b4..bb6da52727c 100644 --- a/Lib/test/test_interpreters/utils.py +++ b/Lib/test/test_interpreters/utils.py @@ -1,5 +1,6 @@ from collections import namedtuple import contextlib +import errno import json import logging import os @@ -51,7 +52,7 @@ def _close_file(file): else: os.close(file) except OSError as exc: - if exc.errno != 9: + if exc.errno != errno.EBADF: raise # re-raise # It was closed already. diff --git a/Lib/test/test_json/json_lines.jsonl b/Lib/test/test_json/json_lines.jsonl new file mode 100644 index 00000000000..d2f29211195 --- /dev/null +++ b/Lib/test/test_json/json_lines.jsonl @@ -0,0 +1,2 @@ +{"ingredients":["frog", "water", "chocolate", "glucose"]} +{"ingredients":["chocolate","steel bolts"]} diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py index 850e5ceeba0..5bc03085e60 100644 --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -77,6 +77,29 @@ def __lt__(self, o): d[1337] = "true.dat" self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}') + # gh-145244: UAF on borrowed key when default callback mutates dict + def test_default_clears_dict_key_uaf(self): + class Evil: + pass + + class AlsoEvil: + pass + + # Use a non-interned string key so it can actually be freed + key = "A" * 100 + target = {key: Evil()} + del key + + def evil_default(obj): + if isinstance(obj, Evil): + target.clear() + return AlsoEvil() + raise TypeError("not serializable") + + with self.assertRaises(TypeError): + self.json.dumps(target, default=evil_default, + check_circular=False) + def test_dumps_str_subclass(self): # Don't call obj.__str__() on str subclasses diff --git a/Lib/test/test_json/test_speedups.py b/Lib/test/test_json/test_speedups.py index 4c0aa5f993b..0b22a0bf4b9 100644 --- a/Lib/test/test_json/test_speedups.py +++ b/Lib/test/test_json/test_speedups.py @@ -1,4 +1,5 @@ from test.test_json import CTest +from test.support import gc_collect class BadBool: @@ -111,3 +112,63 @@ def test_current_indent_level(self): self.assertEqual(enc(['spam', {'ham': 'eggs'}], 3)[0], expected2) self.assertRaises(TypeError, enc, ['spam', {'ham': 'eggs'}], 3.0) self.assertRaises(TypeError, enc, ['spam', {'ham': 'eggs'}]) + + def test_mutate_dict_items_during_encode(self): + # gh-142831: Clearing the items list via a re-entrant key encoder + # must not cause a use-after-free. BadDict.items() returns a + # mutable list; encode_str clears it while iterating. + items = None + + class BadDict(dict): + def items(self): + nonlocal items + items = [("boom", object())] + return items + + cleared = False + def encode_str(obj): + nonlocal items, cleared + if items is not None: + items.clear() + items = None + cleared = True + gc_collect() + return '"x"' + + encoder = self.json.encoder.c_make_encoder( + None, lambda o: "null", + encode_str, None, + ": ", ", ", False, + False, True + ) + + # Must not crash (use-after-free under ASan before fix) + encoder(BadDict(real=1), 0) + self.assertTrue(cleared) + + def test_mutate_list_during_encode(self): + # gh-142831: Clearing a list mid-iteration via the default + # callback must not cause a use-after-free. + call_count = 0 + lst = [object() for _ in range(10)] + + def default(obj): + nonlocal call_count + call_count += 1 + if call_count == 3: + lst.clear() + gc_collect() + return None + + encoder = self.json.encoder.c_make_encoder( + None, default, + self.json.encoder.c_encode_basestring, None, + ": ", ", ", False, + False, True + ) + + # Must not crash (use-after-free under ASan before fix) + encoder(lst, 0) + # Verify the mutation path was actually hit and the loop + # stopped iterating after the list was cleared. + self.assertEqual(call_count, 3) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 7b5d217a215..0a96b318b15 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -1,4 +1,5 @@ import errno +import pathlib import os import sys import textwrap @@ -157,6 +158,14 @@ def test_jsonlines(self): self.assertEqual(process.stdout, self.jsonlines_expect) self.assertEqual(process.stderr, '') + @force_not_colorized + def test_jsonlines_from_file(self): + jsonl = pathlib.Path(__file__).parent / 'json_lines.jsonl' + args = sys.executable, '-m', self.module, '--json-lines', jsonl + process = subprocess.run(args, capture_output=True, text=True, check=True) + self.assertEqual(process.stdout, self.jsonlines_expect) + self.assertEqual(process.stderr, '') + def test_help_flag(self): rc, out, err = assert_python_ok('-m', self.module, '-h', PYTHON_COLORS='0') diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index 78db4219e29..9c4d91c456d 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -317,6 +317,138 @@ def test_recursion_limit(self): last.append([0]) self.assertRaises(ValueError, marshal.dumps, head) + def test_reference_loop_list(self): + a = [] + a.append(a) + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, list) + self.assertIs(b[0], b) + + def test_reference_loop_dict(self): + a = {} + a[None] = a + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, dict) + self.assertIs(b[None], b) + + def test_reference_loop_tuple(self): + a = ([],) + a[0].append(a) + for v in range(3): + self.assertRaises(ValueError, marshal.dumps, a, v) + for v in range(3, marshal.version + 1): + d = marshal.dumps(a, v) + b = marshal.loads(d) + self.assertIsInstance(b, tuple) + self.assertIsInstance(b[0], list) + self.assertIs(b[0][0], b) + + def test_reference_loop_code(self): + def f(): + return 1234.5 + code = f.__code__ + a = [] + code = code.replace(co_consts=code.co_consts + (a,)) + # This test creates a reference loop which leads to reference leaks, + # so we need to break the loop manually. See gh-148722. + self.addCleanup(a.clear) + a.append(code) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, code, v) + + def test_reference_loop_slice(self): + a = slice([], None) + a.start.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + a = slice(None, []) + a.stop.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + a = slice(None, None, []) + a.step.append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + def test_reference_loop_frozendict(self): + a = frozendict({None: []}) + a[None].append(a) + for v in range(marshal.version + 1): + self.assertRaises(ValueError, marshal.dumps, a, v) + + def test_loads_reference_loop_list(self): + data = b'\xdb\x01\x00\x00\x00r\x00\x00\x00\x00' # [] + a = marshal.loads(data) + self.assertIsInstance(a, list) + self.assertIs(a[0], a) + + def test_loads_reference_loop_dict(self): + data = b'\xfbNr\x00\x00\x00\x000' # {None: } + a = marshal.loads(data) + self.assertIsInstance(a, dict) + self.assertIs(a[None], a) + + def test_loads_abnormal_reference_loops(self): + # Indirect self-references of tuples. + data = b'\xa8\x01\x00\x00\x00[\x01\x00\x00\x00r\x00\x00\x00\x00' # ([],) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIsInstance(a[0], list) + self.assertIs(a[0][0], a) + + data = b'\xa8\x01\x00\x00\x00{Nr\x00\x00\x00\x000' # ({None: },) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIsInstance(a[0], dict) + self.assertIs(a[0][None], a) + + # Direct self-reference which cannot be created in Python. + # This creates a reference loop which cannot be collected. + if False: + data = b'\xa8\x01\x00\x00\x00r\x00\x00\x00\x00' # (,) + a = marshal.loads(data) + self.assertIsInstance(a, tuple) + self.assertIs(a[0], a) + + # Direct self-references which cannot be created in Python + # because of unhashability. + data = b'\xfbr\x00\x00\x00\x00N0' # {: None} + self.assertRaises(TypeError, marshal.loads, data) + data = b'\xbc\x01\x00\x00\x00r\x00\x00\x00\x00' # {} + self.assertRaises(TypeError, marshal.loads, data) + + for data in [ + # Indirect self-references of immutable objects. + b'\xba[\x01\x00\x00\x00r\x00\x00\x00\x00NN', # slice([], None) + b'\xbaN[\x01\x00\x00\x00r\x00\x00\x00\x00N', # slice(None, []) + b'\xbaNN[\x01\x00\x00\x00r\x00\x00\x00\x00', # slice(None, None, []) + b'\xba{Nr\x00\x00\x00\x000NN', # slice({None: }, None) + b'\xbaN{Nr\x00\x00\x00\x000N', # slice(None, {None: }) + b'\xbaNN{Nr\x00\x00\x00\x000', # slice(None, None, {None: }) + b'\xfdN[\x01\x00\x00\x00r\x00\x00\x00\x000', # frozendict({None: []}) + b'\xfdN{Nr\x00\x00\x00\x0000', # frozendict({None: {None: }) + + # Direct self-references which cannot be created in Python. + b'\xbe\x01\x00\x00\x00r\x00\x00\x00\x00', # frozenset({}) + b'\xfdNr\x00\x00\x00\x000', # frozendict({None: }) + b'\xfdr\x00\x00\x00\x00N0', # frozendict({: None}) + b'\xbar\x00\x00\x00\x00NN', # slice(, None) + b'\xbaNr\x00\x00\x00\x00N', # slice(None, ) + b'\xbaNNr\x00\x00\x00\x00', # slice(None, None, ) + ]: + with self.subTest(data=data): + self.assertRaises(ValueError, marshal.loads, data) + def test_exact_type_match(self): # Former bug: # >>> class Int(int): pass diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 22b9f6af758..820574584b5 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -648,6 +648,28 @@ def check_equal(view, is_equal): m = memoryview(data).cast(complex_format) check_equal(m, True) + def test_boolean_format(self): + # Test '?' format (keep all the checks below for UBSan) + # See github.com/python/cpython/issues/148390. + + # m1a and m1b are equivalent to [False, True, False] + m1a = memoryview(b'\0\2\0').cast('?') + self.assertEqual(m1a.tolist(), [False, True, False]) + m1b = memoryview(b'\0\4\0').cast('?') + self.assertEqual(m1b.tolist(), [False, True, False]) + self.assertEqual(m1a, m1b) + + # m2a and m2b are equivalent to [True, True, True] + m2a = memoryview(b'\1\3\5').cast('?') + self.assertEqual(m2a.tolist(), [True, True, True]) + m2b = memoryview(b'\2\4\6').cast('?') + self.assertEqual(m2b.tolist(), [True, True, True]) + self.assertEqual(m2a, m2b) + + allbytes = bytes(range(256)) + allbytes = memoryview(allbytes).cast('?') + self.assertEqual(allbytes.tolist(), [False] + [True] * 255) + class BytesMemorySliceTest(unittest.TestCase, BaseMemorySliceTests, BaseBytesMemoryTests): diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 116a8bac6fb..b8861d09e15 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -196,13 +196,10 @@ def test_c_return_count(self): (E.BRANCH, "branch"), ] -EXCEPT_EVENTS = [ +SIMPLE_EVENTS = INSTRUMENTED_EVENTS + [ (E.RAISE, "raise"), - (E.PY_UNWIND, "unwind"), (E.EXCEPTION_HANDLED, "exception_handled"), -] - -SIMPLE_EVENTS = INSTRUMENTED_EVENTS + EXCEPT_EVENTS + [ + (E.PY_UNWIND, "unwind"), (E.C_RAISE, "c_raise"), (E.C_RETURN, "c_return"), ] @@ -738,18 +735,6 @@ def test_disable_legal_events(self): sys.monitoring.register_callback(TEST_TOOL, event, None) - def test_disable_illegal_events(self): - for event, name in EXCEPT_EVENTS: - try: - counter = CounterWithDisable() - counter.disable = True - sys.monitoring.register_callback(TEST_TOOL, event, counter) - sys.monitoring.set_events(TEST_TOOL, event) - with self.assertRaises(ValueError): - self.raise_handle_reraise() - finally: - sys.monitoring.set_events(TEST_TOOL, 0) - sys.monitoring.register_callback(TEST_TOOL, event, None) class ExceptionRecorder: @@ -1481,8 +1466,334 @@ def func3(): ('line', 'func3', 6)]) def test_set_non_local_event(self): + # C_RETURN/C_RAISE are ancillary (derived) events — not settable as local with self.assertRaises(ValueError): - sys.monitoring.set_local_events(TEST_TOOL, just_call.__code__, E.RAISE) + sys.monitoring.set_local_events(TEST_TOOL, just_call.__code__, E.C_RETURN) + + def test_local_reraise(self): + """RERAISE fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + events = set() + + def callback(code, offset, exc): + events.add(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RERAISE) + try: + foo() + except RuntimeError: + pass + try: + bar() # should NOT trigger the callback + except RuntimeError: + pass + self.assertEqual(events, {'foo'}) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, None) + + def test_local_reraise_disable(self): + """Returning DISABLE from a RERAISE callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + raise + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RERAISE) + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RERAISE, None) + + def test_local_py_throw(self): + """PY_THROW fires as a local event only for the instrumented code object.""" + + def gen_foo(): + yield 1 + yield 2 + + def gen_bar(): + yield 1 + yield 2 + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, callback) + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, E.PY_THROW) + + g = gen_foo() + next(g) + try: + g.throw(RuntimeError("test")) + except RuntimeError: + pass + + h = gen_bar() + next(h) + try: + h.throw(RuntimeError("test")) # should NOT trigger the callback + except RuntimeError: + pass + + self.assertEqual(events, ['gen_foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, None) + + def test_local_py_throw_disable(self): + """Returning DISABLE from a PY_THROW callback disables it for that code object.""" + + call_count = 0 + + def gen_foo(): + yield 1 + yield 2 + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, callback) + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, E.PY_THROW) + + g = gen_foo() + next(g) + try: + g.throw(RuntimeError("test")) + except RuntimeError: + pass + self.assertEqual(call_count, 1) + + g2 = gen_foo() + next(g2) + try: + g2.throw(RuntimeError("test")) + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, gen_foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_THROW, None) + + def test_local_raise(self): + """RAISE fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RAISE) + foo() + bar() # should NOT trigger the callback + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, None) + + def test_local_raise_disable(self): + """Returning DISABLE from a RAISE callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.RAISE) + foo() + self.assertEqual(call_count, 1) + foo() + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.RAISE, None) + + def test_local_exception_handled(self): + """EXCEPTION_HANDLED fires as a local event only for the instrumented code object.""" + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def bar(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.EXCEPTION_HANDLED) + foo() + bar() # should NOT trigger the callback + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, None) + + def test_local_exception_handled_disable(self): + """Returning DISABLE from an EXCEPTION_HANDLED callback disables it for that code object.""" + + call_count = 0 + + def foo(): + try: + raise RuntimeError("test") + except RuntimeError: + pass + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.EXCEPTION_HANDLED) + foo() + self.assertEqual(call_count, 1) + foo() + self.assertEqual(call_count, 1) # not fired again — disabled + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.EXCEPTION_HANDLED, None) + + def test_local_py_unwind(self): + """PY_UNWIND fires as a local event only for the instrumented code object.""" + + def foo(): + raise RuntimeError("test") + + def bar(): + raise RuntimeError("test") + + events = [] + + def callback(code, offset, exc): + events.append(code.co_name) + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.PY_UNWIND) + + try: + foo() + except RuntimeError: + pass + + try: + bar() # should NOT trigger the callback + except RuntimeError: + pass + + self.assertEqual(events, ['foo']) + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, None) + + def test_local_py_unwind_disable(self): + """Returning DISABLE from a PY_UNWIND callback disables it for that code object.""" + + call_count = 0 + + def foo(): + raise RuntimeError("test") + + def callback(code, offset, exc): + nonlocal call_count + call_count += 1 + return sys.monitoring.DISABLE + + try: + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, callback) + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, E.PY_UNWIND) + + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # fired once + + try: + foo() + except RuntimeError: + pass + self.assertEqual(call_count, 1) # not fired again — disabled by DISABLE return + + finally: + sys.monitoring.set_local_events(TEST_TOOL, foo.__code__, 0) + sys.monitoring.register_callback(TEST_TOOL, E.PY_UNWIND, None) def line_from_offset(code, offset): for start, end, line in code.co_lines(): @@ -1612,11 +1923,11 @@ def whilefunc(n=0): ('branch right', 'whilefunc', 1, 3)]) self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [ - ('branch left', 'func', 30, 34), - ('branch right', 'func', 46, 60), - ('branch left', 'func', 30, 34), - ('branch left', 'func', 46, 52), - ('branch right', 'func', 30, 72)]) + ('branch left', 'func', 32, 36), + ('branch right', 'func', 48, 62), + ('branch left', 'func', 32, 36), + ('branch left', 'func', 48, 54), + ('branch right', 'func', 32, 74)]) def test_except_star(self): diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 5f40ad1d7a0..f5f408fcb4b 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1423,6 +1423,21 @@ def binary_op_add_extend(): self.assert_specialized(binary_op_add_extend, "BINARY_OP_EXTEND") self.assert_no_opcode(binary_op_add_extend, "BINARY_OP") + def binary_op_add_extend_sequences(): + l1 = [1, 2] + l2 = [None] + t1 = (1, 2) + t2 = (None,) + for _ in range(100): + list_sum = l1 + l2 + self.assertEqual(list_sum, [1, 2, None]) + tuple_sum = t1 + t2 + self.assertEqual(tuple_sum, (1, 2, None)) + + binary_op_add_extend_sequences() + self.assert_specialized(binary_op_add_extend_sequences, "BINARY_OP_EXTEND") + self.assert_no_opcode(binary_op_add_extend_sequences, "BINARY_OP") + def binary_op_zero_division(): def compactlong_lhs(arg): 42 / arg @@ -1964,6 +1979,15 @@ def for_iter_tuple(): self.assert_specialized(for_iter_tuple, "FOR_ITER_TUPLE") self.assert_no_opcode(for_iter_tuple, "FOR_ITER") + s = "abcdefghij" + def for_iter_str(): + for i in s: + self.assertIn(i, s) + + for_iter_str() + self.assert_specialized(for_iter_str, "FOR_ITER_VIRTUAL") + self.assert_no_opcode(for_iter_str, "FOR_ITER") + r = range(10) def for_iter_range(): for i in r: @@ -1981,6 +2005,30 @@ def for_iter_generator(): self.assert_specialized(for_iter_generator, "FOR_ITER_GEN") self.assert_no_opcode(for_iter_generator, "FOR_ITER") + @cpython_only + @requires_specialization + def test_get_iter(self): + L = list(range(10)) + def get_iter_list(): + n = 10 + while n: + n -= 1 + for i in L: + break + get_iter_list() + self.assert_specialized(get_iter_list, "GET_ITER_VIRTUAL") + self.assert_no_opcode(get_iter_list, "GET_ITER") + + def get_iter_gen(): + n = 10 + while n: + n -= 1 + for i in (i for i in range(10)): + break + get_iter_gen() + self.assert_specialized(get_iter_gen, "GET_ITER_SELF") + self.assert_no_opcode(get_iter_gen, "GET_ITER") + @cpython_only @requires_specialization def test_call_list_append(self): diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index 5d0857b059e..29cce4ee6d2 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -2762,6 +2762,96 @@ def test_patma_255(self): self.assertEqual(y, 1) self.assertIs(z, x) + def test_patma_256(self): + x = 0 + match x: + case +0: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_257(self): + x = 0 + match x: + case +0.0: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_258(self): + x = 0 + match x: + case +0j: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_259(self): + x = 0 + match x: + case +0.0j: + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) + + def test_patma_260(self): + x = 1 + match x: + case +1: + y = 0 + self.assertEqual(x, 1) + self.assertEqual(y, 0) + + def test_patma_261(self): + x = 1.5 + match x: + case +1.5: + y = 0 + self.assertEqual(x, 1.5) + self.assertEqual(y, 0) + + def test_patma_262(self): + x = 1j + match x: + case +1j: + y = 0 + self.assertEqual(x, 1j) + self.assertEqual(y, 0) + + def test_patma_263(self): + x = 1.5j + match x: + case +1.5j: + y = 0 + self.assertEqual(x, 1.5j) + self.assertEqual(y, 0) + + def test_patma_264(self): + x = 0.25 + 1.75j + match x: + case +0.25 + 1.75j: + y = 0 + self.assertEqual(x, 0.25 + 1.75j) + self.assertEqual(y, 0) + + def test_patma_265(self): + x = 0.25 - 1.75j + match x: + case 0.25 - +1.75j: + y = 0 + self.assertEqual(x, 0.25 - 1.75j) + self.assertEqual(y, 0) + + def test_patma_266(self): + x = 0 + match x: + case +1e1000: + y = 0 + case 0: + y = 1 + self.assertEqual(x, 0) + self.assertEqual(y, 1) + def test_patma_runtime_checkable_protocol(self): # Runtime-checkable protocol from typing import Protocol, runtime_checkable diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index e0cc010f155..abb071451d8 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -1,3 +1,4 @@ +import ast import dis import gc from itertools import combinations, product @@ -1131,6 +1132,53 @@ def f(self): class DirectCfgOptimizerTests(CfgOptimizationTestCase): + def test_optimize_cfg_const_index_out_of_range(self): + insts = [ + ('LOAD_CONST', 2, 0), + ('RETURN_VALUE', None, 0), + ] + seq = self.seq_from_insts(insts) + with self.assertRaisesRegex(ValueError, "out of range"): + _testinternalcapi.optimize_cfg(seq, [0, 1], 0) + + def test_optimize_cfg_consts_must_be_list(self): + insts = [ + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + seq = self.seq_from_insts(insts) + with self.assertRaisesRegex(TypeError, "consts must be a list"): + _testinternalcapi.optimize_cfg(seq, (0,), 0) + + def test_compiler_codegen_metadata_consts_roundtrips_optimize_cfg(self): + tree = ast.parse("x = (1, 2)", mode="exec", optimize=1) + insts, meta = _testinternalcapi.compiler_codegen(tree, "", 0) + consts = meta["consts"] + self.assertIsInstance(consts, list) + _testinternalcapi.optimize_cfg(insts, consts, 0) + + def test_compiler_codegen_consts_include_none_required_for_implicit_return(self): + # Module "pass" only needs the const table entry for None once + # _PyCodegen_AddReturnAtEnd runs. If metadata["consts"] were taken + # before that, the list would not match LOAD_CONST opargs (here: 0 + # for None), and optimize_cfg would read out of range. + tree = ast.parse("pass", mode="exec", optimize=1) + insts, meta = _testinternalcapi.compiler_codegen(tree, "", 0) + consts = meta["consts"] + self.assertEqual(consts, [None]) + + load_const = opcode.opmap["LOAD_CONST"] + self.assertEqual( + [t[1] for t in insts.get_instructions() if t[0] == load_const], + [0], + ) + + # As if consts were snapshotted before AddReturnAtEnd: still LOAD_CONST 0, no row. + with self.assertRaisesRegex(ValueError, "out of range"): + _testinternalcapi.optimize_cfg(insts, [], 0) + + _testinternalcapi.optimize_cfg(insts, list(consts), 0) + def cfg_optimization_test(self, insts, expected_insts, consts=None, expected_consts=None, nlocals=0): diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 45e081c233f..041c2072b9e 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -1515,6 +1515,86 @@ def test_user_string(self): 'jumped over a ' 'lazy dog'}""") + def test_template(self): + d = t"" + self.assertEqual(pprint.pformat(d), + "Template(strings=('',), interpolations=())") + self.assertEqual(pprint.pformat(d), repr(d)) + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('',), + interpolations=())""") + name = "World" + d = t"Hello {name}" + self.assertEqual(pprint.pformat(d), +"""\ +Template(strings=('Hello ', ''), + interpolations=(Interpolation('World', 'name', None, ''),))""") + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('Hello ', + '!'), + interpolations=(Interpolation({'name': 'Python', + 'version': {3.13: False, + 3.14: True}}, + ' ' + '{"name": ' + '"Python", ' + '"version": ' + 'ver}', + 's', + 'z'),))""") + + def test_expand_template(self): + d = t"" + self.assertEqual( + pprint.pformat(d, expand=True), + "Template(strings=('',), interpolations=())", + ) + name = "World" + d = t"Hello {name}" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', ''), + interpolations=( + Interpolation( + value='World', + expression='name', + conversion=None, + format_spec='', + ), + ), +)""", + ) + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', '!'), + interpolations=( + Interpolation( + value={ + 'name': 'Python', + 'version': { + 3.13: False, + 3.14: True, + }, + }, + expression=' {"name": "Python", ' + '"version": ver}', + conversion='s', + format_spec='z', + ), + ), +)""", + ) + def test_expand_dataclass(self): @dataclasses.dataclass class DummyDataclass: diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index cace780f79f..aaa91aca36e 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -510,6 +510,34 @@ def _test_exception(self, have_source): self.assertIn('call_with_frame("StartElement"', entries[1].line) + def test_invalid_NotStandalone(self): + parser = expat.ParserCreate() + parser.NotStandaloneHandler = mock.Mock(return_value="bad value") + parser.ElementDeclHandler = lambda _1, _2: None + + payload = b"""\ +]> +""" + with self.assertRaises(TypeError) as cm: + parser.Parse(payload, True) + parser.NotStandaloneHandler.assert_called_once() + + notes = ["invalid 'NotStandalone' event handler return value"] + self.assertEqual(cm.exception.__notes__, notes) + + def test_invalid_ExternalEntityRefHandler(self): + parser = expat.ParserCreate() + parser.UseForeignDTD() + parser.SetParamEntityParsing(expat.XML_PARAM_ENTITY_PARSING_ALWAYS) + parser.ExternalEntityRefHandler = mock.Mock(return_value=None) + + with self.assertRaises(TypeError) as cm: + parser.Parse(b"", True) + parser.ExternalEntityRefHandler.assert_called_once() + + notes = ["invalid 'ExternalEntityRef' event handler return value"] + self.assertEqual(cm.exception.__notes__, notes) + # Test Current* members: class PositionTest(unittest.TestCase): diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 0946289328c..02f6e0c74b5 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -2230,10 +2230,7 @@ def test_unload_tests(self): self.check_executed_tests(output, tests, stats=3) def check_add_python_opts(self, option): - # --fast-ci and --slow-ci add "-u -W default -bb -E" options to Python - - # Skip test if _testinternalcapi is missing - import_helper.import_module('_testinternalcapi') + # --fast-ci and --slow-ci add "-u -W error -bb -E" options to Python code = textwrap.dedent(r""" import sys @@ -2248,25 +2245,26 @@ def check_add_python_opts(self, option): use_environment = (support.is_emscripten or support.is_wasi) class WorkerTests(unittest.TestCase): - @unittest.skipUnless(config_get is None, 'need config_get()') + @unittest.skipIf(config_get is None, 'need config_get()') def test_config(self): - config = config_get() # -u option self.assertEqual(config_get('buffered_stdio'), 0) - # -W default option - self.assertTrue(config_get('warnoptions'), ['default']) + # -W error option + self.assertEqual(config_get('warnoptions'), + ['error', 'error::BytesWarning']) # -bb option - self.assertTrue(config_get('bytes_warning'), 2) + self.assertEqual(config_get('bytes_warning'), 2) # -E option - self.assertTrue(config_get('use_environment'), use_environment) + self.assertEqual(config_get('use_environment'), use_environment) def test_python_opts(self): # -u option self.assertTrue(sys.__stdout__.write_through) self.assertTrue(sys.__stderr__.write_through) - # -W default option - self.assertTrue(sys.warnoptions, ['default']) + # -W error option + self.assertEqual(sys.warnoptions, + ['error', 'error::BytesWarning']) # -bb option self.assertEqual(sys.flags.bytes_warning, 2) diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 27cd125078e..850cb66a89b 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -5,6 +5,7 @@ import subprocess import sys import unittest +from contextlib import contextmanager from functools import partial from textwrap import dedent from test import support @@ -67,6 +68,19 @@ def spawn_repl(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, custom=F spawn_asyncio_repl = partial(spawn_repl, "-m", "asyncio", custom=True) +@contextmanager +def temp_pythonstartup(*, source: str, histfile: str = ".pythonhist"): + """Create environment variables for a PYTHONSTARTUP script in a temporary directory.""" + with os_helper.temp_dir() as tmpdir: + filename = os.path.join(tmpdir, "pythonstartup.py") + with open(filename, "w") as f: + f.write(source) + yield { + "PYTHONSTARTUP": filename, + "PYTHON_HISTORY": os.path.join(tmpdir, histfile) + } + + def run_on_interactive_mode(source): """Spawn a new Python interpreter, pass the given input source code from the stdin and return the @@ -276,8 +290,6 @@ def make_repl(env): """) % script self.assertIn(expected, output) - - def test_runsource_show_syntax_error_location(self): user_input = dedent("""def f(x, x): ... """) @@ -449,6 +461,33 @@ def test_quiet_mode(self): self.assertEqual(p.returncode, 0) self.assertEqual(output[:3], ">>>") + @support.force_not_colorized + @support.subTests( + ("startup_code", "expected_error"), + [ + ("some invalid syntax\n", "SyntaxError: invalid syntax"), + ("1/0\n", "ZeroDivisionError: division by zero"), + ], + ) + def test_pythonstartup_failure(self, startup_code, expected_error): + startup_env = self.enterContext( + temp_pythonstartup(source=startup_code, histfile=".asyncio_history")) + + p = spawn_repl( + "-qm", "asyncio", + env=os.environ | startup_env, + isolated=False, + custom=True) + p.stdin.write("print('user code', 'executed')\n") + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + tb_hint = f'File "{startup_env["PYTHONSTARTUP"]}", line 1' + self.assertIn(tb_hint, output) + self.assertIn(expected_error, output) + + self.assertIn("user code executed", output) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index cd90e332443..92ff5131a58 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4674,7 +4674,9 @@ def cb_raising(ssl_sock, server_name, initial_context): sni_name='supermessage') # Allow for flexible libssl error messages. - regex = "(SSLV3_ALERT_HANDSHAKE_FAILURE|NO_PRIVATE_VALUE)" + regex = ("(TLS_ALERT_HANDSHAKE_FAILURE" + "|SSLV3_ALERT_HANDSHAKE_FAILURE" + "|NO_PRIVATE_VALUE)") self.assertRegex(cm.exception.reason, regex) self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError) @@ -5566,15 +5568,20 @@ def non_linux_skip_if_other_okay_error(self, err): return # Expect the full test setup to always work on Linux. if (isinstance(err, ConnectionResetError) or (isinstance(err, OSError) and err.errno == errno.EINVAL) or - re.search('wrong.version.number', str(getattr(err, "reason", "")), re.I)): + re.search('wrong.version.number', str(getattr(err, "reason", "")), re.I) or + re.search('record.layer.failure', str(getattr(err, "reason", "")), re.I) + ): # On Windows the TCP RST leads to a ConnectionResetError # (ECONNRESET) which Linux doesn't appear to surface to userspace. # If wrap_socket() winds up on the "if connected:" path and doing - # the actual wrapping... we get an SSLError from OpenSSL. Typically - # WRONG_VERSION_NUMBER. While appropriate, neither is the scenario - # we're specifically trying to test. The way this test is written - # is known to work on Linux. We'll skip it anywhere else that it - # does not present as doing so. + # the actual wrapping... we get an SSLError from OpenSSL. This is + # typically WRONG_VERSION_NUMBER. The same happens on iOS, but + # RECORD_LAYER_FAILURE is the error. + # + # While appropriate, neither is the scenario we're specifically + # trying to test. The way this test is written is known to work on + # Linux. We'll skip it anywhere else that it does not present as + # doing so. try: self.skipTest(f"Could not recreate conditions on {sys.platform}:" f" {err=}") diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index dfc8ef6d2c5..5ac28870455 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -8,7 +8,6 @@ import platform import sys from test import support -from test.support import warnings_helper from test.support import skip_if_buggy_ucrt_strfptime, run_with_locales from datetime import date as datetime_date @@ -639,15 +638,11 @@ def test_escaping(self): need_escaping = r".^$*+?{}\[]|)(" self.assertTrue(_strptime._strptime_time(need_escaping, need_escaping)) - @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-70647 def test_feb29_on_leap_year_without_year(self): - time.strptime("Feb 29", "%b %d") - - @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-70647 - def test_mar1_comes_after_feb29_even_when_omitting_the_year(self): - self.assertLess( - time.strptime("Feb 29", "%b %d"), - time.strptime("Mar 1", "%b %d")) + with self.assertRaises(ValueError): + time.strptime("Feb 29", "%b %d") + with self.assertRaises(ValueError): + time.strptime("Mar 1", "%b %d") def test_strptime_F_format(self): test_date = "2025-10-26" diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 0c567961184..3237a9cb498 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -22,6 +22,7 @@ import sysconfig import select import shutil +import socket import threading import gc import textwrap @@ -1044,19 +1045,49 @@ def test_communicate_timeout_large_input(self): # On Windows, stdin writing must also honor the timeout rather than # blocking indefinitely when the pipe buffer fills. - # Input larger than typical pipe buffer (4-64KB on Windows) - input_data = b"x" * (128 * 1024) + input_data = b"x" * (128 * 1024) # > typical pipe buffer + + # Cross-platform wake mechanism: the slow reader connects to a + # loopback TCP socket and blocks in select() on it (capped at 9s + # as a safety net we don't expect to hit). After phase 1 raises + # TimeoutExpired, the parent sends a byte to release the child so + # it drains stdin. A socket (rather than a raw pipe) is required + # because Windows select() only supports sockets, not arbitrary + # file descriptors. + server = socket.create_server(('127.0.0.1', 0), backlog=1) + server.settimeout(10) # bound the accept() if the child fails to start + port = server.getsockname()[1] + # The child sends one byte (low byte of its PID) first so the parent + # can detect the rare case of an unrelated process on the same host + # connecting to our ephemeral port before our child does. A single + # byte gives 1/256 collision odds, which is plenty for flake-prevention. + slow_reader = ( + "import os, socket, sys, select; " + f"s = socket.create_connection(('127.0.0.1', {port}), timeout=9); " + "s.sendall(bytes([os.getpid() & 0xff])); " + "select.select([s], [], [], 9); " + "sys.stdout.buffer.write(sys.stdin.buffer.read())" + ) p = subprocess.Popen( - [sys.executable, "-c", - "import sys, time; " - "time.sleep(30); " # Don't read stdin for a long time - "sys.stdout.buffer.write(sys.stdin.buffer.read())"], + [sys.executable, "-c", slow_reader], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + conn = None try: + conn, _ = server.accept() + server.close() + server = None + + conn.settimeout(5) + peer_byte = conn.recv(1) + conn.settimeout(None) + self.assertEqual(peer_byte, bytes([p.pid & 0xff]), + f"loopback handshake byte {peer_byte!r} != " + f"low byte of child PID {p.pid} ({p.pid & 0xff:#x})") + timeout = 0.2 start = time.monotonic() try: @@ -1065,7 +1096,7 @@ def test_communicate_timeout_large_input(self): elapsed = time.monotonic() - start self.fail( f"TimeoutExpired not raised. communicate() completed in " - f"{elapsed:.2f}s, but subprocess sleeps for 30s. " + f"{elapsed:.2f}s, but slow reader stalls for up to 9s. " "Stdin writing blocked without enforcing timeout.") except subprocess.TimeoutExpired: elapsed = time.monotonic() - start @@ -1073,11 +1104,16 @@ def test_communicate_timeout_large_input(self): # Timeout should occur close to the specified timeout value, # not after waiting for the subprocess to finish sleeping. # Allow generous margin for slow CI, but must be well under - # the subprocess sleep time. + # the slow-reader's stall cap. self.assertLess(elapsed, 5.0, f"TimeoutExpired raised after {elapsed:.2f}s; expected ~{timeout}s. " "Stdin writing blocked without checking timeout.") + # Release the slow reader so it stops blocking and drains stdin. + conn.sendall(b'go') + conn.close() + conn = None + # After timeout, continue communication. The remaining input # should be sent and we should receive all data back. stdout, stderr = p.communicate() @@ -1087,6 +1123,10 @@ def test_communicate_timeout_large_input(self): f"Expected {len(input_data)} bytes output but got {len(stdout)}") self.assertEqual(stdout, input_data) finally: + if conn is not None: + conn.close() + if server is not None: + server.close() p.kill() p.wait() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index a729efee18c..34a773ee937 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1798,7 +1798,7 @@ def delx(self): del self.__x check((1,2,3), vsize('') + self.P + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn12PIPc' + fmt = 'P2nPI13Pl4Pn9Pn12PI2Pc' s = vsize(fmt) check(int, s) typeid = 'n' if support.Py_GIL_DISABLED else '' diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index be8f6b05765..1850f053aaf 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -358,11 +358,11 @@ def test_strptime(self): # Should be able to go round-trip from strftime to strptime without # raising an exception. tt = time.gmtime(self.t) - for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'D', 'F', 'H', 'I', + for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'D', 'e', 'F', 'H', 'I', 'j', 'm', 'M', 'n', 'p', 'S', 't', 'T', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = '%' + directive - if directive == 'd': + if directive in ('d', 'e'): format += ',%Y' # Avoid GH-70647. strf_output = time.strftime(format, tt) try: @@ -387,10 +387,13 @@ def test_strptime_exception_context(self): self.assertTrue(e.exception.__suppress_context__) def test_strptime_leap_year(self): - # GH-70647: warns if parsing a format with a day and no year. + # GH-70647: %d errors if parsing a format with a day and no year. + with self.assertRaises(ValueError): + time.strptime('02-07 18:28', '%m-%d %H:%M') + # %e without a year is deprecated, scheduled for removal in 3.17. with self.assertWarnsRegex(DeprecationWarning, r'.*day of month without a year.*'): - time.strptime('02-07 18:28', '%m-%d %H:%M') + time.strptime('02-07 18:28', '%m-%e %H:%M') def test_asctime(self): time.asctime(time.gmtime(self.t)) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index ca67e381958..ab53a20cff5 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -3326,6 +3326,7 @@ def test_newline_at_the_end_of_buffer(self): run_test_script(file_name) +@support.force_not_colorized_test_class class CommandLineTest(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py index d40eb382c53..d459f497e33 100644 --- a/Lib/test/test_type_annotations.py +++ b/Lib/test/test_type_annotations.py @@ -836,6 +836,23 @@ def test_complex_comprehension_inlining_exec(self): lamb = list(genexp)[0] self.assertEqual(lamb(), 42) + def test_annotate_qualname(self): + code = """ + def f() -> None: + def nested() -> None: pass + return nested + class Outer: + x: int + def method(self, x: int): + pass + """ + ns = run_code(code) + method = ns["Outer"].method + self.assertEqual(method.__annotate__.__qualname__, "Outer.method.__annotate__") + self.assertEqual(ns["f"].__annotate__.__qualname__, "f.__annotate__") + self.assertEqual(ns["f"]().__annotate__.__qualname__, "f..nested.__annotate__") + self.assertEqual(ns["Outer"].__annotate__.__qualname__, "Outer.__annotate__") + # gh-138349 def test_module_level_annotation_plus_listcomp(self): cases = [ diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index c6f08ff8a05..6c3d67fb6b7 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -29,7 +29,7 @@ from typing import assert_type, cast, runtime_checkable from typing import get_type_hints from typing import get_origin, get_args, get_protocol_members -from typing import override +from typing import override, disjoint_base from typing import is_typeddict, is_protocol from typing import reveal_type from typing import dataclass_transform @@ -780,7 +780,7 @@ def test_typevartuple_none(self): self.assertIs(U_None.__default__, None) self.assertIs(U_None.has_default(), True) - class X[**Ts]: ... + class X[*Ts]: ... Ts, = X.__type_params__ self.assertIs(Ts.__default__, NoDefault) self.assertIs(Ts.has_default(), False) @@ -1288,6 +1288,57 @@ def test_cannot_call_instance(self): with self.assertRaises(TypeError): Ts() + def test_default_variance(self): + Ts = TypeVarTuple('Ts') + self.assertIs(Ts.__covariant__, False) + self.assertIs(Ts.__contravariant__, False) + self.assertIs(Ts.__infer_variance__, False) + self.assertIsNone(Ts.__bound__) + + def test_covariant(self): + Ts_co = TypeVarTuple('Ts_co', covariant=True) + self.assertIs(Ts_co.__covariant__, True) + self.assertIs(Ts_co.__contravariant__, False) + self.assertIs(Ts_co.__infer_variance__, False) + + def test_contravariant(self): + Ts_contra = TypeVarTuple('Ts_contra', contravariant=True) + self.assertIs(Ts_contra.__covariant__, False) + self.assertIs(Ts_contra.__contravariant__, True) + self.assertIs(Ts_contra.__infer_variance__, False) + + def test_infer_variance(self): + Ts = TypeVarTuple('Ts', infer_variance=True) + self.assertIs(Ts.__covariant__, False) + self.assertIs(Ts.__contravariant__, False) + self.assertIs(Ts.__infer_variance__, True) + + def test_bound(self): + Ts_bound = TypeVarTuple('Ts_bound', bound=int) + self.assertIs(Ts_bound.__bound__, int) + Ts_no_bound = TypeVarTuple('Ts_no_bound') + self.assertIsNone(Ts_no_bound.__bound__) + + def test_no_bivariant(self): + with self.assertRaises(ValueError): + TypeVarTuple('Ts', covariant=True, contravariant=True) + + def test_cannot_combine_explicit_and_infer(self): + with self.assertRaises(ValueError): + TypeVarTuple('Ts', covariant=True, infer_variance=True) + with self.assertRaises(ValueError): + TypeVarTuple('Ts', contravariant=True, infer_variance=True) + + def test_repr_with_variance(self): + Ts = TypeVarTuple('Ts') + self.assertEqual(repr(Ts), '~Ts') + Ts_co = TypeVarTuple('Ts_co', covariant=True) + self.assertEqual(repr(Ts_co), '+Ts_co') + Ts_contra = TypeVarTuple('Ts_contra', contravariant=True) + self.assertEqual(repr(Ts_contra), '-Ts_contra') + Ts_infer = TypeVarTuple('Ts_infer', infer_variance=True) + self.assertEqual(repr(Ts_infer), 'Ts_infer') + def test_unpacked_typevartuple_is_equal_to_itself(self): Ts = TypeVarTuple('Ts') self.assertEqual((*Ts,)[0], (*Ts,)[0]) @@ -1427,16 +1478,16 @@ def test_repr_is_correct(self): class G1(Generic[*Ts]): pass class G2(Generic[Unpack[Ts]]): pass - self.assertEqual(repr(Ts), 'Ts') + self.assertEqual(repr(Ts), '~Ts') - self.assertEqual(repr((*Ts,)[0]), 'typing.Unpack[Ts]') - self.assertEqual(repr(Unpack[Ts]), 'typing.Unpack[Ts]') + self.assertEqual(repr((*Ts,)[0]), 'typing.Unpack[~Ts]') + self.assertEqual(repr(Unpack[Ts]), 'typing.Unpack[~Ts]') - self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[Ts]]') - self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[typing.Unpack[Ts]]') + self.assertEqual(repr(tuple[*Ts]), 'tuple[typing.Unpack[~Ts]]') + self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[typing.Unpack[~Ts]]') - self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[Ts]]') - self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), 'typing.Unpack[typing.Tuple[typing.Unpack[Ts]]]') + self.assertEqual(repr(*tuple[*Ts]), '*tuple[typing.Unpack[~Ts]]') + self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), 'typing.Unpack[typing.Tuple[typing.Unpack[~Ts]]]') def test_variadic_class_repr_is_correct(self): Ts = TypeVarTuple('Ts') @@ -1475,61 +1526,61 @@ def test_variadic_class_alias_repr_is_correct(self): class A(Generic[Unpack[Ts]]): pass B = A[*Ts] - self.assertEndsWith(repr(B), 'A[typing.Unpack[Ts]]') + self.assertEndsWith(repr(B), 'A[typing.Unpack[~Ts]]') self.assertEndsWith(repr(B[()]), 'A[()]') self.assertEndsWith(repr(B[float]), 'A[float]') self.assertEndsWith(repr(B[float, str]), 'A[float, str]') C = A[Unpack[Ts]] - self.assertEndsWith(repr(C), 'A[typing.Unpack[Ts]]') + self.assertEndsWith(repr(C), 'A[typing.Unpack[~Ts]]') self.assertEndsWith(repr(C[()]), 'A[()]') self.assertEndsWith(repr(C[float]), 'A[float]') self.assertEndsWith(repr(C[float, str]), 'A[float, str]') D = A[*Ts, int] - self.assertEndsWith(repr(D), 'A[typing.Unpack[Ts], int]') + self.assertEndsWith(repr(D), 'A[typing.Unpack[~Ts], int]') self.assertEndsWith(repr(D[()]), 'A[int]') self.assertEndsWith(repr(D[float]), 'A[float, int]') self.assertEndsWith(repr(D[float, str]), 'A[float, str, int]') E = A[Unpack[Ts], int] - self.assertEndsWith(repr(E), 'A[typing.Unpack[Ts], int]') + self.assertEndsWith(repr(E), 'A[typing.Unpack[~Ts], int]') self.assertEndsWith(repr(E[()]), 'A[int]') self.assertEndsWith(repr(E[float]), 'A[float, int]') self.assertEndsWith(repr(E[float, str]), 'A[float, str, int]') F = A[int, *Ts] - self.assertEndsWith(repr(F), 'A[int, typing.Unpack[Ts]]') + self.assertEndsWith(repr(F), 'A[int, typing.Unpack[~Ts]]') self.assertEndsWith(repr(F[()]), 'A[int]') self.assertEndsWith(repr(F[float]), 'A[int, float]') self.assertEndsWith(repr(F[float, str]), 'A[int, float, str]') G = A[int, Unpack[Ts]] - self.assertEndsWith(repr(G), 'A[int, typing.Unpack[Ts]]') + self.assertEndsWith(repr(G), 'A[int, typing.Unpack[~Ts]]') self.assertEndsWith(repr(G[()]), 'A[int]') self.assertEndsWith(repr(G[float]), 'A[int, float]') self.assertEndsWith(repr(G[float, str]), 'A[int, float, str]') H = A[int, *Ts, str] - self.assertEndsWith(repr(H), 'A[int, typing.Unpack[Ts], str]') + self.assertEndsWith(repr(H), 'A[int, typing.Unpack[~Ts], str]') self.assertEndsWith(repr(H[()]), 'A[int, str]') self.assertEndsWith(repr(H[float]), 'A[int, float, str]') self.assertEndsWith(repr(H[float, str]), 'A[int, float, str, str]') I = A[int, Unpack[Ts], str] - self.assertEndsWith(repr(I), 'A[int, typing.Unpack[Ts], str]') + self.assertEndsWith(repr(I), 'A[int, typing.Unpack[~Ts], str]') self.assertEndsWith(repr(I[()]), 'A[int, str]') self.assertEndsWith(repr(I[float]), 'A[int, float, str]') self.assertEndsWith(repr(I[float, str]), 'A[int, float, str, str]') J = A[*Ts, *tuple[str, ...]] - self.assertEndsWith(repr(J), 'A[typing.Unpack[Ts], *tuple[str, ...]]') + self.assertEndsWith(repr(J), 'A[typing.Unpack[~Ts], *tuple[str, ...]]') self.assertEndsWith(repr(J[()]), 'A[*tuple[str, ...]]') self.assertEndsWith(repr(J[float]), 'A[float, *tuple[str, ...]]') self.assertEndsWith(repr(J[float, str]), 'A[float, str, *tuple[str, ...]]') K = A[Unpack[Ts], Unpack[Tuple[str, ...]]] - self.assertEndsWith(repr(K), 'A[typing.Unpack[Ts], typing.Unpack[typing.Tuple[str, ...]]]') + self.assertEndsWith(repr(K), 'A[typing.Unpack[~Ts], typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[()]), 'A[typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[float]), 'A[float, typing.Unpack[typing.Tuple[str, ...]]]') self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]') @@ -1550,9 +1601,9 @@ class G(type(Unpack[Ts])): pass with self.assertRaisesRegex(TypeError, r'Cannot subclass typing\.Unpack'): class H(Unpack): pass - with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): + with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[~Ts\]'): class I(*Ts): pass - with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[Ts\]'): + with self.assertRaisesRegex(TypeError, r'Cannot subclass typing.Unpack\[~Ts\]'): class J(Unpack[Ts]): pass def test_variadic_class_args_are_correct(self): @@ -5596,13 +5647,13 @@ class TsP(Generic[*Ts, P]): MyCallable[[int], bool]: "MyCallable[[int], bool]", MyCallable[[int, str], bool]: "MyCallable[[int, str], bool]", MyCallable[[int, list[int]], bool]: "MyCallable[[int, list[int]], bool]", - MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[typing.Unpack[Ts], ~P], ~T]", + MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[typing.Unpack[~Ts], ~P], ~T]", DoubleSpec[P2, P, T]: "DoubleSpec[~P2, ~P, ~T]", DoubleSpec[[int], [str], bool]: "DoubleSpec[[int], [str], bool]", DoubleSpec[[int, int], [str, str], bool]: "DoubleSpec[[int, int], [str, str], bool]", - TsP[*Ts, P]: "TsP[typing.Unpack[Ts], ~P]", + TsP[*Ts, P]: "TsP[typing.Unpack[~Ts], ~P]", TsP[int, str, list[int], []]: "TsP[int, str, list[int], []]", TsP[int, [str, list[int]]]: "TsP[int, [str, list[int]]]", @@ -6837,6 +6888,24 @@ def test_get_type_hints_wrapped_decoratored_func(self): self.assertEqual(gth(ForRefExample.func), expects) self.assertEqual(gth(ForRefExample.nested), expects) + def test_get_type_hints_wrapped_cycle_self(self): + # gh-146553: __wrapped__ self-reference must raise ValueError, + # not loop forever. + def f(x: int) -> str: ... + f.__wrapped__ = f + with self.assertRaisesRegex(ValueError, 'wrapper loop'): + get_type_hints(f) + + def test_get_type_hints_wrapped_cycle_mutual(self): + # gh-146553: mutual __wrapped__ cycle (a -> b -> a) must raise + # ValueError, not loop forever. + def a(): ... + def b(): ... + a.__wrapped__ = b + b.__wrapped__ = a + with self.assertRaisesRegex(ValueError, 'wrapper loop'): + get_type_hints(a) + def test_get_type_hints_annotated(self): def foobar(x: List['X']): ... X = Annotated[int, (1, 10)] @@ -7269,6 +7338,13 @@ class TD[UniqueT](TypedDict): self.assertEqual(TD.__annotations__, {'a': EqualToForwardRef('UniqueT', owner=TD, module=TD.__module__)}) self.assertEqual(get_type_hints(TD), {'a': TD.__type_params__[0]}) + def test_get_type_hints_order(self): + """Ensure that the order of function annotations matches the order they're defined""" + def f(positional: int, /, normal: str, *args: bytes, kwarg: list, **kwargs: bool) -> tuple: + pass + + self.assertEqual(list(gth(f)), ["positional", "normal", "args", "kwarg", "kwargs", "return"]) + class GetUtilitiesTestCase(TestCase): def test_get_origin(self): @@ -10913,6 +10989,18 @@ def bar(self): self.assertNotIn('__magic__', dir_items) +class DisjointBaseTests(BaseTestCase): + def test_disjoint_base_unmodified(self): + class C: ... + self.assertIs(C, disjoint_base(C)) + + def test_dunder_disjoint_base(self): + @disjoint_base + class C: ... + + self.assertIs(C.__disjoint_base__, True) + + class RevealTypeTests(BaseTestCase): def test_reveal_type(self): obj = object() diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 86886ac768f..d3723c04820 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -430,6 +430,30 @@ def test_setframerate_rounds(self, arg, expected): f.setframerate(arg) self.assertEqual(f.getframerate(), expected) + def test_write_odd_data_chunk_pads_and_updates_riff_size(self): + # gh-117716: odd-sized data chunks must be padded with one zero byte. + with io.BytesIO() as output: + with wave.open(output, mode='wb') as w: + w.setnchannels(1) + w.setsampwidth(1) + w.setframerate(48000) + w.writeframes(b'\x80') + + value = output.getvalue() + + self.assertEqual(value[-1], 0) + self.assertEqual( + int.from_bytes(value[4:8], byteorder='little'), + 38, + ) + + with wave.open(io.BytesIO(value), mode='rb') as r: + self.assertEqual(r.getnchannels(), 1) + self.assertEqual(r.getsampwidth(), 1) + self.assertEqual(r.getframerate(), 48000) + self.assertEqual(r.getnframes(), 1) + self.assertEqual(r.readframes(-1), b'\x80') + class WaveOpen(unittest.TestCase): def test_open_pathlike(self): diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 299dc185fcf..2ba3af8d5bf 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -119,6 +119,15 @@ def test_open_bad_new_parameter(self): arguments=[URL], kw=dict(new=999)) + def test_reject_action_dash_prefixes(self): + browser = self.browser_class(name=CMD_NAME) + with self.assertRaises(ValueError): + browser.open('%action--incognito') + # new=1: action is "--new-window", so "%action" itself expands to + # a dash-prefixed flag even with no dash in the original URL. + with self.assertRaises(ValueError): + browser.open('%action', new=1) + class EdgeCommandTest(CommandTestMixin, unittest.TestCase): diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index b380d0276b0..43864820688 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -3190,6 +3190,19 @@ def __deepcopy__(self, memo): self.assertEqual([c.tag for c in children[3:]], [a.tag, b.tag, a.tag, b.tag]) + @support.skip_if_unlimited_stack_size + @support.skip_emscripten_stack_overflow() + @support.skip_wasi_stack_overflow() + def test_deeply_nested_deepcopy(self): + # This should raise a RecursionError and not crash. + # See https://github.com/python/cpython/issues/148801. + root = cur = ET.Element('s') + for _ in range(150_000): + cur = ET.SubElement(cur, 'u') + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + copy.deepcopy(root) + class MutationDeleteElementPath(str): def __new__(cls, elem, *args): @@ -3258,6 +3271,16 @@ def test_findtext_with_mutating(self): e.extend([ET.Element('bar')]) e.findtext(cls(e, 'x')) + def test_findtext_with_mutating_non_none_text(self): + for cls in [MutationDeleteElementPath, MutationClearElementPath]: + with self.subTest(cls): + e = ET.Element('foo') + child = ET.Element('bar') + child.text = str(object()) + e.append(child) + del child + repr(e.findtext(cls(e, 'x'))) + def test_findtext_with_error(self): e = ET.Element('foo') e.extend([ET.Element('bar')]) diff --git a/Lib/tokenize.py b/Lib/tokenize.py index 11c134482db..52cf3f0b7cc 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -35,6 +35,7 @@ from token import * from token import EXACT_TOKEN_TYPES import _tokenize +lazy import _colorize cookie_re = re.compile(br'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII) blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) @@ -505,6 +506,56 @@ def generate_tokens(readline): """ return _generate_tokens_from_c_tokenizer(readline, extra_tokens=True) + +def _get_token_colors(syntax, tokenize): + """Map token type numbers to theme colors.""" + return frozendict({ + COMMENT: syntax.comment, + DEDENT: tokenize.whitespace, + ENCODING: tokenize.whitespace, + ENDMARKER: tokenize.whitespace, + ERRORTOKEN: tokenize.error, + FSTRING_START: syntax.string, + FSTRING_MIDDLE: syntax.string, + FSTRING_END: syntax.string, + INDENT: tokenize.whitespace, + NAME: syntax.reset, + NEWLINE: tokenize.whitespace, + NL: tokenize.whitespace, + NUMBER: syntax.number, + OP: syntax.op, + SOFT_KEYWORD: syntax.soft_keyword, + STRING: syntax.string, + TSTRING_START: syntax.string, + TSTRING_MIDDLE: syntax.string, + TSTRING_END: syntax.string, + }) + + +def _format_tokens(tokens, *, color=False, exact=False): + theme = _colorize.get_theme(force_no_color=not color) + s = theme.syntax + t = theme.tokenize + token_colors = _get_token_colors(s, t) + for token in tokens: + token_range = ( + f"{t.position}{token.start[0]}" + f"{t.delimiter},{t.position}{token.start[1]}" + f"{t.delimiter}-" + f"{t.position}{token.end[0]}" + f"{t.delimiter},{t.position}{token.end[1]}" + f"{t.delimiter}:" + ) + token_color = token_colors.get(token.type, s.reset) + token_name = tok_name[token.exact_type if exact else token.type] + visible_range = f"{token.start[0]},{token.start[1]}-{token.end[0]},{token.end[1]}:" + yield ( + f"{token_range}{' ' * (20 - len(visible_range))}" + f"{token_color}{token_name:<15}" + f"{s.reset}{token.string!r:<15}" + ) + + def _main(args=None): import argparse @@ -524,7 +575,7 @@ def error(message, filename=None, location=None): sys.exit(1) # Parse the arguments and options - parser = argparse.ArgumentParser(color=True) + parser = argparse.ArgumentParser() parser.add_argument(dest='filename', nargs='?', metavar='filename.py', help='the file to tokenize; defaults to stdin') @@ -545,13 +596,8 @@ def error(message, filename=None, location=None): # Output the tokenization - for token in tokens: - token_type = token.type - if args.exact: - token_type = token.exact_type - token_range = "%d,%d-%d,%d:" % (token.start + token.end) - print("%-20s%-15s%-15r" % - (token_range, tok_name[token_type], token.string)) + for line in _format_tokens(tokens, color=True, exact=args.exact): + print(line) except IndentationError as err: line, column = err.args[1][1:3] error(err.args[0], filename, (line, column)) diff --git a/Lib/typing.py b/Lib/typing.py index e78fb8b71a9..46e7122b6c9 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -126,6 +126,7 @@ 'cast', 'clear_overloads', 'dataclass_transform', + 'disjoint_base', 'evaluate_forward_ref', 'final', 'get_args', @@ -2485,8 +2486,12 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False, else: nsobj = obj # Find globalns for the unwrapped object. + seen = {id(nsobj)} while hasattr(nsobj, '__wrapped__'): nsobj = nsobj.__wrapped__ + if id(nsobj) in seen: + raise ValueError(f'wrapper loop when unwrapping {obj!r}') + seen.add(id(nsobj)) globalns = getattr(nsobj, '__globals__', {}) if localns is None: localns = globalns @@ -2794,6 +2799,29 @@ class Other(Leaf): # Error reported by type checker return f +def disjoint_base(cls): + """This decorator marks a class as a disjoint base. + + Child classes of a disjoint base cannot inherit from other disjoint bases that are + not parent or child classes of the disjoint base. + + For example: + + @disjoint_base + class Disjoint1: pass + + @disjoint_base + class Disjoint2: pass + + class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error + + Type checkers can use knowledge of disjoint bases to detect unreachable code + and determine when two types can overlap. + """ + cls.__disjoint_base__ = True + return cls + + # Some unconstrained type variables. These were initially used by the container types. # They were never meant for export and are now unused, but we keep them around to # avoid breaking compatibility with users who import them. @@ -3588,7 +3616,7 @@ def isatty(self) -> bool: pass @abstractmethod - def read(self, n: int = -1) -> AnyStr: + def read(self, n: int = -1, /) -> AnyStr: pass @abstractmethod @@ -3596,15 +3624,15 @@ def readable(self) -> bool: pass @abstractmethod - def readline(self, limit: int = -1) -> AnyStr: + def readline(self, limit: int = -1, /) -> AnyStr: pass @abstractmethod - def readlines(self, hint: int = -1) -> list[AnyStr]: + def readlines(self, hint: int = -1, /) -> list[AnyStr]: pass @abstractmethod - def seek(self, offset: int, whence: int = 0) -> int: + def seek(self, offset: int, whence: int = 0, /) -> int: pass @abstractmethod @@ -3616,7 +3644,7 @@ def tell(self) -> int: pass @abstractmethod - def truncate(self, size: int | None = None) -> int: + def truncate(self, size: int | None = None, /) -> int: pass @abstractmethod @@ -3624,11 +3652,11 @@ def writable(self) -> bool: pass @abstractmethod - def write(self, s: AnyStr) -> int: + def write(self, s: AnyStr, /) -> int: pass @abstractmethod - def writelines(self, lines: list[AnyStr]) -> None: + def writelines(self, lines: list[AnyStr], /) -> None: pass @abstractmethod @@ -3636,7 +3664,7 @@ def __enter__(self) -> IO[AnyStr]: pass @abstractmethod - def __exit__(self, type, value, traceback) -> None: + def __exit__(self, type, value, traceback, /) -> None: pass @@ -3646,7 +3674,7 @@ class BinaryIO(IO[bytes]): __slots__ = () @abstractmethod - def write(self, s: bytes | bytearray) -> int: + def write(self, s: bytes | bytearray, /) -> int: pass @abstractmethod diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index 35533e4b551..06f4753d73b 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -1,34 +1,32 @@ -@echo off - -rem This file is UTF-8 encoded, so we need to update the current code page while executing it -for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( - set _OLD_CODEPAGE=%%a +@rem This file is UTF-8 encoded, so we need to update the current code page while executing it +@for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do @( + @set _OLD_CODEPAGE=%%a ) -if defined _OLD_CODEPAGE ( - "%SystemRoot%\System32\chcp.com" 65001 > nul +@if defined _OLD_CODEPAGE ( + @"%SystemRoot%\System32\chcp.com" 65001 > nul ) -set "VIRTUAL_ENV=__VENV_DIR__" +@set "VIRTUAL_ENV=__VENV_DIR__" -if not defined PROMPT set PROMPT=$P$G +@if not defined PROMPT @set PROMPT=$P$G -if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% -if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% +@if defined _OLD_VIRTUAL_PROMPT @set PROMPT=%_OLD_VIRTUAL_PROMPT% +@if defined _OLD_VIRTUAL_PYTHONHOME @set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% -set "_OLD_VIRTUAL_PROMPT=%PROMPT%" -set "PROMPT=(__VENV_PROMPT__) %PROMPT%" +@set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +@set "PROMPT=(__VENV_PROMPT__) %PROMPT%" -if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% -set PYTHONHOME= +@if defined PYTHONHOME @set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +@set PYTHONHOME= -if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% -if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% +@if defined _OLD_VIRTUAL_PATH @set PATH=%_OLD_VIRTUAL_PATH% +@if not defined _OLD_VIRTUAL_PATH @set _OLD_VIRTUAL_PATH=%PATH% -set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" -set "VIRTUAL_ENV_PROMPT=__VENV_PROMPT__" +@set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" +@set "VIRTUAL_ENV_PROMPT=__VENV_PROMPT__" :END -if defined _OLD_CODEPAGE ( - "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul - set _OLD_CODEPAGE= +@if defined _OLD_CODEPAGE ( + @"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + @set _OLD_CODEPAGE= ) diff --git a/Lib/venv/scripts/nt/deactivate.bat b/Lib/venv/scripts/nt/deactivate.bat index 62a39a7584f..4a04fb7c0be 100644 --- a/Lib/venv/scripts/nt/deactivate.bat +++ b/Lib/venv/scripts/nt/deactivate.bat @@ -1,22 +1,20 @@ -@echo off - -if defined _OLD_VIRTUAL_PROMPT ( - set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +@if defined _OLD_VIRTUAL_PROMPT ( + @set "PROMPT=%_OLD_VIRTUAL_PROMPT%" ) -set _OLD_VIRTUAL_PROMPT= +@set _OLD_VIRTUAL_PROMPT= -if defined _OLD_VIRTUAL_PYTHONHOME ( - set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" - set _OLD_VIRTUAL_PYTHONHOME= +@if defined _OLD_VIRTUAL_PYTHONHOME ( + @set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + @set _OLD_VIRTUAL_PYTHONHOME= ) -if defined _OLD_VIRTUAL_PATH ( - set "PATH=%_OLD_VIRTUAL_PATH%" +@if defined _OLD_VIRTUAL_PATH ( + @set "PATH=%_OLD_VIRTUAL_PATH%" ) -set _OLD_VIRTUAL_PATH= +@set _OLD_VIRTUAL_PATH= -set VIRTUAL_ENV= -set VIRTUAL_ENV_PROMPT= +@set VIRTUAL_ENV= +@set VIRTUAL_ENV_PROMPT= :END diff --git a/Lib/wave.py b/Lib/wave.py index 6e84c107b9f..c4e1a493a7e 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -611,6 +611,8 @@ def close(self): try: if self._file: self._ensure_header_written(0) + if self._datawritten & 1: + self._file.write(b'\x00') if self._datalength != self._datawritten: self._patchheader() self._file.flush() @@ -651,7 +653,7 @@ def _write_header(self, initlength): has_fact = self._needs_fact_chunk() header_overhead = 36 + (12 if has_fact else 0) self._file.write(struct.pack(' Python calls into specialized opcodes which the replacement interpreter loop can choose to respect and perform inlined dispatch. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst new file mode 100644 index 00000000000..4a04658551c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-23-11-34-37.gh-issue-142186.v8Yp3W.rst @@ -0,0 +1,3 @@ +Global :mod:`sys.monitoring` events can now be turned on and disabled on a +per code object basis. Returning ``DISABLE`` from a callback disables the +event for the entire code object (for the current tool). diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst new file mode 100644 index 00000000000..c819a830f8b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-25-12-00-00.gh-issue-146306.B9f62e.rst @@ -0,0 +1,2 @@ +Specialize float true division in the tier 2 optimizer with inplace +mutation for uniquely-referenced operands. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst new file mode 100644 index 00000000000..4d7537f2529 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-08-49-35.gh-issue-146455.f54083a9.rst @@ -0,0 +1 @@ +Fix O(N²) compile-time regression in constant folding after it was moved from AST to CFG optimizer. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst new file mode 100644 index 00000000000..b8ae19f5877 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-21-44.gh-issue-148208.JAxpDU.rst @@ -0,0 +1 @@ +Fix recursion depth leak in :c:func:`PyObject_Print` diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst new file mode 100644 index 00000000000..2c273fc4dab --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-07-20-37-23.gh-issue-148222.uF4D4E.rst @@ -0,0 +1 @@ +Fix vectorcall support in :class:`types.GenericAlias` when the underlying type does not support the vectorcall protocol. Fix possible leaks in :class:`types.GenericAlias` and :class:`types.UnionType` in case of memory error. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst new file mode 100644 index 00000000000..0a7ba0b27d9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-15-12-53.gh-issue-148398.g62jCA.rst @@ -0,0 +1 @@ +Fix a bug in the JIT optimizer where class attribute loads were not invalidated after type mutation. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst new file mode 100644 index 00000000000..33c4b75bfb9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-11-17-28-52.gh-issue-148393.lX6gwN.rst @@ -0,0 +1,2 @@ +Fix data races between :c:func:`PyDict_Watch` / :c:func:`PyDict_Unwatch` +and concurrent dict mutation in the :term:`free-threaded build`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst new file mode 100644 index 00000000000..88196467330 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-12-17-27-28.gh-issue-148390.MAhw7F.rst @@ -0,0 +1,5 @@ +Fix an undefined behavior in :class:`memoryview` when using the native +boolean format (``?``) in :meth:`~memoryview.cast`. Previously, on some +common platforms, calling ``memoryview(b).cast("?").tolist()`` incorrectly +returned ``[False]`` instead of ``[True]`` for any even byte *b*. +Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst new file mode 100644 index 00000000000..53d91c8198f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-16-52-33.gh-issue-148515.09xulC.rst @@ -0,0 +1,2 @@ +Fix a bug in the JIT optimizer reading operands for uops with multiple +caches. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst new file mode 100644 index 00000000000..282b9917664 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-13-23-21-45.gh-issue-145239.pL8qRt.rst @@ -0,0 +1,3 @@ +Unary plus is now accepted in :keyword:`match` literal patterns, mirroring +the existing support for unary minus. +Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst new file mode 100644 index 00000000000..d3242235c60 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-20-37-02.gh-issue-148653.nbbHMh.rst @@ -0,0 +1,2 @@ +Forbid :mod:`marshalling ` recursive code objects, :class:`slice` +and :class:`frozendict` objects which cannot be correctly unmarshalled. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst new file mode 100644 index 00000000000..392becaffb7 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-14-36-44.gh-issue-148820.XhOGhA.rst @@ -0,0 +1,5 @@ +Fix a race in :c:type:`!_PyRawMutex` on the free-threaded build where a +``Py_PARK_INTR`` return from ``_PySemaphore_Wait`` could let the waiter +destroy its semaphore before the unlocking thread's +``_PySemaphore_Wakeup`` completed, causing a fatal ``ReleaseSemaphore`` +error. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst new file mode 100644 index 00000000000..54c04bbc28d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-22-14-55-18.gh-issue-113956.0VEXd6.rst @@ -0,0 +1,4 @@ +Fix a data race in :func:`sys.intern` in the free-threaded build when +interning a string owned by another thread. An interned copy owned by the +current thread is used instead when it is not safe to immortalize the +original. diff --git a/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst b/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst new file mode 100644 index 00000000000..0fbe5a699ef --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-04-17-02-28-55.gh-issue-148663.MHIbRB.rst @@ -0,0 +1,2 @@ +Document that :class:`calendar.IllegalMonthError` is a subclass of both +:exc:`ValueError` and :exc:`IndexError` since Python 3.12. diff --git a/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst b/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst new file mode 100644 index 00000000000..e8e181cac21 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2021-10-03-21-55-34.gh-issue-89520.etEExa.rst @@ -0,0 +1,3 @@ +Make IDLE extension configuration look at user config files, allowing +user-installed extensions to have settings and key bindings defined in +~/.idlerc. diff --git a/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst b/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst new file mode 100644 index 00000000000..5ea1dfc9b51 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2025-10-05-19-33-39.gh-issue-139551.TX9BRc.rst @@ -0,0 +1 @@ +Support rendering :exc:`BaseExceptionGroup` in IDLE. diff --git a/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst b/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst new file mode 100644 index 00000000000..831f6ac6287 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2026-03-07-20-47-40.gh-issue-94523.dq7m2k.rst @@ -0,0 +1,2 @@ +Detect file if modified at local disk and prompt to ask refresh. Patch by +Shixian Li. diff --git a/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst b/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst new file mode 100644 index 00000000000..546d47b8a2f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-09-17-20-20-01.gh-issue-96894.t7my0A.rst @@ -0,0 +1,2 @@ +Do not turn echo off for subsequent commands in batch activators +(``activate.bat`` and ``deactivate.bat``) of :mod:`venv`. diff --git a/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst b/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst new file mode 100644 index 00000000000..d7204c28936 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-09-12-48-37.gh-issue-123853.e-zFxb.rst @@ -0,0 +1,3 @@ +Update the table of Windows language code identifiers (LCIDs) used by +:func:`locale.getdefaultlocale` on Windows to protocol version 16.0 +(2024-04-23). diff --git a/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst b/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst new file mode 100644 index 00000000000..1696a2dd172 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-24-07-18-40.gh-issue-108951.jyKygP.rst @@ -0,0 +1 @@ +Add :meth:`~asyncio.TaskGroup.cancel` which cancels unfinished tasks and exits the group without error. diff --git a/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst new file mode 100644 index 00000000000..9cc1d5a389c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-17-15-26-35.gh-issue-132631.IDFZfb.rst @@ -0,0 +1,2 @@ +Fix "I/O operation on closed file" when parsing JSON Lines file with +:mod:`JSON CLI `. diff --git a/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst new file mode 100644 index 00000000000..94e0c1e0b22 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst @@ -0,0 +1 @@ +Add t-strings support to pprint functions diff --git a/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst new file mode 100644 index 00000000000..09643956d98 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-18-12-13-39.gh-issue-140287.49iU-4.rst @@ -0,0 +1,2 @@ +The :mod:`asyncio` REPL now handles exceptions when executing :envvar:`PYTHONSTARTUP` scripts. +Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst b/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst new file mode 100644 index 00000000000..95aa41e9226 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-17-02-55-03.gh-issue-108411.up7MAc.rst @@ -0,0 +1,2 @@ +``typing.IO`` and ``typing.BinaryIO`` method arguments are now +positional-only. diff --git a/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst b/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst new file mode 100644 index 00000000000..5fa3cd2727a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-17-04-10-35.gh-issue-142831.ee3t4L.rst @@ -0,0 +1,2 @@ +Fix a crash in the :mod:`json` module where a use-after-free could occur if +the object being encoded is modified during serialization. diff --git a/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst b/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst new file mode 100644 index 00000000000..c1d3ec806e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-19-21-23-18.gh-issue-105936.dGrzjM.rst @@ -0,0 +1,5 @@ +Attempting to mutate non-field attributes of :mod:`dataclasses` +with both *frozen* and *slots* being ``True`` now raises +:class:`~dataclasses.FrozenInstanceError` instead of :class:`TypeError`. +Their non-dataclass subclasses can now freely mutate non-field attributes, +and the original non-slotted class can be garbage collected. diff --git a/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst b/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst new file mode 100644 index 00000000000..9fd39743ca5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-07-12-54-20.gh-issue-70647.Bja_Lk.rst @@ -0,0 +1,3 @@ +:meth:`~datetime.datetime.strptime` now raises :exc:`ValueError` when the +format string contains ``%d`` without a year directive. +Using ``%e`` without a year now emits a :exc:`DeprecationWarning`. diff --git a/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst b/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst new file mode 100644 index 00000000000..586c7d3495a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-12-18-05-16.gh-issue-137855.2_PTbg.rst @@ -0,0 +1 @@ +Reduce the import time of :mod:`dataclasses` module by ~20%. diff --git a/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst new file mode 100644 index 00000000000..1c2e06c86f6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145105.csv-reader-reentrant.rst @@ -0,0 +1,2 @@ +Fix crash in :mod:`csv` reader when iterating with a re-entrant iterator +that calls :func:`next` on the same reader from within ``__next__``. diff --git a/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst b/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst new file mode 100644 index 00000000000..45be0109677 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-22-19-36-00.gh-issue-145056.TH8nX4.rst @@ -0,0 +1 @@ +Add support for :class:`frozendict` in :meth:`dataclasses.asdict` and :meth:`dataclasses.astuple`. diff --git a/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst b/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst new file mode 100644 index 00000000000..2fae260377c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-25-10-00-00.gh-issue-145200.m_4PAtcI.rst @@ -0,0 +1,2 @@ +:mod:`hashlib`: fix a memory leak when allocating +or initializing an OpenSSL HMAC context fails. diff --git a/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst b/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst new file mode 100644 index 00000000000..77182a3f2c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-25-22-20-00.gh-issue-117716.w6kYp9.rst @@ -0,0 +1 @@ +Fix :mod:`wave` writing of odd-sized ``data`` chunks by appending the required RIFF pad byte and correcting the RIFF chunk size field accordingly. diff --git a/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst b/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst new file mode 100644 index 00000000000..07d7c1fe85e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-26-12-00-00.gh-issue-145244.Kj31cp.rst @@ -0,0 +1,2 @@ +Fixed a use-after-free in :mod:`json` encoder when a ``default`` callback +mutates the dictionary being serialized. diff --git a/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst b/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst new file mode 100644 index 00000000000..1beea3694c4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-22-23-42-22.gh-issue-146313.RtDeAd.rst @@ -0,0 +1,4 @@ +Fix a deadlock in :mod:`multiprocessing`'s resource tracker +where the parent process could hang indefinitely in :func:`os.waitpid` +during interpreter shutdown if a child created via :func:`os.fork` still +held the resource tracker's pipe open. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst b/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst new file mode 100644 index 00000000000..2103024b616 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-28-11-31-32.gh-issue-146563.cXtSym.rst @@ -0,0 +1,2 @@ +:mod:`xml.parsers.expat`: add an exception note when a custom Expat handler +return value cannot be properly interpreted. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst b/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst new file mode 100644 index 00000000000..4a0e15d01c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-01-07-10-49.gh-issue-147957.QXf5Xx.rst @@ -0,0 +1 @@ +Guarantees that :meth:`collections.UserDict.popitem` will pop in the same order as the wrapped dictionary rather than an arbitrary order. diff --git a/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst b/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst new file mode 100644 index 00000000000..dd5bc6022e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-04-20-22-02.gh-issue-148100.lSmGQi.rst @@ -0,0 +1,3 @@ +:term:`Soft deprecate ` :func:`re.match` and +:meth:`re.Pattern.match` in favour of :func:`re.prefixmatch` and +:meth:`re.Pattern.prefixmatch`. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst b/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst new file mode 100644 index 00000000000..dd88be0ad25 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-07-12-37-53.gh-issue-148207.YhGem4.rst @@ -0,0 +1,3 @@ +:class:`typing.TypeVarTuple` now accepts ``bound``, ``covariant``, +``contravariant``, and ``infer_variance`` parameters, matching the interface +of :class:`typing.TypeVar` and :class:`typing.ParamSpec`. diff --git a/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst b/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst new file mode 100644 index 00000000000..87a568b50c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-07-14-13-40.gh-issue-148192.34AUYQ.rst @@ -0,0 +1,3 @@ +``email.generator.Generator._make_boundary`` could fail to detect a duplicate +boundary string if linesep was not \n. It now correctly detects boundary +strings when linesep is \r\n as well. diff --git a/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst new file mode 100644 index 00000000000..0ec08c2d2fd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst @@ -0,0 +1,2 @@ +Improve import time of :mod:`dataclasses` module by lazy importing :mod:`re` +and :mod:`copy` modules. diff --git a/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst b/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst new file mode 100644 index 00000000000..eafefb8a6c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-11-17-28-06.gh-issue-127012.h3rLYS.rst @@ -0,0 +1,2 @@ +``importlib.abc.Traversable.read_text`` now allows/solicits an +``errors`` parameter. diff --git a/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst b/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst new file mode 100644 index 00000000000..1e18015ed9c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-12-12-31-45.gh-issue-121190.O6-E5_.rst @@ -0,0 +1,2 @@ +``importlib.resources.files()`` now emits a more meaningful error message +when module spec is None (as found in some ``__main__`` modules). diff --git a/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst new file mode 100644 index 00000000000..3bb66235079 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst @@ -0,0 +1,2 @@ +:mod:`configparser`: prevent quadratic behavior when a :exc:`~configparser.ParsingError` +is raised after a parser fails to parse multiple lines. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst b/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst new file mode 100644 index 00000000000..85b99531d03 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-13-06-22-27.gh-issue-148464.Bj_NZy.rst @@ -0,0 +1,3 @@ +Add missing ``__ctype_le/be__`` attributes for +:class:`~ctypes.c_float_complex` and :class:`~ctypes.c_double_complex`. Patch +by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst b/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst new file mode 100644 index 00000000000..0812dc9efb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-13-21-38-50.gh-issue-144881.3kPqXw.rst @@ -0,0 +1,4 @@ +:mod:`asyncio` debugging tools (``python -m asyncio ps`` and ``pstree``) +now retry automatically on transient errors that can occur when attaching +to a process under active thread delegation. The number of retries can be +controlled with the ``--retries`` flag. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst b/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst new file mode 100644 index 00000000000..7995dec397f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-14-09-04-35.gh-issue-148508.-GiXml.rst @@ -0,0 +1,2 @@ +An intermittent timing error when running SSL tests on iOS has been +resolved. diff --git a/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst b/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst new file mode 100644 index 00000000000..44216318d47 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-15-11-00-39.gh-issue-146553.VGOsoP.rst @@ -0,0 +1,2 @@ +Fix infinite loop in :func:`typing.get_type_hints` when ``__wrapped__`` +forms a cycle. Patch by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst b/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst new file mode 100644 index 00000000000..d7acdb09838 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-15-20-32-55.gh-issue-148639.-dwsjB.rst @@ -0,0 +1,2 @@ +Implement :pep:`800`, adding the :deco:`typing.disjoint_base` decorator. +Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst b/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst new file mode 100644 index 00000000000..b69f94a1766 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-16-13-30-00.gh-issue-148651.ZsTdLk.rst @@ -0,0 +1,2 @@ +Fix reference leak in :class:`compression.zstd.ZstdDecompressor` when an +invalid option key is passed. diff --git a/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst b/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst new file mode 100644 index 00000000000..1e367716e5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-17-16-31-58.gh-issue-148688.vVugFn.rst @@ -0,0 +1,2 @@ +:mod:`bz2`, :mod:`compression.zstd`, :mod:`lzma`, :mod:`zlib`: Fix a double +free on memory allocation failure. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst b/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst new file mode 100644 index 00000000000..db5e94c0cca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst @@ -0,0 +1,3 @@ +:mod:`xml.etree.ElementTree`: Fix a use-after-free in +:meth:`Element.findtext ` when the +element tree is mutated concurrently during the search. diff --git a/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst b/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst new file mode 100644 index 00000000000..6fcd30e8f05 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-20-18-29-21.gh-issue-148801.ROeNqs.rst @@ -0,0 +1,2 @@ +:mod:`xml.etree.ElementTree`: Fix a crash in :meth:`Element.__deepcopy__ +` on deeply nested trees. diff --git a/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst b/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst new file mode 100644 index 00000000000..d3790079545 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-23-07-38-04.gh-issue-148680.___ePl.rst @@ -0,0 +1 @@ +``ForwardRef`` objects that contain internal names to represent known objects now show the ``type_repr`` of the known object rather than the internal ``__annotationlib_name_x__`` name when evaluated as strings. diff --git a/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst b/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst new file mode 100644 index 00000000000..f9783266f5c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-23-21-47-49.gh-issue-148947.W4V2lG.rst @@ -0,0 +1,2 @@ +Fix crash in :deco:`dataclasses.dataclass` with ``slots=True`` that occurred +when a function found within the class had an empty ``__class__`` cell. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst b/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst new file mode 100644 index 00000000000..4f4a8365b6c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-11-56-05.gh-issue-146311.iHWO0v.rst @@ -0,0 +1,7 @@ +Add a *canonical* keyword-only parameter to the base16, base32, base64, +base85, ascii85, and Z85 decoders in :mod:`base64` and :mod:`binascii`. +When true, encodings with non-zero padding bits (base16/32/64) or +non-canonical encodings (base85/ascii85) are rejected. Single-character +final groups in :func:`binascii.a2b_ascii85` and :func:`binascii.a2b_base85` +are now always rejected as encoding violations, regardless of *canonical*; +previously they were silently ignored and produced no output bytes. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst b/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst new file mode 100644 index 00000000000..e36c7745f40 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-12-50-46.gh-issue-148981.YMM4Y9.rst @@ -0,0 +1 @@ +Add *color* parameter to :func:`ast.dump`. diff --git a/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst b/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst new file mode 100644 index 00000000000..336ed42e51f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-25-18-09-16.gh-issue-148991.AZ64Et.rst @@ -0,0 +1 @@ +Add colour to :mod:`tokenize` CLI output. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst new file mode 100644 index 00000000000..45cdeebe1b6 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst @@ -0,0 +1,2 @@ +A bypass in :mod:`webbrowser` allowed URLs prefixed with ``%action`` to pass +the dash-prefix safety check. diff --git a/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst new file mode 100644 index 00000000000..ed138a54a85 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst @@ -0,0 +1,2 @@ +Hardened :mod:`!_remote_debugging` by validating remote debug offset tables +before using them to size memory reads or interpret remote layouts. diff --git a/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst b/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst new file mode 100644 index 00000000000..adc2c928714 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-08-14-25-47.gh-issue-148252.IEp9Rt.rst @@ -0,0 +1,3 @@ +Fixed stack depth calculation in :mod:`!_remote_debugging` when decoding +certain ``.pyb`` inputs on 32-bit builds. Issue originally identified and +diagnosed by Tristan Madani (@TristanInSec on GitHub). diff --git a/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst new file mode 100644 index 00000000000..9502189ab19 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst @@ -0,0 +1,5 @@ +Fix a dangling input pointer in :class:`lzma.LZMADecompressor`, +:class:`bz2.BZ2Decompressor`, and internal :class:`!zlib._ZlibDecompressor` +when memory allocation fails with :exc:`MemoryError`, which could let a +subsequent :meth:`!decompress` call read or write through a stale pointer to +the already-released caller buffer. diff --git a/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst b/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst new file mode 100644 index 00000000000..0b5cf85fedf --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-20-15-31-37.gh-issue-148808._Z8JL0.rst @@ -0,0 +1,3 @@ +Added buffer boundary check when using ``nbytes`` parameter with +:meth:`!asyncio.AbstractEventLoop.sock_recvfrom_into`. Only +relevant for Windows and the :class:`asyncio.ProactorEventLoop`. diff --git a/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst b/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst new file mode 100644 index 00000000000..d7d376737e4 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst @@ -0,0 +1,3 @@ +Base64-encode values when embedding cookies to JavaScript using the +:meth:`http.cookies.BaseCookie.js_output` method to avoid injection +and escaping. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 606a0a88d26..101737a2782 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1,4 +1,4 @@ -# This file lists the contents of the Limited API and Stable ABI. +# This file lists the contents of Limited API and Stable ABI. # Please append new items at the end. # The syntax of this file is not fixed. @@ -46,15 +46,24 @@ # - 'opaque': No members are part of the ABI, nor is the size. The Limited # API only handles these via pointers. The C definition should be # incomplete (opaque). -# - 'members': Only specific members are part of the stable ABI. -# The struct's size may change, so it can't be used in arrays. +# - 'abi3t-opaque': 'full-abi' in abi3; 'opaque' in abi3t. +# For docs, the generated annotation refers to details that need to +# be added to the ReST file manually. +# - 'members': +# - 'opaque' in abi3t. +# - In abi3, only specific members are part of the stable ABI. +# The struct's size may change, so it can't be used in arrays. # Do not add new structs of this kind without an extremely good reason. +# For docs, the generated annotation refers to details that need to +# be added to the ReST file manually. # - members: For `struct` with struct_abi_kind = 'members', a list of the # exposed members. # - doc: for `feature_macro`, the blurb added in documentation # - windows: for `feature_macro`, this macro is defined on Windows. # (This info is used to generate the DLL manifest and needs to be available # on all platforms.) +# - abi3t_opaque: In abi3t, this struct is opaque (as if `struct_abi_kind` +# was 'opaque' and `members` was missing). # Removing items from this file is generally not allowed, and additions should # be considered with that in mind. See the devguide for exact rules: @@ -107,10 +116,10 @@ struct_abi_kind = 'full-abi' [struct.PyModuleDef_Base] added = '3.2' - struct_abi_kind = 'full-abi' + struct_abi_kind = 'abi3t-opaque' [struct.PyModuleDef] added = '3.2' - struct_abi_kind = 'full-abi' + struct_abi_kind = 'abi3t-opaque' [struct.PyStructSequence_Field] added = '3.2' struct_abi_kind = 'full-abi' diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 7b8cbf3ed96..4bff90e6fd2 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -524,10 +524,12 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) if (d->eof) { FT_ATOMIC_STORE_CHAR_RELAXED(d->needs_input, 0); if (d->bzs_avail_in_real > 0) { - Py_XSETREF(d->unused_data, - PyBytes_FromStringAndSize(bzs->next_in, d->bzs_avail_in_real)); - if (d->unused_data == NULL) + PyObject *unused_data = PyBytes_FromStringAndSize( + bzs->next_in, d->bzs_avail_in_real); + if (unused_data == NULL) { goto error; + } + Py_XSETREF(d->unused_data, unused_data); } } else if (d->bzs_avail_in_real == 0) { @@ -569,6 +571,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) return result; error: + bzs->next_in = NULL; Py_XDECREF(result); return NULL; } @@ -687,12 +690,13 @@ static PyObject * BZ2Decompressor_unused_data_get(PyObject *op, void *Py_UNUSED(ignored)) { BZ2Decompressor *self = _BZ2Decompressor_CAST(op); - PyMutex_Lock(&self->mutex); - PyObject *result = Py_XNewRef(self->unused_data); - PyMutex_Unlock(&self->mutex); - if (result == NULL) { - PyErr_SetString(PyExc_AttributeError, "unused_data"); + if (!FT_ATOMIC_LOAD_CHAR_RELAXED(self->eof)) { + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); } + PyMutex_Lock(&self->mutex); + assert(self->unused_data != NULL); + PyObject *result = Py_NewRef(self->unused_data); + PyMutex_Unlock(&self->mutex); return result; } diff --git a/Modules/_csv.c b/Modules/_csv.c index 9d6190a11c4..a7fcc78e058 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -965,6 +965,12 @@ Reader_iternext_lock_held(PyObject *op) Py_DECREF(lineobj); return NULL; } + if (self->fields == NULL) { + PyErr_SetString(module_state->error_obj, + "iterator has already advanced the reader"); + Py_DECREF(lineobj); + return NULL; + } ++self->line_num; kind = PyUnicode_KIND(lineobj); data = PyUnicode_DATA(lineobj); diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 55eade1c830..0bdc30a0cb3 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2222,6 +2222,31 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) return NULL; } +static int +set_stginfo_ffi_type_pointer(StgInfo *stginfo, struct fielddesc *fmt) +{ + if (!fmt->pffi_type->elements) { + stginfo->ffi_type_pointer = *fmt->pffi_type; + } + else { + /* From primitive types - only complex types have the elements + struct field as non-NULL (two element array). */ + assert(fmt->pffi_type->type == FFI_TYPE_COMPLEX); + const size_t els_size = 2 * sizeof(ffi_type *); + stginfo->ffi_type_pointer.size = fmt->pffi_type->size; + stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment; + stginfo->ffi_type_pointer.type = fmt->pffi_type->type; + stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size); + if (!stginfo->ffi_type_pointer.elements) { + PyErr_NoMemory(); + return -1; + } + memcpy(stginfo->ffi_type_pointer.elements, + fmt->pffi_type->elements, els_size); + } + return 0; +} + static PyMethodDef c_void_p_methods[] = {C_VOID_P_FROM_PARAM_METHODDEF {0}}; static PyMethodDef c_char_p_methods[] = {C_CHAR_P_FROM_PARAM_METHODDEF {0}}; static PyMethodDef c_wchar_p_methods[] = {C_WCHAR_P_FROM_PARAM_METHODDEF {0}}; @@ -2266,8 +2291,10 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type, Py_DECREF(result); return NULL; } - - stginfo->ffi_type_pointer = *fmt->pffi_type; + if (set_stginfo_ffi_type_pointer(stginfo, fmt)) { + Py_DECREF(result); + return NULL; + } stginfo->align = fmt->pffi_type->alignment; stginfo->length = 0; stginfo->size = fmt->pffi_type->size; @@ -2362,18 +2389,8 @@ PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds) if (!stginfo) { goto error; } - - if (!fmt->pffi_type->elements) { - stginfo->ffi_type_pointer = *fmt->pffi_type; - } - else { - const size_t els_size = sizeof(fmt->pffi_type->elements); - stginfo->ffi_type_pointer.size = fmt->pffi_type->size; - stginfo->ffi_type_pointer.alignment = fmt->pffi_type->alignment; - stginfo->ffi_type_pointer.type = fmt->pffi_type->type; - stginfo->ffi_type_pointer.elements = PyMem_Malloc(els_size); - memcpy(stginfo->ffi_type_pointer.elements, - fmt->pffi_type->elements, els_size); + if (set_stginfo_ffi_type_pointer(stginfo, fmt)) { + goto error; } stginfo->align = fmt->pffi_type->alignment; stginfo->length = 0; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 4ebca0e0b3d..b0dc11fdddc 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -792,6 +792,44 @@ D_get(void *ptr, Py_ssize_t size) return PyComplex_FromDoubles(x[0], x[1]); } +static PyObject * +D_set_sw(void *ptr, PyObject *value, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(double))); + Py_complex c = PyComplex_AsCComplex(value); + + if (c.real == -1 && PyErr_Occurred()) { + return NULL; + } +#ifdef WORDS_BIGENDIAN + if (PyFloat_Pack8(c.real, ptr, 1) + || PyFloat_Pack8(c.imag, ptr + sizeof(double), 1)) + { + return NULL; + } +#else + if (PyFloat_Pack8(c.real, ptr, 0) + || PyFloat_Pack8(c.imag, ptr + sizeof(double), 0)) + { + return NULL; + } +#endif + _RET(value); +} + +static PyObject * +D_get_sw(void *ptr, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(double))); +#ifdef WORDS_BIGENDIAN + return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 1), + PyFloat_Unpack8(ptr + sizeof(double), 1)); +#else + return PyComplex_FromDoubles(PyFloat_Unpack8(ptr, 0), + PyFloat_Unpack8(ptr + sizeof(double), 0)); +#endif +} + /* F: float complex */ static PyObject * F_set(void *ptr, PyObject *value, Py_ssize_t size) @@ -817,6 +855,44 @@ F_get(void *ptr, Py_ssize_t size) return PyComplex_FromDoubles(x[0], x[1]); } +static PyObject * +F_set_sw(void *ptr, PyObject *value, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(float))); + Py_complex c = PyComplex_AsCComplex(value); + + if (c.real == -1 && PyErr_Occurred()) { + return NULL; + } +#ifdef WORDS_BIGENDIAN + if (PyFloat_Pack4(c.real, ptr, 1) + || PyFloat_Pack4(c.imag, ptr + sizeof(float), 1)) + { + return NULL; + } +#else + if (PyFloat_Pack4(c.real, ptr, 0) + || PyFloat_Pack4(c.imag, ptr + sizeof(float), 0)) + { + return NULL; + } +#endif + _RET(value); +} + +static PyObject * +F_get_sw(void *ptr, Py_ssize_t size) +{ + assert(NUM_BITS(size) || (size == 2*sizeof(float))); +#ifdef WORDS_BIGENDIAN + return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 1), + PyFloat_Unpack4(ptr + sizeof(float), 1)); +#else + return PyComplex_FromDoubles(PyFloat_Unpack4(ptr, 0), + PyFloat_Unpack4(ptr + sizeof(float), 0)); +#endif +} + /* G: long double complex */ static PyObject * G_set(void *ptr, PyObject *value, Py_ssize_t size) @@ -1602,7 +1678,9 @@ for base_code, base_c_type in [ #if defined(_Py_FFI_SUPPORT_C_COMPLEX) if (Py_FFI_COMPLEX_AVAILABLE) { TABLE_ENTRY(D, &ffi_type_complex_double); + TABLE_ENTRY_SW(D, &ffi_type_complex_double); TABLE_ENTRY(F, &ffi_type_complex_float); + TABLE_ENTRY_SW(F, &ffi_type_complex_float); TABLE_ENTRY(G, &ffi_type_complex_longdouble); } #endif diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index e2185c4bd03..cbd1e026df2 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -16,6 +16,7 @@ #endif #include "Python.h" +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_dict.h" // _PyDict_CopyAsDict() #include "pycore_pyhash.h" // _Py_HashSecret #include "pycore_tuple.h" // _PyTuple_FromPair @@ -572,7 +573,7 @@ element_get_attrib(ElementObject* self) LOCAL(PyObject*) element_get_text(ElementObject* self) { - /* return borrowed reference to text attribute */ + /* return new reference to text attribute */ PyObject *res = self->text; @@ -587,13 +588,13 @@ element_get_text(ElementObject* self) } } - return res; + return Py_NewRef(res); } LOCAL(PyObject*) element_get_tail(ElementObject* self) { - /* return borrowed reference to text attribute */ + /* return new reference to tail attribute */ PyObject *res = self->tail; @@ -608,7 +609,7 @@ element_get_tail(ElementObject* self) } } - return res; + return Py_NewRef(res); } static PyObject* @@ -811,26 +812,31 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) /*[clinic end generated code: output=eefc3df50465b642 input=a2d40348c0aade10]*/ { Py_ssize_t i; - ElementObject* element; + ElementObject* element = NULL; PyObject* tag; PyObject* attrib; PyObject* text; PyObject* tail; PyObject* id; + if (_Py_EnterRecursiveCall(" in Element.__deepcopy__")) { + return NULL; + } + PyTypeObject *tp = Py_TYPE(self); elementtreestate *st = get_elementtree_state_by_type(tp); // The deepcopy() helper takes care of incrementing the refcount // of the object to copy so to avoid use-after-frees. tag = deepcopy(st, self->tag, memo); - if (!tag) - return NULL; + if (!tag) { + goto error; + } if (self->extra && self->extra->attrib) { attrib = deepcopy(st, self->extra->attrib, memo); if (!attrib) { Py_DECREF(tag); - return NULL; + goto error; } } else { attrib = NULL; @@ -841,8 +847,9 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) Py_DECREF(tag); Py_XDECREF(attrib); - if (!element) - return NULL; + if (!element) { + goto error; + } text = deepcopy(st, JOIN_OBJ(self->text), memo); if (!text) @@ -904,10 +911,12 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) if (i < 0) goto error; + _Py_LeaveRecursiveCall(); return (PyObject*) element; error: - Py_DECREF(element); + _Py_LeaveRecursiveCall(); + Py_XDECREF(element); return NULL; } @@ -1350,9 +1359,9 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls, PyObject *text = element_get_text((ElementObject *)item); Py_DECREF(item); if (text == Py_None) { + Py_DECREF(text); return Py_GetConstant(Py_CONSTANT_EMPTY_STR); } - Py_XINCREF(text); return text; } Py_DECREF(item); @@ -2055,16 +2064,14 @@ static PyObject* element_text_getter(PyObject *op, void *closure) { ElementObject *self = _Element_CAST(op); - PyObject *res = element_get_text(self); - return Py_XNewRef(res); + return element_get_text(self); } static PyObject* element_tail_getter(PyObject *op, void *closure) { ElementObject *self = _Element_CAST(op); - PyObject *res = element_get_tail(self); - return Py_XNewRef(res); + return element_get_tail(self); } static PyObject* @@ -2307,16 +2314,14 @@ elementiter_next(PyObject *op) continue; gettext: + Py_DECREF(elem); if (!text) { - Py_DECREF(elem); return NULL; } if (text == Py_None) { - Py_DECREF(elem); + Py_DECREF(text); } else { - Py_INCREF(text); - Py_DECREF(elem); rc = PyObject_IsTrue(text); if (rc > 0) return text; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 938a6ce5b96..fa3eceb74d1 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -1006,6 +1006,7 @@ _hashlib_HASH_get_blocksize(PyObject *op, void *Py_UNUSED(closure)) { HASHobject *self = HASHobject_CAST(op); long block_size = EVP_MD_CTX_block_size(self->ctx); + assert(block_size > 0); return PyLong_FromLong(block_size); } @@ -1014,6 +1015,7 @@ _hashlib_HASH_get_digestsize(PyObject *op, void *Py_UNUSED(closure)) { HASHobject *self = HASHobject_CAST(op); long size = EVP_MD_CTX_size(self->ctx); + assert(size > 0); return PyLong_FromLong(size); } @@ -2103,6 +2105,7 @@ hashlib_HMAC_CTX_new_from_digestmod(_hashlibstate *state, PY_EVP_MD_free(md); #endif if (r == 0) { + hashlib_openssl_HMAC_CTX_free(ctx); if (is_xof) { /* use a better default error message if an XOF is used */ raise_unsupported_algorithm_error(state, digestmod); @@ -2199,7 +2202,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, * * On error, set an exception and return BAD_DIGEST_SIZE. */ -static unsigned int +static int _hashlib_hmac_digest_size(HMACobject *self) { assert(EVP_MAX_MD_SIZE < INT_MAX); @@ -2214,15 +2217,18 @@ _hashlib_hmac_digest_size(HMACobject *self) } int digest_size = EVP_MD_size(md); /* digest_size < 0 iff EVP_MD context is NULL (which is impossible here) */ - assert(digest_size >= 0); assert(digest_size <= (int)EVP_MAX_MD_SIZE); + if (digest_size < 0) { + raise_ssl_error(PyExc_SystemError, "invalid digest size"); + return BAD_DIGEST_SIZE; + } #endif /* digest_size == 0 means that the context is not entirely initialized */ if (digest_size == 0) { - raise_ssl_error(PyExc_ValueError, "missing digest size"); + raise_ssl_error(PyExc_SystemError, "missing digest size"); return BAD_DIGEST_SIZE; } - return (unsigned int)digest_size; + return (int)digest_size; } static int @@ -2320,7 +2326,7 @@ _hashlib_HMAC_update_impl(HMACobject *self, PyObject *msg) static Py_ssize_t _hmac_digest(HMACobject *self, unsigned char *buf) { - unsigned int digest_size = _hashlib_hmac_digest_size(self); + int digest_size = _hashlib_hmac_digest_size(self); assert(digest_size <= EVP_MAX_MD_SIZE); if (digest_size == BAD_DIGEST_SIZE) { assert(PyErr_Occurred()); @@ -2385,7 +2391,7 @@ static PyObject * _hashlib_hmac_get_digest_size(PyObject *op, void *Py_UNUSED(closure)) { HMACobject *self = HMACobject_CAST(op); - unsigned int size = _hashlib_hmac_digest_size(self); + int size = _hashlib_hmac_digest_size(self); return size == BAD_DIGEST_SIZE ? NULL : PyLong_FromLong(size); } diff --git a/Modules/_json.c b/Modules/_json.c index a20466de8c5..1f454768355 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1745,15 +1745,12 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *key, *value; for (Py_ssize_t i = 0; i < PyList_GET_SIZE(items); i++) { PyObject *item = PyList_GET_ITEM(items, i); -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on items can get suspended + // gh-142831: encoder_encode_key_value() can invoke user code + // that mutates the items list, invalidating this borrowed ref. Py_INCREF(item); -#endif if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) { PyErr_SetString(PyExc_ValueError, "items must return 2-tuples"); -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif return -1; } @@ -1762,14 +1759,10 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, if (encoder_encode_key_value(s, writer, first, dct, key, value, indent_level, indent_cache, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(item); -#endif } return 0; @@ -1784,24 +1777,19 @@ _encoder_iterate_dict_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(dct, &pos, &key, &value)) { -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on dct can get suspended + // gh-145244: encoder_encode_key_value() can invoke user code + // that mutates the dict, invalidating these borrowed refs. Py_INCREF(key); Py_INCREF(value); -#endif if (encoder_encode_key_value(s, writer, first, dct, key, value, indent_level, indent_cache, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(key); Py_DECREF(value); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(key); Py_DECREF(value); -#endif } return 0; } @@ -1905,28 +1893,21 @@ _encoder_iterate_fast_seq_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer, { for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); -#ifdef Py_GIL_DISABLED - // gh-119438: in the free-threading build the critical section on s_fast can get suspended + // gh-142831: encoder_listencode_obj() can invoke user code + // that mutates the sequence, invalidating this borrowed ref. Py_INCREF(obj); -#endif if (i) { if (PyUnicodeWriter_WriteStr(writer, separator) < 0) { -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif return -1; } } if (encoder_listencode_obj(s, writer, obj, indent_level, indent_cache)) { _PyErr_FormatNote("when serializing %T item %zd", seq, i); -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif return -1; } -#ifdef Py_GIL_DISABLED Py_DECREF(obj); -#endif } return 0; } diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 3c391675d7b..00ee68dcea2 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1100,6 +1100,7 @@ decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) return result; error: + lzs->next_in = NULL; Py_XDECREF(result); return NULL; } diff --git a/Modules/_remote_debugging/_remote_debugging.h b/Modules/_remote_debugging/_remote_debugging.h index 3722273dfd2..07738d45e42 100644 --- a/Modules/_remote_debugging/_remote_debugging.h +++ b/Modules/_remote_debugging/_remote_debugging.h @@ -120,9 +120,10 @@ typedef enum _WIN32_THREADSTATE { * MACROS AND CONSTANTS * ============================================================================ */ -#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset))) +#define GET_MEMBER(type, obj, offset) \ + (*(const type *)memcpy(&(type){0}, (const char *)(obj) + (offset), sizeof(type))) #define CLEAR_PTR_TAG(ptr) (((uintptr_t)(ptr) & ~Py_TAG_BITS)) -#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset)))) +#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(GET_MEMBER(type, obj, offset))) /* Size macros for opaque buffers */ #define SIZEOF_BYTES_OBJ sizeof(PyBytesObject) @@ -417,6 +418,7 @@ extern void cached_code_metadata_destroy(void *ptr); /* Validation */ extern int is_prerelease_version(uint64_t version); extern int validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets); +#define PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS (-2) /* ============================================================================ * MEMORY READING FUNCTION DECLARATIONS diff --git a/Modules/_remote_debugging/asyncio.c b/Modules/_remote_debugging/asyncio.c index 263c502a857..fc7487d4044 100644 --- a/Modules/_remote_debugging/asyncio.c +++ b/Modules/_remote_debugging/asyncio.c @@ -6,6 +6,7 @@ ******************************************************************************/ #include "_remote_debugging.h" +#include "debug_offsets_validation.h" /* ============================================================================ * ASYNCIO DEBUG ADDRESS FUNCTIONS @@ -71,8 +72,13 @@ read_async_debug(RemoteUnwinderObject *unwinder) int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, async_debug_addr, size, &unwinder->async_debug_offsets); if (result < 0) { set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read AsyncioDebug offsets"); + return result; } - return result; + if (_PyRemoteDebug_ValidateAsyncDebugOffsets(&unwinder->async_debug_offsets) < 0) { + set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid AsyncioDebug offsets"); + return PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS; + } + return 0; } int @@ -85,7 +91,11 @@ ensure_async_debug_offsets(RemoteUnwinderObject *unwinder) // Try to load async debug offsets (the target process may have // loaded asyncio since we last checked) - if (read_async_debug(unwinder) < 0) { + int result = read_async_debug(unwinder); + if (result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) { + return -1; + } + if (result < 0) { PyErr_Clear(); PyErr_SetString(PyExc_RuntimeError, "AsyncioDebug section not available"); set_exception_cause(unwinder, PyExc_RuntimeError, diff --git a/Modules/_remote_debugging/binary_io_reader.c b/Modules/_remote_debugging/binary_io_reader.c index 616213541e1..aca93e9cb1a 100644 --- a/Modules/_remote_debugging/binary_io_reader.c +++ b/Modules/_remote_debugging/binary_io_reader.c @@ -601,6 +601,20 @@ reader_get_or_create_thread_state(BinaryReader *reader, uint64_t thread_id, * STACK DECODING HELPERS * ============================================================================ */ +/* Validate that final_depth fits in the stack buffer. + * Uses uint64_t to prevent overflow on 32-bit platforms. */ +static inline int +validate_stack_depth(ReaderThreadState *ts, uint64_t final_depth) +{ + if (final_depth > ts->current_stack_capacity) { + PyErr_Format(PyExc_ValueError, + "Final stack depth %llu exceeds capacity %zu", + (unsigned long long)final_depth, ts->current_stack_capacity); + return -1; + } + return 0; +} + /* Decode a full stack from sample data. * Updates ts->current_stack and ts->current_stack_depth. * Returns 0 on success, -1 on error (bounds violation). */ @@ -658,12 +672,9 @@ decode_stack_suffix(ReaderThreadState *ts, const uint8_t *data, return -1; } - /* Validate final depth doesn't exceed capacity */ - size_t final_depth = (size_t)shared + new_count; - if (final_depth > ts->current_stack_capacity) { - PyErr_Format(PyExc_ValueError, - "Final stack depth %zu exceeds capacity %zu", - final_depth, ts->current_stack_capacity); + /* Use uint64_t to prevent overflow on 32-bit platforms */ + uint64_t final_depth = (uint64_t)shared + new_count; + if (validate_stack_depth(ts, final_depth) < 0) { return -1; } @@ -713,12 +724,9 @@ decode_stack_pop_push(ReaderThreadState *ts, const uint8_t *data, } size_t keep = (ts->current_stack_depth > pop) ? ts->current_stack_depth - pop : 0; - /* Validate final depth doesn't exceed capacity */ - size_t final_depth = keep + push; - if (final_depth > ts->current_stack_capacity) { - PyErr_Format(PyExc_ValueError, - "Final stack depth %zu exceeds capacity %zu", - final_depth, ts->current_stack_capacity); + /* Use uint64_t to prevent overflow on 32-bit platforms */ + uint64_t final_depth = (uint64_t)keep + push; + if (validate_stack_depth(ts, final_depth) < 0) { return -1; } diff --git a/Modules/_remote_debugging/debug_offsets_validation.h b/Modules/_remote_debugging/debug_offsets_validation.h new file mode 100644 index 00000000000..32800e767b3 --- /dev/null +++ b/Modules/_remote_debugging/debug_offsets_validation.h @@ -0,0 +1,483 @@ +#ifndef Py_REMOTE_DEBUG_OFFSETS_VALIDATION_H +#define Py_REMOTE_DEBUG_OFFSETS_VALIDATION_H + +/* + * The remote debugging tables are read from the target process and must be + * treated as untrusted input. This header centralizes the one-time validation + * that runs immediately after those tables are read, before the unwinder uses + * any reported sizes or offsets to copy remote structs into fixed local + * buffers or to interpret those local copies. + * + * The key rule is simple: every offset that is later dereferenced against a + * local buffer or local object view must appear in one of the field lists + * below. Validation then checks two bounds for each field: + * + * 1. The field must fit within the section size reported by the target. + * 2. The same field must also fit within the local buffer or local layout the + * debugger will actually use. + * + * Sections that are copied into fixed local buffers also have their reported + * size checked against the corresponding local buffer size up front. + * + * This is intentionally front-loaded. Once validation succeeds, the hot path + * can keep using the raw offsets without adding per-sample bounds checks. + * + * Maintenance rule: if either exported table grows, the static_asserts below + * should yell at you. When that happens, update the matching field lists in + * this file in the same change. And if you add a new field that the unwinder + * is going to poke at later, put it in the right list here too, so nobody has + * to rediscover this the annoying way. + */ +#define FIELD_SIZE(type, member) sizeof(((type *)0)->member) + +enum { + PY_REMOTE_DEBUG_OFFSETS_TOTAL_SIZE = 840, + PY_REMOTE_ASYNC_DEBUG_OFFSETS_TOTAL_SIZE = 104, +}; + +/* + * These asserts are the coordination tripwire for table growth. If either + * exported table changes size, update the validation lists below in the same + * change. + */ +static_assert( + sizeof(_Py_DebugOffsets) == PY_REMOTE_DEBUG_OFFSETS_TOTAL_SIZE, + "Update _remote_debugging validation for _Py_DebugOffsets"); +static_assert( + sizeof(struct _Py_AsyncioModuleDebugOffsets) == + PY_REMOTE_ASYNC_DEBUG_OFFSETS_TOTAL_SIZE, + "Update _remote_debugging validation for _Py_AsyncioModuleDebugOffsets"); + +/* + * This logic lives in a private header because it is shared by module.c and + * asyncio.c. Keep the helpers static inline so they stay local to those users + * without adding another compilation unit or exported symbols. + */ +static inline int +validate_section_size(const char *section_name, uint64_t size) +{ + if (size == 0) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s.size must be greater than zero", + section_name); + return -1; + } + return 0; +} + +static inline int +validate_read_size(const char *section_name, uint64_t size, size_t buffer_size) +{ + if (validate_section_size(section_name, size) < 0) { + return -1; + } + if (size > buffer_size) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s.size=%llu exceeds local buffer size %zu", + section_name, + (unsigned long long)size, + buffer_size); + return -1; + } + return 0; +} + +static inline int +validate_span( + const char *field_name, + uint64_t offset, + size_t width, + uint64_t limit, + const char *limit_name) +{ + uint64_t span = (uint64_t)width; + if (span > limit || offset > limit - span) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s=%llu with width %zu exceeds %s %llu", + field_name, + (unsigned long long)offset, + width, + limit_name, + (unsigned long long)limit); + return -1; + } + return 0; +} + +static inline int +validate_alignment( + const char *field_name, + uint64_t offset, + size_t alignment) +{ + if (alignment > 1 && offset % alignment != 0) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s=%llu is not aligned to %zu bytes", + field_name, + (unsigned long long)offset, + alignment); + return -1; + } + return 0; +} + +static inline int +validate_field( + const char *field_name, + uint64_t reported_size, + uint64_t offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (validate_alignment(field_name, offset, alignment) < 0) { + return -1; + } + if (validate_span(field_name, offset, width, reported_size, "reported size") < 0) { + return -1; + } + return validate_span(field_name, offset, width, buffer_size, "local buffer size"); +} + +static inline int +validate_nested_field( + const char *field_name, + uint64_t reported_size, + uint64_t base_offset, + uint64_t nested_offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (base_offset > UINT64_MAX - nested_offset) { + PyErr_Format( + PyExc_RuntimeError, + "Invalid debug offsets: %s overflows the offset calculation", + field_name); + return -1; + } + return validate_field( + field_name, + reported_size, + base_offset + nested_offset, + width, + alignment, + buffer_size); +} + +static inline int +validate_fixed_field( + const char *field_name, + uint64_t offset, + size_t width, + size_t alignment, + size_t buffer_size) +{ + if (validate_alignment(field_name, offset, alignment) < 0) { + return -1; + } + return validate_span(field_name, offset, width, buffer_size, "local buffer size"); +} + +#define PY_REMOTE_DEBUG_VALIDATE_SECTION(section) \ + do { \ + if (validate_section_size(#section, debug_offsets->section.size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(section, buffer_size) \ + do { \ + if (validate_read_size(#section, debug_offsets->section.size, buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_FIELD(section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_field( \ + #section "." #field, \ + debug_offsets->section.size, \ + debug_offsets->section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD(section, base, nested_section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_nested_field( \ + #section "." #base "." #field, \ + debug_offsets->section.size, \ + debug_offsets->section.base, \ + debug_offsets->nested_section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +#define PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(section, field, field_size, field_alignment, buffer_size) \ + do { \ + if (validate_fixed_field( \ + #section "." #field, \ + debug_offsets->section.field, \ + field_size, \ + field_alignment, \ + buffer_size) < 0) { \ + return -1; \ + } \ + } while (0) + +/* + * Each list below must include every offset that is later dereferenced against + * a local buffer or local object view. The validator checks that each field + * stays within both the remote table's reported section size and the local + * buffer size we use when reading that section. If a new dereferenced field is + * added to the offset tables, add it to the matching list here. + * + * Sections not listed here are present in the offset tables but not used by + * the unwinder, so no validation is needed for them. + */ +#define PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(runtime_state, interpreters_head, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_THREAD_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(thread_state, native_thread_id, sizeof(unsigned long), _Alignof(long), buffer_size); \ + APPLY(thread_state, interp, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, datastack_chunk, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, status, FIELD_SIZE(PyThreadState, _status), _Alignof(unsigned int), buffer_size); \ + APPLY(thread_state, holds_gil, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(thread_state, gil_requested, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(thread_state, current_exception, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, thread_id, sizeof(unsigned long), _Alignof(long), buffer_size); \ + APPLY(thread_state, next, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, current_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, base_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(thread_state, last_profiled_frame, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(interpreter_state, id, sizeof(int64_t), _Alignof(int64_t), buffer_size); \ + APPLY(interpreter_state, next, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, threads_head, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, threads_main, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_state, gil_runtime_state_locked, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(interpreter_state, gil_runtime_state_holder, sizeof(PyThreadState *), _Alignof(PyThreadState *), buffer_size); \ + APPLY(interpreter_state, code_object_generation, sizeof(uint64_t), _Alignof(uint64_t), buffer_size); \ + APPLY(interpreter_state, tlbc_generation, sizeof(uint32_t), _Alignof(uint32_t), buffer_size) + +#define PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS(APPLY, buffer_size) \ + APPLY(interpreter_frame, previous, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, executable, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, instr_ptr, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, owner, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(interpreter_frame, stackpointer, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(interpreter_frame, tlbc_index, sizeof(int32_t), _Alignof(int32_t), buffer_size) + +#define PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(code_object, qualname, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, filename, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, linetable, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(code_object, firstlineno, sizeof(int), _Alignof(int), buffer_size); \ + APPLY(code_object, co_code_adaptive, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(code_object, co_tlbc, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_SET_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(set_object, used, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(set_object, mask, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(set_object, table, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size) + +#define PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(long_object, lv_tag, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(long_object, ob_digit, sizeof(digit), _Alignof(digit), buffer_size) + +#define PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(bytes_object, ob_size, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(bytes_object, ob_sval, sizeof(char), _Alignof(char), buffer_size) + +#define PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(unicode_object, length, sizeof(Py_ssize_t), _Alignof(Py_ssize_t), buffer_size); \ + APPLY(unicode_object, asciiobject_size, sizeof(char), _Alignof(char), buffer_size) + +#define PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(gen_object, gi_frame_state, sizeof(int8_t), _Alignof(int8_t), buffer_size); \ + APPLY(gen_object, gi_iframe, FIELD_SIZE(PyGenObject, gi_iframe), _Alignof(_PyInterpreterFrame), buffer_size) + +#define PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_task_object, task_name, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_awaited_by, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_is_task, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(asyncio_task_object, task_awaited_by_is_set, sizeof(char), _Alignof(char), buffer_size); \ + APPLY(asyncio_task_object, task_coro, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_task_object, task_node, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +#define PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_interpreter_state, asyncio_tasks_head, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +#define PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS(APPLY, buffer_size) \ + APPLY(asyncio_thread_state, asyncio_running_loop, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_thread_state, asyncio_running_task, sizeof(uintptr_t), _Alignof(uintptr_t), buffer_size); \ + APPLY(asyncio_thread_state, asyncio_tasks_head, SIZEOF_LLIST_NODE, _Alignof(struct llist_node), buffer_size) + +/* Called once after reading _Py_DebugOffsets, before any hot-path use. */ +static inline int +_PyRemoteDebug_ValidateDebugOffsetsLayout(struct _Py_DebugOffsets *debug_offsets) +{ + /* Validate every field the unwinder dereferences against a local buffer + * or local object view. Fields used only for remote address arithmetic + * (e.g. runtime_state.interpreters_head) are also checked as a sanity + * bound on the offset value. */ + PY_REMOTE_DEBUG_VALIDATE_SECTION(runtime_state); + PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(_PyRuntimeState)); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_state); + PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + INTERP_STATE_BUFFER_SIZE); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(thread_state, SIZEOF_THREAD_STATE); + PY_REMOTE_DEBUG_THREAD_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_THREAD_STATE); + PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD( + err_stackitem, + exc_value, + sizeof(uintptr_t), + _Alignof(uintptr_t), + sizeof(_PyErr_StackItem)); + PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD( + thread_state, + exc_state, + err_stackitem, + exc_value, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_THREAD_STATE); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(gc, SIZEOF_GC_RUNTIME_STATE); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + gc, + frame, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_GC_RUNTIME_STATE); + PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD( + interpreter_state, + gc, + gc, + frame, + sizeof(uintptr_t), + _Alignof(uintptr_t), + INTERP_STATE_BUFFER_SIZE); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_frame); + PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_INTERP_FRAME); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(code_object); + PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_CODE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(pyobject); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + pyobject, + ob_type, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_PYOBJECT); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(type_object); + PY_REMOTE_DEBUG_VALIDATE_FIELD( + type_object, + tp_flags, + sizeof(unsigned long), + _Alignof(unsigned long), + SIZEOF_TYPE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(set_object); + PY_REMOTE_DEBUG_SET_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_SET_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(long_object, SIZEOF_LONG_OBJ); + PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_LONG_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(bytes_object); + PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_BYTES_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(unicode_object); + PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_UNICODE_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_SECTION(gen_object); + PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_GEN_OBJ); + + PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD( + llist_node, + next, + sizeof(uintptr_t), + _Alignof(uintptr_t), + SIZEOF_LLIST_NODE); + + return 0; +} + +/* Called once when AsyncioDebug is loaded, before any task inspection uses it. */ +static inline int +_PyRemoteDebug_ValidateAsyncDebugOffsets( + struct _Py_AsyncioModuleDebugOffsets *debug_offsets) +{ + PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(asyncio_task_object, SIZEOF_TASK_OBJ); + PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + SIZEOF_TASK_OBJ); + PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_interpreter_state); + PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(PyInterpreterState)); + PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_thread_state); + PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS( + PY_REMOTE_DEBUG_VALIDATE_FIELD, + sizeof(_PyThreadStateImpl)); + return 0; +} + +#undef PY_REMOTE_DEBUG_VALIDATE_SECTION +#undef PY_REMOTE_DEBUG_VALIDATE_READ_SECTION +#undef PY_REMOTE_DEBUG_VALIDATE_FIELD +#undef PY_REMOTE_DEBUG_VALIDATE_NESTED_FIELD +#undef PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD +#undef PY_REMOTE_DEBUG_RUNTIME_STATE_FIELDS +#undef PY_REMOTE_DEBUG_THREAD_STATE_FIELDS +#undef PY_REMOTE_DEBUG_INTERPRETER_STATE_FIELDS +#undef PY_REMOTE_DEBUG_INTERPRETER_FRAME_FIELDS +#undef PY_REMOTE_DEBUG_CODE_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_SET_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_LONG_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_BYTES_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_UNICODE_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_GEN_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_TASK_OBJECT_FIELDS +#undef PY_REMOTE_DEBUG_ASYNC_INTERPRETER_STATE_FIELDS +#undef PY_REMOTE_DEBUG_ASYNC_THREAD_STATE_FIELDS +#undef FIELD_SIZE + +#endif diff --git a/Modules/_remote_debugging/frames.c b/Modules/_remote_debugging/frames.c index a0b4a1e8a1e..bbdfce3f720 100644 --- a/Modules/_remote_debugging/frames.c +++ b/Modules/_remote_debugging/frames.c @@ -148,7 +148,9 @@ find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr) uintptr_t base = chunks->chunks[i].remote_addr + offsetof(_PyStackChunk, data); size_t payload = chunks->chunks[i].size - offsetof(_PyStackChunk, data); - if (remote_ptr >= base && remote_ptr < base + payload) { + if (payload >= SIZEOF_INTERP_FRAME && + remote_ptr >= base && + remote_ptr <= base + payload - SIZEOF_INTERP_FRAME) { return (char *)chunks->chunks[i].local_copy + (remote_ptr - chunks->chunks[i].remote_addr); } } diff --git a/Modules/_remote_debugging/module.c b/Modules/_remote_debugging/module.c index f86bbf8ce55..32f2cbacf21 100644 --- a/Modules/_remote_debugging/module.c +++ b/Modules/_remote_debugging/module.c @@ -7,6 +7,7 @@ #include "_remote_debugging.h" #include "binary_io.h" +#include "debug_offsets_validation.h" /* Forward declarations for clinic-generated code */ typedef struct { @@ -240,7 +241,7 @@ validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets) return -1; } - return 0; + return _PyRemoteDebug_ValidateDebugOffsetsLayout(debug_offsets); } /* ============================================================================ @@ -374,7 +375,11 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self, // Try to read async debug offsets, but don't fail if they're not available self->async_debug_offsets_available = 1; - if (read_async_debug(self) < 0) { + int async_debug_result = read_async_debug(self); + if (async_debug_result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) { + return -1; + } + if (async_debug_result < 0) { PyErr_Clear(); memset(&self->async_debug_offsets, 0, sizeof(self->async_debug_offsets)); self->async_debug_offsets_available = 0; diff --git a/Modules/_remote_debugging/threads.c b/Modules/_remote_debugging/threads.c index a38bb945169..e303c667ea0 100644 --- a/Modules/_remote_debugging/threads.c +++ b/Modules/_remote_debugging/threads.c @@ -192,7 +192,7 @@ get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread char stat_path[256]; char buffer[2048] = ""; - snprintf(stat_path, sizeof(stat_path), "/proc/%d/task/%lu/stat", unwinder->handle.pid, tid); + snprintf(stat_path, sizeof(stat_path), "/proc/%d/task/%" PRIu64 "/stat", unwinder->handle.pid, tid); int fd = open(stat_path, O_RDONLY); if (fd == -1) { @@ -314,19 +314,6 @@ unwind_stack_for_thread( long tid = GET_MEMBER(long, ts, unwinder->debug_offsets.thread_state.native_thread_id); - // Read GC collecting state from the interpreter (before any skip checks) - uintptr_t interp_addr = GET_MEMBER(uintptr_t, ts, unwinder->debug_offsets.thread_state.interp); - - // Read the GC runtime state from the interpreter state - uintptr_t gc_addr = interp_addr + unwinder->debug_offsets.interpreter_state.gc; - char gc_state[SIZEOF_GC_RUNTIME_STATE]; - if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, gc_addr, unwinder->debug_offsets.gc.size, gc_state) < 0) { - set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read GC state"); - goto error; - } - STATS_INC(unwinder, memory_reads); - STATS_ADD(unwinder, memory_bytes_read, unwinder->debug_offsets.gc.size); - // Calculate thread status using flags (always) int status_flags = 0; diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 4e563379098..ea8a6d3fc1d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -153,16 +153,18 @@ static void _PySSLFixErrno(void) { /* Include generated data (error codes) */ /* See Tools/ssl/make_ssl_data.py for notes on adding a new version. */ -#if (OPENSSL_VERSION_NUMBER >= 0x30401000L) -#include "_ssl_data_36.h" +#if (OPENSSL_VERSION_NUMBER >= 0x40000000L) +# include "_ssl_data_40.h" +#elif (OPENSSL_VERSION_NUMBER >= 0x30401000L) +# include "_ssl_data_36.h" #elif (OPENSSL_VERSION_NUMBER >= 0x30100000L) -#include "_ssl_data_340.h" +# include "_ssl_data_340.h" #elif (OPENSSL_VERSION_NUMBER >= 0x30000000L) -#include "_ssl_data_300.h" +# include "_ssl_data_300.h" #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) -#include "_ssl_data_111.h" +# include "_ssl_data_111.h" #else -#error Unsupported OpenSSL version +# error Unsupported OpenSSL version #endif #if (OPENSSL_VERSION_NUMBER >= 0x40000000L) diff --git a/Modules/_ssl_data_40.h b/Modules/_ssl_data_40.h new file mode 100644 index 00000000000..ea615f655bb --- /dev/null +++ b/Modules/_ssl_data_40.h @@ -0,0 +1,9357 @@ +/* File generated by Tools/ssl/make_ssl_data.py */ +/* Generated on 2026-04-15T09:18:34.696139+00:00 */ +/* Generated from Git commit v3.15.0a8-132-gd14e31ed683 */ + +/* generated from args.lib2errnum */ +static struct py_ssl_library_code library_codes[] = { +#ifdef ERR_LIB_ASN1 + {"ASN1", ERR_LIB_ASN1}, +#endif +#ifdef ERR_LIB_ASYNC + {"ASYNC", ERR_LIB_ASYNC}, +#endif +#ifdef ERR_LIB_BIO + {"BIO", ERR_LIB_BIO}, +#endif +#ifdef ERR_LIB_BN + {"BN", ERR_LIB_BN}, +#endif +#ifdef ERR_LIB_BUF + {"BUF", ERR_LIB_BUF}, +#endif +#ifdef ERR_LIB_CMP + {"CMP", ERR_LIB_CMP}, +#endif +#ifdef ERR_LIB_CMS + {"CMS", ERR_LIB_CMS}, +#endif +#ifdef ERR_LIB_COMP + {"COMP", ERR_LIB_COMP}, +#endif +#ifdef ERR_LIB_CONF + {"CONF", ERR_LIB_CONF}, +#endif +#ifdef ERR_LIB_CRMF + {"CRMF", ERR_LIB_CRMF}, +#endif +#ifdef ERR_LIB_CRYPTO + {"CRYPTO", ERR_LIB_CRYPTO}, +#endif +#ifdef ERR_LIB_CT + {"CT", ERR_LIB_CT}, +#endif +#ifdef ERR_LIB_DH + {"DH", ERR_LIB_DH}, +#endif +#ifdef ERR_LIB_DSA + {"DSA", ERR_LIB_DSA}, +#endif +#ifdef ERR_LIB_DSO + {"DSO", ERR_LIB_DSO}, +#endif +#ifdef ERR_LIB_EC + {"EC", ERR_LIB_EC}, +#endif +#ifdef ERR_LIB_ECDH + {"ECDH", ERR_LIB_ECDH}, +#endif +#ifdef ERR_LIB_ECDSA + {"ECDSA", ERR_LIB_ECDSA}, +#endif +#ifdef ERR_LIB_ENGINE + {"ENGINE", ERR_LIB_ENGINE}, +#endif +#ifdef ERR_LIB_ESS + {"ESS", ERR_LIB_ESS}, +#endif +#ifdef ERR_LIB_EVP + {"EVP", ERR_LIB_EVP}, +#endif +#ifdef ERR_LIB_FIPS + {"FIPS", ERR_LIB_FIPS}, +#endif +#ifdef ERR_LIB_HMAC + {"HMAC", ERR_LIB_HMAC}, +#endif +#ifdef ERR_LIB_HTTP + {"HTTP", ERR_LIB_HTTP}, +#endif +#ifdef ERR_LIB_JPAKE + {"JPAKE", ERR_LIB_JPAKE}, +#endif +#ifdef ERR_LIB_KDF + {"KDF", ERR_LIB_KDF}, +#endif +#ifdef ERR_LIB_METH + {"METH", ERR_LIB_METH}, +#endif +#ifdef ERR_LIB_NONE + {"NONE", ERR_LIB_NONE}, +#endif +#ifdef ERR_LIB_OBJ + {"OBJ", ERR_LIB_OBJ}, +#endif +#ifdef ERR_LIB_OCSP + {"OCSP", ERR_LIB_OCSP}, +#endif +#ifdef ERR_LIB_OSSL_DECODER + {"OSSL_DECODER", ERR_LIB_OSSL_DECODER}, +#endif +#ifdef ERR_LIB_OSSL_ENCODER + {"OSSL_ENCODER", ERR_LIB_OSSL_ENCODER}, +#endif +#ifdef ERR_LIB_OSSL_STORE + {"OSSL_STORE", ERR_LIB_OSSL_STORE}, +#endif +#ifdef ERR_LIB_PEM + {"PEM", ERR_LIB_PEM}, +#endif +#ifdef ERR_LIB_PKCS12 + {"PKCS12", ERR_LIB_PKCS12}, +#endif +#ifdef ERR_LIB_PKCS7 + {"PKCS7", ERR_LIB_PKCS7}, +#endif +#ifdef ERR_LIB_PROP + {"PROP", ERR_LIB_PROP}, +#endif +#ifdef ERR_LIB_PROV + {"PROV", ERR_LIB_PROV}, +#endif +#ifdef ERR_LIB_PROXY + {"PROXY", ERR_LIB_PROXY}, +#endif +#ifdef ERR_LIB_RAND + {"RAND", ERR_LIB_RAND}, +#endif +#ifdef ERR_LIB_RSA + {"RSA", ERR_LIB_RSA}, +#endif +#ifdef ERR_LIB_RSAREF + {"RSAREF", ERR_LIB_RSAREF}, +#endif +#ifdef ERR_LIB_SM2 + {"SM2", ERR_LIB_SM2}, +#endif +#ifdef ERR_LIB_SSL + {"SSL", ERR_LIB_SSL}, +#endif +#ifdef ERR_LIB_SSL2 + {"SSL2", ERR_LIB_SSL2}, +#endif +#ifdef ERR_LIB_SSL23 + {"SSL23", ERR_LIB_SSL23}, +#endif +#ifdef ERR_LIB_SSL3 + {"SSL3", ERR_LIB_SSL3}, +#endif +#ifdef ERR_LIB_SYS + {"SYS", ERR_LIB_SYS}, +#endif +#ifdef ERR_LIB_TS + {"TS", ERR_LIB_TS}, +#endif +#ifdef ERR_LIB_UI + {"UI", ERR_LIB_UI}, +#endif +#ifdef ERR_LIB_USER + {"USER", ERR_LIB_USER}, +#endif +#ifdef ERR_LIB_X509 + {"X509", ERR_LIB_X509}, +#endif +#ifdef ERR_LIB_X509V3 + {"X509V3", ERR_LIB_X509V3}, +#endif + {NULL, 0} /* sentinel */ +}; + +/* generated from args.reasons */ +static struct py_ssl_error_code error_codes[] = { + #ifdef ASN1_R_ADDING_OBJECT + {"ADDING_OBJECT", ERR_LIB_ASN1, ASN1_R_ADDING_OBJECT}, + #else + {"ADDING_OBJECT", 13, 171}, + #endif + #ifdef ASN1_R_ASN1_PARSE_ERROR + {"ASN1_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR}, + #else + {"ASN1_PARSE_ERROR", 13, 203}, + #endif + #ifdef ASN1_R_ASN1_SIG_PARSE_ERROR + {"ASN1_SIG_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR}, + #else + {"ASN1_SIG_PARSE_ERROR", 13, 204}, + #endif + #ifdef ASN1_R_AUX_ERROR + {"AUX_ERROR", ERR_LIB_ASN1, ASN1_R_AUX_ERROR}, + #else + {"AUX_ERROR", 13, 100}, + #endif + #ifdef ASN1_R_BAD_OBJECT_HEADER + {"BAD_OBJECT_HEADER", ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER}, + #else + {"BAD_OBJECT_HEADER", 13, 102}, + #endif + #ifdef ASN1_R_BAD_TEMPLATE + {"BAD_TEMPLATE", ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE}, + #else + {"BAD_TEMPLATE", 13, 230}, + #endif + #ifdef ASN1_R_BMPSTRING_IS_WRONG_LENGTH + {"BMPSTRING_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH}, + #else + {"BMPSTRING_IS_WRONG_LENGTH", 13, 214}, + #endif + #ifdef ASN1_R_BN_LIB + {"BN_LIB", ERR_LIB_ASN1, ASN1_R_BN_LIB}, + #else + {"BN_LIB", 13, 105}, + #endif + #ifdef ASN1_R_BOOLEAN_IS_WRONG_LENGTH + {"BOOLEAN_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH}, + #else + {"BOOLEAN_IS_WRONG_LENGTH", 13, 106}, + #endif + #ifdef ASN1_R_BUFFER_TOO_SMALL + {"BUFFER_TOO_SMALL", ERR_LIB_ASN1, ASN1_R_BUFFER_TOO_SMALL}, + #else + {"BUFFER_TOO_SMALL", 13, 107}, + #endif + #ifdef ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER + {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER}, + #else + {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", 13, 108}, + #endif + #ifdef ASN1_R_CONTEXT_NOT_INITIALISED + {"CONTEXT_NOT_INITIALISED", ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED}, + #else + {"CONTEXT_NOT_INITIALISED", 13, 217}, + #endif + #ifdef ASN1_R_DATA_IS_WRONG + {"DATA_IS_WRONG", ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG}, + #else + {"DATA_IS_WRONG", 13, 109}, + #endif + #ifdef ASN1_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_ASN1, ASN1_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 13, 110}, + #endif + #ifdef ASN1_R_DEPTH_EXCEEDED + {"DEPTH_EXCEEDED", ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED}, + #else + {"DEPTH_EXCEEDED", 13, 174}, + #endif + #ifdef ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED + {"DIGEST_AND_KEY_TYPE_NOT_SUPPORTED", ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED}, + #else + {"DIGEST_AND_KEY_TYPE_NOT_SUPPORTED", 13, 198}, + #endif + #ifdef ASN1_R_ENCODE_ERROR + {"ENCODE_ERROR", ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR}, + #else + {"ENCODE_ERROR", 13, 112}, + #endif + #ifdef ASN1_R_ERROR_GETTING_TIME + {"ERROR_GETTING_TIME", ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME}, + #else + {"ERROR_GETTING_TIME", 13, 173}, + #endif + #ifdef ASN1_R_ERROR_LOADING_SECTION + {"ERROR_LOADING_SECTION", ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION}, + #else + {"ERROR_LOADING_SECTION", 13, 172}, + #endif + #ifdef ASN1_R_ERROR_SETTING_CIPHER_PARAMS + {"ERROR_SETTING_CIPHER_PARAMS", ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS}, + #else + {"ERROR_SETTING_CIPHER_PARAMS", 13, 114}, + #endif + #ifdef ASN1_R_EXPECTING_AN_INTEGER + {"EXPECTING_AN_INTEGER", ERR_LIB_ASN1, ASN1_R_EXPECTING_AN_INTEGER}, + #else + {"EXPECTING_AN_INTEGER", 13, 115}, + #endif + #ifdef ASN1_R_EXPECTING_AN_OBJECT + {"EXPECTING_AN_OBJECT", ERR_LIB_ASN1, ASN1_R_EXPECTING_AN_OBJECT}, + #else + {"EXPECTING_AN_OBJECT", 13, 116}, + #endif + #ifdef ASN1_R_EXPLICIT_LENGTH_MISMATCH + {"EXPLICIT_LENGTH_MISMATCH", ERR_LIB_ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH}, + #else + {"EXPLICIT_LENGTH_MISMATCH", 13, 119}, + #endif + #ifdef ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED + {"EXPLICIT_TAG_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED}, + #else + {"EXPLICIT_TAG_NOT_CONSTRUCTED", 13, 120}, + #endif + #ifdef ASN1_R_FIELD_MISSING + {"FIELD_MISSING", ERR_LIB_ASN1, ASN1_R_FIELD_MISSING}, + #else + {"FIELD_MISSING", 13, 121}, + #endif + #ifdef ASN1_R_FIRST_NUM_TOO_LARGE + {"FIRST_NUM_TOO_LARGE", ERR_LIB_ASN1, ASN1_R_FIRST_NUM_TOO_LARGE}, + #else + {"FIRST_NUM_TOO_LARGE", 13, 122}, + #endif + #ifdef ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT + {"GENERALIZEDTIME_IS_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT}, + #else + {"GENERALIZEDTIME_IS_TOO_SHORT", 13, 232}, + #endif + #ifdef ASN1_R_HEADER_TOO_LONG + {"HEADER_TOO_LONG", ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG}, + #else + {"HEADER_TOO_LONG", 13, 123}, + #endif + #ifdef ASN1_R_ILLEGAL_BITSTRING_FORMAT + {"ILLEGAL_BITSTRING_FORMAT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT}, + #else + {"ILLEGAL_BITSTRING_FORMAT", 13, 175}, + #endif + #ifdef ASN1_R_ILLEGAL_BOOLEAN + {"ILLEGAL_BOOLEAN", ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN}, + #else + {"ILLEGAL_BOOLEAN", 13, 176}, + #endif + #ifdef ASN1_R_ILLEGAL_CHARACTERS + {"ILLEGAL_CHARACTERS", ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS}, + #else + {"ILLEGAL_CHARACTERS", 13, 124}, + #endif + #ifdef ASN1_R_ILLEGAL_FORMAT + {"ILLEGAL_FORMAT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT}, + #else + {"ILLEGAL_FORMAT", 13, 177}, + #endif + #ifdef ASN1_R_ILLEGAL_HEX + {"ILLEGAL_HEX", ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX}, + #else + {"ILLEGAL_HEX", 13, 178}, + #endif + #ifdef ASN1_R_ILLEGAL_IMPLICIT_TAG + {"ILLEGAL_IMPLICIT_TAG", ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG}, + #else + {"ILLEGAL_IMPLICIT_TAG", 13, 179}, + #endif + #ifdef ASN1_R_ILLEGAL_INTEGER + {"ILLEGAL_INTEGER", ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER}, + #else + {"ILLEGAL_INTEGER", 13, 180}, + #endif + #ifdef ASN1_R_ILLEGAL_NEGATIVE_VALUE + {"ILLEGAL_NEGATIVE_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE}, + #else + {"ILLEGAL_NEGATIVE_VALUE", 13, 226}, + #endif + #ifdef ASN1_R_ILLEGAL_NESTED_TAGGING + {"ILLEGAL_NESTED_TAGGING", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING}, + #else + {"ILLEGAL_NESTED_TAGGING", 13, 181}, + #endif + #ifdef ASN1_R_ILLEGAL_NULL + {"ILLEGAL_NULL", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL}, + #else + {"ILLEGAL_NULL", 13, 125}, + #endif + #ifdef ASN1_R_ILLEGAL_NULL_VALUE + {"ILLEGAL_NULL_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE}, + #else + {"ILLEGAL_NULL_VALUE", 13, 182}, + #endif + #ifdef ASN1_R_ILLEGAL_OBJECT + {"ILLEGAL_OBJECT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT}, + #else + {"ILLEGAL_OBJECT", 13, 183}, + #endif + #ifdef ASN1_R_ILLEGAL_OPTIONAL_ANY + {"ILLEGAL_OPTIONAL_ANY", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY}, + #else + {"ILLEGAL_OPTIONAL_ANY", 13, 126}, + #endif + #ifdef ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE + {"ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE}, + #else + {"ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE", 13, 170}, + #endif + #ifdef ASN1_R_ILLEGAL_PADDING + {"ILLEGAL_PADDING", ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING}, + #else + {"ILLEGAL_PADDING", 13, 221}, + #endif + #ifdef ASN1_R_ILLEGAL_TAGGED_ANY + {"ILLEGAL_TAGGED_ANY", ERR_LIB_ASN1, ASN1_R_ILLEGAL_TAGGED_ANY}, + #else + {"ILLEGAL_TAGGED_ANY", 13, 127}, + #endif + #ifdef ASN1_R_ILLEGAL_TIME_VALUE + {"ILLEGAL_TIME_VALUE", ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE}, + #else + {"ILLEGAL_TIME_VALUE", 13, 184}, + #endif + #ifdef ASN1_R_ILLEGAL_ZERO_CONTENT + {"ILLEGAL_ZERO_CONTENT", ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT}, + #else + {"ILLEGAL_ZERO_CONTENT", 13, 222}, + #endif + #ifdef ASN1_R_INTEGER_NOT_ASCII_FORMAT + {"INTEGER_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT}, + #else + {"INTEGER_NOT_ASCII_FORMAT", 13, 185}, + #endif + #ifdef ASN1_R_INTEGER_TOO_LARGE_FOR_LONG + {"INTEGER_TOO_LARGE_FOR_LONG", ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG}, + #else + {"INTEGER_TOO_LARGE_FOR_LONG", 13, 128}, + #endif + #ifdef ASN1_R_INVALID_BIT_STRING_BITS_LEFT + {"INVALID_BIT_STRING_BITS_LEFT", ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT}, + #else + {"INVALID_BIT_STRING_BITS_LEFT", 13, 220}, + #endif + #ifdef ASN1_R_INVALID_BMPSTRING_LENGTH + {"INVALID_BMPSTRING_LENGTH", ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH}, + #else + {"INVALID_BMPSTRING_LENGTH", 13, 129}, + #endif + #ifdef ASN1_R_INVALID_DIGIT + {"INVALID_DIGIT", ERR_LIB_ASN1, ASN1_R_INVALID_DIGIT}, + #else + {"INVALID_DIGIT", 13, 130}, + #endif + #ifdef ASN1_R_INVALID_MIME_TYPE + {"INVALID_MIME_TYPE", ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE}, + #else + {"INVALID_MIME_TYPE", 13, 205}, + #endif + #ifdef ASN1_R_INVALID_MODIFIER + {"INVALID_MODIFIER", ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER}, + #else + {"INVALID_MODIFIER", 13, 186}, + #endif + #ifdef ASN1_R_INVALID_NUMBER + {"INVALID_NUMBER", ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER}, + #else + {"INVALID_NUMBER", 13, 187}, + #endif + #ifdef ASN1_R_INVALID_OBJECT_ENCODING + {"INVALID_OBJECT_ENCODING", ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING}, + #else + {"INVALID_OBJECT_ENCODING", 13, 216}, + #endif + #ifdef ASN1_R_INVALID_SCRYPT_PARAMETERS + {"INVALID_SCRYPT_PARAMETERS", ERR_LIB_ASN1, ASN1_R_INVALID_SCRYPT_PARAMETERS}, + #else + {"INVALID_SCRYPT_PARAMETERS", 13, 227}, + #endif + #ifdef ASN1_R_INVALID_SEPARATOR + {"INVALID_SEPARATOR", ERR_LIB_ASN1, ASN1_R_INVALID_SEPARATOR}, + #else + {"INVALID_SEPARATOR", 13, 131}, + #endif + #ifdef ASN1_R_INVALID_STRING_TABLE_VALUE + {"INVALID_STRING_TABLE_VALUE", ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE}, + #else + {"INVALID_STRING_TABLE_VALUE", 13, 218}, + #endif + #ifdef ASN1_R_INVALID_UNIVERSALSTRING_LENGTH + {"INVALID_UNIVERSALSTRING_LENGTH", ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH}, + #else + {"INVALID_UNIVERSALSTRING_LENGTH", 13, 133}, + #endif + #ifdef ASN1_R_INVALID_UTF8STRING + {"INVALID_UTF8STRING", ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING}, + #else + {"INVALID_UTF8STRING", 13, 134}, + #endif + #ifdef ASN1_R_INVALID_VALUE + {"INVALID_VALUE", ERR_LIB_ASN1, ASN1_R_INVALID_VALUE}, + #else + {"INVALID_VALUE", 13, 219}, + #endif + #ifdef ASN1_R_LENGTH_TOO_LONG + {"LENGTH_TOO_LONG", ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG}, + #else + {"LENGTH_TOO_LONG", 13, 231}, + #endif + #ifdef ASN1_R_LIST_ERROR + {"LIST_ERROR", ERR_LIB_ASN1, ASN1_R_LIST_ERROR}, + #else + {"LIST_ERROR", 13, 188}, + #endif + #ifdef ASN1_R_MIME_NO_CONTENT_TYPE + {"MIME_NO_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE}, + #else + {"MIME_NO_CONTENT_TYPE", 13, 206}, + #endif + #ifdef ASN1_R_MIME_PARSE_ERROR + {"MIME_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR}, + #else + {"MIME_PARSE_ERROR", 13, 207}, + #endif + #ifdef ASN1_R_MIME_SIG_PARSE_ERROR + {"MIME_SIG_PARSE_ERROR", ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR}, + #else + {"MIME_SIG_PARSE_ERROR", 13, 208}, + #endif + #ifdef ASN1_R_MISSING_EOC + {"MISSING_EOC", ERR_LIB_ASN1, ASN1_R_MISSING_EOC}, + #else + {"MISSING_EOC", 13, 137}, + #endif + #ifdef ASN1_R_MISSING_SECOND_NUMBER + {"MISSING_SECOND_NUMBER", ERR_LIB_ASN1, ASN1_R_MISSING_SECOND_NUMBER}, + #else + {"MISSING_SECOND_NUMBER", 13, 138}, + #endif + #ifdef ASN1_R_MISSING_VALUE + {"MISSING_VALUE", ERR_LIB_ASN1, ASN1_R_MISSING_VALUE}, + #else + {"MISSING_VALUE", 13, 189}, + #endif + #ifdef ASN1_R_MSTRING_NOT_UNIVERSAL + {"MSTRING_NOT_UNIVERSAL", ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL}, + #else + {"MSTRING_NOT_UNIVERSAL", 13, 139}, + #endif + #ifdef ASN1_R_MSTRING_WRONG_TAG + {"MSTRING_WRONG_TAG", ERR_LIB_ASN1, ASN1_R_MSTRING_WRONG_TAG}, + #else + {"MSTRING_WRONG_TAG", 13, 140}, + #endif + #ifdef ASN1_R_NESTED_ASN1_STRING + {"NESTED_ASN1_STRING", ERR_LIB_ASN1, ASN1_R_NESTED_ASN1_STRING}, + #else + {"NESTED_ASN1_STRING", 13, 197}, + #endif + #ifdef ASN1_R_NESTED_TOO_DEEP + {"NESTED_TOO_DEEP", ERR_LIB_ASN1, ASN1_R_NESTED_TOO_DEEP}, + #else + {"NESTED_TOO_DEEP", 13, 201}, + #endif + #ifdef ASN1_R_NON_HEX_CHARACTERS + {"NON_HEX_CHARACTERS", ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS}, + #else + {"NON_HEX_CHARACTERS", 13, 141}, + #endif + #ifdef ASN1_R_NOT_ASCII_FORMAT + {"NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT}, + #else + {"NOT_ASCII_FORMAT", 13, 190}, + #endif + #ifdef ASN1_R_NOT_ENOUGH_DATA + {"NOT_ENOUGH_DATA", ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA}, + #else + {"NOT_ENOUGH_DATA", 13, 142}, + #endif + #ifdef ASN1_R_NO_CONTENT_TYPE + {"NO_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE}, + #else + {"NO_CONTENT_TYPE", 13, 209}, + #endif + #ifdef ASN1_R_NO_MATCHING_CHOICE_TYPE + {"NO_MATCHING_CHOICE_TYPE", ERR_LIB_ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE}, + #else + {"NO_MATCHING_CHOICE_TYPE", 13, 143}, + #endif + #ifdef ASN1_R_NO_MULTIPART_BODY_FAILURE + {"NO_MULTIPART_BODY_FAILURE", ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE}, + #else + {"NO_MULTIPART_BODY_FAILURE", 13, 210}, + #endif + #ifdef ASN1_R_NO_MULTIPART_BOUNDARY + {"NO_MULTIPART_BOUNDARY", ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY}, + #else + {"NO_MULTIPART_BOUNDARY", 13, 211}, + #endif + #ifdef ASN1_R_NO_SIG_CONTENT_TYPE + {"NO_SIG_CONTENT_TYPE", ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE}, + #else + {"NO_SIG_CONTENT_TYPE", 13, 212}, + #endif + #ifdef ASN1_R_NULL_IS_WRONG_LENGTH + {"NULL_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_NULL_IS_WRONG_LENGTH}, + #else + {"NULL_IS_WRONG_LENGTH", 13, 144}, + #endif + #ifdef ASN1_R_OBJECT_NOT_ASCII_FORMAT + {"OBJECT_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT}, + #else + {"OBJECT_NOT_ASCII_FORMAT", 13, 191}, + #endif + #ifdef ASN1_R_ODD_NUMBER_OF_CHARS + {"ODD_NUMBER_OF_CHARS", ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS}, + #else + {"ODD_NUMBER_OF_CHARS", 13, 145}, + #endif + #ifdef ASN1_R_SECOND_NUMBER_TOO_LARGE + {"SECOND_NUMBER_TOO_LARGE", ERR_LIB_ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE}, + #else + {"SECOND_NUMBER_TOO_LARGE", 13, 147}, + #endif + #ifdef ASN1_R_SEQUENCE_LENGTH_MISMATCH + {"SEQUENCE_LENGTH_MISMATCH", ERR_LIB_ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH}, + #else + {"SEQUENCE_LENGTH_MISMATCH", 13, 148}, + #endif + #ifdef ASN1_R_SEQUENCE_NOT_CONSTRUCTED + {"SEQUENCE_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED}, + #else + {"SEQUENCE_NOT_CONSTRUCTED", 13, 149}, + #endif + #ifdef ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG + {"SEQUENCE_OR_SET_NEEDS_CONFIG", ERR_LIB_ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG}, + #else + {"SEQUENCE_OR_SET_NEEDS_CONFIG", 13, 192}, + #endif + #ifdef ASN1_R_SHORT_LINE + {"SHORT_LINE", ERR_LIB_ASN1, ASN1_R_SHORT_LINE}, + #else + {"SHORT_LINE", 13, 150}, + #endif + #ifdef ASN1_R_SIG_INVALID_MIME_TYPE + {"SIG_INVALID_MIME_TYPE", ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE}, + #else + {"SIG_INVALID_MIME_TYPE", 13, 213}, + #endif + #ifdef ASN1_R_STREAMING_NOT_SUPPORTED + {"STREAMING_NOT_SUPPORTED", ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED}, + #else + {"STREAMING_NOT_SUPPORTED", 13, 202}, + #endif + #ifdef ASN1_R_STRING_TOO_LONG + {"STRING_TOO_LONG", ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG}, + #else + {"STRING_TOO_LONG", 13, 151}, + #endif + #ifdef ASN1_R_STRING_TOO_SHORT + {"STRING_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT}, + #else + {"STRING_TOO_SHORT", 13, 152}, + #endif + #ifdef ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD + {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", ERR_LIB_ASN1, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD}, + #else + {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", 13, 154}, + #endif + #ifdef ASN1_R_TIME_NOT_ASCII_FORMAT + {"TIME_NOT_ASCII_FORMAT", ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT}, + #else + {"TIME_NOT_ASCII_FORMAT", 13, 193}, + #endif + #ifdef ASN1_R_TOO_LARGE + {"TOO_LARGE", ERR_LIB_ASN1, ASN1_R_TOO_LARGE}, + #else + {"TOO_LARGE", 13, 223}, + #endif + #ifdef ASN1_R_TOO_LONG + {"TOO_LONG", ERR_LIB_ASN1, ASN1_R_TOO_LONG}, + #else + {"TOO_LONG", 13, 155}, + #endif + #ifdef ASN1_R_TOO_SMALL + {"TOO_SMALL", ERR_LIB_ASN1, ASN1_R_TOO_SMALL}, + #else + {"TOO_SMALL", 13, 224}, + #endif + #ifdef ASN1_R_TYPE_NOT_CONSTRUCTED + {"TYPE_NOT_CONSTRUCTED", ERR_LIB_ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED}, + #else + {"TYPE_NOT_CONSTRUCTED", 13, 156}, + #endif + #ifdef ASN1_R_TYPE_NOT_PRIMITIVE + {"TYPE_NOT_PRIMITIVE", ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE}, + #else + {"TYPE_NOT_PRIMITIVE", 13, 195}, + #endif + #ifdef ASN1_R_UNEXPECTED_EOC + {"UNEXPECTED_EOC", ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC}, + #else + {"UNEXPECTED_EOC", 13, 159}, + #endif + #ifdef ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH + {"UNIVERSALSTRING_IS_WRONG_LENGTH", ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH}, + #else + {"UNIVERSALSTRING_IS_WRONG_LENGTH", 13, 215}, + #endif + #ifdef ASN1_R_UNKNOWN_DIGEST + {"UNKNOWN_DIGEST", ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST}, + #else + {"UNKNOWN_DIGEST", 13, 229}, + #endif + #ifdef ASN1_R_UNKNOWN_FORMAT + {"UNKNOWN_FORMAT", ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT}, + #else + {"UNKNOWN_FORMAT", 13, 160}, + #endif + #ifdef ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM + {"UNKNOWN_MESSAGE_DIGEST_ALGORITHM", ERR_LIB_ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM}, + #else + {"UNKNOWN_MESSAGE_DIGEST_ALGORITHM", 13, 161}, + #endif + #ifdef ASN1_R_UNKNOWN_OBJECT_TYPE + {"UNKNOWN_OBJECT_TYPE", ERR_LIB_ASN1, ASN1_R_UNKNOWN_OBJECT_TYPE}, + #else + {"UNKNOWN_OBJECT_TYPE", 13, 162}, + #endif + #ifdef ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE + {"UNKNOWN_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE}, + #else + {"UNKNOWN_PUBLIC_KEY_TYPE", 13, 163}, + #endif + #ifdef ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM + {"UNKNOWN_SIGNATURE_ALGORITHM", ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM}, + #else + {"UNKNOWN_SIGNATURE_ALGORITHM", 13, 199}, + #endif + #ifdef ASN1_R_UNKNOWN_TAG + {"UNKNOWN_TAG", ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG}, + #else + {"UNKNOWN_TAG", 13, 194}, + #endif + #ifdef ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE + {"UNSUPPORTED_ANY_DEFINED_BY_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE}, + #else + {"UNSUPPORTED_ANY_DEFINED_BY_TYPE", 13, 164}, + #endif + #ifdef ASN1_R_UNSUPPORTED_CIPHER + {"UNSUPPORTED_CIPHER", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_CIPHER}, + #else + {"UNSUPPORTED_CIPHER", 13, 228}, + #endif + #ifdef ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE + {"UNSUPPORTED_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE}, + #else + {"UNSUPPORTED_PUBLIC_KEY_TYPE", 13, 167}, + #endif + #ifdef ASN1_R_UNSUPPORTED_TYPE + {"UNSUPPORTED_TYPE", ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE}, + #else + {"UNSUPPORTED_TYPE", 13, 196}, + #endif + #ifdef ASN1_R_UTCTIME_IS_TOO_SHORT + {"UTCTIME_IS_TOO_SHORT", ERR_LIB_ASN1, ASN1_R_UTCTIME_IS_TOO_SHORT}, + #else + {"UTCTIME_IS_TOO_SHORT", 13, 233}, + #endif + #ifdef ASN1_R_WRONG_INTEGER_TYPE + {"WRONG_INTEGER_TYPE", ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE}, + #else + {"WRONG_INTEGER_TYPE", 13, 225}, + #endif + #ifdef ASN1_R_WRONG_PUBLIC_KEY_TYPE + {"WRONG_PUBLIC_KEY_TYPE", ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE}, + #else + {"WRONG_PUBLIC_KEY_TYPE", 13, 200}, + #endif + #ifdef ASN1_R_WRONG_TAG + {"WRONG_TAG", ERR_LIB_ASN1, ASN1_R_WRONG_TAG}, + #else + {"WRONG_TAG", 13, 168}, + #endif + #ifdef ASYNC_R_FAILED_TO_SET_POOL + {"FAILED_TO_SET_POOL", ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL}, + #else + {"FAILED_TO_SET_POOL", 51, 101}, + #endif + #ifdef ASYNC_R_FAILED_TO_SWAP_CONTEXT + {"FAILED_TO_SWAP_CONTEXT", ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT}, + #else + {"FAILED_TO_SWAP_CONTEXT", 51, 102}, + #endif + #ifdef ASYNC_R_INIT_FAILED + {"INIT_FAILED", ERR_LIB_ASYNC, ASYNC_R_INIT_FAILED}, + #else + {"INIT_FAILED", 51, 105}, + #endif + #ifdef ASYNC_R_INVALID_POOL_SIZE + {"INVALID_POOL_SIZE", ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE}, + #else + {"INVALID_POOL_SIZE", 51, 103}, + #endif + #ifdef BIO_R_ACCEPT_ERROR + {"ACCEPT_ERROR", ERR_LIB_BIO, BIO_R_ACCEPT_ERROR}, + #else + {"ACCEPT_ERROR", 32, 100}, + #endif + #ifdef BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET + {"ADDRINFO_ADDR_IS_NOT_AF_INET", ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET}, + #else + {"ADDRINFO_ADDR_IS_NOT_AF_INET", 32, 141}, + #endif + #ifdef BIO_R_AMBIGUOUS_HOST_OR_SERVICE + {"AMBIGUOUS_HOST_OR_SERVICE", ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE}, + #else + {"AMBIGUOUS_HOST_OR_SERVICE", 32, 129}, + #endif + #ifdef BIO_R_BAD_FOPEN_MODE + {"BAD_FOPEN_MODE", ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE}, + #else + {"BAD_FOPEN_MODE", 32, 101}, + #endif + #ifdef BIO_R_BROKEN_PIPE + {"BROKEN_PIPE", ERR_LIB_BIO, BIO_R_BROKEN_PIPE}, + #else + {"BROKEN_PIPE", 32, 124}, + #endif + #ifdef BIO_R_CONNECT_ERROR + {"CONNECT_ERROR", ERR_LIB_BIO, BIO_R_CONNECT_ERROR}, + #else + {"CONNECT_ERROR", 32, 103}, + #endif + #ifdef BIO_R_CONNECT_TIMEOUT + {"CONNECT_TIMEOUT", ERR_LIB_BIO, BIO_R_CONNECT_TIMEOUT}, + #else + {"CONNECT_TIMEOUT", 32, 147}, + #endif + #ifdef BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET + {"GETHOSTBYNAME_ADDR_IS_NOT_AF_INET", ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET}, + #else + {"GETHOSTBYNAME_ADDR_IS_NOT_AF_INET", 32, 107}, + #endif + #ifdef BIO_R_GETSOCKNAME_ERROR + {"GETSOCKNAME_ERROR", ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR}, + #else + {"GETSOCKNAME_ERROR", 32, 132}, + #endif + #ifdef BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS + {"GETSOCKNAME_TRUNCATED_ADDRESS", ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS}, + #else + {"GETSOCKNAME_TRUNCATED_ADDRESS", 32, 133}, + #endif + #ifdef BIO_R_GETTING_SOCKTYPE + {"GETTING_SOCKTYPE", ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE}, + #else + {"GETTING_SOCKTYPE", 32, 134}, + #endif + #ifdef BIO_R_INVALID_ARGUMENT + {"INVALID_ARGUMENT", ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT}, + #else + {"INVALID_ARGUMENT", 32, 125}, + #endif + #ifdef BIO_R_INVALID_SOCKET + {"INVALID_SOCKET", ERR_LIB_BIO, BIO_R_INVALID_SOCKET}, + #else + {"INVALID_SOCKET", 32, 135}, + #endif + #ifdef BIO_R_IN_USE + {"IN_USE", ERR_LIB_BIO, BIO_R_IN_USE}, + #else + {"IN_USE", 32, 123}, + #endif + #ifdef BIO_R_LENGTH_TOO_LONG + {"LENGTH_TOO_LONG", ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG}, + #else + {"LENGTH_TOO_LONG", 32, 102}, + #endif + #ifdef BIO_R_LISTEN_V6_ONLY + {"LISTEN_V6_ONLY", ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY}, + #else + {"LISTEN_V6_ONLY", 32, 136}, + #endif + #ifdef BIO_R_LOCAL_ADDR_NOT_AVAILABLE + {"LOCAL_ADDR_NOT_AVAILABLE", ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE}, + #else + {"LOCAL_ADDR_NOT_AVAILABLE", 32, 111}, + #endif + #ifdef BIO_R_LOOKUP_RETURNED_NOTHING + {"LOOKUP_RETURNED_NOTHING", ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING}, + #else + {"LOOKUP_RETURNED_NOTHING", 32, 142}, + #endif + #ifdef BIO_R_MALFORMED_HOST_OR_SERVICE + {"MALFORMED_HOST_OR_SERVICE", ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE}, + #else + {"MALFORMED_HOST_OR_SERVICE", 32, 130}, + #endif + #ifdef BIO_R_NBIO_CONNECT_ERROR + {"NBIO_CONNECT_ERROR", ERR_LIB_BIO, BIO_R_NBIO_CONNECT_ERROR}, + #else + {"NBIO_CONNECT_ERROR", 32, 110}, + #endif + #ifdef BIO_R_NON_FATAL + {"NON_FATAL", ERR_LIB_BIO, BIO_R_NON_FATAL}, + #else + {"NON_FATAL", 32, 112}, + #endif + #ifdef BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED + {"NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED", ERR_LIB_BIO, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED}, + #else + {"NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED", 32, 143}, + #endif + #ifdef BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED + {"NO_HOSTNAME_OR_SERVICE_SPECIFIED", ERR_LIB_BIO, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED}, + #else + {"NO_HOSTNAME_OR_SERVICE_SPECIFIED", 32, 144}, + #endif + #ifdef BIO_R_NO_PORT_DEFINED + {"NO_PORT_DEFINED", ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED}, + #else + {"NO_PORT_DEFINED", 32, 113}, + #endif + #ifdef BIO_R_NO_SUCH_FILE + {"NO_SUCH_FILE", ERR_LIB_BIO, BIO_R_NO_SUCH_FILE}, + #else + {"NO_SUCH_FILE", 32, 128}, + #endif + #ifdef BIO_R_PEER_ADDR_NOT_AVAILABLE + {"PEER_ADDR_NOT_AVAILABLE", ERR_LIB_BIO, BIO_R_PEER_ADDR_NOT_AVAILABLE}, + #else + {"PEER_ADDR_NOT_AVAILABLE", 32, 114}, + #endif + #ifdef BIO_R_PORT_MISMATCH + {"PORT_MISMATCH", ERR_LIB_BIO, BIO_R_PORT_MISMATCH}, + #else + {"PORT_MISMATCH", 32, 150}, + #endif + #ifdef BIO_R_TFO_DISABLED + {"TFO_DISABLED", ERR_LIB_BIO, BIO_R_TFO_DISABLED}, + #else + {"TFO_DISABLED", 32, 106}, + #endif + #ifdef BIO_R_TFO_NO_KERNEL_SUPPORT + {"TFO_NO_KERNEL_SUPPORT", ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT}, + #else + {"TFO_NO_KERNEL_SUPPORT", 32, 108}, + #endif + #ifdef BIO_R_TRANSFER_ERROR + {"TRANSFER_ERROR", ERR_LIB_BIO, BIO_R_TRANSFER_ERROR}, + #else + {"TRANSFER_ERROR", 32, 104}, + #endif + #ifdef BIO_R_TRANSFER_TIMEOUT + {"TRANSFER_TIMEOUT", ERR_LIB_BIO, BIO_R_TRANSFER_TIMEOUT}, + #else + {"TRANSFER_TIMEOUT", 32, 105}, + #endif + #ifdef BIO_R_UNABLE_TO_BIND_SOCKET + {"UNABLE_TO_BIND_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET}, + #else + {"UNABLE_TO_BIND_SOCKET", 32, 117}, + #endif + #ifdef BIO_R_UNABLE_TO_CREATE_SOCKET + {"UNABLE_TO_CREATE_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET}, + #else + {"UNABLE_TO_CREATE_SOCKET", 32, 118}, + #endif + #ifdef BIO_R_UNABLE_TO_KEEPALIVE + {"UNABLE_TO_KEEPALIVE", ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE}, + #else + {"UNABLE_TO_KEEPALIVE", 32, 137}, + #endif + #ifdef BIO_R_UNABLE_TO_LISTEN_SOCKET + {"UNABLE_TO_LISTEN_SOCKET", ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET}, + #else + {"UNABLE_TO_LISTEN_SOCKET", 32, 119}, + #endif + #ifdef BIO_R_UNABLE_TO_NODELAY + {"UNABLE_TO_NODELAY", ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY}, + #else + {"UNABLE_TO_NODELAY", 32, 138}, + #endif + #ifdef BIO_R_UNABLE_TO_REUSEADDR + {"UNABLE_TO_REUSEADDR", ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR}, + #else + {"UNABLE_TO_REUSEADDR", 32, 139}, + #endif + #ifdef BIO_R_UNABLE_TO_TFO + {"UNABLE_TO_TFO", ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO}, + #else + {"UNABLE_TO_TFO", 32, 109}, + #endif + #ifdef BIO_R_UNAVAILABLE_IP_FAMILY + {"UNAVAILABLE_IP_FAMILY", ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY}, + #else + {"UNAVAILABLE_IP_FAMILY", 32, 145}, + #endif + #ifdef BIO_R_UNINITIALIZED + {"UNINITIALIZED", ERR_LIB_BIO, BIO_R_UNINITIALIZED}, + #else + {"UNINITIALIZED", 32, 120}, + #endif + #ifdef BIO_R_UNKNOWN_INFO_TYPE + {"UNKNOWN_INFO_TYPE", ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE}, + #else + {"UNKNOWN_INFO_TYPE", 32, 140}, + #endif + #ifdef BIO_R_UNSUPPORTED_IP_FAMILY + {"UNSUPPORTED_IP_FAMILY", ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY}, + #else + {"UNSUPPORTED_IP_FAMILY", 32, 146}, + #endif + #ifdef BIO_R_UNSUPPORTED_METHOD + {"UNSUPPORTED_METHOD", ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD}, + #else + {"UNSUPPORTED_METHOD", 32, 121}, + #endif + #ifdef BIO_R_UNSUPPORTED_PROTOCOL_FAMILY + {"UNSUPPORTED_PROTOCOL_FAMILY", ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY}, + #else + {"UNSUPPORTED_PROTOCOL_FAMILY", 32, 131}, + #endif + #ifdef BIO_R_WRITE_TO_READ_ONLY_BIO + {"WRITE_TO_READ_ONLY_BIO", ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO}, + #else + {"WRITE_TO_READ_ONLY_BIO", 32, 126}, + #endif + #ifdef BIO_R_WSASTARTUP + {"WSASTARTUP", ERR_LIB_BIO, BIO_R_WSASTARTUP}, + #else + {"WSASTARTUP", 32, 122}, + #endif + #ifdef BN_R_ARG2_LT_ARG3 + {"ARG2_LT_ARG3", ERR_LIB_BN, BN_R_ARG2_LT_ARG3}, + #else + {"ARG2_LT_ARG3", 3, 100}, + #endif + #ifdef BN_R_BAD_RECIPROCAL + {"BAD_RECIPROCAL", ERR_LIB_BN, BN_R_BAD_RECIPROCAL}, + #else + {"BAD_RECIPROCAL", 3, 101}, + #endif + #ifdef BN_R_BIGNUM_TOO_LONG + {"BIGNUM_TOO_LONG", ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG}, + #else + {"BIGNUM_TOO_LONG", 3, 114}, + #endif + #ifdef BN_R_BITS_TOO_SMALL + {"BITS_TOO_SMALL", ERR_LIB_BN, BN_R_BITS_TOO_SMALL}, + #else + {"BITS_TOO_SMALL", 3, 118}, + #endif + #ifdef BN_R_CALLED_WITH_EVEN_MODULUS + {"CALLED_WITH_EVEN_MODULUS", ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS}, + #else + {"CALLED_WITH_EVEN_MODULUS", 3, 102}, + #endif + #ifdef BN_R_DIV_BY_ZERO + {"DIV_BY_ZERO", ERR_LIB_BN, BN_R_DIV_BY_ZERO}, + #else + {"DIV_BY_ZERO", 3, 103}, + #endif + #ifdef BN_R_ENCODING_ERROR + {"ENCODING_ERROR", ERR_LIB_BN, BN_R_ENCODING_ERROR}, + #else + {"ENCODING_ERROR", 3, 104}, + #endif + #ifdef BN_R_EXPAND_ON_STATIC_BIGNUM_DATA + {"EXPAND_ON_STATIC_BIGNUM_DATA", ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA}, + #else + {"EXPAND_ON_STATIC_BIGNUM_DATA", 3, 105}, + #endif + #ifdef BN_R_INPUT_NOT_REDUCED + {"INPUT_NOT_REDUCED", ERR_LIB_BN, BN_R_INPUT_NOT_REDUCED}, + #else + {"INPUT_NOT_REDUCED", 3, 110}, + #endif + #ifdef BN_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_BN, BN_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 3, 106}, + #endif + #ifdef BN_R_INVALID_RANGE + {"INVALID_RANGE", ERR_LIB_BN, BN_R_INVALID_RANGE}, + #else + {"INVALID_RANGE", 3, 115}, + #endif + #ifdef BN_R_INVALID_SHIFT + {"INVALID_SHIFT", ERR_LIB_BN, BN_R_INVALID_SHIFT}, + #else + {"INVALID_SHIFT", 3, 119}, + #endif + #ifdef BN_R_NOT_A_SQUARE + {"NOT_A_SQUARE", ERR_LIB_BN, BN_R_NOT_A_SQUARE}, + #else + {"NOT_A_SQUARE", 3, 111}, + #endif + #ifdef BN_R_NOT_INITIALIZED + {"NOT_INITIALIZED", ERR_LIB_BN, BN_R_NOT_INITIALIZED}, + #else + {"NOT_INITIALIZED", 3, 107}, + #endif + #ifdef BN_R_NO_INVERSE + {"NO_INVERSE", ERR_LIB_BN, BN_R_NO_INVERSE}, + #else + {"NO_INVERSE", 3, 108}, + #endif + #ifdef BN_R_NO_PRIME_CANDIDATE + {"NO_PRIME_CANDIDATE", ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE}, + #else + {"NO_PRIME_CANDIDATE", 3, 121}, + #endif + #ifdef BN_R_NO_SOLUTION + {"NO_SOLUTION", ERR_LIB_BN, BN_R_NO_SOLUTION}, + #else + {"NO_SOLUTION", 3, 116}, + #endif + #ifdef BN_R_NO_SUITABLE_DIGEST + {"NO_SUITABLE_DIGEST", ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST}, + #else + {"NO_SUITABLE_DIGEST", 3, 120}, + #endif + #ifdef BN_R_PRIVATE_KEY_TOO_LARGE + {"PRIVATE_KEY_TOO_LARGE", ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE}, + #else + {"PRIVATE_KEY_TOO_LARGE", 3, 117}, + #endif + #ifdef BN_R_P_IS_NOT_PRIME + {"P_IS_NOT_PRIME", ERR_LIB_BN, BN_R_P_IS_NOT_PRIME}, + #else + {"P_IS_NOT_PRIME", 3, 112}, + #endif + #ifdef BN_R_TOO_MANY_ITERATIONS + {"TOO_MANY_ITERATIONS", ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS}, + #else + {"TOO_MANY_ITERATIONS", 3, 113}, + #endif + #ifdef BN_R_TOO_MANY_TEMPORARY_VARIABLES + {"TOO_MANY_TEMPORARY_VARIABLES", ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES}, + #else + {"TOO_MANY_TEMPORARY_VARIABLES", 3, 109}, + #endif + #ifdef CMP_R_ALGORITHM_NOT_SUPPORTED + {"ALGORITHM_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_ALGORITHM_NOT_SUPPORTED}, + #else + {"ALGORITHM_NOT_SUPPORTED", 58, 139}, + #endif + #ifdef CMP_R_BAD_CHECKAFTER_IN_POLLREP + {"BAD_CHECKAFTER_IN_POLLREP", ERR_LIB_CMP, CMP_R_BAD_CHECKAFTER_IN_POLLREP}, + #else + {"BAD_CHECKAFTER_IN_POLLREP", 58, 167}, + #endif + #ifdef CMP_R_BAD_REQUEST_ID + {"BAD_REQUEST_ID", ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID}, + #else + {"BAD_REQUEST_ID", 58, 108}, + #endif + #ifdef CMP_R_CERTHASH_UNMATCHED + {"CERTHASH_UNMATCHED", ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED}, + #else + {"CERTHASH_UNMATCHED", 58, 156}, + #endif + #ifdef CMP_R_CERTID_NOT_FOUND + {"CERTID_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND}, + #else + {"CERTID_NOT_FOUND", 58, 109}, + #endif + #ifdef CMP_R_CERTIFICATE_NOT_ACCEPTED + {"CERTIFICATE_NOT_ACCEPTED", ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED}, + #else + {"CERTIFICATE_NOT_ACCEPTED", 58, 169}, + #endif + #ifdef CMP_R_CERTIFICATE_NOT_FOUND + {"CERTIFICATE_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND}, + #else + {"CERTIFICATE_NOT_FOUND", 58, 112}, + #endif + #ifdef CMP_R_CERTREQMSG_NOT_FOUND + {"CERTREQMSG_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND}, + #else + {"CERTREQMSG_NOT_FOUND", 58, 157}, + #endif + #ifdef CMP_R_CERTRESPONSE_NOT_FOUND + {"CERTRESPONSE_NOT_FOUND", ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND}, + #else + {"CERTRESPONSE_NOT_FOUND", 58, 113}, + #endif + #ifdef CMP_R_CERT_AND_KEY_DO_NOT_MATCH + {"CERT_AND_KEY_DO_NOT_MATCH", ERR_LIB_CMP, CMP_R_CERT_AND_KEY_DO_NOT_MATCH}, + #else + {"CERT_AND_KEY_DO_NOT_MATCH", 58, 114}, + #endif + #ifdef CMP_R_CHECKAFTER_OUT_OF_RANGE + {"CHECKAFTER_OUT_OF_RANGE", ERR_LIB_CMP, CMP_R_CHECKAFTER_OUT_OF_RANGE}, + #else + {"CHECKAFTER_OUT_OF_RANGE", 58, 181}, + #endif + #ifdef CMP_R_ENCOUNTERED_KEYUPDATEWARNING + {"ENCOUNTERED_KEYUPDATEWARNING", ERR_LIB_CMP, CMP_R_ENCOUNTERED_KEYUPDATEWARNING}, + #else + {"ENCOUNTERED_KEYUPDATEWARNING", 58, 176}, + #endif + #ifdef CMP_R_ENCOUNTERED_WAITING + {"ENCOUNTERED_WAITING", ERR_LIB_CMP, CMP_R_ENCOUNTERED_WAITING}, + #else + {"ENCOUNTERED_WAITING", 58, 162}, + #endif + #ifdef CMP_R_ERROR_CALCULATING_PROTECTION + {"ERROR_CALCULATING_PROTECTION", ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION}, + #else + {"ERROR_CALCULATING_PROTECTION", 58, 115}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTCONF + {"ERROR_CREATING_CERTCONF", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF}, + #else + {"ERROR_CREATING_CERTCONF", 58, 116}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTREP + {"ERROR_CREATING_CERTREP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP}, + #else + {"ERROR_CREATING_CERTREP", 58, 117}, + #endif + #ifdef CMP_R_ERROR_CREATING_CERTREQ + {"ERROR_CREATING_CERTREQ", ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ}, + #else + {"ERROR_CREATING_CERTREQ", 58, 163}, + #endif + #ifdef CMP_R_ERROR_CREATING_ERROR + {"ERROR_CREATING_ERROR", ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR}, + #else + {"ERROR_CREATING_ERROR", 58, 118}, + #endif + #ifdef CMP_R_ERROR_CREATING_GENM + {"ERROR_CREATING_GENM", ERR_LIB_CMP, CMP_R_ERROR_CREATING_GENM}, + #else + {"ERROR_CREATING_GENM", 58, 119}, + #endif + #ifdef CMP_R_ERROR_CREATING_GENP + {"ERROR_CREATING_GENP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_GENP}, + #else + {"ERROR_CREATING_GENP", 58, 120}, + #endif + #ifdef CMP_R_ERROR_CREATING_PKICONF + {"ERROR_CREATING_PKICONF", ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF}, + #else + {"ERROR_CREATING_PKICONF", 58, 122}, + #endif + #ifdef CMP_R_ERROR_CREATING_POLLREP + {"ERROR_CREATING_POLLREP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP}, + #else + {"ERROR_CREATING_POLLREP", 58, 123}, + #endif + #ifdef CMP_R_ERROR_CREATING_POLLREQ + {"ERROR_CREATING_POLLREQ", ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ}, + #else + {"ERROR_CREATING_POLLREQ", 58, 124}, + #endif + #ifdef CMP_R_ERROR_CREATING_RP + {"ERROR_CREATING_RP", ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP}, + #else + {"ERROR_CREATING_RP", 58, 125}, + #endif + #ifdef CMP_R_ERROR_CREATING_RR + {"ERROR_CREATING_RR", ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR}, + #else + {"ERROR_CREATING_RR", 58, 126}, + #endif + #ifdef CMP_R_ERROR_PARSING_PKISTATUS + {"ERROR_PARSING_PKISTATUS", ERR_LIB_CMP, CMP_R_ERROR_PARSING_PKISTATUS}, + #else + {"ERROR_PARSING_PKISTATUS", 58, 107}, + #endif + #ifdef CMP_R_ERROR_PROCESSING_MESSAGE + {"ERROR_PROCESSING_MESSAGE", ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE}, + #else + {"ERROR_PROCESSING_MESSAGE", 58, 158}, + #endif + #ifdef CMP_R_ERROR_PROTECTING_MESSAGE + {"ERROR_PROTECTING_MESSAGE", ERR_LIB_CMP, CMP_R_ERROR_PROTECTING_MESSAGE}, + #else + {"ERROR_PROTECTING_MESSAGE", 58, 127}, + #endif + #ifdef CMP_R_ERROR_SETTING_CERTHASH + {"ERROR_SETTING_CERTHASH", ERR_LIB_CMP, CMP_R_ERROR_SETTING_CERTHASH}, + #else + {"ERROR_SETTING_CERTHASH", 58, 128}, + #endif + #ifdef CMP_R_ERROR_UNEXPECTED_CERTCONF + {"ERROR_UNEXPECTED_CERTCONF", ERR_LIB_CMP, CMP_R_ERROR_UNEXPECTED_CERTCONF}, + #else + {"ERROR_UNEXPECTED_CERTCONF", 58, 160}, + #endif + #ifdef CMP_R_ERROR_VALIDATING_PROTECTION + {"ERROR_VALIDATING_PROTECTION", ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION}, + #else + {"ERROR_VALIDATING_PROTECTION", 58, 140}, + #endif + #ifdef CMP_R_ERROR_VALIDATING_SIGNATURE + {"ERROR_VALIDATING_SIGNATURE", ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE}, + #else + {"ERROR_VALIDATING_SIGNATURE", 58, 171}, + #endif + #ifdef CMP_R_EXPECTED_POLLREQ + {"EXPECTED_POLLREQ", ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ}, + #else + {"EXPECTED_POLLREQ", 58, 104}, + #endif + #ifdef CMP_R_FAILED_BUILDING_OWN_CHAIN + {"FAILED_BUILDING_OWN_CHAIN", ERR_LIB_CMP, CMP_R_FAILED_BUILDING_OWN_CHAIN}, + #else + {"FAILED_BUILDING_OWN_CHAIN", 58, 164}, + #endif + #ifdef CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY + {"FAILED_EXTRACTING_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY}, + #else + {"FAILED_EXTRACTING_CENTRAL_GEN_KEY", 58, 203}, + #endif + #ifdef CMP_R_FAILED_EXTRACTING_PUBKEY + {"FAILED_EXTRACTING_PUBKEY", ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_PUBKEY}, + #else + {"FAILED_EXTRACTING_PUBKEY", 58, 141}, + #endif + #ifdef CMP_R_FAILURE_OBTAINING_RANDOM + {"FAILURE_OBTAINING_RANDOM", ERR_LIB_CMP, CMP_R_FAILURE_OBTAINING_RANDOM}, + #else + {"FAILURE_OBTAINING_RANDOM", 58, 110}, + #endif + #ifdef CMP_R_FAIL_INFO_OUT_OF_RANGE + {"FAIL_INFO_OUT_OF_RANGE", ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE}, + #else + {"FAIL_INFO_OUT_OF_RANGE", 58, 129}, + #endif + #ifdef CMP_R_GENERATE_CERTREQTEMPLATE + {"GENERATE_CERTREQTEMPLATE", ERR_LIB_CMP, CMP_R_GENERATE_CERTREQTEMPLATE}, + #else + {"GENERATE_CERTREQTEMPLATE", 58, 197}, + #endif + #ifdef CMP_R_GENERATE_CRLSTATUS + {"GENERATE_CRLSTATUS", ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS}, + #else + {"GENERATE_CRLSTATUS", 58, 198}, + #endif + #ifdef CMP_R_GETTING_GENP + {"GETTING_GENP", ERR_LIB_CMP, CMP_R_GETTING_GENP}, + #else + {"GETTING_GENP", 58, 192}, + #endif + #ifdef CMP_R_GET_ITAV + {"GET_ITAV", ERR_LIB_CMP, CMP_R_GET_ITAV}, + #else + {"GET_ITAV", 58, 199}, + #endif + #ifdef CMP_R_INVALID_ARGS + {"INVALID_ARGS", ERR_LIB_CMP, CMP_R_INVALID_ARGS}, + #else + {"INVALID_ARGS", 58, 100}, + #endif + #ifdef CMP_R_INVALID_GENP + {"INVALID_GENP", ERR_LIB_CMP, CMP_R_INVALID_GENP}, + #else + {"INVALID_GENP", 58, 193}, + #endif + #ifdef CMP_R_INVALID_KEYSPEC + {"INVALID_KEYSPEC", ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC}, + #else + {"INVALID_KEYSPEC", 58, 202}, + #endif + #ifdef CMP_R_INVALID_OPTION + {"INVALID_OPTION", ERR_LIB_CMP, CMP_R_INVALID_OPTION}, + #else + {"INVALID_OPTION", 58, 174}, + #endif + #ifdef CMP_R_INVALID_ROOTCAKEYUPDATE + {"INVALID_ROOTCAKEYUPDATE", ERR_LIB_CMP, CMP_R_INVALID_ROOTCAKEYUPDATE}, + #else + {"INVALID_ROOTCAKEYUPDATE", 58, 195}, + #endif + #ifdef CMP_R_MISSING_CENTRAL_GEN_KEY + {"MISSING_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_MISSING_CENTRAL_GEN_KEY}, + #else + {"MISSING_CENTRAL_GEN_KEY", 58, 204}, + #endif + #ifdef CMP_R_MISSING_CERTID + {"MISSING_CERTID", ERR_LIB_CMP, CMP_R_MISSING_CERTID}, + #else + {"MISSING_CERTID", 58, 165}, + #endif + #ifdef CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION + {"MISSING_KEY_INPUT_FOR_CREATING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION}, + #else + {"MISSING_KEY_INPUT_FOR_CREATING_PROTECTION", 58, 130}, + #endif + #ifdef CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE + {"MISSING_KEY_USAGE_DIGITALSIGNATURE", ERR_LIB_CMP, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE}, + #else + {"MISSING_KEY_USAGE_DIGITALSIGNATURE", 58, 142}, + #endif + #ifdef CMP_R_MISSING_P10CSR + {"MISSING_P10CSR", ERR_LIB_CMP, CMP_R_MISSING_P10CSR}, + #else + {"MISSING_P10CSR", 58, 121}, + #endif + #ifdef CMP_R_MISSING_PBM_SECRET + {"MISSING_PBM_SECRET", ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET}, + #else + {"MISSING_PBM_SECRET", 58, 166}, + #endif + #ifdef CMP_R_MISSING_PRIVATE_KEY + {"MISSING_PRIVATE_KEY", ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY}, + #else + {"MISSING_PRIVATE_KEY", 58, 131}, + #endif + #ifdef CMP_R_MISSING_PRIVATE_KEY_FOR_POPO + {"MISSING_PRIVATE_KEY_FOR_POPO", ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO}, + #else + {"MISSING_PRIVATE_KEY_FOR_POPO", 58, 190}, + #endif + #ifdef CMP_R_MISSING_PROTECTION + {"MISSING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_PROTECTION}, + #else + {"MISSING_PROTECTION", 58, 143}, + #endif + #ifdef CMP_R_MISSING_PUBLIC_KEY + {"MISSING_PUBLIC_KEY", ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY}, + #else + {"MISSING_PUBLIC_KEY", 58, 183}, + #endif + #ifdef CMP_R_MISSING_REFERENCE_CERT + {"MISSING_REFERENCE_CERT", ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT}, + #else + {"MISSING_REFERENCE_CERT", 58, 168}, + #endif + #ifdef CMP_R_MISSING_SECRET + {"MISSING_SECRET", ERR_LIB_CMP, CMP_R_MISSING_SECRET}, + #else + {"MISSING_SECRET", 58, 178}, + #endif + #ifdef CMP_R_MISSING_SENDER_IDENTIFICATION + {"MISSING_SENDER_IDENTIFICATION", ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION}, + #else + {"MISSING_SENDER_IDENTIFICATION", 58, 111}, + #endif + #ifdef CMP_R_MISSING_TRUST_ANCHOR + {"MISSING_TRUST_ANCHOR", ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR}, + #else + {"MISSING_TRUST_ANCHOR", 58, 179}, + #endif + #ifdef CMP_R_MISSING_TRUST_STORE + {"MISSING_TRUST_STORE", ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE}, + #else + {"MISSING_TRUST_STORE", 58, 144}, + #endif + #ifdef CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED + {"MULTIPLE_REQUESTS_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED}, + #else + {"MULTIPLE_REQUESTS_NOT_SUPPORTED", 58, 161}, + #endif + #ifdef CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED + {"MULTIPLE_RESPONSES_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED}, + #else + {"MULTIPLE_RESPONSES_NOT_SUPPORTED", 58, 170}, + #endif + #ifdef CMP_R_MULTIPLE_SAN_SOURCES + {"MULTIPLE_SAN_SOURCES", ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES}, + #else + {"MULTIPLE_SAN_SOURCES", 58, 102}, + #endif + #ifdef CMP_R_NO_STDIO + {"NO_STDIO", ERR_LIB_CMP, CMP_R_NO_STDIO}, + #else + {"NO_STDIO", 58, 194}, + #endif + #ifdef CMP_R_NO_SUITABLE_SENDER_CERT + {"NO_SUITABLE_SENDER_CERT", ERR_LIB_CMP, CMP_R_NO_SUITABLE_SENDER_CERT}, + #else + {"NO_SUITABLE_SENDER_CERT", 58, 145}, + #endif + #ifdef CMP_R_NULL_ARGUMENT + {"NULL_ARGUMENT", ERR_LIB_CMP, CMP_R_NULL_ARGUMENT}, + #else + {"NULL_ARGUMENT", 58, 103}, + #endif + #ifdef CMP_R_PKIBODY_ERROR + {"PKIBODY_ERROR", ERR_LIB_CMP, CMP_R_PKIBODY_ERROR}, + #else + {"PKIBODY_ERROR", 58, 146}, + #endif + #ifdef CMP_R_PKISTATUSINFO_NOT_FOUND + {"PKISTATUSINFO_NOT_FOUND", ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND}, + #else + {"PKISTATUSINFO_NOT_FOUND", 58, 132}, + #endif + #ifdef CMP_R_POLLING_FAILED + {"POLLING_FAILED", ERR_LIB_CMP, CMP_R_POLLING_FAILED}, + #else + {"POLLING_FAILED", 58, 172}, + #endif + #ifdef CMP_R_POTENTIALLY_INVALID_CERTIFICATE + {"POTENTIALLY_INVALID_CERTIFICATE", ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE}, + #else + {"POTENTIALLY_INVALID_CERTIFICATE", 58, 147}, + #endif + #ifdef CMP_R_RECEIVED_ERROR + {"RECEIVED_ERROR", ERR_LIB_CMP, CMP_R_RECEIVED_ERROR}, + #else + {"RECEIVED_ERROR", 58, 180}, + #endif + #ifdef CMP_R_RECIPNONCE_UNMATCHED + {"RECIPNONCE_UNMATCHED", ERR_LIB_CMP, CMP_R_RECIPNONCE_UNMATCHED}, + #else + {"RECIPNONCE_UNMATCHED", 58, 148}, + #endif + #ifdef CMP_R_REQUEST_NOT_ACCEPTED + {"REQUEST_NOT_ACCEPTED", ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED}, + #else + {"REQUEST_NOT_ACCEPTED", 58, 149}, + #endif + #ifdef CMP_R_REQUEST_REJECTED_BY_SERVER + {"REQUEST_REJECTED_BY_SERVER", ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER}, + #else + {"REQUEST_REJECTED_BY_SERVER", 58, 182}, + #endif + #ifdef CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED + {"SENDER_GENERALNAME_TYPE_NOT_SUPPORTED", ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED}, + #else + {"SENDER_GENERALNAME_TYPE_NOT_SUPPORTED", 58, 150}, + #endif + #ifdef CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG + {"SRVCERT_DOES_NOT_VALIDATE_MSG", ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG}, + #else + {"SRVCERT_DOES_NOT_VALIDATE_MSG", 58, 151}, + #endif + #ifdef CMP_R_TOTAL_TIMEOUT + {"TOTAL_TIMEOUT", ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT}, + #else + {"TOTAL_TIMEOUT", 58, 184}, + #endif + #ifdef CMP_R_TRANSACTIONID_UNMATCHED + {"TRANSACTIONID_UNMATCHED", ERR_LIB_CMP, CMP_R_TRANSACTIONID_UNMATCHED}, + #else + {"TRANSACTIONID_UNMATCHED", 58, 152}, + #endif + #ifdef CMP_R_TRANSFER_ERROR + {"TRANSFER_ERROR", ERR_LIB_CMP, CMP_R_TRANSFER_ERROR}, + #else + {"TRANSFER_ERROR", 58, 159}, + #endif + #ifdef CMP_R_UNCLEAN_CTX + {"UNCLEAN_CTX", ERR_LIB_CMP, CMP_R_UNCLEAN_CTX}, + #else + {"UNCLEAN_CTX", 58, 191}, + #endif + #ifdef CMP_R_UNEXPECTED_CENTRAL_GEN_KEY + {"UNEXPECTED_CENTRAL_GEN_KEY", ERR_LIB_CMP, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY}, + #else + {"UNEXPECTED_CENTRAL_GEN_KEY", 58, 205}, + #endif + #ifdef CMP_R_UNEXPECTED_CERTPROFILE + {"UNEXPECTED_CERTPROFILE", ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE}, + #else + {"UNEXPECTED_CERTPROFILE", 58, 196}, + #endif + #ifdef CMP_R_UNEXPECTED_CRLSTATUSLIST + {"UNEXPECTED_CRLSTATUSLIST", ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST}, + #else + {"UNEXPECTED_CRLSTATUSLIST", 58, 201}, + #endif + #ifdef CMP_R_UNEXPECTED_PKIBODY + {"UNEXPECTED_PKIBODY", ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY}, + #else + {"UNEXPECTED_PKIBODY", 58, 133}, + #endif + #ifdef CMP_R_UNEXPECTED_PKISTATUS + {"UNEXPECTED_PKISTATUS", ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS}, + #else + {"UNEXPECTED_PKISTATUS", 58, 185}, + #endif + #ifdef CMP_R_UNEXPECTED_POLLREQ + {"UNEXPECTED_POLLREQ", ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ}, + #else + {"UNEXPECTED_POLLREQ", 58, 105}, + #endif + #ifdef CMP_R_UNEXPECTED_PVNO + {"UNEXPECTED_PVNO", ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO}, + #else + {"UNEXPECTED_PVNO", 58, 153}, + #endif + #ifdef CMP_R_UNEXPECTED_SENDER + {"UNEXPECTED_SENDER", ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER}, + #else + {"UNEXPECTED_SENDER", 58, 106}, + #endif + #ifdef CMP_R_UNKNOWN_ALGORITHM_ID + {"UNKNOWN_ALGORITHM_ID", ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID}, + #else + {"UNKNOWN_ALGORITHM_ID", 58, 134}, + #endif + #ifdef CMP_R_UNKNOWN_CERT_TYPE + {"UNKNOWN_CERT_TYPE", ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE}, + #else + {"UNKNOWN_CERT_TYPE", 58, 135}, + #endif + #ifdef CMP_R_UNKNOWN_CRL_ISSUER + {"UNKNOWN_CRL_ISSUER", ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER}, + #else + {"UNKNOWN_CRL_ISSUER", 58, 200}, + #endif + #ifdef CMP_R_UNKNOWN_PKISTATUS + {"UNKNOWN_PKISTATUS", ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS}, + #else + {"UNKNOWN_PKISTATUS", 58, 186}, + #endif + #ifdef CMP_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_CMP, CMP_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 58, 136}, + #endif + #ifdef CMP_R_UNSUPPORTED_KEY_TYPE + {"UNSUPPORTED_KEY_TYPE", ERR_LIB_CMP, CMP_R_UNSUPPORTED_KEY_TYPE}, + #else + {"UNSUPPORTED_KEY_TYPE", 58, 137}, + #endif + #ifdef CMP_R_UNSUPPORTED_PKIBODY + {"UNSUPPORTED_PKIBODY", ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY}, + #else + {"UNSUPPORTED_PKIBODY", 58, 101}, + #endif + #ifdef CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC + {"UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC", ERR_LIB_CMP, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC}, + #else + {"UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC", 58, 154}, + #endif + #ifdef CMP_R_VALUE_TOO_LARGE + {"VALUE_TOO_LARGE", ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE}, + #else + {"VALUE_TOO_LARGE", 58, 175}, + #endif + #ifdef CMP_R_VALUE_TOO_SMALL + {"VALUE_TOO_SMALL", ERR_LIB_CMP, CMP_R_VALUE_TOO_SMALL}, + #else + {"VALUE_TOO_SMALL", 58, 177}, + #endif + #ifdef CMP_R_WRONG_ALGORITHM_OID + {"WRONG_ALGORITHM_OID", ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID}, + #else + {"WRONG_ALGORITHM_OID", 58, 138}, + #endif + #ifdef CMP_R_WRONG_CERTID + {"WRONG_CERTID", ERR_LIB_CMP, CMP_R_WRONG_CERTID}, + #else + {"WRONG_CERTID", 58, 189}, + #endif + #ifdef CMP_R_WRONG_CERTID_IN_RP + {"WRONG_CERTID_IN_RP", ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP}, + #else + {"WRONG_CERTID_IN_RP", 58, 187}, + #endif + #ifdef CMP_R_WRONG_PBM_VALUE + {"WRONG_PBM_VALUE", ERR_LIB_CMP, CMP_R_WRONG_PBM_VALUE}, + #else + {"WRONG_PBM_VALUE", 58, 155}, + #endif + #ifdef CMP_R_WRONG_RP_COMPONENT_COUNT + {"WRONG_RP_COMPONENT_COUNT", ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT}, + #else + {"WRONG_RP_COMPONENT_COUNT", 58, 188}, + #endif + #ifdef CMP_R_WRONG_SERIAL_IN_RP + {"WRONG_SERIAL_IN_RP", ERR_LIB_CMP, CMP_R_WRONG_SERIAL_IN_RP}, + #else + {"WRONG_SERIAL_IN_RP", 58, 173}, + #endif + #ifdef CMS_R_ADD_SIGNER_ERROR + {"ADD_SIGNER_ERROR", ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR}, + #else + {"ADD_SIGNER_ERROR", 46, 99}, + #endif + #ifdef CMS_R_ATTRIBUTE_ERROR + {"ATTRIBUTE_ERROR", ERR_LIB_CMS, CMS_R_ATTRIBUTE_ERROR}, + #else + {"ATTRIBUTE_ERROR", 46, 161}, + #endif + #ifdef CMS_R_CERTIFICATE_ALREADY_PRESENT + {"CERTIFICATE_ALREADY_PRESENT", ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT}, + #else + {"CERTIFICATE_ALREADY_PRESENT", 46, 175}, + #endif + #ifdef CMS_R_CERTIFICATE_HAS_NO_KEYID + {"CERTIFICATE_HAS_NO_KEYID", ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID}, + #else + {"CERTIFICATE_HAS_NO_KEYID", 46, 160}, + #endif + #ifdef CMS_R_CERTIFICATE_VERIFY_ERROR + {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR}, + #else + {"CERTIFICATE_VERIFY_ERROR", 46, 100}, + #endif + #ifdef CMS_R_CIPHER_AEAD_IN_ENVELOPED_DATA + {"CIPHER_AEAD_IN_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_IN_ENVELOPED_DATA}, + #else + {"CIPHER_AEAD_IN_ENVELOPED_DATA", 46, 200}, + #endif + #ifdef CMS_R_CIPHER_AEAD_SET_TAG_ERROR + {"CIPHER_AEAD_SET_TAG_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR}, + #else + {"CIPHER_AEAD_SET_TAG_ERROR", 46, 184}, + #endif + #ifdef CMS_R_CIPHER_GET_TAG + {"CIPHER_GET_TAG", ERR_LIB_CMS, CMS_R_CIPHER_GET_TAG}, + #else + {"CIPHER_GET_TAG", 46, 185}, + #endif + #ifdef CMS_R_CIPHER_INITIALISATION_ERROR + {"CIPHER_INITIALISATION_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR}, + #else + {"CIPHER_INITIALISATION_ERROR", 46, 101}, + #endif + #ifdef CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR + {"CIPHER_PARAMETER_INITIALISATION_ERROR", ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR}, + #else + {"CIPHER_PARAMETER_INITIALISATION_ERROR", 46, 102}, + #endif + #ifdef CMS_R_CMS_DATAFINAL_ERROR + {"CMS_DATAFINAL_ERROR", ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR}, + #else + {"CMS_DATAFINAL_ERROR", 46, 103}, + #endif + #ifdef CMS_R_CMS_LIB + {"CMS_LIB", ERR_LIB_CMS, CMS_R_CMS_LIB}, + #else + {"CMS_LIB", 46, 104}, + #endif + #ifdef CMS_R_CONTENTIDENTIFIER_MISMATCH + {"CONTENTIDENTIFIER_MISMATCH", ERR_LIB_CMS, CMS_R_CONTENTIDENTIFIER_MISMATCH}, + #else + {"CONTENTIDENTIFIER_MISMATCH", 46, 170}, + #endif + #ifdef CMS_R_CONTENT_NOT_FOUND + {"CONTENT_NOT_FOUND", ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND}, + #else + {"CONTENT_NOT_FOUND", 46, 105}, + #endif + #ifdef CMS_R_CONTENT_TYPE_MISMATCH + {"CONTENT_TYPE_MISMATCH", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_MISMATCH}, + #else + {"CONTENT_TYPE_MISMATCH", 46, 171}, + #endif + #ifdef CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA + {"CONTENT_TYPE_NOT_COMPRESSED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA}, + #else + {"CONTENT_TYPE_NOT_COMPRESSED_DATA", 46, 106}, + #endif + #ifdef CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA + {"CONTENT_TYPE_NOT_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA}, + #else + {"CONTENT_TYPE_NOT_ENVELOPED_DATA", 46, 107}, + #endif + #ifdef CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA + {"CONTENT_TYPE_NOT_SIGNED_DATA", ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA}, + #else + {"CONTENT_TYPE_NOT_SIGNED_DATA", 46, 108}, + #endif + #ifdef CMS_R_CONTENT_VERIFY_ERROR + {"CONTENT_VERIFY_ERROR", ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR}, + #else + {"CONTENT_VERIFY_ERROR", 46, 109}, + #endif + #ifdef CMS_R_CTRL_ERROR + {"CTRL_ERROR", ERR_LIB_CMS, CMS_R_CTRL_ERROR}, + #else + {"CTRL_ERROR", 46, 110}, + #endif + #ifdef CMS_R_CTRL_FAILURE + {"CTRL_FAILURE", ERR_LIB_CMS, CMS_R_CTRL_FAILURE}, + #else + {"CTRL_FAILURE", 46, 111}, + #endif + #ifdef CMS_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_CMS, CMS_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 46, 187}, + #endif + #ifdef CMS_R_DECRYPT_ERROR + {"DECRYPT_ERROR", ERR_LIB_CMS, CMS_R_DECRYPT_ERROR}, + #else + {"DECRYPT_ERROR", 46, 112}, + #endif + #ifdef CMS_R_ERROR_GETTING_PUBLIC_KEY + {"ERROR_GETTING_PUBLIC_KEY", ERR_LIB_CMS, CMS_R_ERROR_GETTING_PUBLIC_KEY}, + #else + {"ERROR_GETTING_PUBLIC_KEY", 46, 113}, + #endif + #ifdef CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE + {"ERROR_READING_MESSAGEDIGEST_ATTRIBUTE", ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE}, + #else + {"ERROR_READING_MESSAGEDIGEST_ATTRIBUTE", 46, 114}, + #endif + #ifdef CMS_R_ERROR_SETTING_KEY + {"ERROR_SETTING_KEY", ERR_LIB_CMS, CMS_R_ERROR_SETTING_KEY}, + #else + {"ERROR_SETTING_KEY", 46, 115}, + #endif + #ifdef CMS_R_ERROR_SETTING_RECIPIENTINFO + {"ERROR_SETTING_RECIPIENTINFO", ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO}, + #else + {"ERROR_SETTING_RECIPIENTINFO", 46, 116}, + #endif + #ifdef CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT + {"ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT", ERR_LIB_CMS, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT}, + #else + {"ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT", 46, 196}, + #endif + #ifdef CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR + {"ESS_SIGNING_CERTID_MISMATCH_ERROR", ERR_LIB_CMS, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR}, + #else + {"ESS_SIGNING_CERTID_MISMATCH_ERROR", 46, 183}, + #endif + #ifdef CMS_R_INVALID_ENCRYPTED_KEY_LENGTH + {"INVALID_ENCRYPTED_KEY_LENGTH", ERR_LIB_CMS, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH}, + #else + {"INVALID_ENCRYPTED_KEY_LENGTH", 46, 117}, + #endif + #ifdef CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER + {"INVALID_KEY_ENCRYPTION_PARAMETER", ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER}, + #else + {"INVALID_KEY_ENCRYPTION_PARAMETER", 46, 176}, + #endif + #ifdef CMS_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 46, 118}, + #endif + #ifdef CMS_R_INVALID_LABEL + {"INVALID_LABEL", ERR_LIB_CMS, CMS_R_INVALID_LABEL}, + #else + {"INVALID_LABEL", 46, 190}, + #endif + #ifdef CMS_R_INVALID_OAEP_PARAMETERS + {"INVALID_OAEP_PARAMETERS", ERR_LIB_CMS, CMS_R_INVALID_OAEP_PARAMETERS}, + #else + {"INVALID_OAEP_PARAMETERS", 46, 191}, + #endif + #ifdef CMS_R_KDF_PARAMETER_ERROR + {"KDF_PARAMETER_ERROR", ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR}, + #else + {"KDF_PARAMETER_ERROR", 46, 186}, + #endif + #ifdef CMS_R_MD_BIO_INIT_ERROR + {"MD_BIO_INIT_ERROR", ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR}, + #else + {"MD_BIO_INIT_ERROR", 46, 119}, + #endif + #ifdef CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH + {"MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH}, + #else + {"MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH", 46, 120}, + #endif + #ifdef CMS_R_MESSAGEDIGEST_WRONG_LENGTH + {"MESSAGEDIGEST_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_WRONG_LENGTH}, + #else + {"MESSAGEDIGEST_WRONG_LENGTH", 46, 121}, + #endif + #ifdef CMS_R_MSGSIGDIGEST_ERROR + {"MSGSIGDIGEST_ERROR", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_ERROR}, + #else + {"MSGSIGDIGEST_ERROR", 46, 172}, + #endif + #ifdef CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE + {"MSGSIGDIGEST_VERIFICATION_FAILURE", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE}, + #else + {"MSGSIGDIGEST_VERIFICATION_FAILURE", 46, 162}, + #endif + #ifdef CMS_R_MSGSIGDIGEST_WRONG_LENGTH + {"MSGSIGDIGEST_WRONG_LENGTH", ERR_LIB_CMS, CMS_R_MSGSIGDIGEST_WRONG_LENGTH}, + #else + {"MSGSIGDIGEST_WRONG_LENGTH", 46, 163}, + #endif + #ifdef CMS_R_NEED_ONE_SIGNER + {"NEED_ONE_SIGNER", ERR_LIB_CMS, CMS_R_NEED_ONE_SIGNER}, + #else + {"NEED_ONE_SIGNER", 46, 164}, + #endif + #ifdef CMS_R_NOT_A_SIGNED_RECEIPT + {"NOT_A_SIGNED_RECEIPT", ERR_LIB_CMS, CMS_R_NOT_A_SIGNED_RECEIPT}, + #else + {"NOT_A_SIGNED_RECEIPT", 46, 165}, + #endif + #ifdef CMS_R_NOT_ENCRYPTED_DATA + {"NOT_ENCRYPTED_DATA", ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA}, + #else + {"NOT_ENCRYPTED_DATA", 46, 122}, + #endif + #ifdef CMS_R_NOT_KEK + {"NOT_KEK", ERR_LIB_CMS, CMS_R_NOT_KEK}, + #else + {"NOT_KEK", 46, 123}, + #endif + #ifdef CMS_R_NOT_KEM + {"NOT_KEM", ERR_LIB_CMS, CMS_R_NOT_KEM}, + #else + {"NOT_KEM", 46, 197}, + #endif + #ifdef CMS_R_NOT_KEY_AGREEMENT + {"NOT_KEY_AGREEMENT", ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT}, + #else + {"NOT_KEY_AGREEMENT", 46, 181}, + #endif + #ifdef CMS_R_NOT_KEY_TRANSPORT + {"NOT_KEY_TRANSPORT", ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT}, + #else + {"NOT_KEY_TRANSPORT", 46, 124}, + #endif + #ifdef CMS_R_NOT_PWRI + {"NOT_PWRI", ERR_LIB_CMS, CMS_R_NOT_PWRI}, + #else + {"NOT_PWRI", 46, 177}, + #endif + #ifdef CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE + {"NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, + #else + {"NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 46, 125}, + #endif + #ifdef CMS_R_NO_CIPHER + {"NO_CIPHER", ERR_LIB_CMS, CMS_R_NO_CIPHER}, + #else + {"NO_CIPHER", 46, 126}, + #endif + #ifdef CMS_R_NO_CONTENT + {"NO_CONTENT", ERR_LIB_CMS, CMS_R_NO_CONTENT}, + #else + {"NO_CONTENT", 46, 127}, + #endif + #ifdef CMS_R_NO_CONTENT_TYPE + {"NO_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_NO_CONTENT_TYPE}, + #else + {"NO_CONTENT_TYPE", 46, 173}, + #endif + #ifdef CMS_R_NO_DEFAULT_DIGEST + {"NO_DEFAULT_DIGEST", ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST}, + #else + {"NO_DEFAULT_DIGEST", 46, 128}, + #endif + #ifdef CMS_R_NO_DIGEST_SET + {"NO_DIGEST_SET", ERR_LIB_CMS, CMS_R_NO_DIGEST_SET}, + #else + {"NO_DIGEST_SET", 46, 129}, + #endif + #ifdef CMS_R_NO_KEY + {"NO_KEY", ERR_LIB_CMS, CMS_R_NO_KEY}, + #else + {"NO_KEY", 46, 130}, + #endif + #ifdef CMS_R_NO_KEY_OR_CERT + {"NO_KEY_OR_CERT", ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT}, + #else + {"NO_KEY_OR_CERT", 46, 174}, + #endif + #ifdef CMS_R_NO_MATCHING_DIGEST + {"NO_MATCHING_DIGEST", ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST}, + #else + {"NO_MATCHING_DIGEST", 46, 131}, + #endif + #ifdef CMS_R_NO_MATCHING_RECIPIENT + {"NO_MATCHING_RECIPIENT", ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT}, + #else + {"NO_MATCHING_RECIPIENT", 46, 132}, + #endif + #ifdef CMS_R_NO_MATCHING_SIGNATURE + {"NO_MATCHING_SIGNATURE", ERR_LIB_CMS, CMS_R_NO_MATCHING_SIGNATURE}, + #else + {"NO_MATCHING_SIGNATURE", 46, 166}, + #endif + #ifdef CMS_R_NO_MSGSIGDIGEST + {"NO_MSGSIGDIGEST", ERR_LIB_CMS, CMS_R_NO_MSGSIGDIGEST}, + #else + {"NO_MSGSIGDIGEST", 46, 167}, + #endif + #ifdef CMS_R_NO_PASSWORD + {"NO_PASSWORD", ERR_LIB_CMS, CMS_R_NO_PASSWORD}, + #else + {"NO_PASSWORD", 46, 178}, + #endif + #ifdef CMS_R_NO_PRIVATE_KEY + {"NO_PRIVATE_KEY", ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY}, + #else + {"NO_PRIVATE_KEY", 46, 133}, + #endif + #ifdef CMS_R_NO_PUBLIC_KEY + {"NO_PUBLIC_KEY", ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY}, + #else + {"NO_PUBLIC_KEY", 46, 134}, + #endif + #ifdef CMS_R_NO_RECEIPT_REQUEST + {"NO_RECEIPT_REQUEST", ERR_LIB_CMS, CMS_R_NO_RECEIPT_REQUEST}, + #else + {"NO_RECEIPT_REQUEST", 46, 168}, + #endif + #ifdef CMS_R_NO_SIGNERS + {"NO_SIGNERS", ERR_LIB_CMS, CMS_R_NO_SIGNERS}, + #else + {"NO_SIGNERS", 46, 135}, + #endif + #ifdef CMS_R_OPERATION_UNSUPPORTED + {"OPERATION_UNSUPPORTED", ERR_LIB_CMS, CMS_R_OPERATION_UNSUPPORTED}, + #else + {"OPERATION_UNSUPPORTED", 46, 182}, + #endif + #ifdef CMS_R_PEER_KEY_ERROR + {"PEER_KEY_ERROR", ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR}, + #else + {"PEER_KEY_ERROR", 46, 188}, + #endif + #ifdef CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, + #else + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 46, 136}, + #endif + #ifdef CMS_R_RECEIPT_DECODE_ERROR + {"RECEIPT_DECODE_ERROR", ERR_LIB_CMS, CMS_R_RECEIPT_DECODE_ERROR}, + #else + {"RECEIPT_DECODE_ERROR", 46, 169}, + #endif + #ifdef CMS_R_RECIPIENT_ERROR + {"RECIPIENT_ERROR", ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR}, + #else + {"RECIPIENT_ERROR", 46, 137}, + #endif + #ifdef CMS_R_SHARED_INFO_ERROR + {"SHARED_INFO_ERROR", ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR}, + #else + {"SHARED_INFO_ERROR", 46, 189}, + #endif + #ifdef CMS_R_SIGNER_CERTIFICATE_NOT_FOUND + {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND}, + #else + {"SIGNER_CERTIFICATE_NOT_FOUND", 46, 138}, + #endif + #ifdef CMS_R_SIGNFINAL_ERROR + {"SIGNFINAL_ERROR", ERR_LIB_CMS, CMS_R_SIGNFINAL_ERROR}, + #else + {"SIGNFINAL_ERROR", 46, 139}, + #endif + #ifdef CMS_R_SMIME_TEXT_ERROR + {"SMIME_TEXT_ERROR", ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR}, + #else + {"SMIME_TEXT_ERROR", 46, 140}, + #endif + #ifdef CMS_R_STORE_INIT_ERROR + {"STORE_INIT_ERROR", ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR}, + #else + {"STORE_INIT_ERROR", 46, 141}, + #endif + #ifdef CMS_R_TYPE_NOT_COMPRESSED_DATA + {"TYPE_NOT_COMPRESSED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA}, + #else + {"TYPE_NOT_COMPRESSED_DATA", 46, 142}, + #endif + #ifdef CMS_R_TYPE_NOT_DATA + {"TYPE_NOT_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA}, + #else + {"TYPE_NOT_DATA", 46, 143}, + #endif + #ifdef CMS_R_TYPE_NOT_DIGESTED_DATA + {"TYPE_NOT_DIGESTED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA}, + #else + {"TYPE_NOT_DIGESTED_DATA", 46, 144}, + #endif + #ifdef CMS_R_TYPE_NOT_ENCRYPTED_DATA + {"TYPE_NOT_ENCRYPTED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA}, + #else + {"TYPE_NOT_ENCRYPTED_DATA", 46, 145}, + #endif + #ifdef CMS_R_TYPE_NOT_ENVELOPED_DATA + {"TYPE_NOT_ENVELOPED_DATA", ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA}, + #else + {"TYPE_NOT_ENVELOPED_DATA", 46, 146}, + #endif + #ifdef CMS_R_UNABLE_TO_FINALIZE_CONTEXT + {"UNABLE_TO_FINALIZE_CONTEXT", ERR_LIB_CMS, CMS_R_UNABLE_TO_FINALIZE_CONTEXT}, + #else + {"UNABLE_TO_FINALIZE_CONTEXT", 46, 147}, + #endif + #ifdef CMS_R_UNKNOWN_CIPHER + {"UNKNOWN_CIPHER", ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER}, + #else + {"UNKNOWN_CIPHER", 46, 148}, + #endif + #ifdef CMS_R_UNKNOWN_DIGEST_ALGORITHM + {"UNKNOWN_DIGEST_ALGORITHM", ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM}, + #else + {"UNKNOWN_DIGEST_ALGORITHM", 46, 149}, + #endif + #ifdef CMS_R_UNKNOWN_ID + {"UNKNOWN_ID", ERR_LIB_CMS, CMS_R_UNKNOWN_ID}, + #else + {"UNKNOWN_ID", 46, 150}, + #endif + #ifdef CMS_R_UNKNOWN_KDF_ALGORITHM + {"UNKNOWN_KDF_ALGORITHM", ERR_LIB_CMS, CMS_R_UNKNOWN_KDF_ALGORITHM}, + #else + {"UNKNOWN_KDF_ALGORITHM", 46, 198}, + #endif + #ifdef CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM + {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, + #else + {"UNSUPPORTED_COMPRESSION_ALGORITHM", 46, 151}, + #endif + #ifdef CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM}, + #else + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", 46, 194}, + #endif + #ifdef CMS_R_UNSUPPORTED_CONTENT_TYPE + {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE}, + #else + {"UNSUPPORTED_CONTENT_TYPE", 46, 152}, + #endif + #ifdef CMS_R_UNSUPPORTED_ENCRYPTION_TYPE + {"UNSUPPORTED_ENCRYPTION_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE}, + #else + {"UNSUPPORTED_ENCRYPTION_TYPE", 46, 192}, + #endif + #ifdef CMS_R_UNSUPPORTED_KDF_ALGORITHM + {"UNSUPPORTED_KDF_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KDF_ALGORITHM}, + #else + {"UNSUPPORTED_KDF_ALGORITHM", 46, 199}, + #endif + #ifdef CMS_R_UNSUPPORTED_KEK_ALGORITHM + {"UNSUPPORTED_KEK_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM}, + #else + {"UNSUPPORTED_KEK_ALGORITHM", 46, 153}, + #endif + #ifdef CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM + {"UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM}, + #else + {"UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM", 46, 179}, + #endif + #ifdef CMS_R_UNSUPPORTED_LABEL_SOURCE + {"UNSUPPORTED_LABEL_SOURCE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE}, + #else + {"UNSUPPORTED_LABEL_SOURCE", 46, 193}, + #endif + #ifdef CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE + {"UNSUPPORTED_RECIPIENTINFO_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE}, + #else + {"UNSUPPORTED_RECIPIENTINFO_TYPE", 46, 155}, + #endif + #ifdef CMS_R_UNSUPPORTED_RECIPIENT_TYPE + {"UNSUPPORTED_RECIPIENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE}, + #else + {"UNSUPPORTED_RECIPIENT_TYPE", 46, 154}, + #endif + #ifdef CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM + {"UNSUPPORTED_SIGNATURE_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM}, + #else + {"UNSUPPORTED_SIGNATURE_ALGORITHM", 46, 195}, + #endif + #ifdef CMS_R_UNSUPPORTED_TYPE + {"UNSUPPORTED_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE}, + #else + {"UNSUPPORTED_TYPE", 46, 156}, + #endif + #ifdef CMS_R_UNWRAP_ERROR + {"UNWRAP_ERROR", ERR_LIB_CMS, CMS_R_UNWRAP_ERROR}, + #else + {"UNWRAP_ERROR", 46, 157}, + #endif + #ifdef CMS_R_UNWRAP_FAILURE + {"UNWRAP_FAILURE", ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE}, + #else + {"UNWRAP_FAILURE", 46, 180}, + #endif + #ifdef CMS_R_VERIFICATION_FAILURE + {"VERIFICATION_FAILURE", ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE}, + #else + {"VERIFICATION_FAILURE", 46, 158}, + #endif + #ifdef CMS_R_WRAP_ERROR + {"WRAP_ERROR", ERR_LIB_CMS, CMS_R_WRAP_ERROR}, + #else + {"WRAP_ERROR", 46, 159}, + #endif + #ifdef COMP_R_BROTLI_DECODE_ERROR + {"BROTLI_DECODE_ERROR", ERR_LIB_COMP, COMP_R_BROTLI_DECODE_ERROR}, + #else + {"BROTLI_DECODE_ERROR", 41, 102}, + #endif + #ifdef COMP_R_BROTLI_ENCODE_ERROR + {"BROTLI_ENCODE_ERROR", ERR_LIB_COMP, COMP_R_BROTLI_ENCODE_ERROR}, + #else + {"BROTLI_ENCODE_ERROR", 41, 103}, + #endif + #ifdef COMP_R_BROTLI_NOT_SUPPORTED + {"BROTLI_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_BROTLI_NOT_SUPPORTED}, + #else + {"BROTLI_NOT_SUPPORTED", 41, 104}, + #endif + #ifdef COMP_R_ZLIB_DEFLATE_ERROR + {"ZLIB_DEFLATE_ERROR", ERR_LIB_COMP, COMP_R_ZLIB_DEFLATE_ERROR}, + #else + {"ZLIB_DEFLATE_ERROR", 41, 99}, + #endif + #ifdef COMP_R_ZLIB_INFLATE_ERROR + {"ZLIB_INFLATE_ERROR", ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR}, + #else + {"ZLIB_INFLATE_ERROR", 41, 100}, + #endif + #ifdef COMP_R_ZLIB_NOT_SUPPORTED + {"ZLIB_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED}, + #else + {"ZLIB_NOT_SUPPORTED", 41, 101}, + #endif + #ifdef COMP_R_ZSTD_COMPRESS_ERROR + {"ZSTD_COMPRESS_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_COMPRESS_ERROR}, + #else + {"ZSTD_COMPRESS_ERROR", 41, 105}, + #endif + #ifdef COMP_R_ZSTD_DECODE_ERROR + {"ZSTD_DECODE_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_DECODE_ERROR}, + #else + {"ZSTD_DECODE_ERROR", 41, 106}, + #endif + #ifdef COMP_R_ZSTD_DECOMPRESS_ERROR + {"ZSTD_DECOMPRESS_ERROR", ERR_LIB_COMP, COMP_R_ZSTD_DECOMPRESS_ERROR}, + #else + {"ZSTD_DECOMPRESS_ERROR", 41, 107}, + #endif + #ifdef COMP_R_ZSTD_NOT_SUPPORTED + {"ZSTD_NOT_SUPPORTED", ERR_LIB_COMP, COMP_R_ZSTD_NOT_SUPPORTED}, + #else + {"ZSTD_NOT_SUPPORTED", 41, 108}, + #endif + #ifdef CONF_R_ERROR_LOADING_DSO + {"ERROR_LOADING_DSO", ERR_LIB_CONF, CONF_R_ERROR_LOADING_DSO}, + #else + {"ERROR_LOADING_DSO", 14, 110}, + #endif + #ifdef CONF_R_INVALID_PRAGMA + {"INVALID_PRAGMA", ERR_LIB_CONF, CONF_R_INVALID_PRAGMA}, + #else + {"INVALID_PRAGMA", 14, 122}, + #endif + #ifdef CONF_R_LIST_CANNOT_BE_NULL + {"LIST_CANNOT_BE_NULL", ERR_LIB_CONF, CONF_R_LIST_CANNOT_BE_NULL}, + #else + {"LIST_CANNOT_BE_NULL", 14, 115}, + #endif + #ifdef CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION + {"MANDATORY_BRACES_IN_VARIABLE_EXPANSION", ERR_LIB_CONF, CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION}, + #else + {"MANDATORY_BRACES_IN_VARIABLE_EXPANSION", 14, 123}, + #endif + #ifdef CONF_R_MISSING_CLOSE_SQUARE_BRACKET + {"MISSING_CLOSE_SQUARE_BRACKET", ERR_LIB_CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET}, + #else + {"MISSING_CLOSE_SQUARE_BRACKET", 14, 100}, + #endif + #ifdef CONF_R_MISSING_EQUAL_SIGN + {"MISSING_EQUAL_SIGN", ERR_LIB_CONF, CONF_R_MISSING_EQUAL_SIGN}, + #else + {"MISSING_EQUAL_SIGN", 14, 101}, + #endif + #ifdef CONF_R_MISSING_INIT_FUNCTION + {"MISSING_INIT_FUNCTION", ERR_LIB_CONF, CONF_R_MISSING_INIT_FUNCTION}, + #else + {"MISSING_INIT_FUNCTION", 14, 112}, + #endif + #ifdef CONF_R_MODULE_INITIALIZATION_ERROR + {"MODULE_INITIALIZATION_ERROR", ERR_LIB_CONF, CONF_R_MODULE_INITIALIZATION_ERROR}, + #else + {"MODULE_INITIALIZATION_ERROR", 14, 109}, + #endif + #ifdef CONF_R_NO_CLOSE_BRACE + {"NO_CLOSE_BRACE", ERR_LIB_CONF, CONF_R_NO_CLOSE_BRACE}, + #else + {"NO_CLOSE_BRACE", 14, 102}, + #endif + #ifdef CONF_R_NO_CONF + {"NO_CONF", ERR_LIB_CONF, CONF_R_NO_CONF}, + #else + {"NO_CONF", 14, 105}, + #endif + #ifdef CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE + {"NO_CONF_OR_ENVIRONMENT_VARIABLE", ERR_LIB_CONF, CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE}, + #else + {"NO_CONF_OR_ENVIRONMENT_VARIABLE", 14, 106}, + #endif + #ifdef CONF_R_NO_SECTION + {"NO_SECTION", ERR_LIB_CONF, CONF_R_NO_SECTION}, + #else + {"NO_SECTION", 14, 107}, + #endif + #ifdef CONF_R_NO_SUCH_FILE + {"NO_SUCH_FILE", ERR_LIB_CONF, CONF_R_NO_SUCH_FILE}, + #else + {"NO_SUCH_FILE", 14, 114}, + #endif + #ifdef CONF_R_NO_VALUE + {"NO_VALUE", ERR_LIB_CONF, CONF_R_NO_VALUE}, + #else + {"NO_VALUE", 14, 108}, + #endif + #ifdef CONF_R_NUMBER_TOO_LARGE + {"NUMBER_TOO_LARGE", ERR_LIB_CONF, CONF_R_NUMBER_TOO_LARGE}, + #else + {"NUMBER_TOO_LARGE", 14, 121}, + #endif + #ifdef CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION + {"OPENSSL_CONF_REFERENCES_MISSING_SECTION", ERR_LIB_CONF, CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION}, + #else + {"OPENSSL_CONF_REFERENCES_MISSING_SECTION", 14, 124}, + #endif + #ifdef CONF_R_RECURSIVE_DIRECTORY_INCLUDE + {"RECURSIVE_DIRECTORY_INCLUDE", ERR_LIB_CONF, CONF_R_RECURSIVE_DIRECTORY_INCLUDE}, + #else + {"RECURSIVE_DIRECTORY_INCLUDE", 14, 111}, + #endif + #ifdef CONF_R_RECURSIVE_SECTION_REFERENCE + {"RECURSIVE_SECTION_REFERENCE", ERR_LIB_CONF, CONF_R_RECURSIVE_SECTION_REFERENCE}, + #else + {"RECURSIVE_SECTION_REFERENCE", 14, 126}, + #endif + #ifdef CONF_R_RELATIVE_PATH + {"RELATIVE_PATH", ERR_LIB_CONF, CONF_R_RELATIVE_PATH}, + #else + {"RELATIVE_PATH", 14, 125}, + #endif + #ifdef CONF_R_SSL_COMMAND_SECTION_EMPTY + {"SSL_COMMAND_SECTION_EMPTY", ERR_LIB_CONF, CONF_R_SSL_COMMAND_SECTION_EMPTY}, + #else + {"SSL_COMMAND_SECTION_EMPTY", 14, 117}, + #endif + #ifdef CONF_R_SSL_COMMAND_SECTION_NOT_FOUND + {"SSL_COMMAND_SECTION_NOT_FOUND", ERR_LIB_CONF, CONF_R_SSL_COMMAND_SECTION_NOT_FOUND}, + #else + {"SSL_COMMAND_SECTION_NOT_FOUND", 14, 118}, + #endif + #ifdef CONF_R_SSL_SECTION_EMPTY + {"SSL_SECTION_EMPTY", ERR_LIB_CONF, CONF_R_SSL_SECTION_EMPTY}, + #else + {"SSL_SECTION_EMPTY", 14, 119}, + #endif + #ifdef CONF_R_SSL_SECTION_NOT_FOUND + {"SSL_SECTION_NOT_FOUND", ERR_LIB_CONF, CONF_R_SSL_SECTION_NOT_FOUND}, + #else + {"SSL_SECTION_NOT_FOUND", 14, 120}, + #endif + #ifdef CONF_R_UNABLE_TO_CREATE_NEW_SECTION + {"UNABLE_TO_CREATE_NEW_SECTION", ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION}, + #else + {"UNABLE_TO_CREATE_NEW_SECTION", 14, 103}, + #endif + #ifdef CONF_R_UNKNOWN_MODULE_NAME + {"UNKNOWN_MODULE_NAME", ERR_LIB_CONF, CONF_R_UNKNOWN_MODULE_NAME}, + #else + {"UNKNOWN_MODULE_NAME", 14, 113}, + #endif + #ifdef CONF_R_VARIABLE_EXPANSION_TOO_LONG + {"VARIABLE_EXPANSION_TOO_LONG", ERR_LIB_CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG}, + #else + {"VARIABLE_EXPANSION_TOO_LONG", 14, 116}, + #endif + #ifdef CONF_R_VARIABLE_HAS_NO_VALUE + {"VARIABLE_HAS_NO_VALUE", ERR_LIB_CONF, CONF_R_VARIABLE_HAS_NO_VALUE}, + #else + {"VARIABLE_HAS_NO_VALUE", 14, 104}, + #endif + #ifdef CRMF_R_BAD_PBM_ITERATIONCOUNT + {"BAD_PBM_ITERATIONCOUNT", ERR_LIB_CRMF, CRMF_R_BAD_PBM_ITERATIONCOUNT}, + #else + {"BAD_PBM_ITERATIONCOUNT", 56, 100}, + #endif + #ifdef CRMF_R_CMS_NOT_SUPPORTED + {"CMS_NOT_SUPPORTED", ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED}, + #else + {"CMS_NOT_SUPPORTED", 56, 122}, + #endif + #ifdef CRMF_R_CRMFERROR + {"CRMFERROR", ERR_LIB_CRMF, CRMF_R_CRMFERROR}, + #else + {"CRMFERROR", 56, 102}, + #endif + #ifdef CRMF_R_ERROR + {"ERROR", ERR_LIB_CRMF, CRMF_R_ERROR}, + #else + {"ERROR", 56, 103}, + #endif + #ifdef CRMF_R_ERROR_DECODING_CERTIFICATE + {"ERROR_DECODING_CERTIFICATE", ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE}, + #else + {"ERROR_DECODING_CERTIFICATE", 56, 104}, + #endif + #ifdef CRMF_R_ERROR_DECODING_ENCRYPTEDKEY + {"ERROR_DECODING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY}, + #else + {"ERROR_DECODING_ENCRYPTEDKEY", 56, 123}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_CERTIFICATE + {"ERROR_DECRYPTING_CERTIFICATE", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE}, + #else + {"ERROR_DECRYPTING_CERTIFICATE", 56, 105}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY + {"ERROR_DECRYPTING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY}, + #else + {"ERROR_DECRYPTING_ENCRYPTEDKEY", 56, 124}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE + {"ERROR_DECRYPTING_ENCRYPTEDVALUE", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE}, + #else + {"ERROR_DECRYPTING_ENCRYPTEDVALUE", 56, 125}, + #endif + #ifdef CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY + {"ERROR_DECRYPTING_SYMMETRIC_KEY", ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY}, + #else + {"ERROR_DECRYPTING_SYMMETRIC_KEY", 56, 106}, + #endif + #ifdef CRMF_R_ERROR_SETTING_PURPOSE + {"ERROR_SETTING_PURPOSE", ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE}, + #else + {"ERROR_SETTING_PURPOSE", 56, 126}, + #endif + #ifdef CRMF_R_ERROR_SIGNING_POPO + {"ERROR_SIGNING_POPO", ERR_LIB_CRMF, CRMF_R_ERROR_SIGNING_POPO}, + #else + {"ERROR_SIGNING_POPO", 56, 129}, + #endif + #ifdef CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY + {"ERROR_VERIFYING_ENCRYPTEDKEY", ERR_LIB_CRMF, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY}, + #else + {"ERROR_VERIFYING_ENCRYPTEDKEY", 56, 127}, + #endif + #ifdef CRMF_R_FAILURE_OBTAINING_RANDOM + {"FAILURE_OBTAINING_RANDOM", ERR_LIB_CRMF, CRMF_R_FAILURE_OBTAINING_RANDOM}, + #else + {"FAILURE_OBTAINING_RANDOM", 56, 107}, + #endif + #ifdef CRMF_R_ITERATIONCOUNT_BELOW_100 + {"ITERATIONCOUNT_BELOW_100", ERR_LIB_CRMF, CRMF_R_ITERATIONCOUNT_BELOW_100}, + #else + {"ITERATIONCOUNT_BELOW_100", 56, 108}, + #endif + #ifdef CRMF_R_MALFORMED_IV + {"MALFORMED_IV", ERR_LIB_CRMF, CRMF_R_MALFORMED_IV}, + #else + {"MALFORMED_IV", 56, 101}, + #endif + #ifdef CRMF_R_NULL_ARGUMENT + {"NULL_ARGUMENT", ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT}, + #else + {"NULL_ARGUMENT", 56, 109}, + #endif + #ifdef CRMF_R_POPOSKINPUT_NOT_SUPPORTED + {"POPOSKINPUT_NOT_SUPPORTED", ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED}, + #else + {"POPOSKINPUT_NOT_SUPPORTED", 56, 113}, + #endif + #ifdef CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN + {"POPO_INCONSISTENT_CENTRAL_KEYGEN", ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN}, + #else + {"POPO_INCONSISTENT_CENTRAL_KEYGEN", 56, 128}, + #endif + #ifdef CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY + {"POPO_INCONSISTENT_PUBLIC_KEY", ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY}, + #else + {"POPO_INCONSISTENT_PUBLIC_KEY", 56, 117}, + #endif + #ifdef CRMF_R_POPO_MISSING + {"POPO_MISSING", ERR_LIB_CRMF, CRMF_R_POPO_MISSING}, + #else + {"POPO_MISSING", 56, 121}, + #endif + #ifdef CRMF_R_POPO_MISSING_PUBLIC_KEY + {"POPO_MISSING_PUBLIC_KEY", ERR_LIB_CRMF, CRMF_R_POPO_MISSING_PUBLIC_KEY}, + #else + {"POPO_MISSING_PUBLIC_KEY", 56, 118}, + #endif + #ifdef CRMF_R_POPO_MISSING_SUBJECT + {"POPO_MISSING_SUBJECT", ERR_LIB_CRMF, CRMF_R_POPO_MISSING_SUBJECT}, + #else + {"POPO_MISSING_SUBJECT", 56, 119}, + #endif + #ifdef CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED + {"POPO_RAVERIFIED_NOT_ACCEPTED", ERR_LIB_CRMF, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED}, + #else + {"POPO_RAVERIFIED_NOT_ACCEPTED", 56, 120}, + #endif + #ifdef CRMF_R_SETTING_MAC_ALGOR_FAILURE + {"SETTING_MAC_ALGOR_FAILURE", ERR_LIB_CRMF, CRMF_R_SETTING_MAC_ALGOR_FAILURE}, + #else + {"SETTING_MAC_ALGOR_FAILURE", 56, 110}, + #endif + #ifdef CRMF_R_SETTING_OWF_ALGOR_FAILURE + {"SETTING_OWF_ALGOR_FAILURE", ERR_LIB_CRMF, CRMF_R_SETTING_OWF_ALGOR_FAILURE}, + #else + {"SETTING_OWF_ALGOR_FAILURE", 56, 111}, + #endif + #ifdef CRMF_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 56, 112}, + #endif + #ifdef CRMF_R_UNSUPPORTED_CIPHER + {"UNSUPPORTED_CIPHER", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER}, + #else + {"UNSUPPORTED_CIPHER", 56, 114}, + #endif + #ifdef CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO + {"UNSUPPORTED_METHOD_FOR_CREATING_POPO", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO}, + #else + {"UNSUPPORTED_METHOD_FOR_CREATING_POPO", 56, 115}, + #endif + #ifdef CRMF_R_UNSUPPORTED_POPO_METHOD + {"UNSUPPORTED_POPO_METHOD", ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD}, + #else + {"UNSUPPORTED_POPO_METHOD", 56, 116}, + #endif + #ifdef CRYPTO_R_BAD_ALGORITHM_NAME + {"BAD_ALGORITHM_NAME", ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME}, + #else + {"BAD_ALGORITHM_NAME", 15, 117}, + #endif + #ifdef CRYPTO_R_CONFLICTING_NAMES + {"CONFLICTING_NAMES", ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES}, + #else + {"CONFLICTING_NAMES", 15, 118}, + #endif + #ifdef CRYPTO_R_HEX_STRING_TOO_SHORT + {"HEX_STRING_TOO_SHORT", ERR_LIB_CRYPTO, CRYPTO_R_HEX_STRING_TOO_SHORT}, + #else + {"HEX_STRING_TOO_SHORT", 15, 121}, + #endif + #ifdef CRYPTO_R_ILLEGAL_HEX_DIGIT + {"ILLEGAL_HEX_DIGIT", ERR_LIB_CRYPTO, CRYPTO_R_ILLEGAL_HEX_DIGIT}, + #else + {"ILLEGAL_HEX_DIGIT", 15, 102}, + #endif + #ifdef CRYPTO_R_INSUFFICIENT_DATA_SPACE + {"INSUFFICIENT_DATA_SPACE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_DATA_SPACE}, + #else + {"INSUFFICIENT_DATA_SPACE", 15, 106}, + #endif + #ifdef CRYPTO_R_INSUFFICIENT_PARAM_SIZE + {"INSUFFICIENT_PARAM_SIZE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_PARAM_SIZE}, + #else + {"INSUFFICIENT_PARAM_SIZE", 15, 107}, + #endif + #ifdef CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE + {"INSUFFICIENT_SECURE_DATA_SPACE", ERR_LIB_CRYPTO, CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE}, + #else + {"INSUFFICIENT_SECURE_DATA_SPACE", 15, 108}, + #endif + #ifdef CRYPTO_R_INTEGER_OVERFLOW + {"INTEGER_OVERFLOW", ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW}, + #else + {"INTEGER_OVERFLOW", 15, 127}, + #endif + #ifdef CRYPTO_R_INVALID_NEGATIVE_VALUE + {"INVALID_NEGATIVE_VALUE", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NEGATIVE_VALUE}, + #else + {"INVALID_NEGATIVE_VALUE", 15, 122}, + #endif + #ifdef CRYPTO_R_INVALID_NULL_ARGUMENT + {"INVALID_NULL_ARGUMENT", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NULL_ARGUMENT}, + #else + {"INVALID_NULL_ARGUMENT", 15, 109}, + #endif + #ifdef CRYPTO_R_INVALID_OSSL_PARAM_TYPE + {"INVALID_OSSL_PARAM_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_OSSL_PARAM_TYPE}, + #else + {"INVALID_OSSL_PARAM_TYPE", 15, 110}, + #endif + #ifdef CRYPTO_R_NO_PARAMS_TO_MERGE + {"NO_PARAMS_TO_MERGE", ERR_LIB_CRYPTO, CRYPTO_R_NO_PARAMS_TO_MERGE}, + #else + {"NO_PARAMS_TO_MERGE", 15, 131}, + #endif + #ifdef CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL + {"NO_SPACE_FOR_TERMINATING_NULL", ERR_LIB_CRYPTO, CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL}, + #else + {"NO_SPACE_FOR_TERMINATING_NULL", 15, 128}, + #endif + #ifdef CRYPTO_R_ODD_NUMBER_OF_DIGITS + {"ODD_NUMBER_OF_DIGITS", ERR_LIB_CRYPTO, CRYPTO_R_ODD_NUMBER_OF_DIGITS}, + #else + {"ODD_NUMBER_OF_DIGITS", 15, 103}, + #endif + #ifdef CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY + {"PARAM_CANNOT_BE_REPRESENTED_EXACTLY", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY}, + #else + {"PARAM_CANNOT_BE_REPRESENTED_EXACTLY", 15, 123}, + #endif + #ifdef CRYPTO_R_PARAM_NOT_INTEGER_TYPE + {"PARAM_NOT_INTEGER_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_NOT_INTEGER_TYPE}, + #else + {"PARAM_NOT_INTEGER_TYPE", 15, 124}, + #endif + #ifdef CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE + {"PARAM_OF_INCOMPATIBLE_TYPE", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE}, + #else + {"PARAM_OF_INCOMPATIBLE_TYPE", 15, 129}, + #endif + #ifdef CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED + {"PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED}, + #else + {"PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED", 15, 125}, + #endif + #ifdef CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT + {"PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT}, + #else + {"PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT", 15, 130}, + #endif + #ifdef CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION + {"PARAM_VALUE_TOO_LARGE_FOR_DESTINATION", ERR_LIB_CRYPTO, CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION}, + #else + {"PARAM_VALUE_TOO_LARGE_FOR_DESTINATION", 15, 126}, + #endif + #ifdef CRYPTO_R_PROVIDER_ALREADY_EXISTS + {"PROVIDER_ALREADY_EXISTS", ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_ALREADY_EXISTS}, + #else + {"PROVIDER_ALREADY_EXISTS", 15, 104}, + #endif + #ifdef CRYPTO_R_PROVIDER_SECTION_ERROR + {"PROVIDER_SECTION_ERROR", ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR}, + #else + {"PROVIDER_SECTION_ERROR", 15, 105}, + #endif + #ifdef CRYPTO_R_RANDOM_SECTION_ERROR + {"RANDOM_SECTION_ERROR", ERR_LIB_CRYPTO, CRYPTO_R_RANDOM_SECTION_ERROR}, + #else + {"RANDOM_SECTION_ERROR", 15, 119}, + #endif + #ifdef CRYPTO_R_SECURE_MALLOC_FAILURE + {"SECURE_MALLOC_FAILURE", ERR_LIB_CRYPTO, CRYPTO_R_SECURE_MALLOC_FAILURE}, + #else + {"SECURE_MALLOC_FAILURE", 15, 111}, + #endif + #ifdef CRYPTO_R_STRING_TOO_LONG + {"STRING_TOO_LONG", ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG}, + #else + {"STRING_TOO_LONG", 15, 112}, + #endif + #ifdef CRYPTO_R_TOO_MANY_BYTES + {"TOO_MANY_BYTES", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES}, + #else + {"TOO_MANY_BYTES", 15, 113}, + #endif + #ifdef CRYPTO_R_TOO_MANY_NAMES + {"TOO_MANY_NAMES", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_NAMES}, + #else + {"TOO_MANY_NAMES", 15, 132}, + #endif + #ifdef CRYPTO_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 15, 114}, + #endif + #ifdef CRYPTO_R_TOO_SMALL_BUFFER + {"TOO_SMALL_BUFFER", ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER}, + #else + {"TOO_SMALL_BUFFER", 15, 116}, + #endif + #ifdef CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION + {"UNKNOWN_NAME_IN_RANDOM_SECTION", ERR_LIB_CRYPTO, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION}, + #else + {"UNKNOWN_NAME_IN_RANDOM_SECTION", 15, 120}, + #endif + #ifdef CRYPTO_R_ZERO_LENGTH_NUMBER + {"ZERO_LENGTH_NUMBER", ERR_LIB_CRYPTO, CRYPTO_R_ZERO_LENGTH_NUMBER}, + #else + {"ZERO_LENGTH_NUMBER", 15, 115}, + #endif + #ifdef CT_R_BASE64_DECODE_ERROR + {"BASE64_DECODE_ERROR", ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR}, + #else + {"BASE64_DECODE_ERROR", 50, 108}, + #endif + #ifdef CT_R_INVALID_LOG_ID_LENGTH + {"INVALID_LOG_ID_LENGTH", ERR_LIB_CT, CT_R_INVALID_LOG_ID_LENGTH}, + #else + {"INVALID_LOG_ID_LENGTH", 50, 100}, + #endif + #ifdef CT_R_LOG_CONF_INVALID + {"LOG_CONF_INVALID", ERR_LIB_CT, CT_R_LOG_CONF_INVALID}, + #else + {"LOG_CONF_INVALID", 50, 109}, + #endif + #ifdef CT_R_LOG_CONF_INVALID_KEY + {"LOG_CONF_INVALID_KEY", ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY}, + #else + {"LOG_CONF_INVALID_KEY", 50, 110}, + #endif + #ifdef CT_R_LOG_CONF_MISSING_DESCRIPTION + {"LOG_CONF_MISSING_DESCRIPTION", ERR_LIB_CT, CT_R_LOG_CONF_MISSING_DESCRIPTION}, + #else + {"LOG_CONF_MISSING_DESCRIPTION", 50, 111}, + #endif + #ifdef CT_R_LOG_CONF_MISSING_KEY + {"LOG_CONF_MISSING_KEY", ERR_LIB_CT, CT_R_LOG_CONF_MISSING_KEY}, + #else + {"LOG_CONF_MISSING_KEY", 50, 112}, + #endif + #ifdef CT_R_LOG_KEY_INVALID + {"LOG_KEY_INVALID", ERR_LIB_CT, CT_R_LOG_KEY_INVALID}, + #else + {"LOG_KEY_INVALID", 50, 113}, + #endif + #ifdef CT_R_SCT_FUTURE_TIMESTAMP + {"SCT_FUTURE_TIMESTAMP", ERR_LIB_CT, CT_R_SCT_FUTURE_TIMESTAMP}, + #else + {"SCT_FUTURE_TIMESTAMP", 50, 116}, + #endif + #ifdef CT_R_SCT_INVALID + {"SCT_INVALID", ERR_LIB_CT, CT_R_SCT_INVALID}, + #else + {"SCT_INVALID", 50, 104}, + #endif + #ifdef CT_R_SCT_INVALID_SIGNATURE + {"SCT_INVALID_SIGNATURE", ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE}, + #else + {"SCT_INVALID_SIGNATURE", 50, 107}, + #endif + #ifdef CT_R_SCT_LIST_INVALID + {"SCT_LIST_INVALID", ERR_LIB_CT, CT_R_SCT_LIST_INVALID}, + #else + {"SCT_LIST_INVALID", 50, 105}, + #endif + #ifdef CT_R_SCT_LOG_ID_MISMATCH + {"SCT_LOG_ID_MISMATCH", ERR_LIB_CT, CT_R_SCT_LOG_ID_MISMATCH}, + #else + {"SCT_LOG_ID_MISMATCH", 50, 114}, + #endif + #ifdef CT_R_SCT_NOT_SET + {"SCT_NOT_SET", ERR_LIB_CT, CT_R_SCT_NOT_SET}, + #else + {"SCT_NOT_SET", 50, 106}, + #endif + #ifdef CT_R_SCT_UNSUPPORTED_VERSION + {"SCT_UNSUPPORTED_VERSION", ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION}, + #else + {"SCT_UNSUPPORTED_VERSION", 50, 115}, + #endif + #ifdef CT_R_UNRECOGNIZED_SIGNATURE_NID + {"UNRECOGNIZED_SIGNATURE_NID", ERR_LIB_CT, CT_R_UNRECOGNIZED_SIGNATURE_NID}, + #else + {"UNRECOGNIZED_SIGNATURE_NID", 50, 101}, + #endif + #ifdef CT_R_UNSUPPORTED_ENTRY_TYPE + {"UNSUPPORTED_ENTRY_TYPE", ERR_LIB_CT, CT_R_UNSUPPORTED_ENTRY_TYPE}, + #else + {"UNSUPPORTED_ENTRY_TYPE", 50, 102}, + #endif + #ifdef CT_R_UNSUPPORTED_VERSION + {"UNSUPPORTED_VERSION", ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION}, + #else + {"UNSUPPORTED_VERSION", 50, 103}, + #endif + #ifdef DH_R_BAD_FFC_PARAMETERS + {"BAD_FFC_PARAMETERS", ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS}, + #else + {"BAD_FFC_PARAMETERS", 5, 127}, + #endif + #ifdef DH_R_BAD_GENERATOR + {"BAD_GENERATOR", ERR_LIB_DH, DH_R_BAD_GENERATOR}, + #else + {"BAD_GENERATOR", 5, 101}, + #endif + #ifdef DH_R_BN_DECODE_ERROR + {"BN_DECODE_ERROR", ERR_LIB_DH, DH_R_BN_DECODE_ERROR}, + #else + {"BN_DECODE_ERROR", 5, 109}, + #endif + #ifdef DH_R_BN_ERROR + {"BN_ERROR", ERR_LIB_DH, DH_R_BN_ERROR}, + #else + {"BN_ERROR", 5, 106}, + #endif + #ifdef DH_R_CHECK_INVALID_J_VALUE + {"CHECK_INVALID_J_VALUE", ERR_LIB_DH, DH_R_CHECK_INVALID_J_VALUE}, + #else + {"CHECK_INVALID_J_VALUE", 5, 115}, + #endif + #ifdef DH_R_CHECK_INVALID_Q_VALUE + {"CHECK_INVALID_Q_VALUE", ERR_LIB_DH, DH_R_CHECK_INVALID_Q_VALUE}, + #else + {"CHECK_INVALID_Q_VALUE", 5, 116}, + #endif + #ifdef DH_R_CHECK_PUBKEY_INVALID + {"CHECK_PUBKEY_INVALID", ERR_LIB_DH, DH_R_CHECK_PUBKEY_INVALID}, + #else + {"CHECK_PUBKEY_INVALID", 5, 122}, + #endif + #ifdef DH_R_CHECK_PUBKEY_TOO_LARGE + {"CHECK_PUBKEY_TOO_LARGE", ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_LARGE}, + #else + {"CHECK_PUBKEY_TOO_LARGE", 5, 123}, + #endif + #ifdef DH_R_CHECK_PUBKEY_TOO_SMALL + {"CHECK_PUBKEY_TOO_SMALL", ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_SMALL}, + #else + {"CHECK_PUBKEY_TOO_SMALL", 5, 124}, + #endif + #ifdef DH_R_CHECK_P_NOT_PRIME + {"CHECK_P_NOT_PRIME", ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME}, + #else + {"CHECK_P_NOT_PRIME", 5, 117}, + #endif + #ifdef DH_R_CHECK_P_NOT_SAFE_PRIME + {"CHECK_P_NOT_SAFE_PRIME", ERR_LIB_DH, DH_R_CHECK_P_NOT_SAFE_PRIME}, + #else + {"CHECK_P_NOT_SAFE_PRIME", 5, 118}, + #endif + #ifdef DH_R_CHECK_Q_NOT_PRIME + {"CHECK_Q_NOT_PRIME", ERR_LIB_DH, DH_R_CHECK_Q_NOT_PRIME}, + #else + {"CHECK_Q_NOT_PRIME", 5, 119}, + #endif + #ifdef DH_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_DH, DH_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 5, 104}, + #endif + #ifdef DH_R_INVALID_PARAMETER_NAME + {"INVALID_PARAMETER_NAME", ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME}, + #else + {"INVALID_PARAMETER_NAME", 5, 110}, + #endif + #ifdef DH_R_INVALID_PARAMETER_NID + {"INVALID_PARAMETER_NID", ERR_LIB_DH, DH_R_INVALID_PARAMETER_NID}, + #else + {"INVALID_PARAMETER_NID", 5, 114}, + #endif + #ifdef DH_R_INVALID_PUBKEY + {"INVALID_PUBKEY", ERR_LIB_DH, DH_R_INVALID_PUBKEY}, + #else + {"INVALID_PUBKEY", 5, 102}, + #endif + #ifdef DH_R_INVALID_SECRET + {"INVALID_SECRET", ERR_LIB_DH, DH_R_INVALID_SECRET}, + #else + {"INVALID_SECRET", 5, 128}, + #endif + #ifdef DH_R_INVALID_SIZE + {"INVALID_SIZE", ERR_LIB_DH, DH_R_INVALID_SIZE}, + #else + {"INVALID_SIZE", 5, 129}, + #endif + #ifdef DH_R_KDF_PARAMETER_ERROR + {"KDF_PARAMETER_ERROR", ERR_LIB_DH, DH_R_KDF_PARAMETER_ERROR}, + #else + {"KDF_PARAMETER_ERROR", 5, 112}, + #endif + #ifdef DH_R_KEYS_NOT_SET + {"KEYS_NOT_SET", ERR_LIB_DH, DH_R_KEYS_NOT_SET}, + #else + {"KEYS_NOT_SET", 5, 108}, + #endif + #ifdef DH_R_MISSING_PUBKEY + {"MISSING_PUBKEY", ERR_LIB_DH, DH_R_MISSING_PUBKEY}, + #else + {"MISSING_PUBKEY", 5, 125}, + #endif + #ifdef DH_R_MODULUS_TOO_LARGE + {"MODULUS_TOO_LARGE", ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE}, + #else + {"MODULUS_TOO_LARGE", 5, 103}, + #endif + #ifdef DH_R_MODULUS_TOO_SMALL + {"MODULUS_TOO_SMALL", ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL}, + #else + {"MODULUS_TOO_SMALL", 5, 126}, + #endif + #ifdef DH_R_NOT_SUITABLE_GENERATOR + {"NOT_SUITABLE_GENERATOR", ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR}, + #else + {"NOT_SUITABLE_GENERATOR", 5, 120}, + #endif + #ifdef DH_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_DH, DH_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 5, 107}, + #endif + #ifdef DH_R_NO_PRIVATE_VALUE + {"NO_PRIVATE_VALUE", ERR_LIB_DH, DH_R_NO_PRIVATE_VALUE}, + #else + {"NO_PRIVATE_VALUE", 5, 100}, + #endif + #ifdef DH_R_PARAMETER_ENCODING_ERROR + {"PARAMETER_ENCODING_ERROR", ERR_LIB_DH, DH_R_PARAMETER_ENCODING_ERROR}, + #else + {"PARAMETER_ENCODING_ERROR", 5, 105}, + #endif + #ifdef DH_R_PEER_KEY_ERROR + {"PEER_KEY_ERROR", ERR_LIB_DH, DH_R_PEER_KEY_ERROR}, + #else + {"PEER_KEY_ERROR", 5, 111}, + #endif + #ifdef DH_R_Q_TOO_LARGE + {"Q_TOO_LARGE", ERR_LIB_DH, DH_R_Q_TOO_LARGE}, + #else + {"Q_TOO_LARGE", 5, 130}, + #endif + #ifdef DH_R_SHARED_INFO_ERROR + {"SHARED_INFO_ERROR", ERR_LIB_DH, DH_R_SHARED_INFO_ERROR}, + #else + {"SHARED_INFO_ERROR", 5, 113}, + #endif + #ifdef DH_R_UNABLE_TO_CHECK_GENERATOR + {"UNABLE_TO_CHECK_GENERATOR", ERR_LIB_DH, DH_R_UNABLE_TO_CHECK_GENERATOR}, + #else + {"UNABLE_TO_CHECK_GENERATOR", 5, 121}, + #endif + #ifdef DSA_R_BAD_FFC_PARAMETERS + {"BAD_FFC_PARAMETERS", ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS}, + #else + {"BAD_FFC_PARAMETERS", 10, 114}, + #endif + #ifdef DSA_R_BAD_Q_VALUE + {"BAD_Q_VALUE", ERR_LIB_DSA, DSA_R_BAD_Q_VALUE}, + #else + {"BAD_Q_VALUE", 10, 102}, + #endif + #ifdef DSA_R_BN_DECODE_ERROR + {"BN_DECODE_ERROR", ERR_LIB_DSA, DSA_R_BN_DECODE_ERROR}, + #else + {"BN_DECODE_ERROR", 10, 108}, + #endif + #ifdef DSA_R_BN_ERROR + {"BN_ERROR", ERR_LIB_DSA, DSA_R_BN_ERROR}, + #else + {"BN_ERROR", 10, 109}, + #endif + #ifdef DSA_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_DSA, DSA_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 10, 104}, + #endif + #ifdef DSA_R_INVALID_DIGEST_TYPE + {"INVALID_DIGEST_TYPE", ERR_LIB_DSA, DSA_R_INVALID_DIGEST_TYPE}, + #else + {"INVALID_DIGEST_TYPE", 10, 106}, + #endif + #ifdef DSA_R_INVALID_PARAMETERS + {"INVALID_PARAMETERS", ERR_LIB_DSA, DSA_R_INVALID_PARAMETERS}, + #else + {"INVALID_PARAMETERS", 10, 112}, + #endif + #ifdef DSA_R_MISSING_PARAMETERS + {"MISSING_PARAMETERS", ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS}, + #else + {"MISSING_PARAMETERS", 10, 101}, + #endif + #ifdef DSA_R_MISSING_PRIVATE_KEY + {"MISSING_PRIVATE_KEY", ERR_LIB_DSA, DSA_R_MISSING_PRIVATE_KEY}, + #else + {"MISSING_PRIVATE_KEY", 10, 111}, + #endif + #ifdef DSA_R_MODULUS_TOO_LARGE + {"MODULUS_TOO_LARGE", ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE}, + #else + {"MODULUS_TOO_LARGE", 10, 103}, + #endif + #ifdef DSA_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_DSA, DSA_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 10, 107}, + #endif + #ifdef DSA_R_PARAMETER_ENCODING_ERROR + {"PARAMETER_ENCODING_ERROR", ERR_LIB_DSA, DSA_R_PARAMETER_ENCODING_ERROR}, + #else + {"PARAMETER_ENCODING_ERROR", 10, 105}, + #endif + #ifdef DSA_R_P_NOT_PRIME + {"P_NOT_PRIME", ERR_LIB_DSA, DSA_R_P_NOT_PRIME}, + #else + {"P_NOT_PRIME", 10, 115}, + #endif + #ifdef DSA_R_Q_NOT_PRIME + {"Q_NOT_PRIME", ERR_LIB_DSA, DSA_R_Q_NOT_PRIME}, + #else + {"Q_NOT_PRIME", 10, 113}, + #endif + #ifdef DSA_R_SEED_LEN_SMALL + {"SEED_LEN_SMALL", ERR_LIB_DSA, DSA_R_SEED_LEN_SMALL}, + #else + {"SEED_LEN_SMALL", 10, 110}, + #endif + #ifdef DSA_R_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_DSA, DSA_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 10, 116}, + #endif + #ifdef DSO_R_CTRL_FAILED + {"CTRL_FAILED", ERR_LIB_DSO, DSO_R_CTRL_FAILED}, + #else + {"CTRL_FAILED", 37, 100}, + #endif + #ifdef DSO_R_DSO_ALREADY_LOADED + {"DSO_ALREADY_LOADED", ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED}, + #else + {"DSO_ALREADY_LOADED", 37, 110}, + #endif + #ifdef DSO_R_EMPTY_FILE_STRUCTURE + {"EMPTY_FILE_STRUCTURE", ERR_LIB_DSO, DSO_R_EMPTY_FILE_STRUCTURE}, + #else + {"EMPTY_FILE_STRUCTURE", 37, 113}, + #endif + #ifdef DSO_R_FAILURE + {"FAILURE", ERR_LIB_DSO, DSO_R_FAILURE}, + #else + {"FAILURE", 37, 114}, + #endif + #ifdef DSO_R_FILENAME_TOO_BIG + {"FILENAME_TOO_BIG", ERR_LIB_DSO, DSO_R_FILENAME_TOO_BIG}, + #else + {"FILENAME_TOO_BIG", 37, 101}, + #endif + #ifdef DSO_R_FINISH_FAILED + {"FINISH_FAILED", ERR_LIB_DSO, DSO_R_FINISH_FAILED}, + #else + {"FINISH_FAILED", 37, 102}, + #endif + #ifdef DSO_R_INCORRECT_FILE_SYNTAX + {"INCORRECT_FILE_SYNTAX", ERR_LIB_DSO, DSO_R_INCORRECT_FILE_SYNTAX}, + #else + {"INCORRECT_FILE_SYNTAX", 37, 115}, + #endif + #ifdef DSO_R_LOAD_FAILED + {"LOAD_FAILED", ERR_LIB_DSO, DSO_R_LOAD_FAILED}, + #else + {"LOAD_FAILED", 37, 103}, + #endif + #ifdef DSO_R_NAME_TRANSLATION_FAILED + {"NAME_TRANSLATION_FAILED", ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED}, + #else + {"NAME_TRANSLATION_FAILED", 37, 109}, + #endif + #ifdef DSO_R_NO_FILENAME + {"NO_FILENAME", ERR_LIB_DSO, DSO_R_NO_FILENAME}, + #else + {"NO_FILENAME", 37, 111}, + #endif + #ifdef DSO_R_NULL_HANDLE + {"NULL_HANDLE", ERR_LIB_DSO, DSO_R_NULL_HANDLE}, + #else + {"NULL_HANDLE", 37, 104}, + #endif + #ifdef DSO_R_SET_FILENAME_FAILED + {"SET_FILENAME_FAILED", ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED}, + #else + {"SET_FILENAME_FAILED", 37, 112}, + #endif + #ifdef DSO_R_STACK_ERROR + {"STACK_ERROR", ERR_LIB_DSO, DSO_R_STACK_ERROR}, + #else + {"STACK_ERROR", 37, 105}, + #endif + #ifdef DSO_R_SYM_FAILURE + {"SYM_FAILURE", ERR_LIB_DSO, DSO_R_SYM_FAILURE}, + #else + {"SYM_FAILURE", 37, 106}, + #endif + #ifdef DSO_R_UNLOAD_FAILED + {"UNLOAD_FAILED", ERR_LIB_DSO, DSO_R_UNLOAD_FAILED}, + #else + {"UNLOAD_FAILED", 37, 107}, + #endif + #ifdef DSO_R_UNSUPPORTED + {"UNSUPPORTED", ERR_LIB_DSO, DSO_R_UNSUPPORTED}, + #else + {"UNSUPPORTED", 37, 108}, + #endif + #ifdef EC_R_ASN1_ERROR + {"ASN1_ERROR", ERR_LIB_EC, EC_R_ASN1_ERROR}, + #else + {"ASN1_ERROR", 16, 115}, + #endif + #ifdef EC_R_BAD_SIGNATURE + {"BAD_SIGNATURE", ERR_LIB_EC, EC_R_BAD_SIGNATURE}, + #else + {"BAD_SIGNATURE", 16, 156}, + #endif + #ifdef EC_R_BIGNUM_OUT_OF_RANGE + {"BIGNUM_OUT_OF_RANGE", ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE}, + #else + {"BIGNUM_OUT_OF_RANGE", 16, 144}, + #endif + #ifdef EC_R_BUFFER_TOO_SMALL + {"BUFFER_TOO_SMALL", ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL}, + #else + {"BUFFER_TOO_SMALL", 16, 100}, + #endif + #ifdef EC_R_CANNOT_INVERT + {"CANNOT_INVERT", ERR_LIB_EC, EC_R_CANNOT_INVERT}, + #else + {"CANNOT_INVERT", 16, 165}, + #endif + #ifdef EC_R_COORDINATES_OUT_OF_RANGE + {"COORDINATES_OUT_OF_RANGE", ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE}, + #else + {"COORDINATES_OUT_OF_RANGE", 16, 146}, + #endif + #ifdef EC_R_CURVE_DOES_NOT_SUPPORT_ECDH + {"CURVE_DOES_NOT_SUPPORT_ECDH", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH}, + #else + {"CURVE_DOES_NOT_SUPPORT_ECDH", 16, 160}, + #endif + #ifdef EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA + {"CURVE_DOES_NOT_SUPPORT_ECDSA", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA}, + #else + {"CURVE_DOES_NOT_SUPPORT_ECDSA", 16, 170}, + #endif + #ifdef EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING + {"CURVE_DOES_NOT_SUPPORT_SIGNING", ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING}, + #else + {"CURVE_DOES_NOT_SUPPORT_SIGNING", 16, 159}, + #endif + #ifdef EC_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_EC, EC_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 16, 142}, + #endif + #ifdef EC_R_DISCRIMINANT_IS_ZERO + {"DISCRIMINANT_IS_ZERO", ERR_LIB_EC, EC_R_DISCRIMINANT_IS_ZERO}, + #else + {"DISCRIMINANT_IS_ZERO", 16, 118}, + #endif + #ifdef EC_R_EC_GROUP_NEW_BY_NAME_FAILURE + {"EC_GROUP_NEW_BY_NAME_FAILURE", ERR_LIB_EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE}, + #else + {"EC_GROUP_NEW_BY_NAME_FAILURE", 16, 119}, + #endif + #ifdef EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED + {"EXPLICIT_PARAMS_NOT_SUPPORTED", ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED}, + #else + {"EXPLICIT_PARAMS_NOT_SUPPORTED", 16, 127}, + #endif + #ifdef EC_R_FAILED_MAKING_PUBLIC_KEY + {"FAILED_MAKING_PUBLIC_KEY", ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY}, + #else + {"FAILED_MAKING_PUBLIC_KEY", 16, 166}, + #endif + #ifdef EC_R_FIELD_TOO_LARGE + {"FIELD_TOO_LARGE", ERR_LIB_EC, EC_R_FIELD_TOO_LARGE}, + #else + {"FIELD_TOO_LARGE", 16, 143}, + #endif + #ifdef EC_R_GF2M_NOT_SUPPORTED + {"GF2M_NOT_SUPPORTED", ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED}, + #else + {"GF2M_NOT_SUPPORTED", 16, 147}, + #endif + #ifdef EC_R_GROUP2PKPARAMETERS_FAILURE + {"GROUP2PKPARAMETERS_FAILURE", ERR_LIB_EC, EC_R_GROUP2PKPARAMETERS_FAILURE}, + #else + {"GROUP2PKPARAMETERS_FAILURE", 16, 120}, + #endif + #ifdef EC_R_I2D_ECPKPARAMETERS_FAILURE + {"I2D_ECPKPARAMETERS_FAILURE", ERR_LIB_EC, EC_R_I2D_ECPKPARAMETERS_FAILURE}, + #else + {"I2D_ECPKPARAMETERS_FAILURE", 16, 121}, + #endif + #ifdef EC_R_INCOMPATIBLE_OBJECTS + {"INCOMPATIBLE_OBJECTS", ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS}, + #else + {"INCOMPATIBLE_OBJECTS", 16, 101}, + #endif + #ifdef EC_R_INVALID_A + {"INVALID_A", ERR_LIB_EC, EC_R_INVALID_A}, + #else + {"INVALID_A", 16, 168}, + #endif + #ifdef EC_R_INVALID_ARGUMENT + {"INVALID_ARGUMENT", ERR_LIB_EC, EC_R_INVALID_ARGUMENT}, + #else + {"INVALID_ARGUMENT", 16, 112}, + #endif + #ifdef EC_R_INVALID_B + {"INVALID_B", ERR_LIB_EC, EC_R_INVALID_B}, + #else + {"INVALID_B", 16, 169}, + #endif + #ifdef EC_R_INVALID_COFACTOR + {"INVALID_COFACTOR", ERR_LIB_EC, EC_R_INVALID_COFACTOR}, + #else + {"INVALID_COFACTOR", 16, 171}, + #endif + #ifdef EC_R_INVALID_COMPRESSED_POINT + {"INVALID_COMPRESSED_POINT", ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT}, + #else + {"INVALID_COMPRESSED_POINT", 16, 110}, + #endif + #ifdef EC_R_INVALID_COMPRESSION_BIT + {"INVALID_COMPRESSION_BIT", ERR_LIB_EC, EC_R_INVALID_COMPRESSION_BIT}, + #else + {"INVALID_COMPRESSION_BIT", 16, 109}, + #endif + #ifdef EC_R_INVALID_CURVE + {"INVALID_CURVE", ERR_LIB_EC, EC_R_INVALID_CURVE}, + #else + {"INVALID_CURVE", 16, 141}, + #endif + #ifdef EC_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_EC, EC_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 16, 151}, + #endif + #ifdef EC_R_INVALID_DIGEST_TYPE + {"INVALID_DIGEST_TYPE", ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE}, + #else + {"INVALID_DIGEST_TYPE", 16, 138}, + #endif + #ifdef EC_R_INVALID_ENCODING + {"INVALID_ENCODING", ERR_LIB_EC, EC_R_INVALID_ENCODING}, + #else + {"INVALID_ENCODING", 16, 102}, + #endif + #ifdef EC_R_INVALID_FIELD + {"INVALID_FIELD", ERR_LIB_EC, EC_R_INVALID_FIELD}, + #else + {"INVALID_FIELD", 16, 103}, + #endif + #ifdef EC_R_INVALID_FORM + {"INVALID_FORM", ERR_LIB_EC, EC_R_INVALID_FORM}, + #else + {"INVALID_FORM", 16, 104}, + #endif + #ifdef EC_R_INVALID_GENERATOR + {"INVALID_GENERATOR", ERR_LIB_EC, EC_R_INVALID_GENERATOR}, + #else + {"INVALID_GENERATOR", 16, 173}, + #endif + #ifdef EC_R_INVALID_GROUP_ORDER + {"INVALID_GROUP_ORDER", ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER}, + #else + {"INVALID_GROUP_ORDER", 16, 122}, + #endif + #ifdef EC_R_INVALID_KEY + {"INVALID_KEY", ERR_LIB_EC, EC_R_INVALID_KEY}, + #else + {"INVALID_KEY", 16, 116}, + #endif + #ifdef EC_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_EC, EC_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 16, 117}, + #endif + #ifdef EC_R_INVALID_NAMED_GROUP_CONVERSION + {"INVALID_NAMED_GROUP_CONVERSION", ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION}, + #else + {"INVALID_NAMED_GROUP_CONVERSION", 16, 174}, + #endif + #ifdef EC_R_INVALID_OUTPUT_LENGTH + {"INVALID_OUTPUT_LENGTH", ERR_LIB_EC, EC_R_INVALID_OUTPUT_LENGTH}, + #else + {"INVALID_OUTPUT_LENGTH", 16, 161}, + #endif + #ifdef EC_R_INVALID_P + {"INVALID_P", ERR_LIB_EC, EC_R_INVALID_P}, + #else + {"INVALID_P", 16, 172}, + #endif + #ifdef EC_R_INVALID_PEER_KEY + {"INVALID_PEER_KEY", ERR_LIB_EC, EC_R_INVALID_PEER_KEY}, + #else + {"INVALID_PEER_KEY", 16, 133}, + #endif + #ifdef EC_R_INVALID_PENTANOMIAL_BASIS + {"INVALID_PENTANOMIAL_BASIS", ERR_LIB_EC, EC_R_INVALID_PENTANOMIAL_BASIS}, + #else + {"INVALID_PENTANOMIAL_BASIS", 16, 132}, + #endif + #ifdef EC_R_INVALID_PRIVATE_KEY + {"INVALID_PRIVATE_KEY", ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY}, + #else + {"INVALID_PRIVATE_KEY", 16, 123}, + #endif + #ifdef EC_R_INVALID_SEED + {"INVALID_SEED", ERR_LIB_EC, EC_R_INVALID_SEED}, + #else + {"INVALID_SEED", 16, 175}, + #endif + #ifdef EC_R_INVALID_TRINOMIAL_BASIS + {"INVALID_TRINOMIAL_BASIS", ERR_LIB_EC, EC_R_INVALID_TRINOMIAL_BASIS}, + #else + {"INVALID_TRINOMIAL_BASIS", 16, 137}, + #endif + #ifdef EC_R_KDF_PARAMETER_ERROR + {"KDF_PARAMETER_ERROR", ERR_LIB_EC, EC_R_KDF_PARAMETER_ERROR}, + #else + {"KDF_PARAMETER_ERROR", 16, 148}, + #endif + #ifdef EC_R_KEYS_NOT_SET + {"KEYS_NOT_SET", ERR_LIB_EC, EC_R_KEYS_NOT_SET}, + #else + {"KEYS_NOT_SET", 16, 140}, + #endif + #ifdef EC_R_LADDER_POST_FAILURE + {"LADDER_POST_FAILURE", ERR_LIB_EC, EC_R_LADDER_POST_FAILURE}, + #else + {"LADDER_POST_FAILURE", 16, 136}, + #endif + #ifdef EC_R_LADDER_PRE_FAILURE + {"LADDER_PRE_FAILURE", ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE}, + #else + {"LADDER_PRE_FAILURE", 16, 153}, + #endif + #ifdef EC_R_LADDER_STEP_FAILURE + {"LADDER_STEP_FAILURE", ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE}, + #else + {"LADDER_STEP_FAILURE", 16, 162}, + #endif + #ifdef EC_R_MISSING_OID + {"MISSING_OID", ERR_LIB_EC, EC_R_MISSING_OID}, + #else + {"MISSING_OID", 16, 167}, + #endif + #ifdef EC_R_MISSING_PARAMETERS + {"MISSING_PARAMETERS", ERR_LIB_EC, EC_R_MISSING_PARAMETERS}, + #else + {"MISSING_PARAMETERS", 16, 124}, + #endif + #ifdef EC_R_MISSING_PRIVATE_KEY + {"MISSING_PRIVATE_KEY", ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY}, + #else + {"MISSING_PRIVATE_KEY", 16, 125}, + #endif + #ifdef EC_R_NEED_NEW_SETUP_VALUES + {"NEED_NEW_SETUP_VALUES", ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES}, + #else + {"NEED_NEW_SETUP_VALUES", 16, 157}, + #endif + #ifdef EC_R_NOT_A_NIST_PRIME + {"NOT_A_NIST_PRIME", ERR_LIB_EC, EC_R_NOT_A_NIST_PRIME}, + #else + {"NOT_A_NIST_PRIME", 16, 135}, + #endif + #ifdef EC_R_NOT_IMPLEMENTED + {"NOT_IMPLEMENTED", ERR_LIB_EC, EC_R_NOT_IMPLEMENTED}, + #else + {"NOT_IMPLEMENTED", 16, 126}, + #endif + #ifdef EC_R_NOT_INITIALIZED + {"NOT_INITIALIZED", ERR_LIB_EC, EC_R_NOT_INITIALIZED}, + #else + {"NOT_INITIALIZED", 16, 111}, + #endif + #ifdef EC_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_EC, EC_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 16, 139}, + #endif + #ifdef EC_R_NO_PRIVATE_VALUE + {"NO_PRIVATE_VALUE", ERR_LIB_EC, EC_R_NO_PRIVATE_VALUE}, + #else + {"NO_PRIVATE_VALUE", 16, 154}, + #endif + #ifdef EC_R_OPERATION_NOT_SUPPORTED + {"OPERATION_NOT_SUPPORTED", ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED}, + #else + {"OPERATION_NOT_SUPPORTED", 16, 152}, + #endif + #ifdef EC_R_PASSED_NULL_PARAMETER + {"PASSED_NULL_PARAMETER", ERR_LIB_EC, EC_R_PASSED_NULL_PARAMETER}, + #else + {"PASSED_NULL_PARAMETER", 16, 134}, + #endif + #ifdef EC_R_PEER_KEY_ERROR + {"PEER_KEY_ERROR", ERR_LIB_EC, EC_R_PEER_KEY_ERROR}, + #else + {"PEER_KEY_ERROR", 16, 149}, + #endif + #ifdef EC_R_POINT_ARITHMETIC_FAILURE + {"POINT_ARITHMETIC_FAILURE", ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE}, + #else + {"POINT_ARITHMETIC_FAILURE", 16, 155}, + #endif + #ifdef EC_R_POINT_AT_INFINITY + {"POINT_AT_INFINITY", ERR_LIB_EC, EC_R_POINT_AT_INFINITY}, + #else + {"POINT_AT_INFINITY", 16, 106}, + #endif + #ifdef EC_R_POINT_COORDINATES_BLIND_FAILURE + {"POINT_COORDINATES_BLIND_FAILURE", ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE}, + #else + {"POINT_COORDINATES_BLIND_FAILURE", 16, 163}, + #endif + #ifdef EC_R_POINT_IS_NOT_ON_CURVE + {"POINT_IS_NOT_ON_CURVE", ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE}, + #else + {"POINT_IS_NOT_ON_CURVE", 16, 107}, + #endif + #ifdef EC_R_RANDOM_NUMBER_GENERATION_FAILED + {"RANDOM_NUMBER_GENERATION_FAILED", ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED}, + #else + {"RANDOM_NUMBER_GENERATION_FAILED", 16, 158}, + #endif + #ifdef EC_R_SHARED_INFO_ERROR + {"SHARED_INFO_ERROR", ERR_LIB_EC, EC_R_SHARED_INFO_ERROR}, + #else + {"SHARED_INFO_ERROR", 16, 150}, + #endif + #ifdef EC_R_SLOT_FULL + {"SLOT_FULL", ERR_LIB_EC, EC_R_SLOT_FULL}, + #else + {"SLOT_FULL", 16, 108}, + #endif + #ifdef EC_R_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_EC, EC_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 16, 176}, + #endif + #ifdef EC_R_UNDEFINED_GENERATOR + {"UNDEFINED_GENERATOR", ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR}, + #else + {"UNDEFINED_GENERATOR", 16, 113}, + #endif + #ifdef EC_R_UNDEFINED_ORDER + {"UNDEFINED_ORDER", ERR_LIB_EC, EC_R_UNDEFINED_ORDER}, + #else + {"UNDEFINED_ORDER", 16, 128}, + #endif + #ifdef EC_R_UNKNOWN_COFACTOR + {"UNKNOWN_COFACTOR", ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR}, + #else + {"UNKNOWN_COFACTOR", 16, 164}, + #endif + #ifdef EC_R_UNKNOWN_GROUP + {"UNKNOWN_GROUP", ERR_LIB_EC, EC_R_UNKNOWN_GROUP}, + #else + {"UNKNOWN_GROUP", 16, 129}, + #endif + #ifdef EC_R_UNKNOWN_ORDER + {"UNKNOWN_ORDER", ERR_LIB_EC, EC_R_UNKNOWN_ORDER}, + #else + {"UNKNOWN_ORDER", 16, 114}, + #endif + #ifdef EC_R_UNSUPPORTED_FIELD + {"UNSUPPORTED_FIELD", ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD}, + #else + {"UNSUPPORTED_FIELD", 16, 131}, + #endif + #ifdef EC_R_WRONG_CURVE_PARAMETERS + {"WRONG_CURVE_PARAMETERS", ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS}, + #else + {"WRONG_CURVE_PARAMETERS", 16, 145}, + #endif + #ifdef EC_R_WRONG_ORDER + {"WRONG_ORDER", ERR_LIB_EC, EC_R_WRONG_ORDER}, + #else + {"WRONG_ORDER", 16, 130}, + #endif + #ifdef ESS_R_EMPTY_ESS_CERT_ID_LIST + {"EMPTY_ESS_CERT_ID_LIST", ERR_LIB_ESS, ESS_R_EMPTY_ESS_CERT_ID_LIST}, + #else + {"EMPTY_ESS_CERT_ID_LIST", 54, 107}, + #endif + #ifdef ESS_R_ESS_CERT_DIGEST_ERROR + {"ESS_CERT_DIGEST_ERROR", ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR}, + #else + {"ESS_CERT_DIGEST_ERROR", 54, 103}, + #endif + #ifdef ESS_R_ESS_CERT_ID_NOT_FOUND + {"ESS_CERT_ID_NOT_FOUND", ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND}, + #else + {"ESS_CERT_ID_NOT_FOUND", 54, 104}, + #endif + #ifdef ESS_R_ESS_CERT_ID_WRONG_ORDER + {"ESS_CERT_ID_WRONG_ORDER", ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER}, + #else + {"ESS_CERT_ID_WRONG_ORDER", 54, 105}, + #endif + #ifdef ESS_R_ESS_DIGEST_ALG_UNKNOWN + {"ESS_DIGEST_ALG_UNKNOWN", ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN}, + #else + {"ESS_DIGEST_ALG_UNKNOWN", 54, 106}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERTIFICATE_ERROR + {"ESS_SIGNING_CERTIFICATE_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERTIFICATE_ERROR}, + #else + {"ESS_SIGNING_CERTIFICATE_ERROR", 54, 102}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERT_ADD_ERROR + {"ESS_SIGNING_CERT_ADD_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERT_ADD_ERROR}, + #else + {"ESS_SIGNING_CERT_ADD_ERROR", 54, 100}, + #endif + #ifdef ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR + {"ESS_SIGNING_CERT_V2_ADD_ERROR", ERR_LIB_ESS, ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR}, + #else + {"ESS_SIGNING_CERT_V2_ADD_ERROR", 54, 101}, + #endif + #ifdef ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE + {"MISSING_SIGNING_CERTIFICATE_ATTRIBUTE", ERR_LIB_ESS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE}, + #else + {"MISSING_SIGNING_CERTIFICATE_ATTRIBUTE", 54, 108}, + #endif + #ifdef EVP_R_AES_KEY_SETUP_FAILED + {"AES_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED}, + #else + {"AES_KEY_SETUP_FAILED", 6, 143}, + #endif + #ifdef EVP_R_ARIA_KEY_SETUP_FAILED + {"ARIA_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_ARIA_KEY_SETUP_FAILED}, + #else + {"ARIA_KEY_SETUP_FAILED", 6, 176}, + #endif + #ifdef EVP_R_BAD_ALGORITHM_NAME + {"BAD_ALGORITHM_NAME", ERR_LIB_EVP, EVP_R_BAD_ALGORITHM_NAME}, + #else + {"BAD_ALGORITHM_NAME", 6, 200}, + #endif + #ifdef EVP_R_BAD_DECRYPT + {"BAD_DECRYPT", ERR_LIB_EVP, EVP_R_BAD_DECRYPT}, + #else + {"BAD_DECRYPT", 6, 100}, + #endif + #ifdef EVP_R_BAD_KEY_LENGTH + {"BAD_KEY_LENGTH", ERR_LIB_EVP, EVP_R_BAD_KEY_LENGTH}, + #else + {"BAD_KEY_LENGTH", 6, 195}, + #endif + #ifdef EVP_R_BUFFER_TOO_SMALL + {"BUFFER_TOO_SMALL", ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL}, + #else + {"BUFFER_TOO_SMALL", 6, 155}, + #endif + #ifdef EVP_R_CACHE_CONSTANTS_FAILED + {"CACHE_CONSTANTS_FAILED", ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED}, + #else + {"CACHE_CONSTANTS_FAILED", 6, 225}, + #endif + #ifdef EVP_R_CAMELLIA_KEY_SETUP_FAILED + {"CAMELLIA_KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_CAMELLIA_KEY_SETUP_FAILED}, + #else + {"CAMELLIA_KEY_SETUP_FAILED", 6, 157}, + #endif + #ifdef EVP_R_CANNOT_GET_PARAMETERS + {"CANNOT_GET_PARAMETERS", ERR_LIB_EVP, EVP_R_CANNOT_GET_PARAMETERS}, + #else + {"CANNOT_GET_PARAMETERS", 6, 197}, + #endif + #ifdef EVP_R_CANNOT_SET_PARAMETERS + {"CANNOT_SET_PARAMETERS", ERR_LIB_EVP, EVP_R_CANNOT_SET_PARAMETERS}, + #else + {"CANNOT_SET_PARAMETERS", 6, 198}, + #endif + #ifdef EVP_R_CIPHER_NOT_GCM_MODE + {"CIPHER_NOT_GCM_MODE", ERR_LIB_EVP, EVP_R_CIPHER_NOT_GCM_MODE}, + #else + {"CIPHER_NOT_GCM_MODE", 6, 184}, + #endif + #ifdef EVP_R_CIPHER_PARAMETER_ERROR + {"CIPHER_PARAMETER_ERROR", ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR}, + #else + {"CIPHER_PARAMETER_ERROR", 6, 122}, + #endif + #ifdef EVP_R_COMMAND_NOT_SUPPORTED + {"COMMAND_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED}, + #else + {"COMMAND_NOT_SUPPORTED", 6, 147}, + #endif + #ifdef EVP_R_CONFLICTING_ALGORITHM_NAME + {"CONFLICTING_ALGORITHM_NAME", ERR_LIB_EVP, EVP_R_CONFLICTING_ALGORITHM_NAME}, + #else + {"CONFLICTING_ALGORITHM_NAME", 6, 201}, + #endif + #ifdef EVP_R_CONTEXT_FINALIZED + {"CONTEXT_FINALIZED", ERR_LIB_EVP, EVP_R_CONTEXT_FINALIZED}, + #else + {"CONTEXT_FINALIZED", 6, 239}, + #endif + #ifdef EVP_R_COPY_ERROR + {"COPY_ERROR", ERR_LIB_EVP, EVP_R_COPY_ERROR}, + #else + {"COPY_ERROR", 6, 173}, + #endif + #ifdef EVP_R_CTRL_NOT_IMPLEMENTED + {"CTRL_NOT_IMPLEMENTED", ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED}, + #else + {"CTRL_NOT_IMPLEMENTED", 6, 132}, + #endif + #ifdef EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED + {"CTRL_OPERATION_NOT_IMPLEMENTED", ERR_LIB_EVP, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED}, + #else + {"CTRL_OPERATION_NOT_IMPLEMENTED", 6, 133}, + #endif + #ifdef EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + {"DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH", ERR_LIB_EVP, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH}, + #else + {"DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH", 6, 138}, + #endif + #ifdef EVP_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_EVP, EVP_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 6, 114}, + #endif + #ifdef EVP_R_DEFAULT_QUERY_PARSE_ERROR + {"DEFAULT_QUERY_PARSE_ERROR", ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR}, + #else + {"DEFAULT_QUERY_PARSE_ERROR", 6, 210}, + #endif + #ifdef EVP_R_DIFFERENT_KEY_TYPES + {"DIFFERENT_KEY_TYPES", ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES}, + #else + {"DIFFERENT_KEY_TYPES", 6, 101}, + #endif + #ifdef EVP_R_DIFFERENT_PARAMETERS + {"DIFFERENT_PARAMETERS", ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS}, + #else + {"DIFFERENT_PARAMETERS", 6, 153}, + #endif + #ifdef EVP_R_ERROR_LOADING_SECTION + {"ERROR_LOADING_SECTION", ERR_LIB_EVP, EVP_R_ERROR_LOADING_SECTION}, + #else + {"ERROR_LOADING_SECTION", 6, 165}, + #endif + #ifdef EVP_R_EXPECTING_AN_HMAC_KEY + {"EXPECTING_AN_HMAC_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_AN_HMAC_KEY}, + #else + {"EXPECTING_AN_HMAC_KEY", 6, 174}, + #endif + #ifdef EVP_R_EXPECTING_AN_RSA_KEY + {"EXPECTING_AN_RSA_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_AN_RSA_KEY}, + #else + {"EXPECTING_AN_RSA_KEY", 6, 127}, + #endif + #ifdef EVP_R_EXPECTING_A_DH_KEY + {"EXPECTING_A_DH_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_DH_KEY}, + #else + {"EXPECTING_A_DH_KEY", 6, 128}, + #endif + #ifdef EVP_R_EXPECTING_A_DSA_KEY + {"EXPECTING_A_DSA_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_DSA_KEY}, + #else + {"EXPECTING_A_DSA_KEY", 6, 129}, + #endif + #ifdef EVP_R_EXPECTING_A_ECX_KEY + {"EXPECTING_A_ECX_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY}, + #else + {"EXPECTING_A_ECX_KEY", 6, 219}, + #endif + #ifdef EVP_R_EXPECTING_A_EC_KEY + {"EXPECTING_A_EC_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_EC_KEY}, + #else + {"EXPECTING_A_EC_KEY", 6, 142}, + #endif + #ifdef EVP_R_EXPECTING_A_POLY1305_KEY + {"EXPECTING_A_POLY1305_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_POLY1305_KEY}, + #else + {"EXPECTING_A_POLY1305_KEY", 6, 164}, + #endif + #ifdef EVP_R_EXPECTING_A_SIPHASH_KEY + {"EXPECTING_A_SIPHASH_KEY", ERR_LIB_EVP, EVP_R_EXPECTING_A_SIPHASH_KEY}, + #else + {"EXPECTING_A_SIPHASH_KEY", 6, 175}, + #endif + #ifdef EVP_R_FINAL_ERROR + {"FINAL_ERROR", ERR_LIB_EVP, EVP_R_FINAL_ERROR}, + #else + {"FINAL_ERROR", 6, 188}, + #endif + #ifdef EVP_R_GENERATE_ERROR + {"GENERATE_ERROR", ERR_LIB_EVP, EVP_R_GENERATE_ERROR}, + #else + {"GENERATE_ERROR", 6, 214}, + #endif + #ifdef EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED + {"GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED}, + #else + {"GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED", 6, 229}, + #endif + #ifdef EVP_R_GET_RAW_KEY_FAILED + {"GET_RAW_KEY_FAILED", ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED}, + #else + {"GET_RAW_KEY_FAILED", 6, 182}, + #endif + #ifdef EVP_R_ILLEGAL_SCRYPT_PARAMETERS + {"ILLEGAL_SCRYPT_PARAMETERS", ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS}, + #else + {"ILLEGAL_SCRYPT_PARAMETERS", 6, 171}, + #endif + #ifdef EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS + {"INACCESSIBLE_DOMAIN_PARAMETERS", ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS}, + #else + {"INACCESSIBLE_DOMAIN_PARAMETERS", 6, 204}, + #endif + #ifdef EVP_R_INACCESSIBLE_KEY + {"INACCESSIBLE_KEY", ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY}, + #else + {"INACCESSIBLE_KEY", 6, 203}, + #endif + #ifdef EVP_R_INITIALIZATION_ERROR + {"INITIALIZATION_ERROR", ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR}, + #else + {"INITIALIZATION_ERROR", 6, 134}, + #endif + #ifdef EVP_R_INPUT_NOT_INITIALIZED + {"INPUT_NOT_INITIALIZED", ERR_LIB_EVP, EVP_R_INPUT_NOT_INITIALIZED}, + #else + {"INPUT_NOT_INITIALIZED", 6, 111}, + #endif + #ifdef EVP_R_INVALID_CUSTOM_LENGTH + {"INVALID_CUSTOM_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_CUSTOM_LENGTH}, + #else + {"INVALID_CUSTOM_LENGTH", 6, 185}, + #endif + #ifdef EVP_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_EVP, EVP_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 6, 152}, + #endif + #ifdef EVP_R_INVALID_IV_LENGTH + {"INVALID_IV_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH}, + #else + {"INVALID_IV_LENGTH", 6, 194}, + #endif + #ifdef EVP_R_INVALID_KEY + {"INVALID_KEY", ERR_LIB_EVP, EVP_R_INVALID_KEY}, + #else + {"INVALID_KEY", 6, 163}, + #endif + #ifdef EVP_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 6, 130}, + #endif + #ifdef EVP_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 6, 221}, + #endif + #ifdef EVP_R_INVALID_NULL_ALGORITHM + {"INVALID_NULL_ALGORITHM", ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM}, + #else + {"INVALID_NULL_ALGORITHM", 6, 218}, + #endif + #ifdef EVP_R_INVALID_OPERATION + {"INVALID_OPERATION", ERR_LIB_EVP, EVP_R_INVALID_OPERATION}, + #else + {"INVALID_OPERATION", 6, 148}, + #endif + #ifdef EVP_R_INVALID_PROVIDER_FUNCTIONS + {"INVALID_PROVIDER_FUNCTIONS", ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS}, + #else + {"INVALID_PROVIDER_FUNCTIONS", 6, 193}, + #endif + #ifdef EVP_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 6, 186}, + #endif + #ifdef EVP_R_INVALID_SECRET_LENGTH + {"INVALID_SECRET_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SECRET_LENGTH}, + #else + {"INVALID_SECRET_LENGTH", 6, 223}, + #endif + #ifdef EVP_R_INVALID_SEED_LENGTH + {"INVALID_SEED_LENGTH", ERR_LIB_EVP, EVP_R_INVALID_SEED_LENGTH}, + #else + {"INVALID_SEED_LENGTH", 6, 220}, + #endif + #ifdef EVP_R_INVALID_VALUE + {"INVALID_VALUE", ERR_LIB_EVP, EVP_R_INVALID_VALUE}, + #else + {"INVALID_VALUE", 6, 222}, + #endif + #ifdef EVP_R_KEYMGMT_EXPORT_FAILURE + {"KEYMGMT_EXPORT_FAILURE", ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE}, + #else + {"KEYMGMT_EXPORT_FAILURE", 6, 205}, + #endif + #ifdef EVP_R_KEY_SETUP_FAILED + {"KEY_SETUP_FAILED", ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED}, + #else + {"KEY_SETUP_FAILED", 6, 180}, + #endif + #ifdef EVP_R_LOCKING_NOT_SUPPORTED + {"LOCKING_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_LOCKING_NOT_SUPPORTED}, + #else + {"LOCKING_NOT_SUPPORTED", 6, 213}, + #endif + #ifdef EVP_R_MEMORY_LIMIT_EXCEEDED + {"MEMORY_LIMIT_EXCEEDED", ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED}, + #else + {"MEMORY_LIMIT_EXCEEDED", 6, 172}, + #endif + #ifdef EVP_R_MESSAGE_DIGEST_IS_NULL + {"MESSAGE_DIGEST_IS_NULL", ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL}, + #else + {"MESSAGE_DIGEST_IS_NULL", 6, 159}, + #endif + #ifdef EVP_R_METHOD_NOT_SUPPORTED + {"METHOD_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED}, + #else + {"METHOD_NOT_SUPPORTED", 6, 144}, + #endif + #ifdef EVP_R_MISSING_PARAMETERS + {"MISSING_PARAMETERS", ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS}, + #else + {"MISSING_PARAMETERS", 6, 103}, + #endif + #ifdef EVP_R_NOT_ABLE_TO_COPY_CTX + {"NOT_ABLE_TO_COPY_CTX", ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX}, + #else + {"NOT_ABLE_TO_COPY_CTX", 6, 190}, + #endif + #ifdef EVP_R_NOT_XOF_OR_INVALID_LENGTH + {"NOT_XOF_OR_INVALID_LENGTH", ERR_LIB_EVP, EVP_R_NOT_XOF_OR_INVALID_LENGTH}, + #else + {"NOT_XOF_OR_INVALID_LENGTH", 6, 178}, + #endif + #ifdef EVP_R_NO_CIPHER_SET + {"NO_CIPHER_SET", ERR_LIB_EVP, EVP_R_NO_CIPHER_SET}, + #else + {"NO_CIPHER_SET", 6, 131}, + #endif + #ifdef EVP_R_NO_DEFAULT_DIGEST + {"NO_DEFAULT_DIGEST", ERR_LIB_EVP, EVP_R_NO_DEFAULT_DIGEST}, + #else + {"NO_DEFAULT_DIGEST", 6, 158}, + #endif + #ifdef EVP_R_NO_DIGEST_SET + {"NO_DIGEST_SET", ERR_LIB_EVP, EVP_R_NO_DIGEST_SET}, + #else + {"NO_DIGEST_SET", 6, 139}, + #endif + #ifdef EVP_R_NO_IMPORT_FUNCTION + {"NO_IMPORT_FUNCTION", ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION}, + #else + {"NO_IMPORT_FUNCTION", 6, 206}, + #endif + #ifdef EVP_R_NO_KEYMGMT_AVAILABLE + {"NO_KEYMGMT_AVAILABLE", ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE}, + #else + {"NO_KEYMGMT_AVAILABLE", 6, 199}, + #endif + #ifdef EVP_R_NO_KEYMGMT_PRESENT + {"NO_KEYMGMT_PRESENT", ERR_LIB_EVP, EVP_R_NO_KEYMGMT_PRESENT}, + #else + {"NO_KEYMGMT_PRESENT", 6, 196}, + #endif + #ifdef EVP_R_NO_KEY_SET + {"NO_KEY_SET", ERR_LIB_EVP, EVP_R_NO_KEY_SET}, + #else + {"NO_KEY_SET", 6, 154}, + #endif + #ifdef EVP_R_NO_OPERATION_SET + {"NO_OPERATION_SET", ERR_LIB_EVP, EVP_R_NO_OPERATION_SET}, + #else + {"NO_OPERATION_SET", 6, 149}, + #endif + #ifdef EVP_R_NULL_MAC_PKEY_CTX + {"NULL_MAC_PKEY_CTX", ERR_LIB_EVP, EVP_R_NULL_MAC_PKEY_CTX}, + #else + {"NULL_MAC_PKEY_CTX", 6, 208}, + #endif + #ifdef EVP_R_ONLY_ONESHOT_SUPPORTED + {"ONLY_ONESHOT_SUPPORTED", ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED}, + #else + {"ONLY_ONESHOT_SUPPORTED", 6, 177}, + #endif + #ifdef EVP_R_OPERATION_NOT_INITIALIZED + {"OPERATION_NOT_INITIALIZED", ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED}, + #else + {"OPERATION_NOT_INITIALIZED", 6, 151}, + #endif + #ifdef EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 6, 150}, + #endif + #ifdef EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE", ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE", 6, 226}, + #endif + #ifdef EVP_R_OUTPUT_WOULD_OVERFLOW + {"OUTPUT_WOULD_OVERFLOW", ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW}, + #else + {"OUTPUT_WOULD_OVERFLOW", 6, 202}, + #endif + #ifdef EVP_R_PARAMETER_TOO_LARGE + {"PARAMETER_TOO_LARGE", ERR_LIB_EVP, EVP_R_PARAMETER_TOO_LARGE}, + #else + {"PARAMETER_TOO_LARGE", 6, 187}, + #endif + #ifdef EVP_R_PARTIALLY_OVERLAPPING + {"PARTIALLY_OVERLAPPING", ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING}, + #else + {"PARTIALLY_OVERLAPPING", 6, 162}, + #endif + #ifdef EVP_R_PBKDF2_ERROR + {"PBKDF2_ERROR", ERR_LIB_EVP, EVP_R_PBKDF2_ERROR}, + #else + {"PBKDF2_ERROR", 6, 181}, + #endif + #ifdef EVP_R_PIPELINE_NOT_SUPPORTED + {"PIPELINE_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PIPELINE_NOT_SUPPORTED}, + #else + {"PIPELINE_NOT_SUPPORTED", 6, 230}, + #endif + #ifdef EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED + {"PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED", ERR_LIB_EVP, EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED}, + #else + {"PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED", 6, 179}, + #endif + #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR + {"PRIVATE_KEY_DECODE_ERROR", ERR_LIB_EVP, EVP_R_PRIVATE_KEY_DECODE_ERROR}, + #else + {"PRIVATE_KEY_DECODE_ERROR", 6, 145}, + #endif + #ifdef EVP_R_PRIVATE_KEY_ENCODE_ERROR + {"PRIVATE_KEY_ENCODE_ERROR", ERR_LIB_EVP, EVP_R_PRIVATE_KEY_ENCODE_ERROR}, + #else + {"PRIVATE_KEY_ENCODE_ERROR", 6, 146}, + #endif + #ifdef EVP_R_PROVIDER_ASYM_CIPHER_FAILURE + {"PROVIDER_ASYM_CIPHER_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE}, + #else + {"PROVIDER_ASYM_CIPHER_FAILURE", 6, 232}, + #endif + #ifdef EVP_R_PROVIDER_ASYM_CIPHER_NOT_SUPPORTED + {"PROVIDER_ASYM_CIPHER_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_NOT_SUPPORTED}, + #else + {"PROVIDER_ASYM_CIPHER_NOT_SUPPORTED", 6, 235}, + #endif + #ifdef EVP_R_PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED + {"PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED}, + #else + {"PROVIDER_GET_CTX_PARAMS_NOT_SUPPORTED", 6, 238}, + #endif + #ifdef EVP_R_PROVIDER_KEYMGMT_FAILURE + {"PROVIDER_KEYMGMT_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_FAILURE}, + #else + {"PROVIDER_KEYMGMT_FAILURE", 6, 233}, + #endif + #ifdef EVP_R_PROVIDER_KEYMGMT_NOT_SUPPORTED + {"PROVIDER_KEYMGMT_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_NOT_SUPPORTED}, + #else + {"PROVIDER_KEYMGMT_NOT_SUPPORTED", 6, 236}, + #endif + #ifdef EVP_R_PROVIDER_SIGNATURE_FAILURE + {"PROVIDER_SIGNATURE_FAILURE", ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE}, + #else + {"PROVIDER_SIGNATURE_FAILURE", 6, 234}, + #endif + #ifdef EVP_R_PROVIDER_SIGNATURE_NOT_SUPPORTED + {"PROVIDER_SIGNATURE_NOT_SUPPORTED", ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_NOT_SUPPORTED}, + #else + {"PROVIDER_SIGNATURE_NOT_SUPPORTED", 6, 237}, + #endif + #ifdef EVP_R_PUBLIC_KEY_NOT_RSA + {"PUBLIC_KEY_NOT_RSA", ERR_LIB_EVP, EVP_R_PUBLIC_KEY_NOT_RSA}, + #else + {"PUBLIC_KEY_NOT_RSA", 6, 106}, + #endif + #ifdef EVP_R_SETTING_XOF_FAILED + {"SETTING_XOF_FAILED", ERR_LIB_EVP, EVP_R_SETTING_XOF_FAILED}, + #else + {"SETTING_XOF_FAILED", 6, 227}, + #endif + #ifdef EVP_R_SET_DEFAULT_PROPERTY_FAILURE + {"SET_DEFAULT_PROPERTY_FAILURE", ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE}, + #else + {"SET_DEFAULT_PROPERTY_FAILURE", 6, 209}, + #endif + #ifdef EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE + {"SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE", ERR_LIB_EVP, EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE}, + #else + {"SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE", 6, 228}, + #endif + #ifdef EVP_R_TOO_MANY_PIPES + {"TOO_MANY_PIPES", ERR_LIB_EVP, EVP_R_TOO_MANY_PIPES}, + #else + {"TOO_MANY_PIPES", 6, 231}, + #endif + #ifdef EVP_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 6, 183}, + #endif + #ifdef EVP_R_UNABLE_TO_ENABLE_LOCKING + {"UNABLE_TO_ENABLE_LOCKING", ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING}, + #else + {"UNABLE_TO_ENABLE_LOCKING", 6, 212}, + #endif + #ifdef EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE + {"UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE", ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE}, + #else + {"UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE", 6, 215}, + #endif + #ifdef EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH + {"UNABLE_TO_GET_RANDOM_STRENGTH", ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH}, + #else + {"UNABLE_TO_GET_RANDOM_STRENGTH", 6, 216}, + #endif + #ifdef EVP_R_UNABLE_TO_LOCK_CONTEXT + {"UNABLE_TO_LOCK_CONTEXT", ERR_LIB_EVP, EVP_R_UNABLE_TO_LOCK_CONTEXT}, + #else + {"UNABLE_TO_LOCK_CONTEXT", 6, 211}, + #endif + #ifdef EVP_R_UNABLE_TO_SET_CALLBACKS + {"UNABLE_TO_SET_CALLBACKS", ERR_LIB_EVP, EVP_R_UNABLE_TO_SET_CALLBACKS}, + #else + {"UNABLE_TO_SET_CALLBACKS", 6, 217}, + #endif + #ifdef EVP_R_UNKNOWN_BITS + {"UNKNOWN_BITS", ERR_LIB_EVP, EVP_R_UNKNOWN_BITS}, + #else + {"UNKNOWN_BITS", 6, 166}, + #endif + #ifdef EVP_R_UNKNOWN_CIPHER + {"UNKNOWN_CIPHER", ERR_LIB_EVP, EVP_R_UNKNOWN_CIPHER}, + #else + {"UNKNOWN_CIPHER", 6, 160}, + #endif + #ifdef EVP_R_UNKNOWN_DIGEST + {"UNKNOWN_DIGEST", ERR_LIB_EVP, EVP_R_UNKNOWN_DIGEST}, + #else + {"UNKNOWN_DIGEST", 6, 161}, + #endif + #ifdef EVP_R_UNKNOWN_KEY_TYPE + {"UNKNOWN_KEY_TYPE", ERR_LIB_EVP, EVP_R_UNKNOWN_KEY_TYPE}, + #else + {"UNKNOWN_KEY_TYPE", 6, 207}, + #endif + #ifdef EVP_R_UNKNOWN_MAX_SIZE + {"UNKNOWN_MAX_SIZE", ERR_LIB_EVP, EVP_R_UNKNOWN_MAX_SIZE}, + #else + {"UNKNOWN_MAX_SIZE", 6, 167}, + #endif + #ifdef EVP_R_UNKNOWN_OPTION + {"UNKNOWN_OPTION", ERR_LIB_EVP, EVP_R_UNKNOWN_OPTION}, + #else + {"UNKNOWN_OPTION", 6, 169}, + #endif + #ifdef EVP_R_UNKNOWN_PBE_ALGORITHM + {"UNKNOWN_PBE_ALGORITHM", ERR_LIB_EVP, EVP_R_UNKNOWN_PBE_ALGORITHM}, + #else + {"UNKNOWN_PBE_ALGORITHM", 6, 121}, + #endif + #ifdef EVP_R_UNKNOWN_SECURITY_BITS + {"UNKNOWN_SECURITY_BITS", ERR_LIB_EVP, EVP_R_UNKNOWN_SECURITY_BITS}, + #else + {"UNKNOWN_SECURITY_BITS", 6, 168}, + #endif + #ifdef EVP_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 6, 156}, + #endif + #ifdef EVP_R_UNSUPPORTED_CIPHER + {"UNSUPPORTED_CIPHER", ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER}, + #else + {"UNSUPPORTED_CIPHER", 6, 107}, + #endif + #ifdef EVP_R_UNSUPPORTED_KEYLENGTH + {"UNSUPPORTED_KEYLENGTH", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH}, + #else + {"UNSUPPORTED_KEYLENGTH", 6, 123}, + #endif + #ifdef EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION + {"UNSUPPORTED_KEY_DERIVATION_FUNCTION", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION}, + #else + {"UNSUPPORTED_KEY_DERIVATION_FUNCTION", 6, 124}, + #endif + #ifdef EVP_R_UNSUPPORTED_KEY_SIZE + {"UNSUPPORTED_KEY_SIZE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_SIZE}, + #else + {"UNSUPPORTED_KEY_SIZE", 6, 108}, + #endif + #ifdef EVP_R_UNSUPPORTED_KEY_TYPE + {"UNSUPPORTED_KEY_TYPE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE}, + #else + {"UNSUPPORTED_KEY_TYPE", 6, 224}, + #endif + #ifdef EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS + {"UNSUPPORTED_NUMBER_OF_ROUNDS", ERR_LIB_EVP, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS}, + #else + {"UNSUPPORTED_NUMBER_OF_ROUNDS", 6, 135}, + #endif + #ifdef EVP_R_UNSUPPORTED_PRF + {"UNSUPPORTED_PRF", ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF}, + #else + {"UNSUPPORTED_PRF", 6, 125}, + #endif + #ifdef EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM + {"UNSUPPORTED_PRIVATE_KEY_ALGORITHM", ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM}, + #else + {"UNSUPPORTED_PRIVATE_KEY_ALGORITHM", 6, 118}, + #endif + #ifdef EVP_R_UNSUPPORTED_SALT_TYPE + {"UNSUPPORTED_SALT_TYPE", ERR_LIB_EVP, EVP_R_UNSUPPORTED_SALT_TYPE}, + #else + {"UNSUPPORTED_SALT_TYPE", 6, 126}, + #endif + #ifdef EVP_R_UPDATE_ERROR + {"UPDATE_ERROR", ERR_LIB_EVP, EVP_R_UPDATE_ERROR}, + #else + {"UPDATE_ERROR", 6, 189}, + #endif + #ifdef EVP_R_WRAP_MODE_NOT_ALLOWED + {"WRAP_MODE_NOT_ALLOWED", ERR_LIB_EVP, EVP_R_WRAP_MODE_NOT_ALLOWED}, + #else + {"WRAP_MODE_NOT_ALLOWED", 6, 170}, + #endif + #ifdef EVP_R_WRONG_FINAL_BLOCK_LENGTH + {"WRONG_FINAL_BLOCK_LENGTH", ERR_LIB_EVP, EVP_R_WRONG_FINAL_BLOCK_LENGTH}, + #else + {"WRONG_FINAL_BLOCK_LENGTH", 6, 109}, + #endif + #ifdef EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE + {"XTS_DATA_UNIT_IS_TOO_LARGE", ERR_LIB_EVP, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE}, + #else + {"XTS_DATA_UNIT_IS_TOO_LARGE", 6, 191}, + #endif + #ifdef EVP_R_XTS_DUPLICATED_KEYS + {"XTS_DUPLICATED_KEYS", ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS}, + #else + {"XTS_DUPLICATED_KEYS", 6, 192}, + #endif + #ifdef HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN + {"ASN1_LEN_EXCEEDS_MAX_RESP_LEN", ERR_LIB_HTTP, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN}, + #else + {"ASN1_LEN_EXCEEDS_MAX_RESP_LEN", 61, 108}, + #endif + #ifdef HTTP_R_CONNECT_FAILURE + {"CONNECT_FAILURE", ERR_LIB_HTTP, HTTP_R_CONNECT_FAILURE}, + #else + {"CONNECT_FAILURE", 61, 100}, + #endif + #ifdef HTTP_R_CONTENT_TYPE_MISMATCH + {"CONTENT_TYPE_MISMATCH", ERR_LIB_HTTP, HTTP_R_CONTENT_TYPE_MISMATCH}, + #else + {"CONTENT_TYPE_MISMATCH", 61, 131}, + #endif + #ifdef HTTP_R_ERROR_PARSING_ASN1_LENGTH + {"ERROR_PARSING_ASN1_LENGTH", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_ASN1_LENGTH}, + #else + {"ERROR_PARSING_ASN1_LENGTH", 61, 109}, + #endif + #ifdef HTTP_R_ERROR_PARSING_CONTENT_LENGTH + {"ERROR_PARSING_CONTENT_LENGTH", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_CONTENT_LENGTH}, + #else + {"ERROR_PARSING_CONTENT_LENGTH", 61, 119}, + #endif + #ifdef HTTP_R_ERROR_PARSING_URL + {"ERROR_PARSING_URL", ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL}, + #else + {"ERROR_PARSING_URL", 61, 101}, + #endif + #ifdef HTTP_R_ERROR_RECEIVING + {"ERROR_RECEIVING", ERR_LIB_HTTP, HTTP_R_ERROR_RECEIVING}, + #else + {"ERROR_RECEIVING", 61, 103}, + #endif + #ifdef HTTP_R_ERROR_SENDING + {"ERROR_SENDING", ERR_LIB_HTTP, HTTP_R_ERROR_SENDING}, + #else + {"ERROR_SENDING", 61, 102}, + #endif + #ifdef HTTP_R_FAILED_READING_DATA + {"FAILED_READING_DATA", ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA}, + #else + {"FAILED_READING_DATA", 61, 128}, + #endif + #ifdef HTTP_R_HEADER_PARSE_ERROR + {"HEADER_PARSE_ERROR", ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR}, + #else + {"HEADER_PARSE_ERROR", 61, 126}, + #endif + #ifdef HTTP_R_INCONSISTENT_CONTENT_LENGTH + {"INCONSISTENT_CONTENT_LENGTH", ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH}, + #else + {"INCONSISTENT_CONTENT_LENGTH", 61, 120}, + #endif + #ifdef HTTP_R_INVALID_PORT_NUMBER + {"INVALID_PORT_NUMBER", ERR_LIB_HTTP, HTTP_R_INVALID_PORT_NUMBER}, + #else + {"INVALID_PORT_NUMBER", 61, 123}, + #endif + #ifdef HTTP_R_INVALID_URL_PATH + {"INVALID_URL_PATH", ERR_LIB_HTTP, HTTP_R_INVALID_URL_PATH}, + #else + {"INVALID_URL_PATH", 61, 125}, + #endif + #ifdef HTTP_R_INVALID_URL_SCHEME + {"INVALID_URL_SCHEME", ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME}, + #else + {"INVALID_URL_SCHEME", 61, 124}, + #endif + #ifdef HTTP_R_MAX_RESP_LEN_EXCEEDED + {"MAX_RESP_LEN_EXCEEDED", ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED}, + #else + {"MAX_RESP_LEN_EXCEEDED", 61, 117}, + #endif + #ifdef HTTP_R_MISSING_ASN1_ENCODING + {"MISSING_ASN1_ENCODING", ERR_LIB_HTTP, HTTP_R_MISSING_ASN1_ENCODING}, + #else + {"MISSING_ASN1_ENCODING", 61, 110}, + #endif + #ifdef HTTP_R_MISSING_CONTENT_TYPE + {"MISSING_CONTENT_TYPE", ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE}, + #else + {"MISSING_CONTENT_TYPE", 61, 121}, + #endif + #ifdef HTTP_R_MISSING_REDIRECT_LOCATION + {"MISSING_REDIRECT_LOCATION", ERR_LIB_HTTP, HTTP_R_MISSING_REDIRECT_LOCATION}, + #else + {"MISSING_REDIRECT_LOCATION", 61, 111}, + #endif + #ifdef HTTP_R_RECEIVED_ERROR + {"RECEIVED_ERROR", ERR_LIB_HTTP, HTTP_R_RECEIVED_ERROR}, + #else + {"RECEIVED_ERROR", 61, 105}, + #endif + #ifdef HTTP_R_RECEIVED_WRONG_HTTP_VERSION + {"RECEIVED_WRONG_HTTP_VERSION", ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION}, + #else + {"RECEIVED_WRONG_HTTP_VERSION", 61, 106}, + #endif + #ifdef HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP + {"REDIRECTION_FROM_HTTPS_TO_HTTP", ERR_LIB_HTTP, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP}, + #else + {"REDIRECTION_FROM_HTTPS_TO_HTTP", 61, 112}, + #endif + #ifdef HTTP_R_REDIRECTION_NOT_ENABLED + {"REDIRECTION_NOT_ENABLED", ERR_LIB_HTTP, HTTP_R_REDIRECTION_NOT_ENABLED}, + #else + {"REDIRECTION_NOT_ENABLED", 61, 116}, + #endif + #ifdef HTTP_R_RESPONSE_LINE_TOO_LONG + {"RESPONSE_LINE_TOO_LONG", ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG}, + #else + {"RESPONSE_LINE_TOO_LONG", 61, 113}, + #endif + #ifdef HTTP_R_RESPONSE_PARSE_ERROR + {"RESPONSE_PARSE_ERROR", ERR_LIB_HTTP, HTTP_R_RESPONSE_PARSE_ERROR}, + #else + {"RESPONSE_PARSE_ERROR", 61, 104}, + #endif + #ifdef HTTP_R_RESPONSE_TOO_MANY_HDRLINES + {"RESPONSE_TOO_MANY_HDRLINES", ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES}, + #else + {"RESPONSE_TOO_MANY_HDRLINES", 61, 130}, + #endif + #ifdef HTTP_R_RETRY_TIMEOUT + {"RETRY_TIMEOUT", ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT}, + #else + {"RETRY_TIMEOUT", 61, 129}, + #endif + #ifdef HTTP_R_SERVER_CANCELED_CONNECTION + {"SERVER_CANCELED_CONNECTION", ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION}, + #else + {"SERVER_CANCELED_CONNECTION", 61, 127}, + #endif + #ifdef HTTP_R_SOCK_NOT_SUPPORTED + {"SOCK_NOT_SUPPORTED", ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED}, + #else + {"SOCK_NOT_SUPPORTED", 61, 122}, + #endif + #ifdef HTTP_R_STATUS_CODE_UNSUPPORTED + {"STATUS_CODE_UNSUPPORTED", ERR_LIB_HTTP, HTTP_R_STATUS_CODE_UNSUPPORTED}, + #else + {"STATUS_CODE_UNSUPPORTED", 61, 114}, + #endif + #ifdef HTTP_R_TLS_NOT_ENABLED + {"TLS_NOT_ENABLED", ERR_LIB_HTTP, HTTP_R_TLS_NOT_ENABLED}, + #else + {"TLS_NOT_ENABLED", 61, 107}, + #endif + #ifdef HTTP_R_TOO_MANY_REDIRECTIONS + {"TOO_MANY_REDIRECTIONS", ERR_LIB_HTTP, HTTP_R_TOO_MANY_REDIRECTIONS}, + #else + {"TOO_MANY_REDIRECTIONS", 61, 115}, + #endif + #ifdef HTTP_R_UNEXPECTED_CONTENT_TYPE + {"UNEXPECTED_CONTENT_TYPE", ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE}, + #else + {"UNEXPECTED_CONTENT_TYPE", 61, 118}, + #endif + #ifdef OBJ_R_OID_EXISTS + {"OID_EXISTS", ERR_LIB_OBJ, OBJ_R_OID_EXISTS}, + #else + {"OID_EXISTS", 8, 102}, + #endif + #ifdef OBJ_R_UNKNOWN_NID + {"UNKNOWN_NID", ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID}, + #else + {"UNKNOWN_NID", 8, 101}, + #endif + #ifdef OBJ_R_UNKNOWN_OBJECT_NAME + {"UNKNOWN_OBJECT_NAME", ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME}, + #else + {"UNKNOWN_OBJECT_NAME", 8, 103}, + #endif + #ifdef OCSP_R_CERTIFICATE_VERIFY_ERROR + {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_OCSP, OCSP_R_CERTIFICATE_VERIFY_ERROR}, + #else + {"CERTIFICATE_VERIFY_ERROR", 39, 101}, + #endif + #ifdef OCSP_R_DIGEST_ERR + {"DIGEST_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_ERR}, + #else + {"DIGEST_ERR", 39, 102}, + #endif + #ifdef OCSP_R_DIGEST_NAME_ERR + {"DIGEST_NAME_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_NAME_ERR}, + #else + {"DIGEST_NAME_ERR", 39, 106}, + #endif + #ifdef OCSP_R_DIGEST_SIZE_ERR + {"DIGEST_SIZE_ERR", ERR_LIB_OCSP, OCSP_R_DIGEST_SIZE_ERR}, + #else + {"DIGEST_SIZE_ERR", 39, 107}, + #endif + #ifdef OCSP_R_ERROR_IN_NEXTUPDATE_FIELD + {"ERROR_IN_NEXTUPDATE_FIELD", ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD}, + #else + {"ERROR_IN_NEXTUPDATE_FIELD", 39, 122}, + #endif + #ifdef OCSP_R_ERROR_IN_THISUPDATE_FIELD + {"ERROR_IN_THISUPDATE_FIELD", ERR_LIB_OCSP, OCSP_R_ERROR_IN_THISUPDATE_FIELD}, + #else + {"ERROR_IN_THISUPDATE_FIELD", 39, 123}, + #endif + #ifdef OCSP_R_MISSING_OCSPSIGNING_USAGE + {"MISSING_OCSPSIGNING_USAGE", ERR_LIB_OCSP, OCSP_R_MISSING_OCSPSIGNING_USAGE}, + #else + {"MISSING_OCSPSIGNING_USAGE", 39, 103}, + #endif + #ifdef OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE + {"NEXTUPDATE_BEFORE_THISUPDATE", ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE}, + #else + {"NEXTUPDATE_BEFORE_THISUPDATE", 39, 124}, + #endif + #ifdef OCSP_R_NOT_BASIC_RESPONSE + {"NOT_BASIC_RESPONSE", ERR_LIB_OCSP, OCSP_R_NOT_BASIC_RESPONSE}, + #else + {"NOT_BASIC_RESPONSE", 39, 104}, + #endif + #ifdef OCSP_R_NO_CERTIFICATES_IN_CHAIN + {"NO_CERTIFICATES_IN_CHAIN", ERR_LIB_OCSP, OCSP_R_NO_CERTIFICATES_IN_CHAIN}, + #else + {"NO_CERTIFICATES_IN_CHAIN", 39, 105}, + #endif + #ifdef OCSP_R_NO_RESPONSE_DATA + {"NO_RESPONSE_DATA", ERR_LIB_OCSP, OCSP_R_NO_RESPONSE_DATA}, + #else + {"NO_RESPONSE_DATA", 39, 108}, + #endif + #ifdef OCSP_R_NO_REVOKED_TIME + {"NO_REVOKED_TIME", ERR_LIB_OCSP, OCSP_R_NO_REVOKED_TIME}, + #else + {"NO_REVOKED_TIME", 39, 109}, + #endif + #ifdef OCSP_R_NO_SIGNER_KEY + {"NO_SIGNER_KEY", ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY}, + #else + {"NO_SIGNER_KEY", 39, 130}, + #endif + #ifdef OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, + #else + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 39, 110}, + #endif + #ifdef OCSP_R_REQUEST_NOT_SIGNED + {"REQUEST_NOT_SIGNED", ERR_LIB_OCSP, OCSP_R_REQUEST_NOT_SIGNED}, + #else + {"REQUEST_NOT_SIGNED", 39, 128}, + #endif + #ifdef OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA + {"RESPONSE_CONTAINS_NO_REVOCATION_DATA", ERR_LIB_OCSP, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA}, + #else + {"RESPONSE_CONTAINS_NO_REVOCATION_DATA", 39, 111}, + #endif + #ifdef OCSP_R_ROOT_CA_NOT_TRUSTED + {"ROOT_CA_NOT_TRUSTED", ERR_LIB_OCSP, OCSP_R_ROOT_CA_NOT_TRUSTED}, + #else + {"ROOT_CA_NOT_TRUSTED", 39, 112}, + #endif + #ifdef OCSP_R_SIGNATURE_FAILURE + {"SIGNATURE_FAILURE", ERR_LIB_OCSP, OCSP_R_SIGNATURE_FAILURE}, + #else + {"SIGNATURE_FAILURE", 39, 117}, + #endif + #ifdef OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND + {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_OCSP, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND}, + #else + {"SIGNER_CERTIFICATE_NOT_FOUND", 39, 118}, + #endif + #ifdef OCSP_R_STATUS_EXPIRED + {"STATUS_EXPIRED", ERR_LIB_OCSP, OCSP_R_STATUS_EXPIRED}, + #else + {"STATUS_EXPIRED", 39, 125}, + #endif + #ifdef OCSP_R_STATUS_NOT_YET_VALID + {"STATUS_NOT_YET_VALID", ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID}, + #else + {"STATUS_NOT_YET_VALID", 39, 126}, + #endif + #ifdef OCSP_R_STATUS_TOO_OLD + {"STATUS_TOO_OLD", ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD}, + #else + {"STATUS_TOO_OLD", 39, 127}, + #endif + #ifdef OCSP_R_UNKNOWN_MESSAGE_DIGEST + {"UNKNOWN_MESSAGE_DIGEST", ERR_LIB_OCSP, OCSP_R_UNKNOWN_MESSAGE_DIGEST}, + #else + {"UNKNOWN_MESSAGE_DIGEST", 39, 119}, + #endif + #ifdef OCSP_R_UNKNOWN_NID + {"UNKNOWN_NID", ERR_LIB_OCSP, OCSP_R_UNKNOWN_NID}, + #else + {"UNKNOWN_NID", 39, 120}, + #endif + #ifdef OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE + {"UNSUPPORTED_REQUESTORNAME_TYPE", ERR_LIB_OCSP, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE}, + #else + {"UNSUPPORTED_REQUESTORNAME_TYPE", 39, 129}, + #endif + #ifdef OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT + {"COULD_NOT_DECODE_OBJECT", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT}, + #else + {"COULD_NOT_DECODE_OBJECT", 60, 101}, + #endif + #ifdef OSSL_DECODER_R_DECODER_NOT_FOUND + {"DECODER_NOT_FOUND", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_DECODER_NOT_FOUND}, + #else + {"DECODER_NOT_FOUND", 60, 102}, + #endif + #ifdef OSSL_DECODER_R_MISSING_GET_PARAMS + {"MISSING_GET_PARAMS", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_MISSING_GET_PARAMS}, + #else + {"MISSING_GET_PARAMS", 60, 100}, + #endif + #ifdef OSSL_ENCODER_R_BAD_PARAMETER_VALUE + {"BAD_PARAMETER_VALUE", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_BAD_PARAMETER_VALUE}, + #else + {"BAD_PARAMETER_VALUE", 59, 103}, + #endif + #ifdef OSSL_ENCODER_R_ENCODER_NOT_FOUND + {"ENCODER_NOT_FOUND", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND}, + #else + {"ENCODER_NOT_FOUND", 59, 101}, + #endif + #ifdef OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY + {"INCORRECT_PROPERTY_QUERY", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY}, + #else + {"INCORRECT_PROPERTY_QUERY", 59, 100}, + #endif + #ifdef OSSL_ENCODER_R_MISSING_GET_PARAMS + {"MISSING_GET_PARAMS", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_MISSING_GET_PARAMS}, + #else + {"MISSING_GET_PARAMS", 59, 102}, + #endif + #ifdef OSSL_ENCODER_R_UNKNOWN_PARAMETER_NAME + {"UNKNOWN_PARAMETER_NAME", ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_UNKNOWN_PARAMETER_NAME}, + #else + {"UNKNOWN_PARAMETER_NAME", 59, 104}, + #endif + #ifdef OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE + {"AMBIGUOUS_CONTENT_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE}, + #else + {"AMBIGUOUS_CONTENT_TYPE", 44, 107}, + #endif + #ifdef OSSL_STORE_R_BAD_PASSWORD_READ + {"BAD_PASSWORD_READ", ERR_LIB_OSSL_STORE, OSSL_STORE_R_BAD_PASSWORD_READ}, + #else + {"BAD_PASSWORD_READ", 44, 115}, + #endif + #ifdef OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC + {"ERROR_VERIFYING_PKCS12_MAC", ERR_LIB_OSSL_STORE, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC}, + #else + {"ERROR_VERIFYING_PKCS12_MAC", 44, 113}, + #endif + #ifdef OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST + {"FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST", ERR_LIB_OSSL_STORE, OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST}, + #else + {"FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST", 44, 121}, + #endif + #ifdef OSSL_STORE_R_INVALID_SCHEME + {"INVALID_SCHEME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME}, + #else + {"INVALID_SCHEME", 44, 106}, + #endif + #ifdef OSSL_STORE_R_IS_NOT_A + {"IS_NOT_A", ERR_LIB_OSSL_STORE, OSSL_STORE_R_IS_NOT_A}, + #else + {"IS_NOT_A", 44, 112}, + #endif + #ifdef OSSL_STORE_R_LOADER_INCOMPLETE + {"LOADER_INCOMPLETE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE}, + #else + {"LOADER_INCOMPLETE", 44, 116}, + #endif + #ifdef OSSL_STORE_R_LOADING_STARTED + {"LOADING_STARTED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED}, + #else + {"LOADING_STARTED", 44, 117}, + #endif + #ifdef OSSL_STORE_R_NOT_A_CERTIFICATE + {"NOT_A_CERTIFICATE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE}, + #else + {"NOT_A_CERTIFICATE", 44, 100}, + #endif + #ifdef OSSL_STORE_R_NOT_A_CRL + {"NOT_A_CRL", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL}, + #else + {"NOT_A_CRL", 44, 101}, + #endif + #ifdef OSSL_STORE_R_NOT_A_NAME + {"NOT_A_NAME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME}, + #else + {"NOT_A_NAME", 44, 103}, + #endif + #ifdef OSSL_STORE_R_NOT_A_PRIVATE_KEY + {"NOT_A_PRIVATE_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY}, + #else + {"NOT_A_PRIVATE_KEY", 44, 102}, + #endif + #ifdef OSSL_STORE_R_NOT_A_PUBLIC_KEY + {"NOT_A_PUBLIC_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY}, + #else + {"NOT_A_PUBLIC_KEY", 44, 122}, + #endif + #ifdef OSSL_STORE_R_NOT_A_SYMMETRIC_KEY + {"NOT_A_SYMMETRIC_KEY", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_SYMMETRIC_KEY}, + #else + {"NOT_A_SYMMETRIC_KEY", 44, 124}, + #endif + #ifdef OSSL_STORE_R_NOT_PARAMETERS + {"NOT_PARAMETERS", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS}, + #else + {"NOT_PARAMETERS", 44, 104}, + #endif + #ifdef OSSL_STORE_R_NO_LOADERS_FOUND + {"NO_LOADERS_FOUND", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NO_LOADERS_FOUND}, + #else + {"NO_LOADERS_FOUND", 44, 123}, + #endif + #ifdef OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR + {"PASSPHRASE_CALLBACK_ERROR", ERR_LIB_OSSL_STORE, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR}, + #else + {"PASSPHRASE_CALLBACK_ERROR", 44, 114}, + #endif + #ifdef OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE + {"PATH_MUST_BE_ABSOLUTE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE}, + #else + {"PATH_MUST_BE_ABSOLUTE", 44, 108}, + #endif + #ifdef OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", ERR_LIB_OSSL_STORE, OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES}, + #else + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", 44, 119}, + #endif + #ifdef OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED + {"UI_PROCESS_INTERRUPTED_OR_CANCELLED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED}, + #else + {"UI_PROCESS_INTERRUPTED_OR_CANCELLED", 44, 109}, + #endif + #ifdef OSSL_STORE_R_UNREGISTERED_SCHEME + {"UNREGISTERED_SCHEME", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME}, + #else + {"UNREGISTERED_SCHEME", 44, 105}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE + {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE}, + #else + {"UNSUPPORTED_CONTENT_TYPE", 44, 110}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_OPERATION + {"UNSUPPORTED_OPERATION", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION}, + #else + {"UNSUPPORTED_OPERATION", 44, 118}, + #endif + #ifdef OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE + {"UNSUPPORTED_SEARCH_TYPE", ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE}, + #else + {"UNSUPPORTED_SEARCH_TYPE", 44, 120}, + #endif + #ifdef OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED + {"URI_AUTHORITY_UNSUPPORTED", ERR_LIB_OSSL_STORE, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED}, + #else + {"URI_AUTHORITY_UNSUPPORTED", 44, 111}, + #endif + #ifdef PEM_R_BAD_BASE64_DECODE + {"BAD_BASE64_DECODE", ERR_LIB_PEM, PEM_R_BAD_BASE64_DECODE}, + #else + {"BAD_BASE64_DECODE", 9, 100}, + #endif + #ifdef PEM_R_BAD_DECRYPT + {"BAD_DECRYPT", ERR_LIB_PEM, PEM_R_BAD_DECRYPT}, + #else + {"BAD_DECRYPT", 9, 101}, + #endif + #ifdef PEM_R_BAD_END_LINE + {"BAD_END_LINE", ERR_LIB_PEM, PEM_R_BAD_END_LINE}, + #else + {"BAD_END_LINE", 9, 102}, + #endif + #ifdef PEM_R_BAD_IV_CHARS + {"BAD_IV_CHARS", ERR_LIB_PEM, PEM_R_BAD_IV_CHARS}, + #else + {"BAD_IV_CHARS", 9, 103}, + #endif + #ifdef PEM_R_BAD_MAGIC_NUMBER + {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER}, + #else + {"BAD_MAGIC_NUMBER", 9, 116}, + #endif + #ifdef PEM_R_BAD_PASSWORD_READ + {"BAD_PASSWORD_READ", ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ}, + #else + {"BAD_PASSWORD_READ", 9, 104}, + #endif + #ifdef PEM_R_BAD_VERSION_NUMBER + {"BAD_VERSION_NUMBER", ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER}, + #else + {"BAD_VERSION_NUMBER", 9, 117}, + #endif + #ifdef PEM_R_BIO_WRITE_FAILURE + {"BIO_WRITE_FAILURE", ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE}, + #else + {"BIO_WRITE_FAILURE", 9, 118}, + #endif + #ifdef PEM_R_CIPHER_IS_NULL + {"CIPHER_IS_NULL", ERR_LIB_PEM, PEM_R_CIPHER_IS_NULL}, + #else + {"CIPHER_IS_NULL", 9, 127}, + #endif + #ifdef PEM_R_ERROR_CONVERTING_PRIVATE_KEY + {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY}, + #else + {"ERROR_CONVERTING_PRIVATE_KEY", 9, 115}, + #endif + #ifdef PEM_R_EXPECTING_DSS_KEY_BLOB + {"EXPECTING_DSS_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB}, + #else + {"EXPECTING_DSS_KEY_BLOB", 9, 131}, + #endif + #ifdef PEM_R_EXPECTING_PRIVATE_KEY_BLOB + {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB}, + #else + {"EXPECTING_PRIVATE_KEY_BLOB", 9, 119}, + #endif + #ifdef PEM_R_EXPECTING_PUBLIC_KEY_BLOB + {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB}, + #else + {"EXPECTING_PUBLIC_KEY_BLOB", 9, 120}, + #endif + #ifdef PEM_R_EXPECTING_RSA_KEY_BLOB + {"EXPECTING_RSA_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB}, + #else + {"EXPECTING_RSA_KEY_BLOB", 9, 132}, + #endif + #ifdef PEM_R_HEADER_TOO_LONG + {"HEADER_TOO_LONG", ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG}, + #else + {"HEADER_TOO_LONG", 9, 128}, + #endif + #ifdef PEM_R_INCONSISTENT_HEADER + {"INCONSISTENT_HEADER", ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER}, + #else + {"INCONSISTENT_HEADER", 9, 121}, + #endif + #ifdef PEM_R_KEYBLOB_HEADER_PARSE_ERROR + {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR}, + #else + {"KEYBLOB_HEADER_PARSE_ERROR", 9, 122}, + #endif + #ifdef PEM_R_KEYBLOB_TOO_SHORT + {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT}, + #else + {"KEYBLOB_TOO_SHORT", 9, 123}, + #endif + #ifdef PEM_R_MISSING_DEK_IV + {"MISSING_DEK_IV", ERR_LIB_PEM, PEM_R_MISSING_DEK_IV}, + #else + {"MISSING_DEK_IV", 9, 129}, + #endif + #ifdef PEM_R_NOT_DEK_INFO + {"NOT_DEK_INFO", ERR_LIB_PEM, PEM_R_NOT_DEK_INFO}, + #else + {"NOT_DEK_INFO", 9, 105}, + #endif + #ifdef PEM_R_NOT_ENCRYPTED + {"NOT_ENCRYPTED", ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED}, + #else + {"NOT_ENCRYPTED", 9, 106}, + #endif + #ifdef PEM_R_NOT_PROC_TYPE + {"NOT_PROC_TYPE", ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE}, + #else + {"NOT_PROC_TYPE", 9, 107}, + #endif + #ifdef PEM_R_NO_START_LINE + {"NO_START_LINE", ERR_LIB_PEM, PEM_R_NO_START_LINE}, + #else + {"NO_START_LINE", 9, 108}, + #endif + #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD + {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, PEM_R_PROBLEMS_GETTING_PASSWORD}, + #else + {"PROBLEMS_GETTING_PASSWORD", 9, 109}, + #endif + #ifdef PEM_R_PVK_DATA_TOO_SHORT + {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT}, + #else + {"PVK_DATA_TOO_SHORT", 9, 124}, + #endif + #ifdef PEM_R_PVK_TOO_SHORT + {"PVK_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT}, + #else + {"PVK_TOO_SHORT", 9, 125}, + #endif + #ifdef PEM_R_READ_KEY + {"READ_KEY", ERR_LIB_PEM, PEM_R_READ_KEY}, + #else + {"READ_KEY", 9, 111}, + #endif + #ifdef PEM_R_SHORT_HEADER + {"SHORT_HEADER", ERR_LIB_PEM, PEM_R_SHORT_HEADER}, + #else + {"SHORT_HEADER", 9, 112}, + #endif + #ifdef PEM_R_UNEXPECTED_DEK_IV + {"UNEXPECTED_DEK_IV", ERR_LIB_PEM, PEM_R_UNEXPECTED_DEK_IV}, + #else + {"UNEXPECTED_DEK_IV", 9, 130}, + #endif + #ifdef PEM_R_UNSUPPORTED_CIPHER + {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER}, + #else + {"UNSUPPORTED_CIPHER", 9, 113}, + #endif + #ifdef PEM_R_UNSUPPORTED_ENCRYPTION + {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION}, + #else + {"UNSUPPORTED_ENCRYPTION", 9, 114}, + #endif + #ifdef PEM_R_UNSUPPORTED_KEY_COMPONENTS + {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS}, + #else + {"UNSUPPORTED_KEY_COMPONENTS", 9, 126}, + #endif + #ifdef PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE + {"UNSUPPORTED_PUBLIC_KEY_TYPE", ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE}, + #else + {"UNSUPPORTED_PUBLIC_KEY_TYPE", 9, 110}, + #endif + #ifdef PEM_R_UNSUPPORTED_PVK_KEY_TYPE + {"UNSUPPORTED_PVK_KEY_TYPE", ERR_LIB_PEM, PEM_R_UNSUPPORTED_PVK_KEY_TYPE}, + #else + {"UNSUPPORTED_PVK_KEY_TYPE", 9, 133}, + #endif + #ifdef PKCS12_R_CALLBACK_FAILED + {"CALLBACK_FAILED", ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED}, + #else + {"CALLBACK_FAILED", 35, 115}, + #endif + #ifdef PKCS12_R_CANT_PACK_STRUCTURE + {"CANT_PACK_STRUCTURE", ERR_LIB_PKCS12, PKCS12_R_CANT_PACK_STRUCTURE}, + #else + {"CANT_PACK_STRUCTURE", 35, 100}, + #endif + #ifdef PKCS12_R_CONTENT_TYPE_NOT_DATA + {"CONTENT_TYPE_NOT_DATA", ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA}, + #else + {"CONTENT_TYPE_NOT_DATA", 35, 121}, + #endif + #ifdef PKCS12_R_DECODE_ERROR + {"DECODE_ERROR", ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR}, + #else + {"DECODE_ERROR", 35, 101}, + #endif + #ifdef PKCS12_R_ENCODE_ERROR + {"ENCODE_ERROR", ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR}, + #else + {"ENCODE_ERROR", 35, 102}, + #endif + #ifdef PKCS12_R_ENCRYPT_ERROR + {"ENCRYPT_ERROR", ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR}, + #else + {"ENCRYPT_ERROR", 35, 103}, + #endif + #ifdef PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE + {"ERROR_SETTING_ENCRYPTED_DATA_TYPE", ERR_LIB_PKCS12, PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE}, + #else + {"ERROR_SETTING_ENCRYPTED_DATA_TYPE", 35, 120}, + #endif + #ifdef PKCS12_R_INVALID_NULL_ARGUMENT + {"INVALID_NULL_ARGUMENT", ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT}, + #else + {"INVALID_NULL_ARGUMENT", 35, 104}, + #endif + #ifdef PKCS12_R_INVALID_NULL_PKCS12_POINTER + {"INVALID_NULL_PKCS12_POINTER", ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER}, + #else + {"INVALID_NULL_PKCS12_POINTER", 35, 105}, + #endif + #ifdef PKCS12_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_PKCS12, PKCS12_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 35, 117}, + #endif + #ifdef PKCS12_R_INVALID_TYPE + {"INVALID_TYPE", ERR_LIB_PKCS12, PKCS12_R_INVALID_TYPE}, + #else + {"INVALID_TYPE", 35, 112}, + #endif + #ifdef PKCS12_R_IV_GEN_ERROR + {"IV_GEN_ERROR", ERR_LIB_PKCS12, PKCS12_R_IV_GEN_ERROR}, + #else + {"IV_GEN_ERROR", 35, 106}, + #endif + #ifdef PKCS12_R_KEY_GEN_ERROR + {"KEY_GEN_ERROR", ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR}, + #else + {"KEY_GEN_ERROR", 35, 107}, + #endif + #ifdef PKCS12_R_MAC_ABSENT + {"MAC_ABSENT", ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT}, + #else + {"MAC_ABSENT", 35, 108}, + #endif + #ifdef PKCS12_R_MAC_GENERATION_ERROR + {"MAC_GENERATION_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR}, + #else + {"MAC_GENERATION_ERROR", 35, 109}, + #endif + #ifdef PKCS12_R_MAC_SETUP_ERROR + {"MAC_SETUP_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR}, + #else + {"MAC_SETUP_ERROR", 35, 110}, + #endif + #ifdef PKCS12_R_MAC_STRING_SET_ERROR + {"MAC_STRING_SET_ERROR", ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR}, + #else + {"MAC_STRING_SET_ERROR", 35, 111}, + #endif + #ifdef PKCS12_R_MAC_VERIFY_FAILURE + {"MAC_VERIFY_FAILURE", ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE}, + #else + {"MAC_VERIFY_FAILURE", 35, 113}, + #endif + #ifdef PKCS12_R_PARSE_ERROR + {"PARSE_ERROR", ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR}, + #else + {"PARSE_ERROR", 35, 114}, + #endif + #ifdef PKCS12_R_PKCS12_CIPHERFINAL_ERROR + {"PKCS12_CIPHERFINAL_ERROR", ERR_LIB_PKCS12, PKCS12_R_PKCS12_CIPHERFINAL_ERROR}, + #else + {"PKCS12_CIPHERFINAL_ERROR", 35, 116}, + #endif + #ifdef PKCS12_R_UNKNOWN_DIGEST_ALGORITHM + {"UNKNOWN_DIGEST_ALGORITHM", ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM}, + #else + {"UNKNOWN_DIGEST_ALGORITHM", 35, 118}, + #endif + #ifdef PKCS12_R_UNSUPPORTED_PKCS12_MODE + {"UNSUPPORTED_PKCS12_MODE", ERR_LIB_PKCS12, PKCS12_R_UNSUPPORTED_PKCS12_MODE}, + #else + {"UNSUPPORTED_PKCS12_MODE", 35, 119}, + #endif + #ifdef PKCS7_R_CERTIFICATE_VERIFY_ERROR + {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR}, + #else + {"CERTIFICATE_VERIFY_ERROR", 33, 117}, + #endif + #ifdef PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER + {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", ERR_LIB_PKCS7, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER}, + #else + {"CIPHER_HAS_NO_OBJECT_IDENTIFIER", 33, 144}, + #endif + #ifdef PKCS7_R_CIPHER_NOT_INITIALIZED + {"CIPHER_NOT_INITIALIZED", ERR_LIB_PKCS7, PKCS7_R_CIPHER_NOT_INITIALIZED}, + #else + {"CIPHER_NOT_INITIALIZED", 33, 116}, + #endif + #ifdef PKCS7_R_CONTENT_AND_DATA_PRESENT + {"CONTENT_AND_DATA_PRESENT", ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT}, + #else + {"CONTENT_AND_DATA_PRESENT", 33, 118}, + #endif + #ifdef PKCS7_R_CTRL_ERROR + {"CTRL_ERROR", ERR_LIB_PKCS7, PKCS7_R_CTRL_ERROR}, + #else + {"CTRL_ERROR", 33, 152}, + #endif + #ifdef PKCS7_R_DECRYPT_ERROR + {"DECRYPT_ERROR", ERR_LIB_PKCS7, PKCS7_R_DECRYPT_ERROR}, + #else + {"DECRYPT_ERROR", 33, 119}, + #endif + #ifdef PKCS7_R_DIGEST_FAILURE + {"DIGEST_FAILURE", ERR_LIB_PKCS7, PKCS7_R_DIGEST_FAILURE}, + #else + {"DIGEST_FAILURE", 33, 101}, + #endif + #ifdef PKCS7_R_ENCRYPTION_CTRL_FAILURE + {"ENCRYPTION_CTRL_FAILURE", ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_CTRL_FAILURE}, + #else + {"ENCRYPTION_CTRL_FAILURE", 33, 149}, + #endif + #ifdef PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE + {"ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_PKCS7, PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, + #else + {"ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 33, 150}, + #endif + #ifdef PKCS7_R_ERROR_ADDING_RECIPIENT + {"ERROR_ADDING_RECIPIENT", ERR_LIB_PKCS7, PKCS7_R_ERROR_ADDING_RECIPIENT}, + #else + {"ERROR_ADDING_RECIPIENT", 33, 120}, + #endif + #ifdef PKCS7_R_ERROR_SETTING_CIPHER + {"ERROR_SETTING_CIPHER", ERR_LIB_PKCS7, PKCS7_R_ERROR_SETTING_CIPHER}, + #else + {"ERROR_SETTING_CIPHER", 33, 121}, + #endif + #ifdef PKCS7_R_INVALID_NULL_POINTER + {"INVALID_NULL_POINTER", ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER}, + #else + {"INVALID_NULL_POINTER", 33, 143}, + #endif + #ifdef PKCS7_R_INVALID_SIGNED_DATA_TYPE + {"INVALID_SIGNED_DATA_TYPE", ERR_LIB_PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE}, + #else + {"INVALID_SIGNED_DATA_TYPE", 33, 155}, + #endif + #ifdef PKCS7_R_NO_CONTENT + {"NO_CONTENT", ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT}, + #else + {"NO_CONTENT", 33, 122}, + #endif + #ifdef PKCS7_R_NO_DEFAULT_DIGEST + {"NO_DEFAULT_DIGEST", ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST}, + #else + {"NO_DEFAULT_DIGEST", 33, 151}, + #endif + #ifdef PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND + {"NO_MATCHING_DIGEST_TYPE_FOUND", ERR_LIB_PKCS7, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND}, + #else + {"NO_MATCHING_DIGEST_TYPE_FOUND", 33, 154}, + #endif + #ifdef PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE + {"NO_RECIPIENT_MATCHES_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE}, + #else + {"NO_RECIPIENT_MATCHES_CERTIFICATE", 33, 115}, + #endif + #ifdef PKCS7_R_NO_SIGNATURES_ON_DATA + {"NO_SIGNATURES_ON_DATA", ERR_LIB_PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA}, + #else + {"NO_SIGNATURES_ON_DATA", 33, 123}, + #endif + #ifdef PKCS7_R_NO_SIGNERS + {"NO_SIGNERS", ERR_LIB_PKCS7, PKCS7_R_NO_SIGNERS}, + #else + {"NO_SIGNERS", 33, 142}, + #endif + #ifdef PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE + {"OPERATION_NOT_SUPPORTED_ON_THIS_TYPE", ERR_LIB_PKCS7, PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE}, + #else + {"OPERATION_NOT_SUPPORTED_ON_THIS_TYPE", 33, 104}, + #endif + #ifdef PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR + {"PKCS7_ADD_SIGNATURE_ERROR", ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR}, + #else + {"PKCS7_ADD_SIGNATURE_ERROR", 33, 124}, + #endif + #ifdef PKCS7_R_PKCS7_ADD_SIGNER_ERROR + {"PKCS7_ADD_SIGNER_ERROR", ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR}, + #else + {"PKCS7_ADD_SIGNER_ERROR", 33, 153}, + #endif + #ifdef PKCS7_R_PKCS7_DATASIGN + {"PKCS7_DATASIGN", ERR_LIB_PKCS7, PKCS7_R_PKCS7_DATASIGN}, + #else + {"PKCS7_DATASIGN", 33, 145}, + #endif + #ifdef PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, + #else + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 33, 127}, + #endif + #ifdef PKCS7_R_SIGNATURE_FAILURE + {"SIGNATURE_FAILURE", ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE}, + #else + {"SIGNATURE_FAILURE", 33, 105}, + #endif + #ifdef PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND + {"SIGNER_CERTIFICATE_NOT_FOUND", ERR_LIB_PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND}, + #else + {"SIGNER_CERTIFICATE_NOT_FOUND", 33, 128}, + #endif + #ifdef PKCS7_R_SIGNING_CTRL_FAILURE + {"SIGNING_CTRL_FAILURE", ERR_LIB_PKCS7, PKCS7_R_SIGNING_CTRL_FAILURE}, + #else + {"SIGNING_CTRL_FAILURE", 33, 147}, + #endif + #ifdef PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE + {"SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE}, + #else + {"SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE", 33, 148}, + #endif + #ifdef PKCS7_R_SMIME_TEXT_ERROR + {"SMIME_TEXT_ERROR", ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR}, + #else + {"SMIME_TEXT_ERROR", 33, 129}, + #endif + #ifdef PKCS7_R_UNABLE_TO_FIND_CERTIFICATE + {"UNABLE_TO_FIND_CERTIFICATE", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE}, + #else + {"UNABLE_TO_FIND_CERTIFICATE", 33, 106}, + #endif + #ifdef PKCS7_R_UNABLE_TO_FIND_MEM_BIO + {"UNABLE_TO_FIND_MEM_BIO", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MEM_BIO}, + #else + {"UNABLE_TO_FIND_MEM_BIO", 33, 107}, + #endif + #ifdef PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST + {"UNABLE_TO_FIND_MESSAGE_DIGEST", ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST}, + #else + {"UNABLE_TO_FIND_MESSAGE_DIGEST", 33, 108}, + #endif + #ifdef PKCS7_R_UNKNOWN_DIGEST_TYPE + {"UNKNOWN_DIGEST_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_DIGEST_TYPE}, + #else + {"UNKNOWN_DIGEST_TYPE", 33, 109}, + #endif + #ifdef PKCS7_R_UNKNOWN_OPERATION + {"UNKNOWN_OPERATION", ERR_LIB_PKCS7, PKCS7_R_UNKNOWN_OPERATION}, + #else + {"UNKNOWN_OPERATION", 33, 110}, + #endif + #ifdef PKCS7_R_UNSUPPORTED_CIPHER_TYPE + {"UNSUPPORTED_CIPHER_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE}, + #else + {"UNSUPPORTED_CIPHER_TYPE", 33, 111}, + #endif + #ifdef PKCS7_R_UNSUPPORTED_CONTENT_TYPE + {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE}, + #else + {"UNSUPPORTED_CONTENT_TYPE", 33, 112}, + #endif + #ifdef PKCS7_R_WRONG_CONTENT_TYPE + {"WRONG_CONTENT_TYPE", ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE}, + #else + {"WRONG_CONTENT_TYPE", 33, 113}, + #endif + #ifdef PKCS7_R_WRONG_PKCS7_TYPE + {"WRONG_PKCS7_TYPE", ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE}, + #else + {"WRONG_PKCS7_TYPE", 33, 114}, + #endif + #ifdef PROP_R_NAME_TOO_LONG + {"NAME_TOO_LONG", ERR_LIB_PROP, PROP_R_NAME_TOO_LONG}, + #else + {"NAME_TOO_LONG", 55, 100}, + #endif + #ifdef PROP_R_NOT_AN_ASCII_CHARACTER + {"NOT_AN_ASCII_CHARACTER", ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER}, + #else + {"NOT_AN_ASCII_CHARACTER", 55, 101}, + #endif + #ifdef PROP_R_NOT_AN_HEXADECIMAL_DIGIT + {"NOT_AN_HEXADECIMAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT}, + #else + {"NOT_AN_HEXADECIMAL_DIGIT", 55, 102}, + #endif + #ifdef PROP_R_NOT_AN_IDENTIFIER + {"NOT_AN_IDENTIFIER", ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER}, + #else + {"NOT_AN_IDENTIFIER", 55, 103}, + #endif + #ifdef PROP_R_NOT_AN_OCTAL_DIGIT + {"NOT_AN_OCTAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT}, + #else + {"NOT_AN_OCTAL_DIGIT", 55, 104}, + #endif + #ifdef PROP_R_NOT_A_DECIMAL_DIGIT + {"NOT_A_DECIMAL_DIGIT", ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT}, + #else + {"NOT_A_DECIMAL_DIGIT", 55, 105}, + #endif + #ifdef PROP_R_NO_MATCHING_STRING_DELIMITER + {"NO_MATCHING_STRING_DELIMITER", ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER}, + #else + {"NO_MATCHING_STRING_DELIMITER", 55, 106}, + #endif + #ifdef PROP_R_NO_VALUE + {"NO_VALUE", ERR_LIB_PROP, PROP_R_NO_VALUE}, + #else + {"NO_VALUE", 55, 107}, + #endif + #ifdef PROP_R_PARSE_FAILED + {"PARSE_FAILED", ERR_LIB_PROP, PROP_R_PARSE_FAILED}, + #else + {"PARSE_FAILED", 55, 108}, + #endif + #ifdef PROP_R_STRING_TOO_LONG + {"STRING_TOO_LONG", ERR_LIB_PROP, PROP_R_STRING_TOO_LONG}, + #else + {"STRING_TOO_LONG", 55, 109}, + #endif + #ifdef PROP_R_TRAILING_CHARACTERS + {"TRAILING_CHARACTERS", ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS}, + #else + {"TRAILING_CHARACTERS", 55, 110}, + #endif + #ifdef PROV_R_ADDITIONAL_INPUT_TOO_LONG + {"ADDITIONAL_INPUT_TOO_LONG", ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG}, + #else + {"ADDITIONAL_INPUT_TOO_LONG", 57, 184}, + #endif + #ifdef PROV_R_ALGORITHM_MISMATCH + {"ALGORITHM_MISMATCH", ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH}, + #else + {"ALGORITHM_MISMATCH", 57, 173}, + #endif + #ifdef PROV_R_ALREADY_INSTANTIATED + {"ALREADY_INSTANTIATED", ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED}, + #else + {"ALREADY_INSTANTIATED", 57, 185}, + #endif + #ifdef PROV_R_BAD_DECRYPT + {"BAD_DECRYPT", ERR_LIB_PROV, PROV_R_BAD_DECRYPT}, + #else + {"BAD_DECRYPT", 57, 100}, + #endif + #ifdef PROV_R_BAD_ENCODING + {"BAD_ENCODING", ERR_LIB_PROV, PROV_R_BAD_ENCODING}, + #else + {"BAD_ENCODING", 57, 141}, + #endif + #ifdef PROV_R_BAD_LENGTH + {"BAD_LENGTH", ERR_LIB_PROV, PROV_R_BAD_LENGTH}, + #else + {"BAD_LENGTH", 57, 142}, + #endif + #ifdef PROV_R_BAD_TLS_CLIENT_VERSION + {"BAD_TLS_CLIENT_VERSION", ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION}, + #else + {"BAD_TLS_CLIENT_VERSION", 57, 161}, + #endif + #ifdef PROV_R_BN_ERROR + {"BN_ERROR", ERR_LIB_PROV, PROV_R_BN_ERROR}, + #else + {"BN_ERROR", 57, 160}, + #endif + #ifdef PROV_R_CIPHER_OPERATION_FAILED + {"CIPHER_OPERATION_FAILED", ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED}, + #else + {"CIPHER_OPERATION_FAILED", 57, 102}, + #endif + #ifdef PROV_R_COFACTOR_REQUIRED + {"COFACTOR_REQUIRED", ERR_LIB_PROV, PROV_R_COFACTOR_REQUIRED}, + #else + {"COFACTOR_REQUIRED", 57, 236}, + #endif + #ifdef PROV_R_DERIVATION_FUNCTION_INIT_FAILED + {"DERIVATION_FUNCTION_INIT_FAILED", ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED}, + #else + {"DERIVATION_FUNCTION_INIT_FAILED", 57, 205}, + #endif + #ifdef PROV_R_DIGEST_NOT_ALLOWED + {"DIGEST_NOT_ALLOWED", ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED}, + #else + {"DIGEST_NOT_ALLOWED", 57, 174}, + #endif + #ifdef PROV_R_EMS_NOT_ENABLED + {"EMS_NOT_ENABLED", ERR_LIB_PROV, PROV_R_EMS_NOT_ENABLED}, + #else + {"EMS_NOT_ENABLED", 57, 233}, + #endif + #ifdef PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS + {"ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS", ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS}, + #else + {"ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS", 57, 244}, + #endif + #ifdef PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK + {"ENTROPY_SOURCE_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK}, + #else + {"ENTROPY_SOURCE_STRENGTH_TOO_WEAK", 57, 186}, + #endif + #ifdef PROV_R_ERROR_INSTANTIATING_DRBG + {"ERROR_INSTANTIATING_DRBG", ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG}, + #else + {"ERROR_INSTANTIATING_DRBG", 57, 188}, + #endif + #ifdef PROV_R_ERROR_RETRIEVING_ENTROPY + {"ERROR_RETRIEVING_ENTROPY", ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY}, + #else + {"ERROR_RETRIEVING_ENTROPY", 57, 189}, + #endif + #ifdef PROV_R_ERROR_RETRIEVING_NONCE + {"ERROR_RETRIEVING_NONCE", ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE}, + #else + {"ERROR_RETRIEVING_NONCE", 57, 190}, + #endif + #ifdef PROV_R_FAILED_DURING_DERIVATION + {"FAILED_DURING_DERIVATION", ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION}, + #else + {"FAILED_DURING_DERIVATION", 57, 164}, + #endif + #ifdef PROV_R_FAILED_TO_CREATE_LOCK + {"FAILED_TO_CREATE_LOCK", ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK}, + #else + {"FAILED_TO_CREATE_LOCK", 57, 180}, + #endif + #ifdef PROV_R_FAILED_TO_DECRYPT + {"FAILED_TO_DECRYPT", ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT}, + #else + {"FAILED_TO_DECRYPT", 57, 162}, + #endif + #ifdef PROV_R_FAILED_TO_GENERATE_KEY + {"FAILED_TO_GENERATE_KEY", ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY}, + #else + {"FAILED_TO_GENERATE_KEY", 57, 121}, + #endif + #ifdef PROV_R_FAILED_TO_GET_PARAMETER + {"FAILED_TO_GET_PARAMETER", ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER}, + #else + {"FAILED_TO_GET_PARAMETER", 57, 103}, + #endif + #ifdef PROV_R_FAILED_TO_SET_PARAMETER + {"FAILED_TO_SET_PARAMETER", ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER}, + #else + {"FAILED_TO_SET_PARAMETER", 57, 104}, + #endif + #ifdef PROV_R_FAILED_TO_SIGN + {"FAILED_TO_SIGN", ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN}, + #else + {"FAILED_TO_SIGN", 57, 175}, + #endif + #ifdef PROV_R_FINAL_CALL_OUT_OF_ORDER + {"FINAL_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER}, + #else + {"FINAL_CALL_OUT_OF_ORDER", 57, 237}, + #endif + #ifdef PROV_R_FIPS_MODULE_CONDITIONAL_ERROR + {"FIPS_MODULE_CONDITIONAL_ERROR", ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR}, + #else + {"FIPS_MODULE_CONDITIONAL_ERROR", 57, 227}, + #endif + #ifdef PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE + {"FIPS_MODULE_ENTERING_ERROR_STATE", ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE}, + #else + {"FIPS_MODULE_ENTERING_ERROR_STATE", 57, 224}, + #endif + #ifdef PROV_R_FIPS_MODULE_IMPORT_PCT_ERROR + {"FIPS_MODULE_IMPORT_PCT_ERROR", ERR_LIB_PROV, PROV_R_FIPS_MODULE_IMPORT_PCT_ERROR}, + #else + {"FIPS_MODULE_IMPORT_PCT_ERROR", 57, 253}, + #endif + #ifdef PROV_R_FIPS_MODULE_IN_ERROR_STATE + {"FIPS_MODULE_IN_ERROR_STATE", ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE}, + #else + {"FIPS_MODULE_IN_ERROR_STATE", 57, 225}, + #endif + #ifdef PROV_R_GENERATE_ERROR + {"GENERATE_ERROR", ERR_LIB_PROV, PROV_R_GENERATE_ERROR}, + #else + {"GENERATE_ERROR", 57, 191}, + #endif + #ifdef PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", ERR_LIB_PROV, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE}, + #else + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", 57, 165}, + #endif + #ifdef PROV_R_INDICATOR_INTEGRITY_FAILURE + {"INDICATOR_INTEGRITY_FAILURE", ERR_LIB_PROV, PROV_R_INDICATOR_INTEGRITY_FAILURE}, + #else + {"INDICATOR_INTEGRITY_FAILURE", 57, 210}, + #endif + #ifdef PROV_R_INIT_CALL_OUT_OF_ORDER + {"INIT_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_INIT_CALL_OUT_OF_ORDER}, + #else + {"INIT_CALL_OUT_OF_ORDER", 57, 238}, + #endif + #ifdef PROV_R_INSUFFICIENT_DRBG_STRENGTH + {"INSUFFICIENT_DRBG_STRENGTH", ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH}, + #else + {"INSUFFICIENT_DRBG_STRENGTH", 57, 181}, + #endif + #ifdef PROV_R_INVALID_AAD + {"INVALID_AAD", ERR_LIB_PROV, PROV_R_INVALID_AAD}, + #else + {"INVALID_AAD", 57, 108}, + #endif + #ifdef PROV_R_INVALID_AEAD + {"INVALID_AEAD", ERR_LIB_PROV, PROV_R_INVALID_AEAD}, + #else + {"INVALID_AEAD", 57, 231}, + #endif + #ifdef PROV_R_INVALID_CIPHER + {"INVALID_CIPHER", ERR_LIB_PROV, PROV_R_INVALID_CIPHER}, + #else + {"INVALID_CIPHER", 57, 260}, + #endif + #ifdef PROV_R_INVALID_CONFIG_DATA + {"INVALID_CONFIG_DATA", ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA}, + #else + {"INVALID_CONFIG_DATA", 57, 211}, + #endif + #ifdef PROV_R_INVALID_CONSTANT_LENGTH + {"INVALID_CONSTANT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH}, + #else + {"INVALID_CONSTANT_LENGTH", 57, 157}, + #endif + #ifdef PROV_R_INVALID_CURVE + {"INVALID_CURVE", ERR_LIB_PROV, PROV_R_INVALID_CURVE}, + #else + {"INVALID_CURVE", 57, 176}, + #endif + #ifdef PROV_R_INVALID_CUSTOM_LENGTH + {"INVALID_CUSTOM_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH}, + #else + {"INVALID_CUSTOM_LENGTH", 57, 111}, + #endif + #ifdef PROV_R_INVALID_DATA + {"INVALID_DATA", ERR_LIB_PROV, PROV_R_INVALID_DATA}, + #else + {"INVALID_DATA", 57, 115}, + #endif + #ifdef PROV_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_PROV, PROV_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 57, 122}, + #endif + #ifdef PROV_R_INVALID_DIGEST_LENGTH + {"INVALID_DIGEST_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH}, + #else + {"INVALID_DIGEST_LENGTH", 57, 166}, + #endif + #ifdef PROV_R_INVALID_DIGEST_SIZE + {"INVALID_DIGEST_SIZE", ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE}, + #else + {"INVALID_DIGEST_SIZE", 57, 218}, + #endif + #ifdef PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION + {"INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION", ERR_LIB_PROV, PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION}, + #else + {"INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION", 57, 243}, + #endif + #ifdef PROV_R_INVALID_FUNCTION_NAME + {"INVALID_FUNCTION_NAME", ERR_LIB_PROV, PROV_R_INVALID_FUNCTION_NAME}, + #else + {"INVALID_FUNCTION_NAME", 57, 258}, + #endif + #ifdef PROV_R_INVALID_INDEX_LENGTH + {"INVALID_INDEX_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_INDEX_LENGTH}, + #else + {"INVALID_INDEX_LENGTH", 57, 259}, + #endif + #ifdef PROV_R_INVALID_INPUT_LENGTH + {"INVALID_INPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH}, + #else + {"INVALID_INPUT_LENGTH", 57, 230}, + #endif + #ifdef PROV_R_INVALID_ITERATION_COUNT + {"INVALID_ITERATION_COUNT", ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT}, + #else + {"INVALID_ITERATION_COUNT", 57, 123}, + #endif + #ifdef PROV_R_INVALID_IV_LENGTH + {"INVALID_IV_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH}, + #else + {"INVALID_IV_LENGTH", 57, 109}, + #endif + #ifdef PROV_R_INVALID_KDF + {"INVALID_KDF", ERR_LIB_PROV, PROV_R_INVALID_KDF}, + #else + {"INVALID_KDF", 57, 232}, + #endif + #ifdef PROV_R_INVALID_KDR + {"INVALID_KDR", ERR_LIB_PROV, PROV_R_INVALID_KDR}, + #else + {"INVALID_KDR", 57, 256}, + #endif + #ifdef PROV_R_INVALID_KEY + {"INVALID_KEY", ERR_LIB_PROV, PROV_R_INVALID_KEY}, + #else + {"INVALID_KEY", 57, 158}, + #endif + #ifdef PROV_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 57, 105}, + #endif + #ifdef PROV_R_INVALID_LABEL + {"INVALID_LABEL", ERR_LIB_PROV, PROV_R_INVALID_LABEL}, + #else + {"INVALID_LABEL", 57, 257}, + #endif + #ifdef PROV_R_INVALID_MAC + {"INVALID_MAC", ERR_LIB_PROV, PROV_R_INVALID_MAC}, + #else + {"INVALID_MAC", 57, 151}, + #endif + #ifdef PROV_R_INVALID_MEMORY_SIZE + {"INVALID_MEMORY_SIZE", ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE}, + #else + {"INVALID_MEMORY_SIZE", 57, 235}, + #endif + #ifdef PROV_R_INVALID_MGF1_MD + {"INVALID_MGF1_MD", ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD}, + #else + {"INVALID_MGF1_MD", 57, 167}, + #endif + #ifdef PROV_R_INVALID_MODE + {"INVALID_MODE", ERR_LIB_PROV, PROV_R_INVALID_MODE}, + #else + {"INVALID_MODE", 57, 125}, + #endif + #ifdef PROV_R_INVALID_OUTPUT_LENGTH + {"INVALID_OUTPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH}, + #else + {"INVALID_OUTPUT_LENGTH", 57, 217}, + #endif + #ifdef PROV_R_INVALID_PADDING_MODE + {"INVALID_PADDING_MODE", ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE}, + #else + {"INVALID_PADDING_MODE", 57, 168}, + #endif + #ifdef PROV_R_INVALID_PREHASHED_DIGEST_LENGTH + {"INVALID_PREHASHED_DIGEST_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH}, + #else + {"INVALID_PREHASHED_DIGEST_LENGTH", 57, 241}, + #endif + #ifdef PROV_R_INVALID_PUBINFO + {"INVALID_PUBINFO", ERR_LIB_PROV, PROV_R_INVALID_PUBINFO}, + #else + {"INVALID_PUBINFO", 57, 198}, + #endif + #ifdef PROV_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 57, 112}, + #endif + #ifdef PROV_R_INVALID_SEED_LENGTH + {"INVALID_SEED_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH}, + #else + {"INVALID_SEED_LENGTH", 57, 154}, + #endif + #ifdef PROV_R_INVALID_SIGNATURE_SIZE + {"INVALID_SIGNATURE_SIZE", ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE}, + #else + {"INVALID_SIGNATURE_SIZE", 57, 179}, + #endif + #ifdef PROV_R_INVALID_STATE + {"INVALID_STATE", ERR_LIB_PROV, PROV_R_INVALID_STATE}, + #else + {"INVALID_STATE", 57, 212}, + #endif + #ifdef PROV_R_INVALID_TAG + {"INVALID_TAG", ERR_LIB_PROV, PROV_R_INVALID_TAG}, + #else + {"INVALID_TAG", 57, 110}, + #endif + #ifdef PROV_R_INVALID_TAG_LENGTH + {"INVALID_TAG_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH}, + #else + {"INVALID_TAG_LENGTH", 57, 118}, + #endif + #ifdef PROV_R_INVALID_THREAD_POOL_SIZE + {"INVALID_THREAD_POOL_SIZE", ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE}, + #else + {"INVALID_THREAD_POOL_SIZE", 57, 234}, + #endif + #ifdef PROV_R_INVALID_UKM_LENGTH + {"INVALID_UKM_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_UKM_LENGTH}, + #else + {"INVALID_UKM_LENGTH", 57, 200}, + #endif + #ifdef PROV_R_INVALID_X931_DIGEST + {"INVALID_X931_DIGEST", ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST}, + #else + {"INVALID_X931_DIGEST", 57, 170}, + #endif + #ifdef PROV_R_IN_ERROR_STATE + {"IN_ERROR_STATE", ERR_LIB_PROV, PROV_R_IN_ERROR_STATE}, + #else + {"IN_ERROR_STATE", 57, 192}, + #endif + #ifdef PROV_R_KEY_SETUP_FAILED + {"KEY_SETUP_FAILED", ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED}, + #else + {"KEY_SETUP_FAILED", 57, 101}, + #endif + #ifdef PROV_R_KEY_SIZE_TOO_SMALL + {"KEY_SIZE_TOO_SMALL", ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL}, + #else + {"KEY_SIZE_TOO_SMALL", 57, 171}, + #endif + #ifdef PROV_R_LENGTH_TOO_LARGE + {"LENGTH_TOO_LARGE", ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE}, + #else + {"LENGTH_TOO_LARGE", 57, 202}, + #endif + #ifdef PROV_R_MISMATCHING_DOMAIN_PARAMETERS + {"MISMATCHING_DOMAIN_PARAMETERS", ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS}, + #else + {"MISMATCHING_DOMAIN_PARAMETERS", 57, 203}, + #endif + #ifdef PROV_R_MISSING_CEK_ALG + {"MISSING_CEK_ALG", ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG}, + #else + {"MISSING_CEK_ALG", 57, 144}, + #endif + #ifdef PROV_R_MISSING_CIPHER + {"MISSING_CIPHER", ERR_LIB_PROV, PROV_R_MISSING_CIPHER}, + #else + {"MISSING_CIPHER", 57, 155}, + #endif + #ifdef PROV_R_MISSING_CONFIG_DATA + {"MISSING_CONFIG_DATA", ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA}, + #else + {"MISSING_CONFIG_DATA", 57, 213}, + #endif + #ifdef PROV_R_MISSING_CONSTANT + {"MISSING_CONSTANT", ERR_LIB_PROV, PROV_R_MISSING_CONSTANT}, + #else + {"MISSING_CONSTANT", 57, 156}, + #endif + #ifdef PROV_R_MISSING_EID + {"MISSING_EID", ERR_LIB_PROV, PROV_R_MISSING_EID}, + #else + {"MISSING_EID", 57, 255}, + #endif + #ifdef PROV_R_MISSING_KEY + {"MISSING_KEY", ERR_LIB_PROV, PROV_R_MISSING_KEY}, + #else + {"MISSING_KEY", 57, 128}, + #endif + #ifdef PROV_R_MISSING_MAC + {"MISSING_MAC", ERR_LIB_PROV, PROV_R_MISSING_MAC}, + #else + {"MISSING_MAC", 57, 150}, + #endif + #ifdef PROV_R_MISSING_MESSAGE_DIGEST + {"MISSING_MESSAGE_DIGEST", ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST}, + #else + {"MISSING_MESSAGE_DIGEST", 57, 129}, + #endif + #ifdef PROV_R_MISSING_OID + {"MISSING_OID", ERR_LIB_PROV, PROV_R_MISSING_OID}, + #else + {"MISSING_OID", 57, 209}, + #endif + #ifdef PROV_R_MISSING_PASS + {"MISSING_PASS", ERR_LIB_PROV, PROV_R_MISSING_PASS}, + #else + {"MISSING_PASS", 57, 130}, + #endif + #ifdef PROV_R_MISSING_SALT + {"MISSING_SALT", ERR_LIB_PROV, PROV_R_MISSING_SALT}, + #else + {"MISSING_SALT", 57, 131}, + #endif + #ifdef PROV_R_MISSING_SECRET + {"MISSING_SECRET", ERR_LIB_PROV, PROV_R_MISSING_SECRET}, + #else + {"MISSING_SECRET", 57, 132}, + #endif + #ifdef PROV_R_MISSING_SEED + {"MISSING_SEED", ERR_LIB_PROV, PROV_R_MISSING_SEED}, + #else + {"MISSING_SEED", 57, 140}, + #endif + #ifdef PROV_R_MISSING_SESSION_ID + {"MISSING_SESSION_ID", ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID}, + #else + {"MISSING_SESSION_ID", 57, 133}, + #endif + #ifdef PROV_R_MISSING_TYPE + {"MISSING_TYPE", ERR_LIB_PROV, PROV_R_MISSING_TYPE}, + #else + {"MISSING_TYPE", 57, 134}, + #endif + #ifdef PROV_R_MISSING_XCGHASH + {"MISSING_XCGHASH", ERR_LIB_PROV, PROV_R_MISSING_XCGHASH}, + #else + {"MISSING_XCGHASH", 57, 135}, + #endif + #ifdef PROV_R_ML_DSA_NO_FORMAT + {"ML_DSA_NO_FORMAT", ERR_LIB_PROV, PROV_R_ML_DSA_NO_FORMAT}, + #else + {"ML_DSA_NO_FORMAT", 57, 245}, + #endif + #ifdef PROV_R_ML_KEM_NO_FORMAT + {"ML_KEM_NO_FORMAT", ERR_LIB_PROV, PROV_R_ML_KEM_NO_FORMAT}, + #else + {"ML_KEM_NO_FORMAT", 57, 246}, + #endif + #ifdef PROV_R_MODULE_INTEGRITY_FAILURE + {"MODULE_INTEGRITY_FAILURE", ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE}, + #else + {"MODULE_INTEGRITY_FAILURE", 57, 214}, + #endif + #ifdef PROV_R_NOT_A_PRIVATE_KEY + {"NOT_A_PRIVATE_KEY", ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY}, + #else + {"NOT_A_PRIVATE_KEY", 57, 221}, + #endif + #ifdef PROV_R_NOT_A_PUBLIC_KEY + {"NOT_A_PUBLIC_KEY", ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY}, + #else + {"NOT_A_PUBLIC_KEY", 57, 220}, + #endif + #ifdef PROV_R_NOT_INSTANTIATED + {"NOT_INSTANTIATED", ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED}, + #else + {"NOT_INSTANTIATED", 57, 193}, + #endif + #ifdef PROV_R_NOT_PARAMETERS + {"NOT_PARAMETERS", ERR_LIB_PROV, PROV_R_NOT_PARAMETERS}, + #else + {"NOT_PARAMETERS", 57, 226}, + #endif + #ifdef PROV_R_NOT_SUPPORTED + {"NOT_SUPPORTED", ERR_LIB_PROV, PROV_R_NOT_SUPPORTED}, + #else + {"NOT_SUPPORTED", 57, 136}, + #endif + #ifdef PROV_R_NOT_XOF_OR_INVALID_LENGTH + {"NOT_XOF_OR_INVALID_LENGTH", ERR_LIB_PROV, PROV_R_NOT_XOF_OR_INVALID_LENGTH}, + #else + {"NOT_XOF_OR_INVALID_LENGTH", 57, 113}, + #endif + #ifdef PROV_R_NO_INSTANCE_ALLOWED + {"NO_INSTANCE_ALLOWED", ERR_LIB_PROV, PROV_R_NO_INSTANCE_ALLOWED}, + #else + {"NO_INSTANCE_ALLOWED", 57, 242}, + #endif + #ifdef PROV_R_NO_KEY_SET + {"NO_KEY_SET", ERR_LIB_PROV, PROV_R_NO_KEY_SET}, + #else + {"NO_KEY_SET", 57, 114}, + #endif + #ifdef PROV_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 57, 177}, + #endif + #ifdef PROV_R_NULL_LENGTH_POINTER + {"NULL_LENGTH_POINTER", ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER}, + #else + {"NULL_LENGTH_POINTER", 57, 247}, + #endif + #ifdef PROV_R_NULL_OUTPUT_BUFFER + {"NULL_OUTPUT_BUFFER", ERR_LIB_PROV, PROV_R_NULL_OUTPUT_BUFFER}, + #else + {"NULL_OUTPUT_BUFFER", 57, 248}, + #endif + #ifdef PROV_R_ONESHOT_CALL_OUT_OF_ORDER + {"ONESHOT_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER}, + #else + {"ONESHOT_CALL_OUT_OF_ORDER", 57, 239}, + #endif + #ifdef PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 57, 178}, + #endif + #ifdef PROV_R_OUTPUT_BUFFER_TOO_SMALL + {"OUTPUT_BUFFER_TOO_SMALL", ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL}, + #else + {"OUTPUT_BUFFER_TOO_SMALL", 57, 106}, + #endif + #ifdef PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS + {"PARENT_CANNOT_GENERATE_RANDOM_NUMBERS", ERR_LIB_PROV, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS}, + #else + {"PARENT_CANNOT_GENERATE_RANDOM_NUMBERS", 57, 228}, + #endif + #ifdef PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED + {"PARENT_CANNOT_SUPPLY_ENTROPY_SEED", ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED}, + #else + {"PARENT_CANNOT_SUPPLY_ENTROPY_SEED", 57, 187}, + #endif + #ifdef PROV_R_PARENT_LOCKING_NOT_ENABLED + {"PARENT_LOCKING_NOT_ENABLED", ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED}, + #else + {"PARENT_LOCKING_NOT_ENABLED", 57, 182}, + #endif + #ifdef PROV_R_PARENT_STRENGTH_TOO_WEAK + {"PARENT_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK}, + #else + {"PARENT_STRENGTH_TOO_WEAK", 57, 194}, + #endif + #ifdef PROV_R_PASSWORD_STRENGTH_TOO_WEAK + {"PASSWORD_STRENGTH_TOO_WEAK", ERR_LIB_PROV, PROV_R_PASSWORD_STRENGTH_TOO_WEAK}, + #else + {"PASSWORD_STRENGTH_TOO_WEAK", 57, 254}, + #endif + #ifdef PROV_R_PATH_MUST_BE_ABSOLUTE + {"PATH_MUST_BE_ABSOLUTE", ERR_LIB_PROV, PROV_R_PATH_MUST_BE_ABSOLUTE}, + #else + {"PATH_MUST_BE_ABSOLUTE", 57, 219}, + #endif + #ifdef PROV_R_PERSONALISATION_STRING_TOO_LONG + {"PERSONALISATION_STRING_TOO_LONG", ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG}, + #else + {"PERSONALISATION_STRING_TOO_LONG", 57, 195}, + #endif + #ifdef PROV_R_PSS_SALTLEN_TOO_SMALL + {"PSS_SALTLEN_TOO_SMALL", ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL}, + #else + {"PSS_SALTLEN_TOO_SMALL", 57, 172}, + #endif + #ifdef PROV_R_REPEATED_PARAMETER + {"REPEATED_PARAMETER", ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER}, + #else + {"REPEATED_PARAMETER", 57, 252}, + #endif + #ifdef PROV_R_REQUEST_TOO_LARGE_FOR_DRBG + {"REQUEST_TOO_LARGE_FOR_DRBG", ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG}, + #else + {"REQUEST_TOO_LARGE_FOR_DRBG", 57, 196}, + #endif + #ifdef PROV_R_REQUIRE_CTR_MODE_CIPHER + {"REQUIRE_CTR_MODE_CIPHER", ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER}, + #else + {"REQUIRE_CTR_MODE_CIPHER", 57, 206}, + #endif + #ifdef PROV_R_RESEED_ERROR + {"RESEED_ERROR", ERR_LIB_PROV, PROV_R_RESEED_ERROR}, + #else + {"RESEED_ERROR", 57, 197}, + #endif + #ifdef PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", ERR_LIB_PROV, PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES}, + #else + {"SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES", 57, 222}, + #endif + #ifdef PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT + {"SEED_SOURCES_MUST_NOT_HAVE_A_PARENT", ERR_LIB_PROV, PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT}, + #else + {"SEED_SOURCES_MUST_NOT_HAVE_A_PARENT", 57, 229}, + #endif + #ifdef PROV_R_SELF_TEST_KAT_FAILURE + {"SELF_TEST_KAT_FAILURE", ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE}, + #else + {"SELF_TEST_KAT_FAILURE", 57, 215}, + #endif + #ifdef PROV_R_SELF_TEST_POST_FAILURE + {"SELF_TEST_POST_FAILURE", ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE}, + #else + {"SELF_TEST_POST_FAILURE", 57, 216}, + #endif + #ifdef PROV_R_TAG_NOT_NEEDED + {"TAG_NOT_NEEDED", ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED}, + #else + {"TAG_NOT_NEEDED", 57, 120}, + #endif + #ifdef PROV_R_TAG_NOT_SET + {"TAG_NOT_SET", ERR_LIB_PROV, PROV_R_TAG_NOT_SET}, + #else + {"TAG_NOT_SET", 57, 119}, + #endif + #ifdef PROV_R_TOO_MANY_RECORDS + {"TOO_MANY_RECORDS", ERR_LIB_PROV, PROV_R_TOO_MANY_RECORDS}, + #else + {"TOO_MANY_RECORDS", 57, 126}, + #endif + #ifdef PROV_R_UNABLE_TO_FIND_CIPHERS + {"UNABLE_TO_FIND_CIPHERS", ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS}, + #else + {"UNABLE_TO_FIND_CIPHERS", 57, 207}, + #endif + #ifdef PROV_R_UNABLE_TO_GET_PARENT_STRENGTH + {"UNABLE_TO_GET_PARENT_STRENGTH", ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH}, + #else + {"UNABLE_TO_GET_PARENT_STRENGTH", 57, 199}, + #endif + #ifdef PROV_R_UNABLE_TO_GET_PASSPHRASE + {"UNABLE_TO_GET_PASSPHRASE", ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE}, + #else + {"UNABLE_TO_GET_PASSPHRASE", 57, 159}, + #endif + #ifdef PROV_R_UNABLE_TO_INITIALISE_CIPHERS + {"UNABLE_TO_INITIALISE_CIPHERS", ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS}, + #else + {"UNABLE_TO_INITIALISE_CIPHERS", 57, 208}, + #endif + #ifdef PROV_R_UNABLE_TO_LOAD_SHA256 + {"UNABLE_TO_LOAD_SHA256", ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256}, + #else + {"UNABLE_TO_LOAD_SHA256", 57, 147}, + #endif + #ifdef PROV_R_UNABLE_TO_LOCK_PARENT + {"UNABLE_TO_LOCK_PARENT", ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT}, + #else + {"UNABLE_TO_LOCK_PARENT", 57, 201}, + #endif + #ifdef PROV_R_UNABLE_TO_RESEED + {"UNABLE_TO_RESEED", ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED}, + #else + {"UNABLE_TO_RESEED", 57, 204}, + #endif + #ifdef PROV_R_UNEXPECTED_KEY_PARAMETERS + {"UNEXPECTED_KEY_PARAMETERS", ERR_LIB_PROV, PROV_R_UNEXPECTED_KEY_PARAMETERS}, + #else + {"UNEXPECTED_KEY_PARAMETERS", 57, 249}, + #endif + #ifdef PROV_R_UNSUPPORTED_CEK_ALG + {"UNSUPPORTED_CEK_ALG", ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG}, + #else + {"UNSUPPORTED_CEK_ALG", 57, 145}, + #endif + #ifdef PROV_R_UNSUPPORTED_KEY_SIZE + {"UNSUPPORTED_KEY_SIZE", ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE}, + #else + {"UNSUPPORTED_KEY_SIZE", 57, 153}, + #endif + #ifdef PROV_R_UNSUPPORTED_MAC_TYPE + {"UNSUPPORTED_MAC_TYPE", ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE}, + #else + {"UNSUPPORTED_MAC_TYPE", 57, 137}, + #endif + #ifdef PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS + {"UNSUPPORTED_NUMBER_OF_ROUNDS", ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS}, + #else + {"UNSUPPORTED_NUMBER_OF_ROUNDS", 57, 152}, + #endif + #ifdef PROV_R_UNSUPPORTED_SELECTION + {"UNSUPPORTED_SELECTION", ERR_LIB_PROV, PROV_R_UNSUPPORTED_SELECTION}, + #else + {"UNSUPPORTED_SELECTION", 57, 250}, + #endif + #ifdef PROV_R_UPDATE_CALL_OUT_OF_ORDER + {"UPDATE_CALL_OUT_OF_ORDER", ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER}, + #else + {"UPDATE_CALL_OUT_OF_ORDER", 57, 240}, + #endif + #ifdef PROV_R_URI_AUTHORITY_UNSUPPORTED + {"URI_AUTHORITY_UNSUPPORTED", ERR_LIB_PROV, PROV_R_URI_AUTHORITY_UNSUPPORTED}, + #else + {"URI_AUTHORITY_UNSUPPORTED", 57, 223}, + #endif + #ifdef PROV_R_VALUE_ERROR + {"VALUE_ERROR", ERR_LIB_PROV, PROV_R_VALUE_ERROR}, + #else + {"VALUE_ERROR", 57, 138}, + #endif + #ifdef PROV_R_WRONG_CIPHERTEXT_SIZE + {"WRONG_CIPHERTEXT_SIZE", ERR_LIB_PROV, PROV_R_WRONG_CIPHERTEXT_SIZE}, + #else + {"WRONG_CIPHERTEXT_SIZE", 57, 251}, + #endif + #ifdef PROV_R_WRONG_FINAL_BLOCK_LENGTH + {"WRONG_FINAL_BLOCK_LENGTH", ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH}, + #else + {"WRONG_FINAL_BLOCK_LENGTH", 57, 107}, + #endif + #ifdef PROV_R_WRONG_OUTPUT_BUFFER_SIZE + {"WRONG_OUTPUT_BUFFER_SIZE", ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE}, + #else + {"WRONG_OUTPUT_BUFFER_SIZE", 57, 139}, + #endif + #ifdef PROV_R_XOF_DIGESTS_NOT_ALLOWED + {"XOF_DIGESTS_NOT_ALLOWED", ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED}, + #else + {"XOF_DIGESTS_NOT_ALLOWED", 57, 183}, + #endif + #ifdef PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE + {"XTS_DATA_UNIT_IS_TOO_LARGE", ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE}, + #else + {"XTS_DATA_UNIT_IS_TOO_LARGE", 57, 148}, + #endif + #ifdef PROV_R_XTS_DUPLICATED_KEYS + {"XTS_DUPLICATED_KEYS", ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS}, + #else + {"XTS_DUPLICATED_KEYS", 57, 149}, + #endif + #ifdef RAND_R_ADDITIONAL_INPUT_TOO_LONG + {"ADDITIONAL_INPUT_TOO_LONG", ERR_LIB_RAND, RAND_R_ADDITIONAL_INPUT_TOO_LONG}, + #else + {"ADDITIONAL_INPUT_TOO_LONG", 36, 102}, + #endif + #ifdef RAND_R_ALREADY_INSTANTIATED + {"ALREADY_INSTANTIATED", ERR_LIB_RAND, RAND_R_ALREADY_INSTANTIATED}, + #else + {"ALREADY_INSTANTIATED", 36, 103}, + #endif + #ifdef RAND_R_ARGUMENT_OUT_OF_RANGE + {"ARGUMENT_OUT_OF_RANGE", ERR_LIB_RAND, RAND_R_ARGUMENT_OUT_OF_RANGE}, + #else + {"ARGUMENT_OUT_OF_RANGE", 36, 105}, + #endif + #ifdef RAND_R_CANNOT_OPEN_FILE + {"CANNOT_OPEN_FILE", ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE}, + #else + {"CANNOT_OPEN_FILE", 36, 121}, + #endif + #ifdef RAND_R_DRBG_ALREADY_INITIALIZED + {"DRBG_ALREADY_INITIALIZED", ERR_LIB_RAND, RAND_R_DRBG_ALREADY_INITIALIZED}, + #else + {"DRBG_ALREADY_INITIALIZED", 36, 129}, + #endif + #ifdef RAND_R_DRBG_NOT_INITIALISED + {"DRBG_NOT_INITIALISED", ERR_LIB_RAND, RAND_R_DRBG_NOT_INITIALISED}, + #else + {"DRBG_NOT_INITIALISED", 36, 104}, + #endif + #ifdef RAND_R_ENTROPY_INPUT_TOO_LONG + {"ENTROPY_INPUT_TOO_LONG", ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG}, + #else + {"ENTROPY_INPUT_TOO_LONG", 36, 106}, + #endif + #ifdef RAND_R_ENTROPY_OUT_OF_RANGE + {"ENTROPY_OUT_OF_RANGE", ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE}, + #else + {"ENTROPY_OUT_OF_RANGE", 36, 124}, + #endif + #ifdef RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED + {"ERROR_ENTROPY_POOL_WAS_IGNORED", ERR_LIB_RAND, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED}, + #else + {"ERROR_ENTROPY_POOL_WAS_IGNORED", 36, 127}, + #endif + #ifdef RAND_R_ERROR_INITIALISING_DRBG + {"ERROR_INITIALISING_DRBG", ERR_LIB_RAND, RAND_R_ERROR_INITIALISING_DRBG}, + #else + {"ERROR_INITIALISING_DRBG", 36, 107}, + #endif + #ifdef RAND_R_ERROR_INSTANTIATING_DRBG + {"ERROR_INSTANTIATING_DRBG", ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG}, + #else + {"ERROR_INSTANTIATING_DRBG", 36, 108}, + #endif + #ifdef RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT + {"ERROR_RETRIEVING_ADDITIONAL_INPUT", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT}, + #else + {"ERROR_RETRIEVING_ADDITIONAL_INPUT", 36, 109}, + #endif + #ifdef RAND_R_ERROR_RETRIEVING_ENTROPY + {"ERROR_RETRIEVING_ENTROPY", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_ENTROPY}, + #else + {"ERROR_RETRIEVING_ENTROPY", 36, 110}, + #endif + #ifdef RAND_R_ERROR_RETRIEVING_NONCE + {"ERROR_RETRIEVING_NONCE", ERR_LIB_RAND, RAND_R_ERROR_RETRIEVING_NONCE}, + #else + {"ERROR_RETRIEVING_NONCE", 36, 111}, + #endif + #ifdef RAND_R_FAILED_TO_CREATE_LOCK + {"FAILED_TO_CREATE_LOCK", ERR_LIB_RAND, RAND_R_FAILED_TO_CREATE_LOCK}, + #else + {"FAILED_TO_CREATE_LOCK", 36, 126}, + #endif + #ifdef RAND_R_FUNC_NOT_IMPLEMENTED + {"FUNC_NOT_IMPLEMENTED", ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED}, + #else + {"FUNC_NOT_IMPLEMENTED", 36, 101}, + #endif + #ifdef RAND_R_FWRITE_ERROR + {"FWRITE_ERROR", ERR_LIB_RAND, RAND_R_FWRITE_ERROR}, + #else + {"FWRITE_ERROR", 36, 123}, + #endif + #ifdef RAND_R_GENERATE_ERROR + {"GENERATE_ERROR", ERR_LIB_RAND, RAND_R_GENERATE_ERROR}, + #else + {"GENERATE_ERROR", 36, 112}, + #endif + #ifdef RAND_R_INSUFFICIENT_DRBG_STRENGTH + {"INSUFFICIENT_DRBG_STRENGTH", ERR_LIB_RAND, RAND_R_INSUFFICIENT_DRBG_STRENGTH}, + #else + {"INSUFFICIENT_DRBG_STRENGTH", 36, 139}, + #endif + #ifdef RAND_R_INTERNAL_ERROR + {"INTERNAL_ERROR", ERR_LIB_RAND, RAND_R_INTERNAL_ERROR}, + #else + {"INTERNAL_ERROR", 36, 113}, + #endif + #ifdef RAND_R_INVALID_PROPERTY_QUERY + {"INVALID_PROPERTY_QUERY", ERR_LIB_RAND, RAND_R_INVALID_PROPERTY_QUERY}, + #else + {"INVALID_PROPERTY_QUERY", 36, 137}, + #endif + #ifdef RAND_R_IN_ERROR_STATE + {"IN_ERROR_STATE", ERR_LIB_RAND, RAND_R_IN_ERROR_STATE}, + #else + {"IN_ERROR_STATE", 36, 114}, + #endif + #ifdef RAND_R_NOT_A_REGULAR_FILE + {"NOT_A_REGULAR_FILE", ERR_LIB_RAND, RAND_R_NOT_A_REGULAR_FILE}, + #else + {"NOT_A_REGULAR_FILE", 36, 122}, + #endif + #ifdef RAND_R_NOT_INSTANTIATED + {"NOT_INSTANTIATED", ERR_LIB_RAND, RAND_R_NOT_INSTANTIATED}, + #else + {"NOT_INSTANTIATED", 36, 115}, + #endif + #ifdef RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED + {"NO_DRBG_IMPLEMENTATION_SELECTED", ERR_LIB_RAND, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED}, + #else + {"NO_DRBG_IMPLEMENTATION_SELECTED", 36, 128}, + #endif + #ifdef RAND_R_PARENT_LOCKING_NOT_ENABLED + {"PARENT_LOCKING_NOT_ENABLED", ERR_LIB_RAND, RAND_R_PARENT_LOCKING_NOT_ENABLED}, + #else + {"PARENT_LOCKING_NOT_ENABLED", 36, 130}, + #endif + #ifdef RAND_R_PARENT_STRENGTH_TOO_WEAK + {"PARENT_STRENGTH_TOO_WEAK", ERR_LIB_RAND, RAND_R_PARENT_STRENGTH_TOO_WEAK}, + #else + {"PARENT_STRENGTH_TOO_WEAK", 36, 131}, + #endif + #ifdef RAND_R_PERSONALISATION_STRING_TOO_LONG + {"PERSONALISATION_STRING_TOO_LONG", ERR_LIB_RAND, RAND_R_PERSONALISATION_STRING_TOO_LONG}, + #else + {"PERSONALISATION_STRING_TOO_LONG", 36, 116}, + #endif + #ifdef RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED + {"PREDICTION_RESISTANCE_NOT_SUPPORTED", ERR_LIB_RAND, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED}, + #else + {"PREDICTION_RESISTANCE_NOT_SUPPORTED", 36, 133}, + #endif + #ifdef RAND_R_PRNG_NOT_SEEDED + {"PRNG_NOT_SEEDED", ERR_LIB_RAND, RAND_R_PRNG_NOT_SEEDED}, + #else + {"PRNG_NOT_SEEDED", 36, 100}, + #endif + #ifdef RAND_R_RANDOM_POOL_IS_EMPTY + {"RANDOM_POOL_IS_EMPTY", ERR_LIB_RAND, RAND_R_RANDOM_POOL_IS_EMPTY}, + #else + {"RANDOM_POOL_IS_EMPTY", 36, 142}, + #endif + #ifdef RAND_R_RANDOM_POOL_OVERFLOW + {"RANDOM_POOL_OVERFLOW", ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW}, + #else + {"RANDOM_POOL_OVERFLOW", 36, 125}, + #endif + #ifdef RAND_R_RANDOM_POOL_UNDERFLOW + {"RANDOM_POOL_UNDERFLOW", ERR_LIB_RAND, RAND_R_RANDOM_POOL_UNDERFLOW}, + #else + {"RANDOM_POOL_UNDERFLOW", 36, 134}, + #endif + #ifdef RAND_R_REQUEST_TOO_LARGE_FOR_DRBG + {"REQUEST_TOO_LARGE_FOR_DRBG", ERR_LIB_RAND, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG}, + #else + {"REQUEST_TOO_LARGE_FOR_DRBG", 36, 117}, + #endif + #ifdef RAND_R_RESEED_ERROR + {"RESEED_ERROR", ERR_LIB_RAND, RAND_R_RESEED_ERROR}, + #else + {"RESEED_ERROR", 36, 118}, + #endif + #ifdef RAND_R_SELFTEST_FAILURE + {"SELFTEST_FAILURE", ERR_LIB_RAND, RAND_R_SELFTEST_FAILURE}, + #else + {"SELFTEST_FAILURE", 36, 119}, + #endif + #ifdef RAND_R_TOO_LITTLE_NONCE_REQUESTED + {"TOO_LITTLE_NONCE_REQUESTED", ERR_LIB_RAND, RAND_R_TOO_LITTLE_NONCE_REQUESTED}, + #else + {"TOO_LITTLE_NONCE_REQUESTED", 36, 135}, + #endif + #ifdef RAND_R_TOO_MUCH_NONCE_REQUESTED + {"TOO_MUCH_NONCE_REQUESTED", ERR_LIB_RAND, RAND_R_TOO_MUCH_NONCE_REQUESTED}, + #else + {"TOO_MUCH_NONCE_REQUESTED", 36, 136}, + #endif + #ifdef RAND_R_UNABLE_TO_CREATE_DRBG + {"UNABLE_TO_CREATE_DRBG", ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG}, + #else + {"UNABLE_TO_CREATE_DRBG", 36, 143}, + #endif + #ifdef RAND_R_UNABLE_TO_FETCH_DRBG + {"UNABLE_TO_FETCH_DRBG", ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG}, + #else + {"UNABLE_TO_FETCH_DRBG", 36, 144}, + #endif + #ifdef RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER + {"UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER", ERR_LIB_RAND, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER}, + #else + {"UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER", 36, 141}, + #endif + #ifdef RAND_R_UNABLE_TO_GET_PARENT_STRENGTH + {"UNABLE_TO_GET_PARENT_STRENGTH", ERR_LIB_RAND, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH}, + #else + {"UNABLE_TO_GET_PARENT_STRENGTH", 36, 138}, + #endif + #ifdef RAND_R_UNABLE_TO_LOCK_PARENT + {"UNABLE_TO_LOCK_PARENT", ERR_LIB_RAND, RAND_R_UNABLE_TO_LOCK_PARENT}, + #else + {"UNABLE_TO_LOCK_PARENT", 36, 140}, + #endif + #ifdef RAND_R_UNSUPPORTED_DRBG_FLAGS + {"UNSUPPORTED_DRBG_FLAGS", ERR_LIB_RAND, RAND_R_UNSUPPORTED_DRBG_FLAGS}, + #else + {"UNSUPPORTED_DRBG_FLAGS", 36, 132}, + #endif + #ifdef RAND_R_UNSUPPORTED_DRBG_TYPE + {"UNSUPPORTED_DRBG_TYPE", ERR_LIB_RAND, RAND_R_UNSUPPORTED_DRBG_TYPE}, + #else + {"UNSUPPORTED_DRBG_TYPE", 36, 120}, + #endif + #ifdef RSA_R_ALGORITHM_MISMATCH + {"ALGORITHM_MISMATCH", ERR_LIB_RSA, RSA_R_ALGORITHM_MISMATCH}, + #else + {"ALGORITHM_MISMATCH", 4, 100}, + #endif + #ifdef RSA_R_BAD_E_VALUE + {"BAD_E_VALUE", ERR_LIB_RSA, RSA_R_BAD_E_VALUE}, + #else + {"BAD_E_VALUE", 4, 101}, + #endif + #ifdef RSA_R_BAD_FIXED_HEADER_DECRYPT + {"BAD_FIXED_HEADER_DECRYPT", ERR_LIB_RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT}, + #else + {"BAD_FIXED_HEADER_DECRYPT", 4, 102}, + #endif + #ifdef RSA_R_BAD_PAD_BYTE_COUNT + {"BAD_PAD_BYTE_COUNT", ERR_LIB_RSA, RSA_R_BAD_PAD_BYTE_COUNT}, + #else + {"BAD_PAD_BYTE_COUNT", 4, 103}, + #endif + #ifdef RSA_R_BAD_SIGNATURE + {"BAD_SIGNATURE", ERR_LIB_RSA, RSA_R_BAD_SIGNATURE}, + #else + {"BAD_SIGNATURE", 4, 104}, + #endif + #ifdef RSA_R_BLOCK_TYPE_IS_NOT_01 + {"BLOCK_TYPE_IS_NOT_01", ERR_LIB_RSA, RSA_R_BLOCK_TYPE_IS_NOT_01}, + #else + {"BLOCK_TYPE_IS_NOT_01", 4, 106}, + #endif + #ifdef RSA_R_BLOCK_TYPE_IS_NOT_02 + {"BLOCK_TYPE_IS_NOT_02", ERR_LIB_RSA, RSA_R_BLOCK_TYPE_IS_NOT_02}, + #else + {"BLOCK_TYPE_IS_NOT_02", 4, 107}, + #endif + #ifdef RSA_R_DATA_GREATER_THAN_MOD_LEN + {"DATA_GREATER_THAN_MOD_LEN", ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN}, + #else + {"DATA_GREATER_THAN_MOD_LEN", 4, 108}, + #endif + #ifdef RSA_R_DATA_TOO_LARGE + {"DATA_TOO_LARGE", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE}, + #else + {"DATA_TOO_LARGE", 4, 109}, + #endif + #ifdef RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE + {"DATA_TOO_LARGE_FOR_KEY_SIZE", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE}, + #else + {"DATA_TOO_LARGE_FOR_KEY_SIZE", 4, 110}, + #endif + #ifdef RSA_R_DATA_TOO_LARGE_FOR_MODULUS + {"DATA_TOO_LARGE_FOR_MODULUS", ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS}, + #else + {"DATA_TOO_LARGE_FOR_MODULUS", 4, 132}, + #endif + #ifdef RSA_R_DATA_TOO_SMALL + {"DATA_TOO_SMALL", ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL}, + #else + {"DATA_TOO_SMALL", 4, 111}, + #endif + #ifdef RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE + {"DATA_TOO_SMALL_FOR_KEY_SIZE", ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE}, + #else + {"DATA_TOO_SMALL_FOR_KEY_SIZE", 4, 122}, + #endif + #ifdef RSA_R_DIGEST_DOES_NOT_MATCH + {"DIGEST_DOES_NOT_MATCH", ERR_LIB_RSA, RSA_R_DIGEST_DOES_NOT_MATCH}, + #else + {"DIGEST_DOES_NOT_MATCH", 4, 158}, + #endif + #ifdef RSA_R_DIGEST_NOT_ALLOWED + {"DIGEST_NOT_ALLOWED", ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED}, + #else + {"DIGEST_NOT_ALLOWED", 4, 145}, + #endif + #ifdef RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY + {"DIGEST_TOO_BIG_FOR_RSA_KEY", ERR_LIB_RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY}, + #else + {"DIGEST_TOO_BIG_FOR_RSA_KEY", 4, 112}, + #endif + #ifdef RSA_R_DMP1_NOT_CONGRUENT_TO_D + {"DMP1_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D}, + #else + {"DMP1_NOT_CONGRUENT_TO_D", 4, 124}, + #endif + #ifdef RSA_R_DMQ1_NOT_CONGRUENT_TO_D + {"DMQ1_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D}, + #else + {"DMQ1_NOT_CONGRUENT_TO_D", 4, 125}, + #endif + #ifdef RSA_R_D_E_NOT_CONGRUENT_TO_1 + {"D_E_NOT_CONGRUENT_TO_1", ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1}, + #else + {"D_E_NOT_CONGRUENT_TO_1", 4, 123}, + #endif + #ifdef RSA_R_FIRST_OCTET_INVALID + {"FIRST_OCTET_INVALID", ERR_LIB_RSA, RSA_R_FIRST_OCTET_INVALID}, + #else + {"FIRST_OCTET_INVALID", 4, 133}, + #endif + #ifdef RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE}, + #else + {"ILLEGAL_OR_UNSUPPORTED_PADDING_MODE", 4, 144}, + #endif + #ifdef RSA_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_RSA, RSA_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 4, 157}, + #endif + #ifdef RSA_R_INVALID_DIGEST_LENGTH + {"INVALID_DIGEST_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH}, + #else + {"INVALID_DIGEST_LENGTH", 4, 143}, + #endif + #ifdef RSA_R_INVALID_HEADER + {"INVALID_HEADER", ERR_LIB_RSA, RSA_R_INVALID_HEADER}, + #else + {"INVALID_HEADER", 4, 137}, + #endif + #ifdef RSA_R_INVALID_KEYPAIR + {"INVALID_KEYPAIR", ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR}, + #else + {"INVALID_KEYPAIR", 4, 171}, + #endif + #ifdef RSA_R_INVALID_KEY_LENGTH + {"INVALID_KEY_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_KEY_LENGTH}, + #else + {"INVALID_KEY_LENGTH", 4, 173}, + #endif + #ifdef RSA_R_INVALID_LABEL + {"INVALID_LABEL", ERR_LIB_RSA, RSA_R_INVALID_LABEL}, + #else + {"INVALID_LABEL", 4, 160}, + #endif + #ifdef RSA_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 4, 181}, + #endif + #ifdef RSA_R_INVALID_MESSAGE_LENGTH + {"INVALID_MESSAGE_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH}, + #else + {"INVALID_MESSAGE_LENGTH", 4, 131}, + #endif + #ifdef RSA_R_INVALID_MGF1_MD + {"INVALID_MGF1_MD", ERR_LIB_RSA, RSA_R_INVALID_MGF1_MD}, + #else + {"INVALID_MGF1_MD", 4, 156}, + #endif + #ifdef RSA_R_INVALID_MODULUS + {"INVALID_MODULUS", ERR_LIB_RSA, RSA_R_INVALID_MODULUS}, + #else + {"INVALID_MODULUS", 4, 174}, + #endif + #ifdef RSA_R_INVALID_MULTI_PRIME_KEY + {"INVALID_MULTI_PRIME_KEY", ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY}, + #else + {"INVALID_MULTI_PRIME_KEY", 4, 167}, + #endif + #ifdef RSA_R_INVALID_OAEP_PARAMETERS + {"INVALID_OAEP_PARAMETERS", ERR_LIB_RSA, RSA_R_INVALID_OAEP_PARAMETERS}, + #else + {"INVALID_OAEP_PARAMETERS", 4, 161}, + #endif + #ifdef RSA_R_INVALID_PADDING + {"INVALID_PADDING", ERR_LIB_RSA, RSA_R_INVALID_PADDING}, + #else + {"INVALID_PADDING", 4, 138}, + #endif + #ifdef RSA_R_INVALID_PADDING_MODE + {"INVALID_PADDING_MODE", ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE}, + #else + {"INVALID_PADDING_MODE", 4, 141}, + #endif + #ifdef RSA_R_INVALID_PSS_PARAMETERS + {"INVALID_PSS_PARAMETERS", ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS}, + #else + {"INVALID_PSS_PARAMETERS", 4, 149}, + #endif + #ifdef RSA_R_INVALID_PSS_SALTLEN + {"INVALID_PSS_SALTLEN", ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN}, + #else + {"INVALID_PSS_SALTLEN", 4, 146}, + #endif + #ifdef RSA_R_INVALID_REQUEST + {"INVALID_REQUEST", ERR_LIB_RSA, RSA_R_INVALID_REQUEST}, + #else + {"INVALID_REQUEST", 4, 175}, + #endif + #ifdef RSA_R_INVALID_SALT_LENGTH + {"INVALID_SALT_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH}, + #else + {"INVALID_SALT_LENGTH", 4, 150}, + #endif + #ifdef RSA_R_INVALID_STRENGTH + {"INVALID_STRENGTH", ERR_LIB_RSA, RSA_R_INVALID_STRENGTH}, + #else + {"INVALID_STRENGTH", 4, 176}, + #endif + #ifdef RSA_R_INVALID_TRAILER + {"INVALID_TRAILER", ERR_LIB_RSA, RSA_R_INVALID_TRAILER}, + #else + {"INVALID_TRAILER", 4, 139}, + #endif + #ifdef RSA_R_INVALID_X931_DIGEST + {"INVALID_X931_DIGEST", ERR_LIB_RSA, RSA_R_INVALID_X931_DIGEST}, + #else + {"INVALID_X931_DIGEST", 4, 142}, + #endif + #ifdef RSA_R_IQMP_NOT_INVERSE_OF_Q + {"IQMP_NOT_INVERSE_OF_Q", ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q}, + #else + {"IQMP_NOT_INVERSE_OF_Q", 4, 126}, + #endif + #ifdef RSA_R_KEY_PRIME_NUM_INVALID + {"KEY_PRIME_NUM_INVALID", ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID}, + #else + {"KEY_PRIME_NUM_INVALID", 4, 165}, + #endif + #ifdef RSA_R_KEY_SIZE_TOO_SMALL + {"KEY_SIZE_TOO_SMALL", ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL}, + #else + {"KEY_SIZE_TOO_SMALL", 4, 120}, + #endif + #ifdef RSA_R_LAST_OCTET_INVALID + {"LAST_OCTET_INVALID", ERR_LIB_RSA, RSA_R_LAST_OCTET_INVALID}, + #else + {"LAST_OCTET_INVALID", 4, 134}, + #endif + #ifdef RSA_R_MGF1_DIGEST_NOT_ALLOWED + {"MGF1_DIGEST_NOT_ALLOWED", ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED}, + #else + {"MGF1_DIGEST_NOT_ALLOWED", 4, 152}, + #endif + #ifdef RSA_R_MISSING_PRIVATE_KEY + {"MISSING_PRIVATE_KEY", ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY}, + #else + {"MISSING_PRIVATE_KEY", 4, 179}, + #endif + #ifdef RSA_R_MODULUS_TOO_LARGE + {"MODULUS_TOO_LARGE", ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE}, + #else + {"MODULUS_TOO_LARGE", 4, 105}, + #endif + #ifdef RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R + {"MP_COEFFICIENT_NOT_INVERSE_OF_R", ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R}, + #else + {"MP_COEFFICIENT_NOT_INVERSE_OF_R", 4, 168}, + #endif + #ifdef RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D + {"MP_EXPONENT_NOT_CONGRUENT_TO_D", ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D}, + #else + {"MP_EXPONENT_NOT_CONGRUENT_TO_D", 4, 169}, + #endif + #ifdef RSA_R_MP_R_NOT_PRIME + {"MP_R_NOT_PRIME", ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME}, + #else + {"MP_R_NOT_PRIME", 4, 170}, + #endif + #ifdef RSA_R_NO_PUBLIC_EXPONENT + {"NO_PUBLIC_EXPONENT", ERR_LIB_RSA, RSA_R_NO_PUBLIC_EXPONENT}, + #else + {"NO_PUBLIC_EXPONENT", 4, 140}, + #endif + #ifdef RSA_R_NULL_BEFORE_BLOCK_MISSING + {"NULL_BEFORE_BLOCK_MISSING", ERR_LIB_RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING}, + #else + {"NULL_BEFORE_BLOCK_MISSING", 4, 113}, + #endif + #ifdef RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES + {"N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES", ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES}, + #else + {"N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES", 4, 172}, + #endif + #ifdef RSA_R_N_DOES_NOT_EQUAL_P_Q + {"N_DOES_NOT_EQUAL_P_Q", ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q}, + #else + {"N_DOES_NOT_EQUAL_P_Q", 4, 127}, + #endif + #ifdef RSA_R_OAEP_DECODING_ERROR + {"OAEP_DECODING_ERROR", ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR}, + #else + {"OAEP_DECODING_ERROR", 4, 121}, + #endif + #ifdef RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", ERR_LIB_RSA, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE}, + #else + {"OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE", 4, 148}, + #endif + #ifdef RSA_R_PADDING_CHECK_FAILED + {"PADDING_CHECK_FAILED", ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED}, + #else + {"PADDING_CHECK_FAILED", 4, 114}, + #endif + #ifdef RSA_R_PAIRWISE_TEST_FAILURE + {"PAIRWISE_TEST_FAILURE", ERR_LIB_RSA, RSA_R_PAIRWISE_TEST_FAILURE}, + #else + {"PAIRWISE_TEST_FAILURE", 4, 177}, + #endif + #ifdef RSA_R_PKCS_DECODING_ERROR + {"PKCS_DECODING_ERROR", ERR_LIB_RSA, RSA_R_PKCS_DECODING_ERROR}, + #else + {"PKCS_DECODING_ERROR", 4, 159}, + #endif + #ifdef RSA_R_PSS_SALTLEN_TOO_SMALL + {"PSS_SALTLEN_TOO_SMALL", ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL}, + #else + {"PSS_SALTLEN_TOO_SMALL", 4, 164}, + #endif + #ifdef RSA_R_PUB_EXPONENT_OUT_OF_RANGE + {"PUB_EXPONENT_OUT_OF_RANGE", ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE}, + #else + {"PUB_EXPONENT_OUT_OF_RANGE", 4, 178}, + #endif + #ifdef RSA_R_P_NOT_PRIME + {"P_NOT_PRIME", ERR_LIB_RSA, RSA_R_P_NOT_PRIME}, + #else + {"P_NOT_PRIME", 4, 128}, + #endif + #ifdef RSA_R_Q_NOT_PRIME + {"Q_NOT_PRIME", ERR_LIB_RSA, RSA_R_Q_NOT_PRIME}, + #else + {"Q_NOT_PRIME", 4, 129}, + #endif + #ifdef RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", ERR_LIB_RSA, RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT}, + #else + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", 4, 180}, + #endif + #ifdef RSA_R_RSA_OPERATIONS_NOT_SUPPORTED + {"RSA_OPERATIONS_NOT_SUPPORTED", ERR_LIB_RSA, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED}, + #else + {"RSA_OPERATIONS_NOT_SUPPORTED", 4, 130}, + #endif + #ifdef RSA_R_SLEN_CHECK_FAILED + {"SLEN_CHECK_FAILED", ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED}, + #else + {"SLEN_CHECK_FAILED", 4, 136}, + #endif + #ifdef RSA_R_SLEN_RECOVERY_FAILED + {"SLEN_RECOVERY_FAILED", ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED}, + #else + {"SLEN_RECOVERY_FAILED", 4, 135}, + #endif + #ifdef RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD + {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", ERR_LIB_RSA, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD}, + #else + {"THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD", 4, 116}, + #endif + #ifdef RSA_R_UNKNOWN_ALGORITHM_TYPE + {"UNKNOWN_ALGORITHM_TYPE", ERR_LIB_RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE}, + #else + {"UNKNOWN_ALGORITHM_TYPE", 4, 117}, + #endif + #ifdef RSA_R_UNKNOWN_DIGEST + {"UNKNOWN_DIGEST", ERR_LIB_RSA, RSA_R_UNKNOWN_DIGEST}, + #else + {"UNKNOWN_DIGEST", 4, 166}, + #endif + #ifdef RSA_R_UNKNOWN_MASK_DIGEST + {"UNKNOWN_MASK_DIGEST", ERR_LIB_RSA, RSA_R_UNKNOWN_MASK_DIGEST}, + #else + {"UNKNOWN_MASK_DIGEST", 4, 151}, + #endif + #ifdef RSA_R_UNKNOWN_PADDING_TYPE + {"UNKNOWN_PADDING_TYPE", ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE}, + #else + {"UNKNOWN_PADDING_TYPE", 4, 118}, + #endif + #ifdef RSA_R_UNSUPPORTED_ENCRYPTION_TYPE + {"UNSUPPORTED_ENCRYPTION_TYPE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE}, + #else + {"UNSUPPORTED_ENCRYPTION_TYPE", 4, 162}, + #endif + #ifdef RSA_R_UNSUPPORTED_LABEL_SOURCE + {"UNSUPPORTED_LABEL_SOURCE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_LABEL_SOURCE}, + #else + {"UNSUPPORTED_LABEL_SOURCE", 4, 163}, + #endif + #ifdef RSA_R_UNSUPPORTED_MASK_ALGORITHM + {"UNSUPPORTED_MASK_ALGORITHM", ERR_LIB_RSA, RSA_R_UNSUPPORTED_MASK_ALGORITHM}, + #else + {"UNSUPPORTED_MASK_ALGORITHM", 4, 153}, + #endif + #ifdef RSA_R_UNSUPPORTED_MASK_PARAMETER + {"UNSUPPORTED_MASK_PARAMETER", ERR_LIB_RSA, RSA_R_UNSUPPORTED_MASK_PARAMETER}, + #else + {"UNSUPPORTED_MASK_PARAMETER", 4, 154}, + #endif + #ifdef RSA_R_UNSUPPORTED_SIGNATURE_TYPE + {"UNSUPPORTED_SIGNATURE_TYPE", ERR_LIB_RSA, RSA_R_UNSUPPORTED_SIGNATURE_TYPE}, + #else + {"UNSUPPORTED_SIGNATURE_TYPE", 4, 155}, + #endif + #ifdef RSA_R_VALUE_MISSING + {"VALUE_MISSING", ERR_LIB_RSA, RSA_R_VALUE_MISSING}, + #else + {"VALUE_MISSING", 4, 147}, + #endif + #ifdef RSA_R_WRONG_SIGNATURE_LENGTH + {"WRONG_SIGNATURE_LENGTH", ERR_LIB_RSA, RSA_R_WRONG_SIGNATURE_LENGTH}, + #else + {"WRONG_SIGNATURE_LENGTH", 4, 119}, + #endif + #ifdef SM2_R_ASN1_ERROR + {"ASN1_ERROR", ERR_LIB_SM2, SM2_R_ASN1_ERROR}, + #else + {"ASN1_ERROR", 53, 100}, + #endif + #ifdef SM2_R_BAD_SIGNATURE + {"BAD_SIGNATURE", ERR_LIB_SM2, SM2_R_BAD_SIGNATURE}, + #else + {"BAD_SIGNATURE", 53, 101}, + #endif + #ifdef SM2_R_BUFFER_TOO_SMALL + {"BUFFER_TOO_SMALL", ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL}, + #else + {"BUFFER_TOO_SMALL", 53, 107}, + #endif + #ifdef SM2_R_DIST_ID_TOO_LARGE + {"DIST_ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_DIST_ID_TOO_LARGE}, + #else + {"DIST_ID_TOO_LARGE", 53, 110}, + #endif + #ifdef SM2_R_ID_NOT_SET + {"ID_NOT_SET", ERR_LIB_SM2, SM2_R_ID_NOT_SET}, + #else + {"ID_NOT_SET", 53, 112}, + #endif + #ifdef SM2_R_ID_TOO_LARGE + {"ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_ID_TOO_LARGE}, + #else + {"ID_TOO_LARGE", 53, 111}, + #endif + #ifdef SM2_R_INVALID_CURVE + {"INVALID_CURVE", ERR_LIB_SM2, SM2_R_INVALID_CURVE}, + #else + {"INVALID_CURVE", 53, 108}, + #endif + #ifdef SM2_R_INVALID_DIGEST + {"INVALID_DIGEST", ERR_LIB_SM2, SM2_R_INVALID_DIGEST}, + #else + {"INVALID_DIGEST", 53, 102}, + #endif + #ifdef SM2_R_INVALID_DIGEST_TYPE + {"INVALID_DIGEST_TYPE", ERR_LIB_SM2, SM2_R_INVALID_DIGEST_TYPE}, + #else + {"INVALID_DIGEST_TYPE", 53, 103}, + #endif + #ifdef SM2_R_INVALID_ENCODING + {"INVALID_ENCODING", ERR_LIB_SM2, SM2_R_INVALID_ENCODING}, + #else + {"INVALID_ENCODING", 53, 104}, + #endif + #ifdef SM2_R_INVALID_FIELD + {"INVALID_FIELD", ERR_LIB_SM2, SM2_R_INVALID_FIELD}, + #else + {"INVALID_FIELD", 53, 105}, + #endif + #ifdef SM2_R_INVALID_PRIVATE_KEY + {"INVALID_PRIVATE_KEY", ERR_LIB_SM2, SM2_R_INVALID_PRIVATE_KEY}, + #else + {"INVALID_PRIVATE_KEY", 53, 113}, + #endif + #ifdef SM2_R_NO_PARAMETERS_SET + {"NO_PARAMETERS_SET", ERR_LIB_SM2, SM2_R_NO_PARAMETERS_SET}, + #else + {"NO_PARAMETERS_SET", 53, 109}, + #endif + #ifdef SM2_R_USER_ID_TOO_LARGE + {"USER_ID_TOO_LARGE", ERR_LIB_SM2, SM2_R_USER_ID_TOO_LARGE}, + #else + {"USER_ID_TOO_LARGE", 53, 106}, + #endif + #ifdef SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY + {"APPLICATION_DATA_AFTER_CLOSE_NOTIFY", ERR_LIB_SSL, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY}, + #else + {"APPLICATION_DATA_AFTER_CLOSE_NOTIFY", 20, 291}, + #endif + #ifdef SSL_R_APP_DATA_IN_HANDSHAKE + {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, SSL_R_APP_DATA_IN_HANDSHAKE}, + #else + {"APP_DATA_IN_HANDSHAKE", 20, 100}, + #endif + #ifdef SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT + {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT}, + #else + {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", 20, 272}, + #endif + #ifdef SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE + {"AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE}, + #else + {"AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE", 20, 158}, + #endif + #ifdef SSL_R_BAD_CERTIFICATE + {"BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_BAD_CERTIFICATE}, + #else + {"BAD_CERTIFICATE", 20, 348}, + #endif + #ifdef SSL_R_BAD_CHANGE_CIPHER_SPEC + {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC}, + #else + {"BAD_CHANGE_CIPHER_SPEC", 20, 103}, + #endif + #ifdef SSL_R_BAD_CIPHER + {"BAD_CIPHER", ERR_LIB_SSL, SSL_R_BAD_CIPHER}, + #else + {"BAD_CIPHER", 20, 186}, + #endif + #ifdef SSL_R_BAD_COMPRESSION_ALGORITHM + {"BAD_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_BAD_COMPRESSION_ALGORITHM}, + #else + {"BAD_COMPRESSION_ALGORITHM", 20, 326}, + #endif + #ifdef SSL_R_BAD_DATA + {"BAD_DATA", ERR_LIB_SSL, SSL_R_BAD_DATA}, + #else + {"BAD_DATA", 20, 390}, + #endif + #ifdef SSL_R_BAD_DATA_RETURNED_BY_CALLBACK + {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK}, + #else + {"BAD_DATA_RETURNED_BY_CALLBACK", 20, 106}, + #endif + #ifdef SSL_R_BAD_DECOMPRESSION + {"BAD_DECOMPRESSION", ERR_LIB_SSL, SSL_R_BAD_DECOMPRESSION}, + #else + {"BAD_DECOMPRESSION", 20, 107}, + #endif + #ifdef SSL_R_BAD_DH_VALUE + {"BAD_DH_VALUE", ERR_LIB_SSL, SSL_R_BAD_DH_VALUE}, + #else + {"BAD_DH_VALUE", 20, 102}, + #endif + #ifdef SSL_R_BAD_DIGEST_LENGTH + {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DIGEST_LENGTH}, + #else + {"BAD_DIGEST_LENGTH", 20, 111}, + #endif + #ifdef SSL_R_BAD_EARLY_DATA + {"BAD_EARLY_DATA", ERR_LIB_SSL, SSL_R_BAD_EARLY_DATA}, + #else + {"BAD_EARLY_DATA", 20, 233}, + #endif + #ifdef SSL_R_BAD_ECC_CERT + {"BAD_ECC_CERT", ERR_LIB_SSL, SSL_R_BAD_ECC_CERT}, + #else + {"BAD_ECC_CERT", 20, 304}, + #endif + #ifdef SSL_R_BAD_ECHCONFIG_EXTENSION + {"BAD_ECHCONFIG_EXTENSION", ERR_LIB_SSL, SSL_R_BAD_ECHCONFIG_EXTENSION}, + #else + {"BAD_ECHCONFIG_EXTENSION", 20, 425}, + #endif + #ifdef SSL_R_BAD_ECPOINT + {"BAD_ECPOINT", ERR_LIB_SSL, SSL_R_BAD_ECPOINT}, + #else + {"BAD_ECPOINT", 20, 306}, + #endif + #ifdef SSL_R_BAD_EXTENSION + {"BAD_EXTENSION", ERR_LIB_SSL, SSL_R_BAD_EXTENSION}, + #else + {"BAD_EXTENSION", 20, 110}, + #endif + #ifdef SSL_R_BAD_HANDSHAKE_LENGTH + {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_LENGTH}, + #else + {"BAD_HANDSHAKE_LENGTH", 20, 332}, + #endif + #ifdef SSL_R_BAD_HANDSHAKE_STATE + {"BAD_HANDSHAKE_STATE", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_STATE}, + #else + {"BAD_HANDSHAKE_STATE", 20, 236}, + #endif + #ifdef SSL_R_BAD_HELLO_REQUEST + {"BAD_HELLO_REQUEST", ERR_LIB_SSL, SSL_R_BAD_HELLO_REQUEST}, + #else + {"BAD_HELLO_REQUEST", 20, 105}, + #endif + #ifdef SSL_R_BAD_HRR_VERSION + {"BAD_HRR_VERSION", ERR_LIB_SSL, SSL_R_BAD_HRR_VERSION}, + #else + {"BAD_HRR_VERSION", 20, 263}, + #endif + #ifdef SSL_R_BAD_KEY_SHARE + {"BAD_KEY_SHARE", ERR_LIB_SSL, SSL_R_BAD_KEY_SHARE}, + #else + {"BAD_KEY_SHARE", 20, 108}, + #endif + #ifdef SSL_R_BAD_KEY_UPDATE + {"BAD_KEY_UPDATE", ERR_LIB_SSL, SSL_R_BAD_KEY_UPDATE}, + #else + {"BAD_KEY_UPDATE", 20, 122}, + #endif + #ifdef SSL_R_BAD_LEGACY_VERSION + {"BAD_LEGACY_VERSION", ERR_LIB_SSL, SSL_R_BAD_LEGACY_VERSION}, + #else + {"BAD_LEGACY_VERSION", 20, 292}, + #endif + #ifdef SSL_R_BAD_LENGTH + {"BAD_LENGTH", ERR_LIB_SSL, SSL_R_BAD_LENGTH}, + #else + {"BAD_LENGTH", 20, 271}, + #endif + #ifdef SSL_R_BAD_PACKET + {"BAD_PACKET", ERR_LIB_SSL, SSL_R_BAD_PACKET}, + #else + {"BAD_PACKET", 20, 240}, + #endif + #ifdef SSL_R_BAD_PACKET_LENGTH + {"BAD_PACKET_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PACKET_LENGTH}, + #else + {"BAD_PACKET_LENGTH", 20, 115}, + #endif + #ifdef SSL_R_BAD_PROTOCOL_VERSION_NUMBER + {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER}, + #else + {"BAD_PROTOCOL_VERSION_NUMBER", 20, 116}, + #endif + #ifdef SSL_R_BAD_PSK + {"BAD_PSK", ERR_LIB_SSL, SSL_R_BAD_PSK}, + #else + {"BAD_PSK", 20, 219}, + #endif + #ifdef SSL_R_BAD_PSK_IDENTITY + {"BAD_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_BAD_PSK_IDENTITY}, + #else + {"BAD_PSK_IDENTITY", 20, 114}, + #endif + #ifdef SSL_R_BAD_RECORD_TYPE + {"BAD_RECORD_TYPE", ERR_LIB_SSL, SSL_R_BAD_RECORD_TYPE}, + #else + {"BAD_RECORD_TYPE", 20, 443}, + #endif + #ifdef SSL_R_BAD_RSA_ENCRYPT + {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_ENCRYPT}, + #else + {"BAD_RSA_ENCRYPT", 20, 119}, + #endif + #ifdef SSL_R_BAD_SIGNATURE + {"BAD_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_SIGNATURE}, + #else + {"BAD_SIGNATURE", 20, 123}, + #endif + #ifdef SSL_R_BAD_SRP_A_LENGTH + {"BAD_SRP_A_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_A_LENGTH}, + #else + {"BAD_SRP_A_LENGTH", 20, 347}, + #endif + #ifdef SSL_R_BAD_SRP_PARAMETERS + {"BAD_SRP_PARAMETERS", ERR_LIB_SSL, SSL_R_BAD_SRP_PARAMETERS}, + #else + {"BAD_SRP_PARAMETERS", 20, 371}, + #endif + #ifdef SSL_R_BAD_SRTP_MKI_VALUE + {"BAD_SRTP_MKI_VALUE", ERR_LIB_SSL, SSL_R_BAD_SRTP_MKI_VALUE}, + #else + {"BAD_SRTP_MKI_VALUE", 20, 352}, + #endif + #ifdef SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST + {"BAD_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST}, + #else + {"BAD_SRTP_PROTECTION_PROFILE_LIST", 20, 353}, + #endif + #ifdef SSL_R_BAD_SSL_FILETYPE + {"BAD_SSL_FILETYPE", ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE}, + #else + {"BAD_SSL_FILETYPE", 20, 124}, + #endif + #ifdef SSL_R_BAD_VALUE + {"BAD_VALUE", ERR_LIB_SSL, SSL_R_BAD_VALUE}, + #else + {"BAD_VALUE", 20, 384}, + #endif + #ifdef SSL_R_BAD_WRITE_RETRY + {"BAD_WRITE_RETRY", ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY}, + #else + {"BAD_WRITE_RETRY", 20, 127}, + #endif + #ifdef SSL_R_BINDER_DOES_NOT_VERIFY + {"BINDER_DOES_NOT_VERIFY", ERR_LIB_SSL, SSL_R_BINDER_DOES_NOT_VERIFY}, + #else + {"BINDER_DOES_NOT_VERIFY", 20, 253}, + #endif + #ifdef SSL_R_BIO_NOT_SET + {"BIO_NOT_SET", ERR_LIB_SSL, SSL_R_BIO_NOT_SET}, + #else + {"BIO_NOT_SET", 20, 128}, + #endif + #ifdef SSL_R_BLOCK_CIPHER_PAD_IS_WRONG + {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG}, + #else + {"BLOCK_CIPHER_PAD_IS_WRONG", 20, 129}, + #endif + #ifdef SSL_R_BN_LIB + {"BN_LIB", ERR_LIB_SSL, SSL_R_BN_LIB}, + #else + {"BN_LIB", 20, 130}, + #endif + #ifdef SSL_R_CALLBACK_FAILED + {"CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_CALLBACK_FAILED}, + #else + {"CALLBACK_FAILED", 20, 234}, + #endif + #ifdef SSL_R_CANNOT_CHANGE_CIPHER + {"CANNOT_CHANGE_CIPHER", ERR_LIB_SSL, SSL_R_CANNOT_CHANGE_CIPHER}, + #else + {"CANNOT_CHANGE_CIPHER", 20, 109}, + #endif + #ifdef SSL_R_CANNOT_GET_GROUP_NAME + {"CANNOT_GET_GROUP_NAME", ERR_LIB_SSL, SSL_R_CANNOT_GET_GROUP_NAME}, + #else + {"CANNOT_GET_GROUP_NAME", 20, 299}, + #endif + #ifdef SSL_R_CA_DN_LENGTH_MISMATCH + {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CA_DN_LENGTH_MISMATCH}, + #else + {"CA_DN_LENGTH_MISMATCH", 20, 131}, + #endif + #ifdef SSL_R_CA_KEY_TOO_SMALL + {"CA_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_CA_KEY_TOO_SMALL}, + #else + {"CA_KEY_TOO_SMALL", 20, 397}, + #endif + #ifdef SSL_R_CA_MD_TOO_WEAK + {"CA_MD_TOO_WEAK", ERR_LIB_SSL, SSL_R_CA_MD_TOO_WEAK}, + #else + {"CA_MD_TOO_WEAK", 20, 398}, + #endif + #ifdef SSL_R_CCS_RECEIVED_EARLY + {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY}, + #else + {"CCS_RECEIVED_EARLY", 20, 133}, + #endif + #ifdef SSL_R_CERTIFICATE_VERIFY_FAILED + {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED}, + #else + {"CERTIFICATE_VERIFY_FAILED", 20, 134}, + #endif + #ifdef SSL_R_CERT_CB_ERROR + {"CERT_CB_ERROR", ERR_LIB_SSL, SSL_R_CERT_CB_ERROR}, + #else + {"CERT_CB_ERROR", 20, 377}, + #endif + #ifdef SSL_R_CERT_LENGTH_MISMATCH + {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CERT_LENGTH_MISMATCH}, + #else + {"CERT_LENGTH_MISMATCH", 20, 135}, + #endif + #ifdef SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED + {"CIPHERSUITE_DIGEST_HAS_CHANGED", ERR_LIB_SSL, SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED}, + #else + {"CIPHERSUITE_DIGEST_HAS_CHANGED", 20, 218}, + #endif + #ifdef SSL_R_CIPHER_CODE_WRONG_LENGTH + {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, SSL_R_CIPHER_CODE_WRONG_LENGTH}, + #else + {"CIPHER_CODE_WRONG_LENGTH", 20, 137}, + #endif + #ifdef SSL_R_CLIENTHELLO_TLSEXT + {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_CLIENTHELLO_TLSEXT}, + #else + {"CLIENTHELLO_TLSEXT", 20, 226}, + #endif + #ifdef SSL_R_COMPRESSED_LENGTH_TOO_LONG + {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_COMPRESSED_LENGTH_TOO_LONG}, + #else + {"COMPRESSED_LENGTH_TOO_LONG", 20, 140}, + #endif + #ifdef SSL_R_COMPRESSION_DISABLED + {"COMPRESSION_DISABLED", ERR_LIB_SSL, SSL_R_COMPRESSION_DISABLED}, + #else + {"COMPRESSION_DISABLED", 20, 343}, + #endif + #ifdef SSL_R_COMPRESSION_FAILURE + {"COMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_COMPRESSION_FAILURE}, + #else + {"COMPRESSION_FAILURE", 20, 141}, + #endif + #ifdef SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE + {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE}, + #else + {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", 20, 307}, + #endif + #ifdef SSL_R_COMPRESSION_LIBRARY_ERROR + {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR}, + #else + {"COMPRESSION_LIBRARY_ERROR", 20, 142}, + #endif + #ifdef SSL_R_CONNECTION_TYPE_NOT_SET + {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, SSL_R_CONNECTION_TYPE_NOT_SET}, + #else + {"CONNECTION_TYPE_NOT_SET", 20, 144}, + #endif + #ifdef SSL_R_CONN_USE_ONLY + {"CONN_USE_ONLY", ERR_LIB_SSL, SSL_R_CONN_USE_ONLY}, + #else + {"CONN_USE_ONLY", 20, 356}, + #endif + #ifdef SSL_R_CONTEXT_NOT_DANE_ENABLED + {"CONTEXT_NOT_DANE_ENABLED", ERR_LIB_SSL, SSL_R_CONTEXT_NOT_DANE_ENABLED}, + #else + {"CONTEXT_NOT_DANE_ENABLED", 20, 167}, + #endif + #ifdef SSL_R_COOKIE_GEN_CALLBACK_FAILURE + {"COOKIE_GEN_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_COOKIE_GEN_CALLBACK_FAILURE}, + #else + {"COOKIE_GEN_CALLBACK_FAILURE", 20, 400}, + #endif + #ifdef SSL_R_COOKIE_MISMATCH + {"COOKIE_MISMATCH", ERR_LIB_SSL, SSL_R_COOKIE_MISMATCH}, + #else + {"COOKIE_MISMATCH", 20, 308}, + #endif + #ifdef SSL_R_COPY_PARAMETERS_FAILED + {"COPY_PARAMETERS_FAILED", ERR_LIB_SSL, SSL_R_COPY_PARAMETERS_FAILED}, + #else + {"COPY_PARAMETERS_FAILED", 20, 296}, + #endif + #ifdef SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED + {"CUSTOM_EXT_HANDLER_ALREADY_INSTALLED", ERR_LIB_SSL, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED}, + #else + {"CUSTOM_EXT_HANDLER_ALREADY_INSTALLED", 20, 206}, + #endif + #ifdef SSL_R_DANE_ALREADY_ENABLED + {"DANE_ALREADY_ENABLED", ERR_LIB_SSL, SSL_R_DANE_ALREADY_ENABLED}, + #else + {"DANE_ALREADY_ENABLED", 20, 172}, + #endif + #ifdef SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL + {"DANE_CANNOT_OVERRIDE_MTYPE_FULL", ERR_LIB_SSL, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL}, + #else + {"DANE_CANNOT_OVERRIDE_MTYPE_FULL", 20, 173}, + #endif + #ifdef SSL_R_DANE_NOT_ENABLED + {"DANE_NOT_ENABLED", ERR_LIB_SSL, SSL_R_DANE_NOT_ENABLED}, + #else + {"DANE_NOT_ENABLED", 20, 175}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_CERTIFICATE + {"DANE_TLSA_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE}, + #else + {"DANE_TLSA_BAD_CERTIFICATE", 20, 180}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE + {"DANE_TLSA_BAD_CERTIFICATE_USAGE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE}, + #else + {"DANE_TLSA_BAD_CERTIFICATE_USAGE", 20, 184}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_DATA_LENGTH + {"DANE_TLSA_BAD_DATA_LENGTH", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DATA_LENGTH}, + #else + {"DANE_TLSA_BAD_DATA_LENGTH", 20, 189}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH + {"DANE_TLSA_BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH}, + #else + {"DANE_TLSA_BAD_DIGEST_LENGTH", 20, 192}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_MATCHING_TYPE + {"DANE_TLSA_BAD_MATCHING_TYPE", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE}, + #else + {"DANE_TLSA_BAD_MATCHING_TYPE", 20, 200}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_PUBLIC_KEY + {"DANE_TLSA_BAD_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY}, + #else + {"DANE_TLSA_BAD_PUBLIC_KEY", 20, 201}, + #endif + #ifdef SSL_R_DANE_TLSA_BAD_SELECTOR + {"DANE_TLSA_BAD_SELECTOR", ERR_LIB_SSL, SSL_R_DANE_TLSA_BAD_SELECTOR}, + #else + {"DANE_TLSA_BAD_SELECTOR", 20, 202}, + #endif + #ifdef SSL_R_DANE_TLSA_NULL_DATA + {"DANE_TLSA_NULL_DATA", ERR_LIB_SSL, SSL_R_DANE_TLSA_NULL_DATA}, + #else + {"DANE_TLSA_NULL_DATA", 20, 203}, + #endif + #ifdef SSL_R_DATA_BETWEEN_CCS_AND_FINISHED + {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED}, + #else + {"DATA_BETWEEN_CCS_AND_FINISHED", 20, 145}, + #endif + #ifdef SSL_R_DATA_LENGTH_TOO_LONG + {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG}, + #else + {"DATA_LENGTH_TOO_LONG", 20, 146}, + #endif + #ifdef SSL_R_DECRYPTION_FAILED + {"DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED}, + #else + {"DECRYPTION_FAILED", 20, 147}, + #endif + #ifdef SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC + {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC}, + #else + {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", 20, 281}, + #endif + #ifdef SSL_R_DH_KEY_TOO_SMALL + {"DH_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL}, + #else + {"DH_KEY_TOO_SMALL", 20, 394}, + #endif + #ifdef SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG + {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG}, + #else + {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", 20, 148}, + #endif + #ifdef SSL_R_DIGEST_CHECK_FAILED + {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, SSL_R_DIGEST_CHECK_FAILED}, + #else + {"DIGEST_CHECK_FAILED", 20, 149}, + #endif + #ifdef SSL_R_DOMAIN_USE_ONLY + {"DOMAIN_USE_ONLY", ERR_LIB_SSL, SSL_R_DOMAIN_USE_ONLY}, + #else + {"DOMAIN_USE_ONLY", 20, 422}, + #endif + #ifdef SSL_R_DTLS_MESSAGE_TOO_BIG + {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, SSL_R_DTLS_MESSAGE_TOO_BIG}, + #else + {"DTLS_MESSAGE_TOO_BIG", 20, 334}, + #endif + #ifdef SSL_R_DUPLICATE_COMPRESSION_ID + {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID}, + #else + {"DUPLICATE_COMPRESSION_ID", 20, 309}, + #endif + #ifdef SSL_R_ECC_CERT_NOT_FOR_SIGNING + {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING}, + #else + {"ECC_CERT_NOT_FOR_SIGNING", 20, 318}, + #endif + #ifdef SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE + {"ECDH_REQUIRED_FOR_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE}, + #else + {"ECDH_REQUIRED_FOR_SUITEB_MODE", 20, 374}, + #endif + #ifdef SSL_R_ECH_DECODE_ERROR + {"ECH_DECODE_ERROR", ERR_LIB_SSL, SSL_R_ECH_DECODE_ERROR}, + #else + {"ECH_DECODE_ERROR", 20, 426}, + #endif + #ifdef SSL_R_ECH_REQUIRED + {"ECH_REQUIRED", ERR_LIB_SSL, SSL_R_ECH_REQUIRED}, + #else + {"ECH_REQUIRED", 20, 424}, + #endif + #ifdef SSL_R_EE_KEY_TOO_SMALL + {"EE_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_EE_KEY_TOO_SMALL}, + #else + {"EE_KEY_TOO_SMALL", 20, 399}, + #endif + #ifdef SSL_R_EMPTY_RAW_PUBLIC_KEY + {"EMPTY_RAW_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_EMPTY_RAW_PUBLIC_KEY}, + #else + {"EMPTY_RAW_PUBLIC_KEY", 20, 349}, + #endif + #ifdef SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST + {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST}, + #else + {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", 20, 354}, + #endif + #ifdef SSL_R_ENCRYPTED_LENGTH_TOO_LONG + {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG}, + #else + {"ENCRYPTED_LENGTH_TOO_LONG", 20, 150}, + #endif + #ifdef SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST + {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST}, + #else + {"ERROR_IN_RECEIVED_CIPHER_LIST", 20, 151}, + #endif + #ifdef SSL_R_ERROR_IN_SYSTEM_DEFAULT_CONFIG + {"ERROR_IN_SYSTEM_DEFAULT_CONFIG", ERR_LIB_SSL, SSL_R_ERROR_IN_SYSTEM_DEFAULT_CONFIG}, + #else + {"ERROR_IN_SYSTEM_DEFAULT_CONFIG", 20, 419}, + #endif + #ifdef SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN + {"ERROR_SETTING_TLSA_BASE_DOMAIN", ERR_LIB_SSL, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN}, + #else + {"ERROR_SETTING_TLSA_BASE_DOMAIN", 20, 204}, + #endif + #ifdef SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE + {"EXCEEDS_MAX_FRAGMENT_SIZE", ERR_LIB_SSL, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE}, + #else + {"EXCEEDS_MAX_FRAGMENT_SIZE", 20, 194}, + #endif + #ifdef SSL_R_EXCESSIVE_MESSAGE_SIZE + {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE}, + #else + {"EXCESSIVE_MESSAGE_SIZE", 20, 152}, + #endif + #ifdef SSL_R_EXTENSION_NOT_RECEIVED + {"EXTENSION_NOT_RECEIVED", ERR_LIB_SSL, SSL_R_EXTENSION_NOT_RECEIVED}, + #else + {"EXTENSION_NOT_RECEIVED", 20, 279}, + #endif + #ifdef SSL_R_EXTRA_DATA_IN_MESSAGE + {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, SSL_R_EXTRA_DATA_IN_MESSAGE}, + #else + {"EXTRA_DATA_IN_MESSAGE", 20, 153}, + #endif + #ifdef SSL_R_EXT_LENGTH_MISMATCH + {"EXT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_EXT_LENGTH_MISMATCH}, + #else + {"EXT_LENGTH_MISMATCH", 20, 163}, + #endif + #ifdef SSL_R_FAILED_TO_GET_PARAMETER + {"FAILED_TO_GET_PARAMETER", ERR_LIB_SSL, SSL_R_FAILED_TO_GET_PARAMETER}, + #else + {"FAILED_TO_GET_PARAMETER", 20, 316}, + #endif + #ifdef SSL_R_FAILED_TO_INIT_ASYNC + {"FAILED_TO_INIT_ASYNC", ERR_LIB_SSL, SSL_R_FAILED_TO_INIT_ASYNC}, + #else + {"FAILED_TO_INIT_ASYNC", 20, 405}, + #endif + #ifdef SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE + {"FEATURE_NEGOTIATION_NOT_COMPLETE", ERR_LIB_SSL, SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE}, + #else + {"FEATURE_NEGOTIATION_NOT_COMPLETE", 20, 417}, + #endif + #ifdef SSL_R_FEATURE_NOT_RENEGOTIABLE + {"FEATURE_NOT_RENEGOTIABLE", ERR_LIB_SSL, SSL_R_FEATURE_NOT_RENEGOTIABLE}, + #else + {"FEATURE_NOT_RENEGOTIABLE", 20, 413}, + #endif + #ifdef SSL_R_FRAGMENTED_CLIENT_HELLO + {"FRAGMENTED_CLIENT_HELLO", ERR_LIB_SSL, SSL_R_FRAGMENTED_CLIENT_HELLO}, + #else + {"FRAGMENTED_CLIENT_HELLO", 20, 401}, + #endif + #ifdef SSL_R_GOT_A_FIN_BEFORE_A_CCS + {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS}, + #else + {"GOT_A_FIN_BEFORE_A_CCS", 20, 154}, + #endif + #ifdef SSL_R_HTTPS_PROXY_REQUEST + {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, SSL_R_HTTPS_PROXY_REQUEST}, + #else + {"HTTPS_PROXY_REQUEST", 20, 155}, + #endif + #ifdef SSL_R_HTTP_REQUEST + {"HTTP_REQUEST", ERR_LIB_SSL, SSL_R_HTTP_REQUEST}, + #else + {"HTTP_REQUEST", 20, 156}, + #endif + #ifdef SSL_R_ILLEGAL_POINT_COMPRESSION + {"ILLEGAL_POINT_COMPRESSION", ERR_LIB_SSL, SSL_R_ILLEGAL_POINT_COMPRESSION}, + #else + {"ILLEGAL_POINT_COMPRESSION", 20, 162}, + #endif + #ifdef SSL_R_ILLEGAL_SUITEB_DIGEST + {"ILLEGAL_SUITEB_DIGEST", ERR_LIB_SSL, SSL_R_ILLEGAL_SUITEB_DIGEST}, + #else + {"ILLEGAL_SUITEB_DIGEST", 20, 380}, + #endif + #ifdef SSL_R_INAPPROPRIATE_FALLBACK + {"INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_INAPPROPRIATE_FALLBACK}, + #else + {"INAPPROPRIATE_FALLBACK", 20, 373}, + #endif + #ifdef SSL_R_INCONSISTENT_COMPRESSION + {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, SSL_R_INCONSISTENT_COMPRESSION}, + #else + {"INCONSISTENT_COMPRESSION", 20, 340}, + #endif + #ifdef SSL_R_INCONSISTENT_EARLY_DATA_ALPN + {"INCONSISTENT_EARLY_DATA_ALPN", ERR_LIB_SSL, SSL_R_INCONSISTENT_EARLY_DATA_ALPN}, + #else + {"INCONSISTENT_EARLY_DATA_ALPN", 20, 222}, + #endif + #ifdef SSL_R_INCONSISTENT_EARLY_DATA_SNI + {"INCONSISTENT_EARLY_DATA_SNI", ERR_LIB_SSL, SSL_R_INCONSISTENT_EARLY_DATA_SNI}, + #else + {"INCONSISTENT_EARLY_DATA_SNI", 20, 231}, + #endif + #ifdef SSL_R_INCONSISTENT_EXTMS + {"INCONSISTENT_EXTMS", ERR_LIB_SSL, SSL_R_INCONSISTENT_EXTMS}, + #else + {"INCONSISTENT_EXTMS", 20, 104}, + #endif + #ifdef SSL_R_INSUFFICIENT_SECURITY + {"INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_INSUFFICIENT_SECURITY}, + #else + {"INSUFFICIENT_SECURITY", 20, 241}, + #endif + #ifdef SSL_R_INVALID_ALERT + {"INVALID_ALERT", ERR_LIB_SSL, SSL_R_INVALID_ALERT}, + #else + {"INVALID_ALERT", 20, 205}, + #endif + #ifdef SSL_R_INVALID_CCS_MESSAGE + {"INVALID_CCS_MESSAGE", ERR_LIB_SSL, SSL_R_INVALID_CCS_MESSAGE}, + #else + {"INVALID_CCS_MESSAGE", 20, 260}, + #endif + #ifdef SSL_R_INVALID_CERTIFICATE_OR_ALG + {"INVALID_CERTIFICATE_OR_ALG", ERR_LIB_SSL, SSL_R_INVALID_CERTIFICATE_OR_ALG}, + #else + {"INVALID_CERTIFICATE_OR_ALG", 20, 238}, + #endif + #ifdef SSL_R_INVALID_COMMAND + {"INVALID_COMMAND", ERR_LIB_SSL, SSL_R_INVALID_COMMAND}, + #else + {"INVALID_COMMAND", 20, 280}, + #endif + #ifdef SSL_R_INVALID_COMPRESSION_ALGORITHM + {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_INVALID_COMPRESSION_ALGORITHM}, + #else + {"INVALID_COMPRESSION_ALGORITHM", 20, 341}, + #endif + #ifdef SSL_R_INVALID_CONFIG + {"INVALID_CONFIG", ERR_LIB_SSL, SSL_R_INVALID_CONFIG}, + #else + {"INVALID_CONFIG", 20, 283}, + #endif + #ifdef SSL_R_INVALID_CONFIGURATION_NAME + {"INVALID_CONFIGURATION_NAME", ERR_LIB_SSL, SSL_R_INVALID_CONFIGURATION_NAME}, + #else + {"INVALID_CONFIGURATION_NAME", 20, 113}, + #endif + #ifdef SSL_R_INVALID_CONTEXT + {"INVALID_CONTEXT", ERR_LIB_SSL, SSL_R_INVALID_CONTEXT}, + #else + {"INVALID_CONTEXT", 20, 282}, + #endif + #ifdef SSL_R_INVALID_CT_VALIDATION_TYPE + {"INVALID_CT_VALIDATION_TYPE", ERR_LIB_SSL, SSL_R_INVALID_CT_VALIDATION_TYPE}, + #else + {"INVALID_CT_VALIDATION_TYPE", 20, 212}, + #endif + #ifdef SSL_R_INVALID_KEY_UPDATE_TYPE + {"INVALID_KEY_UPDATE_TYPE", ERR_LIB_SSL, SSL_R_INVALID_KEY_UPDATE_TYPE}, + #else + {"INVALID_KEY_UPDATE_TYPE", 20, 120}, + #endif + #ifdef SSL_R_INVALID_MAX_EARLY_DATA + {"INVALID_MAX_EARLY_DATA", ERR_LIB_SSL, SSL_R_INVALID_MAX_EARLY_DATA}, + #else + {"INVALID_MAX_EARLY_DATA", 20, 174}, + #endif + #ifdef SSL_R_INVALID_NULL_CMD_NAME + {"INVALID_NULL_CMD_NAME", ERR_LIB_SSL, SSL_R_INVALID_NULL_CMD_NAME}, + #else + {"INVALID_NULL_CMD_NAME", 20, 385}, + #endif + #ifdef SSL_R_INVALID_RAW_PUBLIC_KEY + {"INVALID_RAW_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_INVALID_RAW_PUBLIC_KEY}, + #else + {"INVALID_RAW_PUBLIC_KEY", 20, 350}, + #endif + #ifdef SSL_R_INVALID_RECORD + {"INVALID_RECORD", ERR_LIB_SSL, SSL_R_INVALID_RECORD}, + #else + {"INVALID_RECORD", 20, 317}, + #endif + #ifdef SSL_R_INVALID_SEQUENCE_NUMBER + {"INVALID_SEQUENCE_NUMBER", ERR_LIB_SSL, SSL_R_INVALID_SEQUENCE_NUMBER}, + #else + {"INVALID_SEQUENCE_NUMBER", 20, 402}, + #endif + #ifdef SSL_R_INVALID_SERVERINFO_DATA + {"INVALID_SERVERINFO_DATA", ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA}, + #else + {"INVALID_SERVERINFO_DATA", 20, 388}, + #endif + #ifdef SSL_R_INVALID_SESSION_ID + {"INVALID_SESSION_ID", ERR_LIB_SSL, SSL_R_INVALID_SESSION_ID}, + #else + {"INVALID_SESSION_ID", 20, 999}, + #endif + #ifdef SSL_R_INVALID_SRP_USERNAME + {"INVALID_SRP_USERNAME", ERR_LIB_SSL, SSL_R_INVALID_SRP_USERNAME}, + #else + {"INVALID_SRP_USERNAME", 20, 357}, + #endif + #ifdef SSL_R_INVALID_STATUS_RESPONSE + {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_INVALID_STATUS_RESPONSE}, + #else + {"INVALID_STATUS_RESPONSE", 20, 328}, + #endif + #ifdef SSL_R_INVALID_TICKET_KEYS_LENGTH + {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH}, + #else + {"INVALID_TICKET_KEYS_LENGTH", 20, 325}, + #endif + #ifdef SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", ERR_LIB_SSL, SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED}, + #else + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", 20, 333}, + #endif + #ifdef SSL_R_LENGTH_MISMATCH + {"LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH}, + #else + {"LENGTH_MISMATCH", 20, 159}, + #endif + #ifdef SSL_R_LENGTH_TOO_LONG + {"LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_LENGTH_TOO_LONG}, + #else + {"LENGTH_TOO_LONG", 20, 404}, + #endif + #ifdef SSL_R_LENGTH_TOO_SHORT + {"LENGTH_TOO_SHORT", ERR_LIB_SSL, SSL_R_LENGTH_TOO_SHORT}, + #else + {"LENGTH_TOO_SHORT", 20, 160}, + #endif + #ifdef SSL_R_LIBRARY_BUG + {"LIBRARY_BUG", ERR_LIB_SSL, SSL_R_LIBRARY_BUG}, + #else + {"LIBRARY_BUG", 20, 274}, + #endif + #ifdef SSL_R_LIBRARY_HAS_NO_CIPHERS + {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS}, + #else + {"LIBRARY_HAS_NO_CIPHERS", 20, 161}, + #endif + #ifdef SSL_R_LISTENER_USE_ONLY + {"LISTENER_USE_ONLY", ERR_LIB_SSL, SSL_R_LISTENER_USE_ONLY}, + #else + {"LISTENER_USE_ONLY", 20, 421}, + #endif + #ifdef SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED + {"MAXIMUM_ENCRYPTED_PKTS_REACHED", ERR_LIB_SSL, SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED}, + #else + {"MAXIMUM_ENCRYPTED_PKTS_REACHED", 20, 395}, + #endif + #ifdef SSL_R_MISSING_DSA_SIGNING_CERT + {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_DSA_SIGNING_CERT}, + #else + {"MISSING_DSA_SIGNING_CERT", 20, 165}, + #endif + #ifdef SSL_R_MISSING_ECDSA_SIGNING_CERT + {"MISSING_ECDSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_ECDSA_SIGNING_CERT}, + #else + {"MISSING_ECDSA_SIGNING_CERT", 20, 381}, + #endif + #ifdef SSL_R_MISSING_FATAL + {"MISSING_FATAL", ERR_LIB_SSL, SSL_R_MISSING_FATAL}, + #else + {"MISSING_FATAL", 20, 256}, + #endif + #ifdef SSL_R_MISSING_PARAMETERS + {"MISSING_PARAMETERS", ERR_LIB_SSL, SSL_R_MISSING_PARAMETERS}, + #else + {"MISSING_PARAMETERS", 20, 290}, + #endif + #ifdef SSL_R_MISSING_PSK_KEX_MODES_EXTENSION + {"MISSING_PSK_KEX_MODES_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_PSK_KEX_MODES_EXTENSION}, + #else + {"MISSING_PSK_KEX_MODES_EXTENSION", 20, 310}, + #endif + #ifdef SSL_R_MISSING_QUIC_TLS_FUNCTIONS + {"MISSING_QUIC_TLS_FUNCTIONS", ERR_LIB_SSL, SSL_R_MISSING_QUIC_TLS_FUNCTIONS}, + #else + {"MISSING_QUIC_TLS_FUNCTIONS", 20, 423}, + #endif + #ifdef SSL_R_MISSING_RSA_CERTIFICATE + {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, + #else + {"MISSING_RSA_CERTIFICATE", 20, 168}, + #endif + #ifdef SSL_R_MISSING_RSA_ENCRYPTING_CERT + {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_ENCRYPTING_CERT}, + #else + {"MISSING_RSA_ENCRYPTING_CERT", 20, 169}, + #endif + #ifdef SSL_R_MISSING_RSA_SIGNING_CERT + {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_SIGNING_CERT}, + #else + {"MISSING_RSA_SIGNING_CERT", 20, 170}, + #endif + #ifdef SSL_R_MISSING_SIGALGS_EXTENSION + {"MISSING_SIGALGS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SIGALGS_EXTENSION}, + #else + {"MISSING_SIGALGS_EXTENSION", 20, 112}, + #endif + #ifdef SSL_R_MISSING_SIGNING_CERT + {"MISSING_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_SIGNING_CERT}, + #else + {"MISSING_SIGNING_CERT", 20, 221}, + #endif + #ifdef SSL_R_MISSING_SRP_PARAM + {"MISSING_SRP_PARAM", ERR_LIB_SSL, SSL_R_MISSING_SRP_PARAM}, + #else + {"MISSING_SRP_PARAM", 20, 358}, + #endif + #ifdef SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION + {"MISSING_SUPPORTED_GROUPS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION}, + #else + {"MISSING_SUPPORTED_GROUPS_EXTENSION", 20, 209}, + #endif + #ifdef SSL_R_MISSING_SUPPORTED_VERSIONS_EXTENSION + {"MISSING_SUPPORTED_VERSIONS_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_SUPPORTED_VERSIONS_EXTENSION}, + #else + {"MISSING_SUPPORTED_VERSIONS_EXTENSION", 20, 420}, + #endif + #ifdef SSL_R_MISSING_TMP_DH_KEY + {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_DH_KEY}, + #else + {"MISSING_TMP_DH_KEY", 20, 171}, + #endif + #ifdef SSL_R_MISSING_TMP_ECDH_KEY + {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_ECDH_KEY}, + #else + {"MISSING_TMP_ECDH_KEY", 20, 311}, + #endif + #ifdef SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA + {"MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA", ERR_LIB_SSL, SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA}, + #else + {"MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA", 20, 293}, + #endif + #ifdef SSL_R_NOT_ON_RECORD_BOUNDARY + {"NOT_ON_RECORD_BOUNDARY", ERR_LIB_SSL, SSL_R_NOT_ON_RECORD_BOUNDARY}, + #else + {"NOT_ON_RECORD_BOUNDARY", 20, 182}, + #endif + #ifdef SSL_R_NOT_REPLACING_CERTIFICATE + {"NOT_REPLACING_CERTIFICATE", ERR_LIB_SSL, SSL_R_NOT_REPLACING_CERTIFICATE}, + #else + {"NOT_REPLACING_CERTIFICATE", 20, 289}, + #endif + #ifdef SSL_R_NOT_SERVER + {"NOT_SERVER", ERR_LIB_SSL, SSL_R_NOT_SERVER}, + #else + {"NOT_SERVER", 20, 284}, + #endif + #ifdef SSL_R_NO_APPLICATION_PROTOCOL + {"NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_NO_APPLICATION_PROTOCOL}, + #else + {"NO_APPLICATION_PROTOCOL", 20, 235}, + #endif + #ifdef SSL_R_NO_CERTIFICATES_RETURNED + {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATES_RETURNED}, + #else + {"NO_CERTIFICATES_RETURNED", 20, 176}, + #endif + #ifdef SSL_R_NO_CERTIFICATE_ASSIGNED + {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED}, + #else + {"NO_CERTIFICATE_ASSIGNED", 20, 177}, + #endif + #ifdef SSL_R_NO_CERTIFICATE_SET + {"NO_CERTIFICATE_SET", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET}, + #else + {"NO_CERTIFICATE_SET", 20, 179}, + #endif + #ifdef SSL_R_NO_CHANGE_FOLLOWING_HRR + {"NO_CHANGE_FOLLOWING_HRR", ERR_LIB_SSL, SSL_R_NO_CHANGE_FOLLOWING_HRR}, + #else + {"NO_CHANGE_FOLLOWING_HRR", 20, 214}, + #endif + #ifdef SSL_R_NO_CIPHERS_AVAILABLE + {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_CIPHERS_AVAILABLE}, + #else + {"NO_CIPHERS_AVAILABLE", 20, 181}, + #endif + #ifdef SSL_R_NO_CIPHERS_SPECIFIED + {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_SPECIFIED}, + #else + {"NO_CIPHERS_SPECIFIED", 20, 183}, + #endif + #ifdef SSL_R_NO_CIPHER_MATCH + {"NO_CIPHER_MATCH", ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH}, + #else + {"NO_CIPHER_MATCH", 20, 185}, + #endif + #ifdef SSL_R_NO_CLIENT_CERT_METHOD + {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_METHOD}, + #else + {"NO_CLIENT_CERT_METHOD", 20, 331}, + #endif + #ifdef SSL_R_NO_COMPRESSION_SPECIFIED + {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_COMPRESSION_SPECIFIED}, + #else + {"NO_COMPRESSION_SPECIFIED", 20, 187}, + #endif + #ifdef SSL_R_NO_COOKIE_CALLBACK_SET + {"NO_COOKIE_CALLBACK_SET", ERR_LIB_SSL, SSL_R_NO_COOKIE_CALLBACK_SET}, + #else + {"NO_COOKIE_CALLBACK_SET", 20, 287}, + #endif + #ifdef SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER + {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER}, + #else + {"NO_GOST_CERTIFICATE_SENT_BY_PEER", 20, 330}, + #endif + #ifdef SSL_R_NO_METHOD_SPECIFIED + {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_METHOD_SPECIFIED}, + #else + {"NO_METHOD_SPECIFIED", 20, 188}, + #endif + #ifdef SSL_R_NO_PEM_EXTENSIONS + {"NO_PEM_EXTENSIONS", ERR_LIB_SSL, SSL_R_NO_PEM_EXTENSIONS}, + #else + {"NO_PEM_EXTENSIONS", 20, 389}, + #endif + #ifdef SSL_R_NO_PRIVATE_KEY_ASSIGNED + {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED}, + #else + {"NO_PRIVATE_KEY_ASSIGNED", 20, 190}, + #endif + #ifdef SSL_R_NO_PROTOCOLS_AVAILABLE + {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_PROTOCOLS_AVAILABLE}, + #else + {"NO_PROTOCOLS_AVAILABLE", 20, 191}, + #endif + #ifdef SSL_R_NO_RENEGOTIATION + {"NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_NO_RENEGOTIATION}, + #else + {"NO_RENEGOTIATION", 20, 339}, + #endif + #ifdef SSL_R_NO_REQUIRED_DIGEST + {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, SSL_R_NO_REQUIRED_DIGEST}, + #else + {"NO_REQUIRED_DIGEST", 20, 324}, + #endif + #ifdef SSL_R_NO_SHARED_CIPHER + {"NO_SHARED_CIPHER", ERR_LIB_SSL, SSL_R_NO_SHARED_CIPHER}, + #else + {"NO_SHARED_CIPHER", 20, 193}, + #endif + #ifdef SSL_R_NO_SHARED_GROUPS + {"NO_SHARED_GROUPS", ERR_LIB_SSL, SSL_R_NO_SHARED_GROUPS}, + #else + {"NO_SHARED_GROUPS", 20, 410}, + #endif + #ifdef SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS + {"NO_SHARED_SIGNATURE_ALGORITHMS", ERR_LIB_SSL, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS}, + #else + {"NO_SHARED_SIGNATURE_ALGORITHMS", 20, 376}, + #endif + #ifdef SSL_R_NO_SRTP_PROFILES + {"NO_SRTP_PROFILES", ERR_LIB_SSL, SSL_R_NO_SRTP_PROFILES}, + #else + {"NO_SRTP_PROFILES", 20, 359}, + #endif + #ifdef SSL_R_NO_STREAM + {"NO_STREAM", ERR_LIB_SSL, SSL_R_NO_STREAM}, + #else + {"NO_STREAM", 20, 355}, + #endif + #ifdef SSL_R_NO_SUITABLE_DIGEST_ALGORITHM + {"NO_SUITABLE_DIGEST_ALGORITHM", ERR_LIB_SSL, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM}, + #else + {"NO_SUITABLE_DIGEST_ALGORITHM", 20, 297}, + #endif + #ifdef SSL_R_NO_SUITABLE_GROUPS + {"NO_SUITABLE_GROUPS", ERR_LIB_SSL, SSL_R_NO_SUITABLE_GROUPS}, + #else + {"NO_SUITABLE_GROUPS", 20, 295}, + #endif + #ifdef SSL_R_NO_SUITABLE_KEY_SHARE + {"NO_SUITABLE_KEY_SHARE", ERR_LIB_SSL, SSL_R_NO_SUITABLE_KEY_SHARE}, + #else + {"NO_SUITABLE_KEY_SHARE", 20, 101}, + #endif + #ifdef SSL_R_NO_SUITABLE_RECORD_LAYER + {"NO_SUITABLE_RECORD_LAYER", ERR_LIB_SSL, SSL_R_NO_SUITABLE_RECORD_LAYER}, + #else + {"NO_SUITABLE_RECORD_LAYER", 20, 322}, + #endif + #ifdef SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM + {"NO_SUITABLE_SIGNATURE_ALGORITHM", ERR_LIB_SSL, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM}, + #else + {"NO_SUITABLE_SIGNATURE_ALGORITHM", 20, 118}, + #endif + #ifdef SSL_R_NO_VALID_SCTS + {"NO_VALID_SCTS", ERR_LIB_SSL, SSL_R_NO_VALID_SCTS}, + #else + {"NO_VALID_SCTS", 20, 216}, + #endif + #ifdef SSL_R_NO_VERIFY_COOKIE_CALLBACK + {"NO_VERIFY_COOKIE_CALLBACK", ERR_LIB_SSL, SSL_R_NO_VERIFY_COOKIE_CALLBACK}, + #else + {"NO_VERIFY_COOKIE_CALLBACK", 20, 403}, + #endif + #ifdef SSL_R_NULL_SSL_CTX + {"NULL_SSL_CTX", ERR_LIB_SSL, SSL_R_NULL_SSL_CTX}, + #else + {"NULL_SSL_CTX", 20, 195}, + #endif + #ifdef SSL_R_NULL_SSL_METHOD_PASSED + {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, SSL_R_NULL_SSL_METHOD_PASSED}, + #else + {"NULL_SSL_METHOD_PASSED", 20, 196}, + #endif + #ifdef SSL_R_OCSP_CALLBACK_FAILURE + {"OCSP_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_OCSP_CALLBACK_FAILURE}, + #else + {"OCSP_CALLBACK_FAILURE", 20, 305}, + #endif + #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED + {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, + #else + {"OLD_SESSION_CIPHER_NOT_RETURNED", 20, 197}, + #endif + #ifdef SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED + {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED}, + #else + {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", 20, 344}, + #endif + #ifdef SSL_R_OVERFLOW_ERROR + {"OVERFLOW_ERROR", ERR_LIB_SSL, SSL_R_OVERFLOW_ERROR}, + #else + {"OVERFLOW_ERROR", 20, 237}, + #endif + #ifdef SSL_R_PACKET_LENGTH_TOO_LONG + {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PACKET_LENGTH_TOO_LONG}, + #else + {"PACKET_LENGTH_TOO_LONG", 20, 198}, + #endif + #ifdef SSL_R_PARSE_TLSEXT + {"PARSE_TLSEXT", ERR_LIB_SSL, SSL_R_PARSE_TLSEXT}, + #else + {"PARSE_TLSEXT", 20, 227}, + #endif + #ifdef SSL_R_PATH_TOO_LONG + {"PATH_TOO_LONG", ERR_LIB_SSL, SSL_R_PATH_TOO_LONG}, + #else + {"PATH_TOO_LONG", 20, 270}, + #endif + #ifdef SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE + {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE}, + #else + {"PEER_DID_NOT_RETURN_A_CERTIFICATE", 20, 199}, + #endif + #ifdef SSL_R_PEM_NAME_BAD_PREFIX + {"PEM_NAME_BAD_PREFIX", ERR_LIB_SSL, SSL_R_PEM_NAME_BAD_PREFIX}, + #else + {"PEM_NAME_BAD_PREFIX", 20, 391}, + #endif + #ifdef SSL_R_PEM_NAME_TOO_SHORT + {"PEM_NAME_TOO_SHORT", ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT}, + #else + {"PEM_NAME_TOO_SHORT", 20, 392}, + #endif + #ifdef SSL_R_PIPELINE_FAILURE + {"PIPELINE_FAILURE", ERR_LIB_SSL, SSL_R_PIPELINE_FAILURE}, + #else + {"PIPELINE_FAILURE", 20, 406}, + #endif + #ifdef SSL_R_POLL_REQUEST_NOT_SUPPORTED + {"POLL_REQUEST_NOT_SUPPORTED", ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED}, + #else + {"POLL_REQUEST_NOT_SUPPORTED", 20, 418}, + #endif + #ifdef SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR + {"POST_HANDSHAKE_AUTH_ENCODING_ERR", ERR_LIB_SSL, SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR}, + #else + {"POST_HANDSHAKE_AUTH_ENCODING_ERR", 20, 278}, + #endif + #ifdef SSL_R_PRIVATE_KEY_MISMATCH + {"PRIVATE_KEY_MISMATCH", ERR_LIB_SSL, SSL_R_PRIVATE_KEY_MISMATCH}, + #else + {"PRIVATE_KEY_MISMATCH", 20, 288}, + #endif + #ifdef SSL_R_PROTOCOL_IS_SHUTDOWN + {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN}, + #else + {"PROTOCOL_IS_SHUTDOWN", 20, 207}, + #endif + #ifdef SSL_R_PSK_IDENTITY_NOT_FOUND + {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, SSL_R_PSK_IDENTITY_NOT_FOUND}, + #else + {"PSK_IDENTITY_NOT_FOUND", 20, 223}, + #endif + #ifdef SSL_R_PSK_NO_CLIENT_CB + {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, SSL_R_PSK_NO_CLIENT_CB}, + #else + {"PSK_NO_CLIENT_CB", 20, 224}, + #endif + #ifdef SSL_R_PSK_NO_SERVER_CB + {"PSK_NO_SERVER_CB", ERR_LIB_SSL, SSL_R_PSK_NO_SERVER_CB}, + #else + {"PSK_NO_SERVER_CB", 20, 225}, + #endif + #ifdef SSL_R_QUIC_HANDSHAKE_LAYER_ERROR + {"QUIC_HANDSHAKE_LAYER_ERROR", ERR_LIB_SSL, SSL_R_QUIC_HANDSHAKE_LAYER_ERROR}, + #else + {"QUIC_HANDSHAKE_LAYER_ERROR", 20, 393}, + #endif + #ifdef SSL_R_QUIC_NETWORK_ERROR + {"QUIC_NETWORK_ERROR", ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR}, + #else + {"QUIC_NETWORK_ERROR", 20, 387}, + #endif + #ifdef SSL_R_QUIC_PROTOCOL_ERROR + {"QUIC_PROTOCOL_ERROR", ERR_LIB_SSL, SSL_R_QUIC_PROTOCOL_ERROR}, + #else + {"QUIC_PROTOCOL_ERROR", 20, 382}, + #endif + #ifdef SSL_R_READ_BIO_NOT_SET + {"READ_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_READ_BIO_NOT_SET}, + #else + {"READ_BIO_NOT_SET", 20, 211}, + #endif + #ifdef SSL_R_READ_TIMEOUT_EXPIRED + {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, SSL_R_READ_TIMEOUT_EXPIRED}, + #else + {"READ_TIMEOUT_EXPIRED", 20, 312}, + #endif + #ifdef SSL_R_RECORDS_NOT_RELEASED + {"RECORDS_NOT_RELEASED", ERR_LIB_SSL, SSL_R_RECORDS_NOT_RELEASED}, + #else + {"RECORDS_NOT_RELEASED", 20, 321}, + #endif + #ifdef SSL_R_RECORD_LAYER_FAILURE + {"RECORD_LAYER_FAILURE", ERR_LIB_SSL, SSL_R_RECORD_LAYER_FAILURE}, + #else + {"RECORD_LAYER_FAILURE", 20, 313}, + #endif + #ifdef SSL_R_RECORD_LENGTH_MISMATCH + {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_RECORD_LENGTH_MISMATCH}, + #else + {"RECORD_LENGTH_MISMATCH", 20, 213}, + #endif + #ifdef SSL_R_RECORD_TOO_SMALL + {"RECORD_TOO_SMALL", ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL}, + #else + {"RECORD_TOO_SMALL", 20, 298}, + #endif + #ifdef SSL_R_REMOTE_PEER_ADDRESS_NOT_SET + {"REMOTE_PEER_ADDRESS_NOT_SET", ERR_LIB_SSL, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET}, + #else + {"REMOTE_PEER_ADDRESS_NOT_SET", 20, 346}, + #endif + #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG + {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, SSL_R_RENEGOTIATE_EXT_TOO_LONG}, + #else + {"RENEGOTIATE_EXT_TOO_LONG", 20, 335}, + #endif + #ifdef SSL_R_RENEGOTIATION_ENCODING_ERR + {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, SSL_R_RENEGOTIATION_ENCODING_ERR}, + #else + {"RENEGOTIATION_ENCODING_ERR", 20, 336}, + #endif + #ifdef SSL_R_RENEGOTIATION_MISMATCH + {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, SSL_R_RENEGOTIATION_MISMATCH}, + #else + {"RENEGOTIATION_MISMATCH", 20, 337}, + #endif + #ifdef SSL_R_REQUEST_PENDING + {"REQUEST_PENDING", ERR_LIB_SSL, SSL_R_REQUEST_PENDING}, + #else + {"REQUEST_PENDING", 20, 285}, + #endif + #ifdef SSL_R_REQUEST_SENT + {"REQUEST_SENT", ERR_LIB_SSL, SSL_R_REQUEST_SENT}, + #else + {"REQUEST_SENT", 20, 286}, + #endif + #ifdef SSL_R_REQUIRED_CIPHER_MISSING + {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_CIPHER_MISSING}, + #else + {"REQUIRED_CIPHER_MISSING", 20, 215}, + #endif + #ifdef SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING + {"REQUIRED_COMPRESSION_ALGORITHM_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING}, + #else + {"REQUIRED_COMPRESSION_ALGORITHM_MISSING", 20, 342}, + #endif + #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING + {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING}, + #else + {"SCSV_RECEIVED_WHEN_RENEGOTIATING", 20, 345}, + #endif + #ifdef SSL_R_SCT_VERIFICATION_FAILED + {"SCT_VERIFICATION_FAILED", ERR_LIB_SSL, SSL_R_SCT_VERIFICATION_FAILED}, + #else + {"SCT_VERIFICATION_FAILED", 20, 208}, + #endif + #ifdef SSL_R_SEQUENCE_CTR_WRAPPED + {"SEQUENCE_CTR_WRAPPED", ERR_LIB_SSL, SSL_R_SEQUENCE_CTR_WRAPPED}, + #else + {"SEQUENCE_CTR_WRAPPED", 20, 327}, + #endif + #ifdef SSL_R_SERVERHELLO_TLSEXT + {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_SERVERHELLO_TLSEXT}, + #else + {"SERVERHELLO_TLSEXT", 20, 275}, + #endif + #ifdef SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED + {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED}, + #else + {"SESSION_ID_CONTEXT_UNINITIALIZED", 20, 277}, + #endif + #ifdef SSL_R_SHUTDOWN_WHILE_IN_INIT + {"SHUTDOWN_WHILE_IN_INIT", ERR_LIB_SSL, SSL_R_SHUTDOWN_WHILE_IN_INIT}, + #else + {"SHUTDOWN_WHILE_IN_INIT", 20, 407}, + #endif + #ifdef SSL_R_SIGNATURE_ALGORITHMS_ERROR + {"SIGNATURE_ALGORITHMS_ERROR", ERR_LIB_SSL, SSL_R_SIGNATURE_ALGORITHMS_ERROR}, + #else + {"SIGNATURE_ALGORITHMS_ERROR", 20, 360}, + #endif + #ifdef SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE + {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE}, + #else + {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", 20, 220}, + #endif + #ifdef SSL_R_SRP_A_CALC + {"SRP_A_CALC", ERR_LIB_SSL, SSL_R_SRP_A_CALC}, + #else + {"SRP_A_CALC", 20, 361}, + #endif + #ifdef SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES + {"SRTP_COULD_NOT_ALLOCATE_PROFILES", ERR_LIB_SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES}, + #else + {"SRTP_COULD_NOT_ALLOCATE_PROFILES", 20, 362}, + #endif + #ifdef SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG + {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", ERR_LIB_SSL, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG}, + #else + {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", 20, 363}, + #endif + #ifdef SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE + {"SRTP_UNKNOWN_PROTECTION_PROFILE", ERR_LIB_SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE}, + #else + {"SRTP_UNKNOWN_PROTECTION_PROFILE", 20, 364}, + #endif + #ifdef SSL_R_SSL_COMMAND_SECTION_EMPTY + {"SSL_COMMAND_SECTION_EMPTY", ERR_LIB_SSL, SSL_R_SSL_COMMAND_SECTION_EMPTY}, + #else + {"SSL_COMMAND_SECTION_EMPTY", 20, 117}, + #endif + #ifdef SSL_R_SSL_COMMAND_SECTION_NOT_FOUND + {"SSL_COMMAND_SECTION_NOT_FOUND", ERR_LIB_SSL, SSL_R_SSL_COMMAND_SECTION_NOT_FOUND}, + #else + {"SSL_COMMAND_SECTION_NOT_FOUND", 20, 125}, + #endif + #ifdef SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION + {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION}, + #else + {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", 20, 228}, + #endif + #ifdef SSL_R_SSL_HANDSHAKE_FAILURE + {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE}, + #else + {"SSL_HANDSHAKE_FAILURE", 20, 229}, + #endif + #ifdef SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS + {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS}, + #else + {"SSL_LIBRARY_HAS_NO_CIPHERS", 20, 230}, + #endif + #ifdef SSL_R_SSL_NEGATIVE_LENGTH + {"SSL_NEGATIVE_LENGTH", ERR_LIB_SSL, SSL_R_SSL_NEGATIVE_LENGTH}, + #else + {"SSL_NEGATIVE_LENGTH", 20, 372}, + #endif + #ifdef SSL_R_SSL_SECTION_EMPTY + {"SSL_SECTION_EMPTY", ERR_LIB_SSL, SSL_R_SSL_SECTION_EMPTY}, + #else + {"SSL_SECTION_EMPTY", 20, 126}, + #endif + #ifdef SSL_R_SSL_SECTION_NOT_FOUND + {"SSL_SECTION_NOT_FOUND", ERR_LIB_SSL, SSL_R_SSL_SECTION_NOT_FOUND}, + #else + {"SSL_SECTION_NOT_FOUND", 20, 136}, + #endif + #ifdef SSL_R_SSL_SESSION_ID_CALLBACK_FAILED + {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED}, + #else + {"SSL_SESSION_ID_CALLBACK_FAILED", 20, 301}, + #endif + #ifdef SSL_R_SSL_SESSION_ID_CONFLICT + {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONFLICT}, + #else + {"SSL_SESSION_ID_CONFLICT", 20, 302}, + #endif + #ifdef SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG + {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG}, + #else + {"SSL_SESSION_ID_CONTEXT_TOO_LONG", 20, 273}, + #endif + #ifdef SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH + {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH}, + #else + {"SSL_SESSION_ID_HAS_BAD_LENGTH", 20, 303}, + #endif + #ifdef SSL_R_SSL_SESSION_ID_TOO_LONG + {"SSL_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_TOO_LONG}, + #else + {"SSL_SESSION_ID_TOO_LONG", 20, 408}, + #endif + #ifdef SSL_R_SSL_SESSION_VERSION_MISMATCH + {"SSL_SESSION_VERSION_MISMATCH", ERR_LIB_SSL, SSL_R_SSL_SESSION_VERSION_MISMATCH}, + #else + {"SSL_SESSION_VERSION_MISMATCH", 20, 210}, + #endif + #ifdef SSL_R_STILL_IN_INIT + {"STILL_IN_INIT", ERR_LIB_SSL, SSL_R_STILL_IN_INIT}, + #else + {"STILL_IN_INIT", 20, 121}, + #endif + #ifdef SSL_R_STREAM_COUNT_LIMITED + {"STREAM_COUNT_LIMITED", ERR_LIB_SSL, SSL_R_STREAM_COUNT_LIMITED}, + #else + {"STREAM_COUNT_LIMITED", 20, 411}, + #endif + #ifdef SSL_R_STREAM_FINISHED + {"STREAM_FINISHED", ERR_LIB_SSL, SSL_R_STREAM_FINISHED}, + #else + {"STREAM_FINISHED", 20, 365}, + #endif + #ifdef SSL_R_STREAM_RECV_ONLY + {"STREAM_RECV_ONLY", ERR_LIB_SSL, SSL_R_STREAM_RECV_ONLY}, + #else + {"STREAM_RECV_ONLY", 20, 366}, + #endif + #ifdef SSL_R_STREAM_RESET + {"STREAM_RESET", ERR_LIB_SSL, SSL_R_STREAM_RESET}, + #else + {"STREAM_RESET", 20, 375}, + #endif + #ifdef SSL_R_STREAM_SEND_ONLY + {"STREAM_SEND_ONLY", ERR_LIB_SSL, SSL_R_STREAM_SEND_ONLY}, + #else + {"STREAM_SEND_ONLY", 20, 379}, + #endif + #ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED + {"TLSV13_ALERT_CERTIFICATE_REQUIRED", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED}, + #else + {"TLSV13_ALERT_CERTIFICATE_REQUIRED", 20, 1116}, + #endif + #ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED + {"TLSV13_ALERT_CERTIFICATE_REQUIRED", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED}, + #else + {"TLSV13_ALERT_CERTIFICATE_REQUIRED", 20, 1116}, + #endif + #ifdef SSL_R_TLSV13_ALERT_MISSING_EXTENSION + {"TLSV13_ALERT_MISSING_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_MISSING_EXTENSION}, + #else + {"TLSV13_ALERT_MISSING_EXTENSION", 20, 1109}, + #endif + #ifdef SSL_R_TLSV13_ALERT_MISSING_EXTENSION + {"TLSV13_ALERT_MISSING_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV13_ALERT_MISSING_EXTENSION}, + #else + {"TLSV13_ALERT_MISSING_EXTENSION", 20, 1109}, + #endif + #ifdef SSL_R_TLSV1_ALERT_ACCESS_DENIED + {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_ACCESS_DENIED}, + #else + {"TLSV1_ALERT_ACCESS_DENIED", 20, 1049}, + #endif + #ifdef SSL_R_TLSV1_ALERT_ACCESS_DENIED + {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_ACCESS_DENIED}, + #else + {"TLSV1_ALERT_ACCESS_DENIED", 20, 1049}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECODE_ERROR + {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECODE_ERROR}, + #else + {"TLSV1_ALERT_DECODE_ERROR", 20, 1050}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECODE_ERROR + {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECODE_ERROR}, + #else + {"TLSV1_ALERT_DECODE_ERROR", 20, 1050}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECRYPTION_FAILED + {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED}, + #else + {"TLSV1_ALERT_DECRYPTION_FAILED", 20, 1021}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECRYPTION_FAILED + {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED}, + #else + {"TLSV1_ALERT_DECRYPTION_FAILED", 20, 1021}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECRYPT_ERROR + {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPT_ERROR}, + #else + {"TLSV1_ALERT_DECRYPT_ERROR", 20, 1051}, + #endif + #ifdef SSL_R_TLSV1_ALERT_DECRYPT_ERROR + {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPT_ERROR}, + #else + {"TLSV1_ALERT_DECRYPT_ERROR", 20, 1051}, + #endif + #ifdef SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION + {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION}, + #else + {"TLSV1_ALERT_EXPORT_RESTRICTION", 20, 1060}, + #endif + #ifdef SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION + {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION}, + #else + {"TLSV1_ALERT_EXPORT_RESTRICTION", 20, 1060}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK + {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK}, + #else + {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", 20, 1086}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK + {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK}, + #else + {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", 20, 1086}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY + {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY}, + #else + {"TLSV1_ALERT_INSUFFICIENT_SECURITY", 20, 1071}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY + {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY}, + #else + {"TLSV1_ALERT_INSUFFICIENT_SECURITY", 20, 1071}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INTERNAL_ERROR + {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INTERNAL_ERROR}, + #else + {"TLSV1_ALERT_INTERNAL_ERROR", 20, 1080}, + #endif + #ifdef SSL_R_TLSV1_ALERT_INTERNAL_ERROR + {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INTERNAL_ERROR}, + #else + {"TLSV1_ALERT_INTERNAL_ERROR", 20, 1080}, + #endif + #ifdef SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL}, + #else + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", 20, 1120}, + #endif + #ifdef SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL}, + #else + {"TLSV1_ALERT_NO_APPLICATION_PROTOCOL", 20, 1120}, + #endif + #ifdef SSL_R_TLSV1_ALERT_NO_RENEGOTIATION + {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION}, + #else + {"TLSV1_ALERT_NO_RENEGOTIATION", 20, 1100}, + #endif + #ifdef SSL_R_TLSV1_ALERT_NO_RENEGOTIATION + {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION}, + #else + {"TLSV1_ALERT_NO_RENEGOTIATION", 20, 1100}, + #endif + #ifdef SSL_R_TLSV1_ALERT_PROTOCOL_VERSION + {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION}, + #else + {"TLSV1_ALERT_PROTOCOL_VERSION", 20, 1070}, + #endif + #ifdef SSL_R_TLSV1_ALERT_PROTOCOL_VERSION + {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION}, + #else + {"TLSV1_ALERT_PROTOCOL_VERSION", 20, 1070}, + #endif + #ifdef SSL_R_TLSV1_ALERT_RECORD_OVERFLOW + {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW}, + #else + {"TLSV1_ALERT_RECORD_OVERFLOW", 20, 1022}, + #endif + #ifdef SSL_R_TLSV1_ALERT_RECORD_OVERFLOW + {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW}, + #else + {"TLSV1_ALERT_RECORD_OVERFLOW", 20, 1022}, + #endif + #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA + {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_CA}, + #else + {"TLSV1_ALERT_UNKNOWN_CA", 20, 1048}, + #endif + #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA + {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_CA}, + #else + {"TLSV1_ALERT_UNKNOWN_CA", 20, 1048}, + #endif + #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY}, + #else + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", 20, 1115}, + #endif + #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY}, + #else + {"TLSV1_ALERT_UNKNOWN_PSK_IDENTITY", 20, 1115}, + #endif + #ifdef SSL_R_TLSV1_ALERT_USER_CANCELLED + {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_USER_CANCELLED}, + #else + {"TLSV1_ALERT_USER_CANCELLED", 20, 1090}, + #endif + #ifdef SSL_R_TLSV1_ALERT_USER_CANCELLED + {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_USER_CANCELLED}, + #else + {"TLSV1_ALERT_USER_CANCELLED", 20, 1090}, + #endif + #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE + {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE}, + #else + {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", 20, 1114}, + #endif + #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE + {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE}, + #else + {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", 20, 1114}, + #endif + #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE + {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE}, + #else + {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", 20, 1113}, + #endif + #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE + {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE}, + #else + {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", 20, 1113}, + #endif + #ifdef SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE + {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE}, + #else + {"TLSV1_CERTIFICATE_UNOBTAINABLE", 20, 1111}, + #endif + #ifdef SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE + {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE}, + #else + {"TLSV1_CERTIFICATE_UNOBTAINABLE", 20, 1111}, + #endif + #ifdef SSL_R_TLSV1_UNRECOGNIZED_NAME + {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, SSL_R_TLSV1_UNRECOGNIZED_NAME}, + #else + {"TLSV1_UNRECOGNIZED_NAME", 20, 1112}, + #endif + #ifdef SSL_R_TLSV1_UNRECOGNIZED_NAME + {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, SSL_R_TLSV1_UNRECOGNIZED_NAME}, + #else + {"TLSV1_UNRECOGNIZED_NAME", 20, 1112}, + #endif + #ifdef SSL_R_TLSV1_UNSUPPORTED_EXTENSION + {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV1_UNSUPPORTED_EXTENSION}, + #else + {"TLSV1_UNSUPPORTED_EXTENSION", 20, 1110}, + #endif + #ifdef SSL_R_TLSV1_UNSUPPORTED_EXTENSION + {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV1_UNSUPPORTED_EXTENSION}, + #else + {"TLSV1_UNSUPPORTED_EXTENSION", 20, 1110}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_CERTIFICATE + {"TLS_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_CERTIFICATE}, + #else + {"TLS_ALERT_BAD_CERTIFICATE", 20, 1042}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_CERTIFICATE + {"TLS_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_CERTIFICATE}, + #else + {"TLS_ALERT_BAD_CERTIFICATE", 20, 1042}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_RECORD_MAC + {"TLS_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_RECORD_MAC}, + #else + {"TLS_ALERT_BAD_RECORD_MAC", 20, 1020}, + #endif + #ifdef SSL_R_TLS_ALERT_BAD_RECORD_MAC + {"TLS_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_TLS_ALERT_BAD_RECORD_MAC}, + #else + {"TLS_ALERT_BAD_RECORD_MAC", 20, 1020}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED + {"TLS_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED}, + #else + {"TLS_ALERT_CERTIFICATE_EXPIRED", 20, 1045}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED + {"TLS_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_EXPIRED}, + #else + {"TLS_ALERT_CERTIFICATE_EXPIRED", 20, 1045}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_REVOKED + {"TLS_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED}, + #else + {"TLS_ALERT_CERTIFICATE_REVOKED", 20, 1044}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_REVOKED + {"TLS_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_REVOKED}, + #else + {"TLS_ALERT_CERTIFICATE_REVOKED", 20, 1044}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN + {"TLS_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN}, + #else + {"TLS_ALERT_CERTIFICATE_UNKNOWN", 20, 1046}, + #endif + #ifdef SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN + {"TLS_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_TLS_ALERT_CERTIFICATE_UNKNOWN}, + #else + {"TLS_ALERT_CERTIFICATE_UNKNOWN", 20, 1046}, + #endif + #ifdef SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE + {"TLS_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE}, + #else + {"TLS_ALERT_DECOMPRESSION_FAILURE", 20, 1030}, + #endif + #ifdef SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE + {"TLS_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_DECOMPRESSION_FAILURE}, + #else + {"TLS_ALERT_DECOMPRESSION_FAILURE", 20, 1030}, + #endif + #ifdef SSL_R_TLS_ALERT_HANDSHAKE_FAILURE + {"TLS_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE}, + #else + {"TLS_ALERT_HANDSHAKE_FAILURE", 20, 1040}, + #endif + #ifdef SSL_R_TLS_ALERT_HANDSHAKE_FAILURE + {"TLS_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_TLS_ALERT_HANDSHAKE_FAILURE}, + #else + {"TLS_ALERT_HANDSHAKE_FAILURE", 20, 1040}, + #endif + #ifdef SSL_R_TLS_ALERT_ILLEGAL_PARAMETER + {"TLS_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER}, + #else + {"TLS_ALERT_ILLEGAL_PARAMETER", 20, 1047}, + #endif + #ifdef SSL_R_TLS_ALERT_ILLEGAL_PARAMETER + {"TLS_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_TLS_ALERT_ILLEGAL_PARAMETER}, + #else + {"TLS_ALERT_ILLEGAL_PARAMETER", 20, 1047}, + #endif + #ifdef SSL_R_TLS_ALERT_NO_CERTIFICATE + {"TLS_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_NO_CERTIFICATE}, + #else + {"TLS_ALERT_NO_CERTIFICATE", 20, 1041}, + #endif + #ifdef SSL_R_TLS_ALERT_NO_CERTIFICATE + {"TLS_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_NO_CERTIFICATE}, + #else + {"TLS_ALERT_NO_CERTIFICATE", 20, 1041}, + #endif + #ifdef SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE + {"TLS_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE}, + #else + {"TLS_ALERT_UNEXPECTED_MESSAGE", 20, 1010}, + #endif + #ifdef SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE + {"TLS_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNEXPECTED_MESSAGE}, + #else + {"TLS_ALERT_UNEXPECTED_MESSAGE", 20, 1010}, + #endif + #ifdef SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE}, + #else + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", 20, 1043}, + #endif + #ifdef SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_TLS_ALERT_UNSUPPORTED_CERTIFICATE}, + #else + {"TLS_ALERT_UNSUPPORTED_CERTIFICATE", 20, 1043}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH + {"TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH}, + #else + {"TLS_EXT_INVALID_MAX_FRAGMENT_LENGTH", 20, 232}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_SERVERNAME + {"TLS_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_SERVERNAME}, + #else + {"TLS_EXT_INVALID_SERVERNAME", 20, 319}, + #endif + #ifdef SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE + {"TLS_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, SSL_R_TLS_EXT_INVALID_SERVERNAME_TYPE}, + #else + {"TLS_EXT_INVALID_SERVERNAME_TYPE", 20, 320}, + #endif + #ifdef SSL_R_TLS_ILLEGAL_EXPORTER_LABEL + {"TLS_ILLEGAL_EXPORTER_LABEL", ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL}, + #else + {"TLS_ILLEGAL_EXPORTER_LABEL", 20, 367}, + #endif + #ifdef SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST + {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST}, + #else + {"TLS_INVALID_ECPOINTFORMAT_LIST", 20, 157}, + #endif + #ifdef SSL_R_TLS_SESSION_ID_TOO_LONG + {"TLS_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_TLS_SESSION_ID_TOO_LONG}, + #else + {"TLS_SESSION_ID_TOO_LONG", 20, 300}, + #endif + #ifdef SSL_R_TOO_MANY_KEY_UPDATES + {"TOO_MANY_KEY_UPDATES", ERR_LIB_SSL, SSL_R_TOO_MANY_KEY_UPDATES}, + #else + {"TOO_MANY_KEY_UPDATES", 20, 132}, + #endif + #ifdef SSL_R_TOO_MANY_WARN_ALERTS + {"TOO_MANY_WARN_ALERTS", ERR_LIB_SSL, SSL_R_TOO_MANY_WARN_ALERTS}, + #else + {"TOO_MANY_WARN_ALERTS", 20, 409}, + #endif + #ifdef SSL_R_TOO_MUCH_EARLY_DATA + {"TOO_MUCH_EARLY_DATA", ERR_LIB_SSL, SSL_R_TOO_MUCH_EARLY_DATA}, + #else + {"TOO_MUCH_EARLY_DATA", 20, 164}, + #endif + #ifdef SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS + {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS}, + #else + {"UNABLE_TO_FIND_ECDH_PARAMETERS", 20, 314}, + #endif + #ifdef SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS + {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS}, + #else + {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", 20, 239}, + #endif + #ifdef SSL_R_UNEXPECTED_CCS_MESSAGE + {"UNEXPECTED_CCS_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_CCS_MESSAGE}, + #else + {"UNEXPECTED_CCS_MESSAGE", 20, 262}, + #endif + #ifdef SSL_R_UNEXPECTED_END_OF_EARLY_DATA + {"UNEXPECTED_END_OF_EARLY_DATA", ERR_LIB_SSL, SSL_R_UNEXPECTED_END_OF_EARLY_DATA}, + #else + {"UNEXPECTED_END_OF_EARLY_DATA", 20, 178}, + #endif + #ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING + {"UNEXPECTED_EOF_WHILE_READING", ERR_LIB_SSL, SSL_R_UNEXPECTED_EOF_WHILE_READING}, + #else + {"UNEXPECTED_EOF_WHILE_READING", 20, 294}, + #endif + #ifdef SSL_R_UNEXPECTED_MESSAGE + {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE}, + #else + {"UNEXPECTED_MESSAGE", 20, 244}, + #endif + #ifdef SSL_R_UNEXPECTED_RECORD + {"UNEXPECTED_RECORD", ERR_LIB_SSL, SSL_R_UNEXPECTED_RECORD}, + #else + {"UNEXPECTED_RECORD", 20, 245}, + #endif + #ifdef SSL_R_UNINITIALIZED + {"UNINITIALIZED", ERR_LIB_SSL, SSL_R_UNINITIALIZED}, + #else + {"UNINITIALIZED", 20, 276}, + #endif + #ifdef SSL_R_UNKNOWN_ALERT_TYPE + {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_ALERT_TYPE}, + #else + {"UNKNOWN_ALERT_TYPE", 20, 246}, + #endif + #ifdef SSL_R_UNKNOWN_CERTIFICATE_TYPE + {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE}, + #else + {"UNKNOWN_CERTIFICATE_TYPE", 20, 247}, + #endif + #ifdef SSL_R_UNKNOWN_CIPHER_RETURNED + {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_RETURNED}, + #else + {"UNKNOWN_CIPHER_RETURNED", 20, 248}, + #endif + #ifdef SSL_R_UNKNOWN_CIPHER_TYPE + {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_TYPE}, + #else + {"UNKNOWN_CIPHER_TYPE", 20, 249}, + #endif + #ifdef SSL_R_UNKNOWN_CMD_NAME + {"UNKNOWN_CMD_NAME", ERR_LIB_SSL, SSL_R_UNKNOWN_CMD_NAME}, + #else + {"UNKNOWN_CMD_NAME", 20, 386}, + #endif + #ifdef SSL_R_UNKNOWN_COMMAND + {"UNKNOWN_COMMAND", ERR_LIB_SSL, SSL_R_UNKNOWN_COMMAND}, + #else + {"UNKNOWN_COMMAND", 20, 139}, + #endif + #ifdef SSL_R_UNKNOWN_DIGEST + {"UNKNOWN_DIGEST", ERR_LIB_SSL, SSL_R_UNKNOWN_DIGEST}, + #else + {"UNKNOWN_DIGEST", 20, 368}, + #endif + #ifdef SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE + {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE}, + #else + {"UNKNOWN_KEY_EXCHANGE_TYPE", 20, 250}, + #endif + #ifdef SSL_R_UNKNOWN_MANDATORY_PARAMETER + {"UNKNOWN_MANDATORY_PARAMETER", ERR_LIB_SSL, SSL_R_UNKNOWN_MANDATORY_PARAMETER}, + #else + {"UNKNOWN_MANDATORY_PARAMETER", 20, 323}, + #endif + #ifdef SSL_R_UNKNOWN_PKEY_TYPE + {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_PKEY_TYPE}, + #else + {"UNKNOWN_PKEY_TYPE", 20, 251}, + #endif + #ifdef SSL_R_UNKNOWN_PROTOCOL + {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, SSL_R_UNKNOWN_PROTOCOL}, + #else + {"UNKNOWN_PROTOCOL", 20, 252}, + #endif + #ifdef SSL_R_UNKNOWN_SSL_VERSION + {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNKNOWN_SSL_VERSION}, + #else + {"UNKNOWN_SSL_VERSION", 20, 254}, + #endif + #ifdef SSL_R_UNKNOWN_STATE + {"UNKNOWN_STATE", ERR_LIB_SSL, SSL_R_UNKNOWN_STATE}, + #else + {"UNKNOWN_STATE", 20, 255}, + #endif + #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED + {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED}, + #else + {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", 20, 338}, + #endif + #ifdef SSL_R_UNSOLICITED_EXTENSION + {"UNSOLICITED_EXTENSION", ERR_LIB_SSL, SSL_R_UNSOLICITED_EXTENSION}, + #else + {"UNSOLICITED_EXTENSION", 20, 217}, + #endif + #ifdef SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM + {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, + #else + {"UNSUPPORTED_COMPRESSION_ALGORITHM", 20, 257}, + #endif + #ifdef SSL_R_UNSUPPORTED_CONFIG_VALUE + {"UNSUPPORTED_CONFIG_VALUE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE}, + #else + {"UNSUPPORTED_CONFIG_VALUE", 20, 414}, + #endif + #ifdef SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS + {"UNSUPPORTED_CONFIG_VALUE_CLASS", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS}, + #else + {"UNSUPPORTED_CONFIG_VALUE_CLASS", 20, 415}, + #endif + #ifdef SSL_R_UNSUPPORTED_CONFIG_VALUE_OP + {"UNSUPPORTED_CONFIG_VALUE_OP", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CONFIG_VALUE_OP}, + #else + {"UNSUPPORTED_CONFIG_VALUE_OP", 20, 416}, + #endif + #ifdef SSL_R_UNSUPPORTED_ELLIPTIC_CURVE + {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE}, + #else + {"UNSUPPORTED_ELLIPTIC_CURVE", 20, 315}, + #endif + #ifdef SSL_R_UNSUPPORTED_PROTOCOL + {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, SSL_R_UNSUPPORTED_PROTOCOL}, + #else + {"UNSUPPORTED_PROTOCOL", 20, 258}, + #endif + #ifdef SSL_R_UNSUPPORTED_SSL_VERSION + {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION}, + #else + {"UNSUPPORTED_SSL_VERSION", 20, 259}, + #endif + #ifdef SSL_R_UNSUPPORTED_STATUS_TYPE + {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_STATUS_TYPE}, + #else + {"UNSUPPORTED_STATUS_TYPE", 20, 329}, + #endif + #ifdef SSL_R_UNSUPPORTED_WRITE_FLAG + {"UNSUPPORTED_WRITE_FLAG", ERR_LIB_SSL, SSL_R_UNSUPPORTED_WRITE_FLAG}, + #else + {"UNSUPPORTED_WRITE_FLAG", 20, 412}, + #endif + #ifdef SSL_R_USE_SRTP_NOT_NEGOTIATED + {"USE_SRTP_NOT_NEGOTIATED", ERR_LIB_SSL, SSL_R_USE_SRTP_NOT_NEGOTIATED}, + #else + {"USE_SRTP_NOT_NEGOTIATED", 20, 369}, + #endif + #ifdef SSL_R_VERSION_TOO_HIGH + {"VERSION_TOO_HIGH", ERR_LIB_SSL, SSL_R_VERSION_TOO_HIGH}, + #else + {"VERSION_TOO_HIGH", 20, 166}, + #endif + #ifdef SSL_R_VERSION_TOO_LOW + {"VERSION_TOO_LOW", ERR_LIB_SSL, SSL_R_VERSION_TOO_LOW}, + #else + {"VERSION_TOO_LOW", 20, 396}, + #endif + #ifdef SSL_R_WRONG_CERTIFICATE_TYPE + {"WRONG_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_CERTIFICATE_TYPE}, + #else + {"WRONG_CERTIFICATE_TYPE", 20, 383}, + #endif + #ifdef SSL_R_WRONG_CIPHER_RETURNED + {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_WRONG_CIPHER_RETURNED}, + #else + {"WRONG_CIPHER_RETURNED", 20, 261}, + #endif + #ifdef SSL_R_WRONG_CURVE + {"WRONG_CURVE", ERR_LIB_SSL, SSL_R_WRONG_CURVE}, + #else + {"WRONG_CURVE", 20, 378}, + #endif + #ifdef SSL_R_WRONG_RPK_TYPE + {"WRONG_RPK_TYPE", ERR_LIB_SSL, SSL_R_WRONG_RPK_TYPE}, + #else + {"WRONG_RPK_TYPE", 20, 351}, + #endif + #ifdef SSL_R_WRONG_SIGNATURE_LENGTH + {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_LENGTH}, + #else + {"WRONG_SIGNATURE_LENGTH", 20, 264}, + #endif + #ifdef SSL_R_WRONG_SIGNATURE_SIZE + {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_SIZE}, + #else + {"WRONG_SIGNATURE_SIZE", 20, 265}, + #endif + #ifdef SSL_R_WRONG_SIGNATURE_TYPE + {"WRONG_SIGNATURE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_TYPE}, + #else + {"WRONG_SIGNATURE_TYPE", 20, 370}, + #endif + #ifdef SSL_R_WRONG_SSL_VERSION + {"WRONG_SSL_VERSION", ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION}, + #else + {"WRONG_SSL_VERSION", 20, 266}, + #endif + #ifdef SSL_R_WRONG_VERSION_NUMBER + {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER}, + #else + {"WRONG_VERSION_NUMBER", 20, 267}, + #endif + #ifdef SSL_R_X509_LIB + {"X509_LIB", ERR_LIB_SSL, SSL_R_X509_LIB}, + #else + {"X509_LIB", 20, 268}, + #endif + #ifdef SSL_R_X509_VERIFICATION_SETUP_PROBLEMS + {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS}, + #else + {"X509_VERIFICATION_SETUP_PROBLEMS", 20, 269}, + #endif + #ifdef TS_R_BAD_PKCS7_TYPE + {"BAD_PKCS7_TYPE", ERR_LIB_TS, TS_R_BAD_PKCS7_TYPE}, + #else + {"BAD_PKCS7_TYPE", 47, 132}, + #endif + #ifdef TS_R_BAD_TYPE + {"BAD_TYPE", ERR_LIB_TS, TS_R_BAD_TYPE}, + #else + {"BAD_TYPE", 47, 133}, + #endif + #ifdef TS_R_CANNOT_LOAD_CERT + {"CANNOT_LOAD_CERT", ERR_LIB_TS, TS_R_CANNOT_LOAD_CERT}, + #else + {"CANNOT_LOAD_CERT", 47, 137}, + #endif + #ifdef TS_R_CANNOT_LOAD_KEY + {"CANNOT_LOAD_KEY", ERR_LIB_TS, TS_R_CANNOT_LOAD_KEY}, + #else + {"CANNOT_LOAD_KEY", 47, 138}, + #endif + #ifdef TS_R_CERTIFICATE_VERIFY_ERROR + {"CERTIFICATE_VERIFY_ERROR", ERR_LIB_TS, TS_R_CERTIFICATE_VERIFY_ERROR}, + #else + {"CERTIFICATE_VERIFY_ERROR", 47, 100}, + #endif + #ifdef TS_R_COULD_NOT_SET_ENGINE + {"COULD_NOT_SET_ENGINE", ERR_LIB_TS, TS_R_COULD_NOT_SET_ENGINE}, + #else + {"COULD_NOT_SET_ENGINE", 47, 127}, + #endif + #ifdef TS_R_COULD_NOT_SET_TIME + {"COULD_NOT_SET_TIME", ERR_LIB_TS, TS_R_COULD_NOT_SET_TIME}, + #else + {"COULD_NOT_SET_TIME", 47, 115}, + #endif + #ifdef TS_R_DETACHED_CONTENT + {"DETACHED_CONTENT", ERR_LIB_TS, TS_R_DETACHED_CONTENT}, + #else + {"DETACHED_CONTENT", 47, 134}, + #endif + #ifdef TS_R_ESS_ADD_SIGNING_CERT_ERROR + {"ESS_ADD_SIGNING_CERT_ERROR", ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_ERROR}, + #else + {"ESS_ADD_SIGNING_CERT_ERROR", 47, 116}, + #endif + #ifdef TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR + {"ESS_ADD_SIGNING_CERT_V2_ERROR", ERR_LIB_TS, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR}, + #else + {"ESS_ADD_SIGNING_CERT_V2_ERROR", 47, 139}, + #endif + #ifdef TS_R_ESS_SIGNING_CERTIFICATE_ERROR + {"ESS_SIGNING_CERTIFICATE_ERROR", ERR_LIB_TS, TS_R_ESS_SIGNING_CERTIFICATE_ERROR}, + #else + {"ESS_SIGNING_CERTIFICATE_ERROR", 47, 101}, + #endif + #ifdef TS_R_INVALID_NULL_POINTER + {"INVALID_NULL_POINTER", ERR_LIB_TS, TS_R_INVALID_NULL_POINTER}, + #else + {"INVALID_NULL_POINTER", 47, 102}, + #endif + #ifdef TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE + {"INVALID_SIGNER_CERTIFICATE_PURPOSE", ERR_LIB_TS, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE}, + #else + {"INVALID_SIGNER_CERTIFICATE_PURPOSE", 47, 117}, + #endif + #ifdef TS_R_MESSAGE_IMPRINT_MISMATCH + {"MESSAGE_IMPRINT_MISMATCH", ERR_LIB_TS, TS_R_MESSAGE_IMPRINT_MISMATCH}, + #else + {"MESSAGE_IMPRINT_MISMATCH", 47, 103}, + #endif + #ifdef TS_R_NONCE_MISMATCH + {"NONCE_MISMATCH", ERR_LIB_TS, TS_R_NONCE_MISMATCH}, + #else + {"NONCE_MISMATCH", 47, 104}, + #endif + #ifdef TS_R_NONCE_NOT_RETURNED + {"NONCE_NOT_RETURNED", ERR_LIB_TS, TS_R_NONCE_NOT_RETURNED}, + #else + {"NONCE_NOT_RETURNED", 47, 105}, + #endif + #ifdef TS_R_NO_CONTENT + {"NO_CONTENT", ERR_LIB_TS, TS_R_NO_CONTENT}, + #else + {"NO_CONTENT", 47, 106}, + #endif + #ifdef TS_R_NO_TIME_STAMP_TOKEN + {"NO_TIME_STAMP_TOKEN", ERR_LIB_TS, TS_R_NO_TIME_STAMP_TOKEN}, + #else + {"NO_TIME_STAMP_TOKEN", 47, 107}, + #endif + #ifdef TS_R_PKCS7_ADD_SIGNATURE_ERROR + {"PKCS7_ADD_SIGNATURE_ERROR", ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNATURE_ERROR}, + #else + {"PKCS7_ADD_SIGNATURE_ERROR", 47, 118}, + #endif + #ifdef TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR + {"PKCS7_ADD_SIGNED_ATTR_ERROR", ERR_LIB_TS, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR}, + #else + {"PKCS7_ADD_SIGNED_ATTR_ERROR", 47, 119}, + #endif + #ifdef TS_R_PKCS7_TO_TS_TST_INFO_FAILED + {"PKCS7_TO_TS_TST_INFO_FAILED", ERR_LIB_TS, TS_R_PKCS7_TO_TS_TST_INFO_FAILED}, + #else + {"PKCS7_TO_TS_TST_INFO_FAILED", 47, 129}, + #endif + #ifdef TS_R_POLICY_MISMATCH + {"POLICY_MISMATCH", ERR_LIB_TS, TS_R_POLICY_MISMATCH}, + #else + {"POLICY_MISMATCH", 47, 108}, + #endif + #ifdef TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", ERR_LIB_TS, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE}, + #else + {"PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE", 47, 120}, + #endif + #ifdef TS_R_RESPONSE_SETUP_ERROR + {"RESPONSE_SETUP_ERROR", ERR_LIB_TS, TS_R_RESPONSE_SETUP_ERROR}, + #else + {"RESPONSE_SETUP_ERROR", 47, 121}, + #endif + #ifdef TS_R_SIGNATURE_FAILURE + {"SIGNATURE_FAILURE", ERR_LIB_TS, TS_R_SIGNATURE_FAILURE}, + #else + {"SIGNATURE_FAILURE", 47, 109}, + #endif + #ifdef TS_R_THERE_MUST_BE_ONE_SIGNER + {"THERE_MUST_BE_ONE_SIGNER", ERR_LIB_TS, TS_R_THERE_MUST_BE_ONE_SIGNER}, + #else + {"THERE_MUST_BE_ONE_SIGNER", 47, 110}, + #endif + #ifdef TS_R_TIME_SYSCALL_ERROR + {"TIME_SYSCALL_ERROR", ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR}, + #else + {"TIME_SYSCALL_ERROR", 47, 122}, + #endif + #ifdef TS_R_TOKEN_NOT_PRESENT + {"TOKEN_NOT_PRESENT", ERR_LIB_TS, TS_R_TOKEN_NOT_PRESENT}, + #else + {"TOKEN_NOT_PRESENT", 47, 130}, + #endif + #ifdef TS_R_TOKEN_PRESENT + {"TOKEN_PRESENT", ERR_LIB_TS, TS_R_TOKEN_PRESENT}, + #else + {"TOKEN_PRESENT", 47, 131}, + #endif + #ifdef TS_R_TSA_NAME_MISMATCH + {"TSA_NAME_MISMATCH", ERR_LIB_TS, TS_R_TSA_NAME_MISMATCH}, + #else + {"TSA_NAME_MISMATCH", 47, 111}, + #endif + #ifdef TS_R_TSA_UNTRUSTED + {"TSA_UNTRUSTED", ERR_LIB_TS, TS_R_TSA_UNTRUSTED}, + #else + {"TSA_UNTRUSTED", 47, 112}, + #endif + #ifdef TS_R_TST_INFO_SETUP_ERROR + {"TST_INFO_SETUP_ERROR", ERR_LIB_TS, TS_R_TST_INFO_SETUP_ERROR}, + #else + {"TST_INFO_SETUP_ERROR", 47, 123}, + #endif + #ifdef TS_R_TS_DATASIGN + {"TS_DATASIGN", ERR_LIB_TS, TS_R_TS_DATASIGN}, + #else + {"TS_DATASIGN", 47, 124}, + #endif + #ifdef TS_R_UNACCEPTABLE_POLICY + {"UNACCEPTABLE_POLICY", ERR_LIB_TS, TS_R_UNACCEPTABLE_POLICY}, + #else + {"UNACCEPTABLE_POLICY", 47, 125}, + #endif + #ifdef TS_R_UNSUPPORTED_MD_ALGORITHM + {"UNSUPPORTED_MD_ALGORITHM", ERR_LIB_TS, TS_R_UNSUPPORTED_MD_ALGORITHM}, + #else + {"UNSUPPORTED_MD_ALGORITHM", 47, 126}, + #endif + #ifdef TS_R_UNSUPPORTED_VERSION + {"UNSUPPORTED_VERSION", ERR_LIB_TS, TS_R_UNSUPPORTED_VERSION}, + #else + {"UNSUPPORTED_VERSION", 47, 113}, + #endif + #ifdef TS_R_VAR_BAD_VALUE + {"VAR_BAD_VALUE", ERR_LIB_TS, TS_R_VAR_BAD_VALUE}, + #else + {"VAR_BAD_VALUE", 47, 135}, + #endif + #ifdef TS_R_VAR_LOOKUP_FAILURE + {"VAR_LOOKUP_FAILURE", ERR_LIB_TS, TS_R_VAR_LOOKUP_FAILURE}, + #else + {"VAR_LOOKUP_FAILURE", 47, 136}, + #endif + #ifdef TS_R_WRONG_CONTENT_TYPE + {"WRONG_CONTENT_TYPE", ERR_LIB_TS, TS_R_WRONG_CONTENT_TYPE}, + #else + {"WRONG_CONTENT_TYPE", 47, 114}, + #endif + #ifdef UI_R_COMMON_OK_AND_CANCEL_CHARACTERS + {"COMMON_OK_AND_CANCEL_CHARACTERS", ERR_LIB_UI, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS}, + #else + {"COMMON_OK_AND_CANCEL_CHARACTERS", 40, 104}, + #endif + #ifdef UI_R_INDEX_TOO_LARGE + {"INDEX_TOO_LARGE", ERR_LIB_UI, UI_R_INDEX_TOO_LARGE}, + #else + {"INDEX_TOO_LARGE", 40, 102}, + #endif + #ifdef UI_R_INDEX_TOO_SMALL + {"INDEX_TOO_SMALL", ERR_LIB_UI, UI_R_INDEX_TOO_SMALL}, + #else + {"INDEX_TOO_SMALL", 40, 103}, + #endif + #ifdef UI_R_NO_RESULT_BUFFER + {"NO_RESULT_BUFFER", ERR_LIB_UI, UI_R_NO_RESULT_BUFFER}, + #else + {"NO_RESULT_BUFFER", 40, 105}, + #endif + #ifdef UI_R_PROCESSING_ERROR + {"PROCESSING_ERROR", ERR_LIB_UI, UI_R_PROCESSING_ERROR}, + #else + {"PROCESSING_ERROR", 40, 107}, + #endif + #ifdef UI_R_RESULT_TOO_LARGE + {"RESULT_TOO_LARGE", ERR_LIB_UI, UI_R_RESULT_TOO_LARGE}, + #else + {"RESULT_TOO_LARGE", 40, 100}, + #endif + #ifdef UI_R_RESULT_TOO_SMALL + {"RESULT_TOO_SMALL", ERR_LIB_UI, UI_R_RESULT_TOO_SMALL}, + #else + {"RESULT_TOO_SMALL", 40, 101}, + #endif + #ifdef UI_R_SYSASSIGN_ERROR + {"SYSASSIGN_ERROR", ERR_LIB_UI, UI_R_SYSASSIGN_ERROR}, + #else + {"SYSASSIGN_ERROR", 40, 109}, + #endif + #ifdef UI_R_SYSDASSGN_ERROR + {"SYSDASSGN_ERROR", ERR_LIB_UI, UI_R_SYSDASSGN_ERROR}, + #else + {"SYSDASSGN_ERROR", 40, 110}, + #endif + #ifdef UI_R_SYSQIOW_ERROR + {"SYSQIOW_ERROR", ERR_LIB_UI, UI_R_SYSQIOW_ERROR}, + #else + {"SYSQIOW_ERROR", 40, 111}, + #endif + #ifdef UI_R_UNKNOWN_CONTROL_COMMAND + {"UNKNOWN_CONTROL_COMMAND", ERR_LIB_UI, UI_R_UNKNOWN_CONTROL_COMMAND}, + #else + {"UNKNOWN_CONTROL_COMMAND", 40, 106}, + #endif + #ifdef UI_R_UNKNOWN_TTYGET_ERRNO_VALUE + {"UNKNOWN_TTYGET_ERRNO_VALUE", ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE}, + #else + {"UNKNOWN_TTYGET_ERRNO_VALUE", 40, 108}, + #endif + #ifdef UI_R_USER_DATA_DUPLICATION_UNSUPPORTED + {"USER_DATA_DUPLICATION_UNSUPPORTED", ERR_LIB_UI, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED}, + #else + {"USER_DATA_DUPLICATION_UNSUPPORTED", 40, 112}, + #endif + #ifdef X509V3_R_BAD_IP_ADDRESS + {"BAD_IP_ADDRESS", ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS}, + #else + {"BAD_IP_ADDRESS", 34, 118}, + #endif + #ifdef X509V3_R_BAD_OBJECT + {"BAD_OBJECT", ERR_LIB_X509V3, X509V3_R_BAD_OBJECT}, + #else + {"BAD_OBJECT", 34, 119}, + #endif + #ifdef X509V3_R_BAD_OPTION + {"BAD_OPTION", ERR_LIB_X509V3, X509V3_R_BAD_OPTION}, + #else + {"BAD_OPTION", 34, 170}, + #endif + #ifdef X509V3_R_BAD_VALUE + {"BAD_VALUE", ERR_LIB_X509V3, X509V3_R_BAD_VALUE}, + #else + {"BAD_VALUE", 34, 171}, + #endif + #ifdef X509V3_R_BN_DEC2BN_ERROR + {"BN_DEC2BN_ERROR", ERR_LIB_X509V3, X509V3_R_BN_DEC2BN_ERROR}, + #else + {"BN_DEC2BN_ERROR", 34, 100}, + #endif + #ifdef X509V3_R_BN_TO_ASN1_INTEGER_ERROR + {"BN_TO_ASN1_INTEGER_ERROR", ERR_LIB_X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR}, + #else + {"BN_TO_ASN1_INTEGER_ERROR", 34, 101}, + #endif + #ifdef X509V3_R_DIRNAME_ERROR + {"DIRNAME_ERROR", ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR}, + #else + {"DIRNAME_ERROR", 34, 149}, + #endif + #ifdef X509V3_R_DISTPOINT_ALREADY_SET + {"DISTPOINT_ALREADY_SET", ERR_LIB_X509V3, X509V3_R_DISTPOINT_ALREADY_SET}, + #else + {"DISTPOINT_ALREADY_SET", 34, 160}, + #endif + #ifdef X509V3_R_DUPLICATE_ZONE_ID + {"DUPLICATE_ZONE_ID", ERR_LIB_X509V3, X509V3_R_DUPLICATE_ZONE_ID}, + #else + {"DUPLICATE_ZONE_ID", 34, 133}, + #endif + #ifdef X509V3_R_EMPTY_KEY_USAGE + {"EMPTY_KEY_USAGE", ERR_LIB_X509V3, X509V3_R_EMPTY_KEY_USAGE}, + #else + {"EMPTY_KEY_USAGE", 34, 169}, + #endif + #ifdef X509V3_R_ERROR_CONVERTING_ZONE + {"ERROR_CONVERTING_ZONE", ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE}, + #else + {"ERROR_CONVERTING_ZONE", 34, 131}, + #endif + #ifdef X509V3_R_ERROR_CREATING_EXTENSION + {"ERROR_CREATING_EXTENSION", ERR_LIB_X509V3, X509V3_R_ERROR_CREATING_EXTENSION}, + #else + {"ERROR_CREATING_EXTENSION", 34, 144}, + #endif + #ifdef X509V3_R_ERROR_IN_EXTENSION + {"ERROR_IN_EXTENSION", ERR_LIB_X509V3, X509V3_R_ERROR_IN_EXTENSION}, + #else + {"ERROR_IN_EXTENSION", 34, 128}, + #endif + #ifdef X509V3_R_EXPECTED_A_SECTION_NAME + {"EXPECTED_A_SECTION_NAME", ERR_LIB_X509V3, X509V3_R_EXPECTED_A_SECTION_NAME}, + #else + {"EXPECTED_A_SECTION_NAME", 34, 137}, + #endif + #ifdef X509V3_R_EXTENSION_EXISTS + {"EXTENSION_EXISTS", ERR_LIB_X509V3, X509V3_R_EXTENSION_EXISTS}, + #else + {"EXTENSION_EXISTS", 34, 145}, + #endif + #ifdef X509V3_R_EXTENSION_NAME_ERROR + {"EXTENSION_NAME_ERROR", ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR}, + #else + {"EXTENSION_NAME_ERROR", 34, 115}, + #endif + #ifdef X509V3_R_EXTENSION_NOT_FOUND + {"EXTENSION_NOT_FOUND", ERR_LIB_X509V3, X509V3_R_EXTENSION_NOT_FOUND}, + #else + {"EXTENSION_NOT_FOUND", 34, 102}, + #endif + #ifdef X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED + {"EXTENSION_SETTING_NOT_SUPPORTED", ERR_LIB_X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED}, + #else + {"EXTENSION_SETTING_NOT_SUPPORTED", 34, 103}, + #endif + #ifdef X509V3_R_EXTENSION_VALUE_ERROR + {"EXTENSION_VALUE_ERROR", ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR}, + #else + {"EXTENSION_VALUE_ERROR", 34, 116}, + #endif + #ifdef X509V3_R_ILLEGAL_EMPTY_EXTENSION + {"ILLEGAL_EMPTY_EXTENSION", ERR_LIB_X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION}, + #else + {"ILLEGAL_EMPTY_EXTENSION", 34, 151}, + #endif + #ifdef X509V3_R_INCORRECT_POLICY_SYNTAX_TAG + {"INCORRECT_POLICY_SYNTAX_TAG", ERR_LIB_X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG}, + #else + {"INCORRECT_POLICY_SYNTAX_TAG", 34, 152}, + #endif + #ifdef X509V3_R_INVALID_ASNUMBER + {"INVALID_ASNUMBER", ERR_LIB_X509V3, X509V3_R_INVALID_ASNUMBER}, + #else + {"INVALID_ASNUMBER", 34, 162}, + #endif + #ifdef X509V3_R_INVALID_ASRANGE + {"INVALID_ASRANGE", ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE}, + #else + {"INVALID_ASRANGE", 34, 163}, + #endif + #ifdef X509V3_R_INVALID_BOOLEAN_STRING + {"INVALID_BOOLEAN_STRING", ERR_LIB_X509V3, X509V3_R_INVALID_BOOLEAN_STRING}, + #else + {"INVALID_BOOLEAN_STRING", 34, 104}, + #endif + #ifdef X509V3_R_INVALID_CERTIFICATE + {"INVALID_CERTIFICATE", ERR_LIB_X509V3, X509V3_R_INVALID_CERTIFICATE}, + #else + {"INVALID_CERTIFICATE", 34, 158}, + #endif + #ifdef X509V3_R_INVALID_EMPTY_NAME + {"INVALID_EMPTY_NAME", ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME}, + #else + {"INVALID_EMPTY_NAME", 34, 108}, + #endif + #ifdef X509V3_R_INVALID_EXTENSION_STRING + {"INVALID_EXTENSION_STRING", ERR_LIB_X509V3, X509V3_R_INVALID_EXTENSION_STRING}, + #else + {"INVALID_EXTENSION_STRING", 34, 105}, + #endif + #ifdef X509V3_R_INVALID_INHERITANCE + {"INVALID_INHERITANCE", ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE}, + #else + {"INVALID_INHERITANCE", 34, 165}, + #endif + #ifdef X509V3_R_INVALID_IPADDRESS + {"INVALID_IPADDRESS", ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS}, + #else + {"INVALID_IPADDRESS", 34, 166}, + #endif + #ifdef X509V3_R_INVALID_MULTIPLE_RDNS + {"INVALID_MULTIPLE_RDNS", ERR_LIB_X509V3, X509V3_R_INVALID_MULTIPLE_RDNS}, + #else + {"INVALID_MULTIPLE_RDNS", 34, 161}, + #endif + #ifdef X509V3_R_INVALID_NAME + {"INVALID_NAME", ERR_LIB_X509V3, X509V3_R_INVALID_NAME}, + #else + {"INVALID_NAME", 34, 106}, + #endif + #ifdef X509V3_R_INVALID_NULL_ARGUMENT + {"INVALID_NULL_ARGUMENT", ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT}, + #else + {"INVALID_NULL_ARGUMENT", 34, 107}, + #endif + #ifdef X509V3_R_INVALID_NULL_VALUE + {"INVALID_NULL_VALUE", ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE}, + #else + {"INVALID_NULL_VALUE", 34, 109}, + #endif + #ifdef X509V3_R_INVALID_NUMBER + {"INVALID_NUMBER", ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER}, + #else + {"INVALID_NUMBER", 34, 140}, + #endif + #ifdef X509V3_R_INVALID_NUMBERS + {"INVALID_NUMBERS", ERR_LIB_X509V3, X509V3_R_INVALID_NUMBERS}, + #else + {"INVALID_NUMBERS", 34, 141}, + #endif + #ifdef X509V3_R_INVALID_OBJECT_IDENTIFIER + {"INVALID_OBJECT_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER}, + #else + {"INVALID_OBJECT_IDENTIFIER", 34, 110}, + #endif + #ifdef X509V3_R_INVALID_OPTION + {"INVALID_OPTION", ERR_LIB_X509V3, X509V3_R_INVALID_OPTION}, + #else + {"INVALID_OPTION", 34, 138}, + #endif + #ifdef X509V3_R_INVALID_POLICY_IDENTIFIER + {"INVALID_POLICY_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER}, + #else + {"INVALID_POLICY_IDENTIFIER", 34, 134}, + #endif + #ifdef X509V3_R_INVALID_PROXY_POLICY_SETTING + {"INVALID_PROXY_POLICY_SETTING", ERR_LIB_X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING}, + #else + {"INVALID_PROXY_POLICY_SETTING", 34, 153}, + #endif + #ifdef X509V3_R_INVALID_PURPOSE + {"INVALID_PURPOSE", ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE}, + #else + {"INVALID_PURPOSE", 34, 146}, + #endif + #ifdef X509V3_R_INVALID_SAFI + {"INVALID_SAFI", ERR_LIB_X509V3, X509V3_R_INVALID_SAFI}, + #else + {"INVALID_SAFI", 34, 164}, + #endif + #ifdef X509V3_R_INVALID_SECTION + {"INVALID_SECTION", ERR_LIB_X509V3, X509V3_R_INVALID_SECTION}, + #else + {"INVALID_SECTION", 34, 135}, + #endif + #ifdef X509V3_R_INVALID_SYNTAX + {"INVALID_SYNTAX", ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX}, + #else + {"INVALID_SYNTAX", 34, 143}, + #endif + #ifdef X509V3_R_ISSUER_DECODE_ERROR + {"ISSUER_DECODE_ERROR", ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR}, + #else + {"ISSUER_DECODE_ERROR", 34, 126}, + #endif + #ifdef X509V3_R_MISSING_VALUE + {"MISSING_VALUE", ERR_LIB_X509V3, X509V3_R_MISSING_VALUE}, + #else + {"MISSING_VALUE", 34, 124}, + #endif + #ifdef X509V3_R_NEED_ORGANIZATION_AND_NUMBERS + {"NEED_ORGANIZATION_AND_NUMBERS", ERR_LIB_X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS}, + #else + {"NEED_ORGANIZATION_AND_NUMBERS", 34, 142}, + #endif + #ifdef X509V3_R_NEGATIVE_PATHLEN + {"NEGATIVE_PATHLEN", ERR_LIB_X509V3, X509V3_R_NEGATIVE_PATHLEN}, + #else + {"NEGATIVE_PATHLEN", 34, 168}, + #endif + #ifdef X509V3_R_NO_CONFIG_DATABASE + {"NO_CONFIG_DATABASE", ERR_LIB_X509V3, X509V3_R_NO_CONFIG_DATABASE}, + #else + {"NO_CONFIG_DATABASE", 34, 136}, + #endif + #ifdef X509V3_R_NO_ISSUER_CERTIFICATE + {"NO_ISSUER_CERTIFICATE", ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE}, + #else + {"NO_ISSUER_CERTIFICATE", 34, 121}, + #endif + #ifdef X509V3_R_NO_ISSUER_DETAILS + {"NO_ISSUER_DETAILS", ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS}, + #else + {"NO_ISSUER_DETAILS", 34, 127}, + #endif + #ifdef X509V3_R_NO_POLICY_IDENTIFIER + {"NO_POLICY_IDENTIFIER", ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER}, + #else + {"NO_POLICY_IDENTIFIER", 34, 139}, + #endif + #ifdef X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED + {"NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED", ERR_LIB_X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED}, + #else + {"NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED", 34, 154}, + #endif + #ifdef X509V3_R_NO_PUBLIC_KEY + {"NO_PUBLIC_KEY", ERR_LIB_X509V3, X509V3_R_NO_PUBLIC_KEY}, + #else + {"NO_PUBLIC_KEY", 34, 114}, + #endif + #ifdef X509V3_R_NO_SUBJECT_DETAILS + {"NO_SUBJECT_DETAILS", ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS}, + #else + {"NO_SUBJECT_DETAILS", 34, 125}, + #endif + #ifdef X509V3_R_OPERATION_NOT_DEFINED + {"OPERATION_NOT_DEFINED", ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED}, + #else + {"OPERATION_NOT_DEFINED", 34, 148}, + #endif + #ifdef X509V3_R_OTHERNAME_ERROR + {"OTHERNAME_ERROR", ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR}, + #else + {"OTHERNAME_ERROR", 34, 147}, + #endif + #ifdef X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED + {"POLICY_LANGUAGE_ALREADY_DEFINED", ERR_LIB_X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED}, + #else + {"POLICY_LANGUAGE_ALREADY_DEFINED", 34, 155}, + #endif + #ifdef X509V3_R_POLICY_PATH_LENGTH + {"POLICY_PATH_LENGTH", ERR_LIB_X509V3, X509V3_R_POLICY_PATH_LENGTH}, + #else + {"POLICY_PATH_LENGTH", 34, 156}, + #endif + #ifdef X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED + {"POLICY_PATH_LENGTH_ALREADY_DEFINED", ERR_LIB_X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED}, + #else + {"POLICY_PATH_LENGTH_ALREADY_DEFINED", 34, 157}, + #endif + #ifdef X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY + {"POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY", ERR_LIB_X509V3, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY}, + #else + {"POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY", 34, 159}, + #endif + #ifdef X509V3_R_PURPOSE_NOT_UNIQUE + {"PURPOSE_NOT_UNIQUE", ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE}, + #else + {"PURPOSE_NOT_UNIQUE", 34, 173}, + #endif + #ifdef X509V3_R_SECTION_NOT_FOUND + {"SECTION_NOT_FOUND", ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND}, + #else + {"SECTION_NOT_FOUND", 34, 150}, + #endif + #ifdef X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS + {"UNABLE_TO_GET_ISSUER_DETAILS", ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS}, + #else + {"UNABLE_TO_GET_ISSUER_DETAILS", 34, 122}, + #endif + #ifdef X509V3_R_UNABLE_TO_GET_ISSUER_KEYID + {"UNABLE_TO_GET_ISSUER_KEYID", ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID}, + #else + {"UNABLE_TO_GET_ISSUER_KEYID", 34, 123}, + #endif + #ifdef X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT + {"UNKNOWN_BIT_STRING_ARGUMENT", ERR_LIB_X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT}, + #else + {"UNKNOWN_BIT_STRING_ARGUMENT", 34, 111}, + #endif + #ifdef X509V3_R_UNKNOWN_EXTENSION + {"UNKNOWN_EXTENSION", ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION}, + #else + {"UNKNOWN_EXTENSION", 34, 129}, + #endif + #ifdef X509V3_R_UNKNOWN_EXTENSION_NAME + {"UNKNOWN_EXTENSION_NAME", ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME}, + #else + {"UNKNOWN_EXTENSION_NAME", 34, 130}, + #endif + #ifdef X509V3_R_UNKNOWN_OPTION + {"UNKNOWN_OPTION", ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION}, + #else + {"UNKNOWN_OPTION", 34, 120}, + #endif + #ifdef X509V3_R_UNKNOWN_VALUE + {"UNKNOWN_VALUE", ERR_LIB_X509V3, X509V3_R_UNKNOWN_VALUE}, + #else + {"UNKNOWN_VALUE", 34, 172}, + #endif + #ifdef X509V3_R_UNSUPPORTED_OPTION + {"UNSUPPORTED_OPTION", ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION}, + #else + {"UNSUPPORTED_OPTION", 34, 117}, + #endif + #ifdef X509V3_R_UNSUPPORTED_TYPE + {"UNSUPPORTED_TYPE", ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE}, + #else + {"UNSUPPORTED_TYPE", 34, 167}, + #endif + #ifdef X509V3_R_USER_TOO_LONG + {"USER_TOO_LONG", ERR_LIB_X509V3, X509V3_R_USER_TOO_LONG}, + #else + {"USER_TOO_LONG", 34, 132}, + #endif + #ifdef X509_R_AKID_MISMATCH + {"AKID_MISMATCH", ERR_LIB_X509, X509_R_AKID_MISMATCH}, + #else + {"AKID_MISMATCH", 11, 110}, + #endif + #ifdef X509_R_BAD_SELECTOR + {"BAD_SELECTOR", ERR_LIB_X509, X509_R_BAD_SELECTOR}, + #else + {"BAD_SELECTOR", 11, 133}, + #endif + #ifdef X509_R_BAD_X509_FILETYPE + {"BAD_X509_FILETYPE", ERR_LIB_X509, X509_R_BAD_X509_FILETYPE}, + #else + {"BAD_X509_FILETYPE", 11, 100}, + #endif + #ifdef X509_R_BASE64_DECODE_ERROR + {"BASE64_DECODE_ERROR", ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR}, + #else + {"BASE64_DECODE_ERROR", 11, 118}, + #endif + #ifdef X509_R_CANT_CHECK_DH_KEY + {"CANT_CHECK_DH_KEY", ERR_LIB_X509, X509_R_CANT_CHECK_DH_KEY}, + #else + {"CANT_CHECK_DH_KEY", 11, 114}, + #endif + #ifdef X509_R_CERTIFICATE_VERIFICATION_FAILED + {"CERTIFICATE_VERIFICATION_FAILED", ERR_LIB_X509, X509_R_CERTIFICATE_VERIFICATION_FAILED}, + #else + {"CERTIFICATE_VERIFICATION_FAILED", 11, 139}, + #endif + #ifdef X509_R_CERT_ALREADY_IN_HASH_TABLE + {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE}, + #else + {"CERT_ALREADY_IN_HASH_TABLE", 11, 101}, + #endif + #ifdef X509_R_CRL_ALREADY_DELTA + {"CRL_ALREADY_DELTA", ERR_LIB_X509, X509_R_CRL_ALREADY_DELTA}, + #else + {"CRL_ALREADY_DELTA", 11, 127}, + #endif + #ifdef X509_R_CRL_VERIFY_FAILURE + {"CRL_VERIFY_FAILURE", ERR_LIB_X509, X509_R_CRL_VERIFY_FAILURE}, + #else + {"CRL_VERIFY_FAILURE", 11, 131}, + #endif + #ifdef X509_R_DUPLICATE_ATTRIBUTE + {"DUPLICATE_ATTRIBUTE", ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE}, + #else + {"DUPLICATE_ATTRIBUTE", 11, 140}, + #endif + #ifdef X509_R_ERROR_GETTING_MD_BY_NID + {"ERROR_GETTING_MD_BY_NID", ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID}, + #else + {"ERROR_GETTING_MD_BY_NID", 11, 141}, + #endif + #ifdef X509_R_ERROR_USING_SIGINF_SET + {"ERROR_USING_SIGINF_SET", ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET}, + #else + {"ERROR_USING_SIGINF_SET", 11, 142}, + #endif + #ifdef X509_R_IDP_MISMATCH + {"IDP_MISMATCH", ERR_LIB_X509, X509_R_IDP_MISMATCH}, + #else + {"IDP_MISMATCH", 11, 128}, + #endif + #ifdef X509_R_INVALID_ATTRIBUTES + {"INVALID_ATTRIBUTES", ERR_LIB_X509, X509_R_INVALID_ATTRIBUTES}, + #else + {"INVALID_ATTRIBUTES", 11, 138}, + #endif + #ifdef X509_R_INVALID_DIRECTORY + {"INVALID_DIRECTORY", ERR_LIB_X509, X509_R_INVALID_DIRECTORY}, + #else + {"INVALID_DIRECTORY", 11, 113}, + #endif + #ifdef X509_R_INVALID_DISTPOINT + {"INVALID_DISTPOINT", ERR_LIB_X509, X509_R_INVALID_DISTPOINT}, + #else + {"INVALID_DISTPOINT", 11, 143}, + #endif + #ifdef X509_R_INVALID_EXTENSION + {"INVALID_EXTENSION", ERR_LIB_X509, X509_R_INVALID_EXTENSION}, + #else + {"INVALID_EXTENSION", 11, 146}, + #endif + #ifdef X509_R_INVALID_FIELD_NAME + {"INVALID_FIELD_NAME", ERR_LIB_X509, X509_R_INVALID_FIELD_NAME}, + #else + {"INVALID_FIELD_NAME", 11, 119}, + #endif + #ifdef X509_R_INVALID_TRUST + {"INVALID_TRUST", ERR_LIB_X509, X509_R_INVALID_TRUST}, + #else + {"INVALID_TRUST", 11, 123}, + #endif + #ifdef X509_R_ISSUER_MISMATCH + {"ISSUER_MISMATCH", ERR_LIB_X509, X509_R_ISSUER_MISMATCH}, + #else + {"ISSUER_MISMATCH", 11, 129}, + #endif + #ifdef X509_R_KEY_TYPE_MISMATCH + {"KEY_TYPE_MISMATCH", ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH}, + #else + {"KEY_TYPE_MISMATCH", 11, 115}, + #endif + #ifdef X509_R_KEY_VALUES_MISMATCH + {"KEY_VALUES_MISMATCH", ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH}, + #else + {"KEY_VALUES_MISMATCH", 11, 116}, + #endif + #ifdef X509_R_LOADING_CERT_DIR + {"LOADING_CERT_DIR", ERR_LIB_X509, X509_R_LOADING_CERT_DIR}, + #else + {"LOADING_CERT_DIR", 11, 103}, + #endif + #ifdef X509_R_LOADING_DEFAULTS + {"LOADING_DEFAULTS", ERR_LIB_X509, X509_R_LOADING_DEFAULTS}, + #else + {"LOADING_DEFAULTS", 11, 104}, + #endif + #ifdef X509_R_METHOD_NOT_SUPPORTED + {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED}, + #else + {"METHOD_NOT_SUPPORTED", 11, 124}, + #endif + #ifdef X509_R_NAME_TOO_LONG + {"NAME_TOO_LONG", ERR_LIB_X509, X509_R_NAME_TOO_LONG}, + #else + {"NAME_TOO_LONG", 11, 134}, + #endif + #ifdef X509_R_NEWER_CRL_NOT_NEWER + {"NEWER_CRL_NOT_NEWER", ERR_LIB_X509, X509_R_NEWER_CRL_NOT_NEWER}, + #else + {"NEWER_CRL_NOT_NEWER", 11, 132}, + #endif + #ifdef X509_R_NO_CERTIFICATE_FOUND + {"NO_CERTIFICATE_FOUND", ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND}, + #else + {"NO_CERTIFICATE_FOUND", 11, 135}, + #endif + #ifdef X509_R_NO_CERTIFICATE_OR_CRL_FOUND + {"NO_CERTIFICATE_OR_CRL_FOUND", ERR_LIB_X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND}, + #else + {"NO_CERTIFICATE_OR_CRL_FOUND", 11, 136}, + #endif + #ifdef X509_R_NO_CERT_SET_FOR_US_TO_VERIFY + {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY}, + #else + {"NO_CERT_SET_FOR_US_TO_VERIFY", 11, 105}, + #endif + #ifdef X509_R_NO_CRL_FOUND + {"NO_CRL_FOUND", ERR_LIB_X509, X509_R_NO_CRL_FOUND}, + #else + {"NO_CRL_FOUND", 11, 137}, + #endif + #ifdef X509_R_NO_CRL_NUMBER + {"NO_CRL_NUMBER", ERR_LIB_X509, X509_R_NO_CRL_NUMBER}, + #else + {"NO_CRL_NUMBER", 11, 130}, + #endif + #ifdef X509_R_PUBLIC_KEY_DECODE_ERROR + {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_DECODE_ERROR}, + #else + {"PUBLIC_KEY_DECODE_ERROR", 11, 125}, + #endif + #ifdef X509_R_PUBLIC_KEY_ENCODE_ERROR + {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR}, + #else + {"PUBLIC_KEY_ENCODE_ERROR", 11, 126}, + #endif + #ifdef X509_R_SHOULD_RETRY + {"SHOULD_RETRY", ERR_LIB_X509, X509_R_SHOULD_RETRY}, + #else + {"SHOULD_RETRY", 11, 106}, + #endif + #ifdef X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN + {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN}, + #else + {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", 11, 107}, + #endif + #ifdef X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY + {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY}, + #else + {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", 11, 108}, + #endif + #ifdef X509_R_UNKNOWN_KEY_TYPE + {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE}, + #else + {"UNKNOWN_KEY_TYPE", 11, 117}, + #endif + #ifdef X509_R_UNKNOWN_NID + {"UNKNOWN_NID", ERR_LIB_X509, X509_R_UNKNOWN_NID}, + #else + {"UNKNOWN_NID", 11, 109}, + #endif + #ifdef X509_R_UNKNOWN_PURPOSE_ID + {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID}, + #else + {"UNKNOWN_PURPOSE_ID", 11, 121}, + #endif + #ifdef X509_R_UNKNOWN_SIGID_ALGS + {"UNKNOWN_SIGID_ALGS", ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS}, + #else + {"UNKNOWN_SIGID_ALGS", 11, 144}, + #endif + #ifdef X509_R_UNKNOWN_TRUST_ID + {"UNKNOWN_TRUST_ID", ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID}, + #else + {"UNKNOWN_TRUST_ID", 11, 120}, + #endif + #ifdef X509_R_UNSUPPORTED_ALGORITHM + {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM}, + #else + {"UNSUPPORTED_ALGORITHM", 11, 111}, + #endif + #ifdef X509_R_UNSUPPORTED_VERSION + {"UNSUPPORTED_VERSION", ERR_LIB_X509, X509_R_UNSUPPORTED_VERSION}, + #else + {"UNSUPPORTED_VERSION", 11, 145}, + #endif + #ifdef X509_R_WRONG_LOOKUP_TYPE + {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE}, + #else + {"WRONG_LOOKUP_TYPE", 11, 112}, + #endif + #ifdef X509_R_WRONG_TYPE + {"WRONG_TYPE", ERR_LIB_X509, X509_R_WRONG_TYPE}, + #else + {"WRONG_TYPE", 11, 122}, + #endif + {NULL, 0, 0} /* sentinel */ +}; diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index c00bad46a54..619f9f50574 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -996,12 +996,51 @@ get_eval_frame_stats(PyObject *self, PyObject *Py_UNUSED(args)) } static PyObject * -set_eval_frame_interp(PyObject *self, PyObject *Py_UNUSED(args)) +record_eval_interp(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc) { - _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), Test_EvalFrame); + if (PyStackRef_FunctionCheck(f->f_funcobj)) { + PyFunctionObject *func = _PyFrame_GetFunction(f); + PyObject *module = _get_current_module(); + assert(module != NULL); + module_state *state = get_module_state(module); + Py_DECREF(module); + int res = PyList_Append(state->record_list, func->func_name); + if (res < 0) { + return NULL; + } + } + + return Test_EvalFrame(tstate, f, exc); +} + +static PyObject * +set_eval_frame_interp(PyObject *self, PyObject *args) +{ + if (PyTuple_GET_SIZE(args) == 1) { + module_state *state = get_module_state(self); + PyObject *list = PyTuple_GET_ITEM(args, 0); + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "argument must be a list"); + return NULL; + } + Py_XSETREF(state->record_list, Py_NewRef(list)); + _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), record_eval_interp); + _PyInterpreterState_SetEvalFrameAllowSpecialization(_PyInterpreterState_GET(), 1); + } else { + _PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), Test_EvalFrame); + _PyInterpreterState_SetEvalFrameAllowSpecialization(_PyInterpreterState_GET(), 1); + } + Py_RETURN_NONE; } +static PyObject * +is_specialization_enabled(PyObject *self, PyObject *Py_UNUSED(args)) +{ + return PyBool_FromLong( + _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())); +} + /*[clinic input] _testinternalcapi.compiler_cleandoc -> object @@ -1042,13 +1081,17 @@ _testinternalcapi.compiler_codegen -> object compile_mode: int = 0 Apply compiler code generation to an AST. + +Return (instruction_sequence, metadata). metadata maps "argcount", +"posonlyargcount", "kwonlyargcount" to ints and "consts" to the list of +constants in LOAD_CONST index order (for use with optimize_cfg). [clinic start generated code]*/ static PyObject * _testinternalcapi_compiler_codegen_impl(PyObject *module, PyObject *ast, PyObject *filename, int optimize, int compile_mode) -/*[clinic end generated code: output=40a68f6e13951cc8 input=a0e00784f1517cd7]*/ +/*[clinic end generated code: output=40a68f6e13951cc8 input=e0c65e5c80efe30e]*/ { PyCompilerFlags *flags = NULL; return _PyCompile_CodeGen(ast, filename, flags, optimize, compile_mode); @@ -1064,12 +1107,15 @@ _testinternalcapi.optimize_cfg -> object nlocals: int Apply compiler optimizations to an instruction list. + +consts must be a list aligned with LOAD_CONST opargs (the "consts" entry +from the metadata dict returned by compiler_codegen for the same unit). [clinic start generated code]*/ static PyObject * _testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, PyObject *consts, int nlocals) -/*[clinic end generated code: output=57c53c3a3dfd1df0 input=6a96d1926d58d7e5]*/ +/*[clinic end generated code: output=57c53c3a3dfd1df0 input=905c3d935e063b27]*/ { return _PyCompile_OptimizeCfg(instructions, consts, nlocals); } @@ -2875,8 +2921,9 @@ static PyMethodDef module_functions[] = { {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS}, {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS}, {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL}, - {"set_eval_frame_interp", set_eval_frame_interp, METH_NOARGS, NULL}, + {"set_eval_frame_interp", set_eval_frame_interp, METH_VARARGS, NULL}, {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL}, + {"is_specialization_enabled", is_specialization_enabled, METH_NOARGS, NULL}, _TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF _TESTINTERNALCAPI_NEW_INSTRUCTION_SEQUENCE_METHODDEF _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF diff --git a/Modules/_testinternalcapi/interpreter.c b/Modules/_testinternalcapi/interpreter.c index 2cd23fa3c58..99dcd18393f 100644 --- a/Modules/_testinternalcapi/interpreter.c +++ b/Modules/_testinternalcapi/interpreter.c @@ -9,6 +9,9 @@ #include "../../Python/ceval_macros.h" +#undef IS_PEP523_HOOKED +#define IS_PEP523_HOOKED(tstate) (tstate->interp->eval_frame != NULL && !tstate->interp->eval_frame_allow_specialization) + int Test_EvalFrame_Resumes, Test_EvalFrame_Loads; #ifdef _Py_TIER2 diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index c2e69d35070..8897854078b 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -342,11 +342,13 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -367,6 +369,9 @@ if (res_o == NULL) { JUMP_TO_LABEL(error); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -1897,7 +1902,7 @@ JUMP_TO_PREDICTED(CALL); } } - // _CHECK_AND_ALLOCATE_OBJECT + // _CHECK_OBJECT { self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; @@ -1919,6 +1924,13 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _ALLOCATE_OBJECT + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -2276,13 +2288,11 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_CLASS + // _GUARD_CALLABLE_BUILTIN_CLASS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -2291,36 +2301,57 @@ JUMP_TO_PREDICTED(CALL); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_BUILTIN_CLASS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2433,7 +2464,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS @@ -2463,20 +2494,36 @@ } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2532,6 +2579,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_BUILTIN_O { args = &stack_pointer[-oparg]; @@ -2539,11 +2594,6 @@ if (!PyStackRef_IsNull(self_or_null)) { args--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -3792,7 +3842,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST @@ -3844,7 +3894,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc, self, @@ -3853,17 +3903,32 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3888,7 +3953,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS @@ -3941,7 +4006,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc, self, @@ -3950,17 +4015,32 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -5833,7 +5913,7 @@ int og_oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); } opcode = og_opcode; @@ -6299,6 +6379,58 @@ DISPATCH(); } + TARGET(FOR_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = FOR_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef null_or_index; + _PyStackRef next; + /* Skip 1 cache entry */ + // _GUARD_NOS_ITER_VIRTUAL + { + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + } + // _FOR_ITER_VIRTUAL + { + null_or_index = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + stack_pointer[-1] = null_or_index; + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_AITER) { #if _Py_TAIL_CALL_INTERP int opcode = GET_AITER; @@ -6419,22 +6551,41 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(GET_ITER); + PREDICTED_GET_ITER:; + _Py_CODEUNIT* const this_instr = next_instr - 2; + (void)this_instr; _PyStackRef iterable; _PyStackRef iter; _PyStackRef index_or_null; - iterable = stack_pointer[-1]; - #ifdef Py_STATS - _Py_GatherStats_GetIter(iterable); - #endif - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (PyStackRef_IsError(result)) { - JUMP_TO_LABEL(pop_1_error); + // _SPECIALIZE_GET_ITER + { + iterable = stack_pointer[-1]; + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_GetIter(iterable, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH_SAME_OPARG(); + } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ + } + // _GET_ITER + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); + } + iter = result; } - iter = result; stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; @@ -6442,6 +6593,76 @@ DISPATCH(); } + TARGET(GET_ITER_SELF) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_SELF; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_SELF); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef res; + /* Skip 1 cache entry */ + // _GUARD_ITERATOR + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_NULL + { + res = PyStackRef_NULL; + } + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + + TARGET(GET_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef zero; + /* Skip 1 cache entry */ + // _GUARD_ITER_VIRTUAL + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_TAGGED_ZERO + { + zero = PyStackRef_TagInt(0); + } + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_LEN) { #if _Py_TAIL_CALL_INTERP int opcode = GET_LEN; @@ -8233,50 +8454,81 @@ INSTRUCTION_STATS(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); _PyStackRef owner; + _PyStackRef new_frame; /* Skip 1 cache entry */ - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - uint32_t func_version = read_u32(&this_instr[4].cache); - PyObject *getattribute = read_obj(&this_instr[6].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert((oparg & 1) == 0); - if (IS_PEP523_HOOKED(tstate)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _GUARD_TYPE_VERSION + { + owner = stack_pointer[-1]; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + assert(type_version != 0); + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - if (FT_ATOMIC_LOAD_UINT_RELAXED(cls->tp_version_tag) != type_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _CHECK_PEP_523 + { + if (IS_PEP523_HOOKED(tstate)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); - PyFunctionObject *f = (PyFunctionObject *)getattribute; - assert(func_version != 0); - if (f->func_version != func_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + { + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *getattribute = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } - PyCodeObject *code = (PyCodeObject *)f->func_code; - assert(code->co_argcount == 2); - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif } - STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( - tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = 10u ; - DISPATCH_INLINED(new_frame); + // _PUSH_FRAME + { + assert(!IS_PEP523_HOOKED(tstate)); + _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(temp->previous == frame || temp->previous->previous == frame); + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = temp; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + LLTRACE_RESUME_FRAME(); + } + DISPATCH(); } TARGET(LOAD_ATTR_INSTANCE_VALUE) { @@ -8765,29 +9017,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -12242,9 +12484,12 @@ } DISPATCH(); } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_CLEAR(tracer->prev_state.recorded_value); - stack_pointer = _PyFrame_GetStackPointer(frame); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_CLEAR(tracer->prev_state.recorded_values[i]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -12255,14 +12500,18 @@ tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; @@ -12868,6 +13117,9 @@ JUMP_TO_LABEL(error); DISPATCH(); } + #if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2) + Py_GCC_ATTRIBUTE((unused)) + #endif LABEL(stop_tracing) { #if _Py_TIER2 diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index 48fe9c14f4e..d99b618c839 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -178,6 +178,9 @@ static void *opcode_targets_table[256] = { &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_FOR_ITER_VIRTUAL, + &&TARGET_GET_ITER_SELF, + &&TARGET_GET_ITER_VIRTUAL, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -230,9 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -473,9 +473,9 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -621,10 +621,13 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_SELF(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); @@ -862,10 +865,13 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST, [FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE, [FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_FOR_ITER_VIRTUAL, [GET_AITER] = _TAIL_CALL_GET_AITER, [GET_ANEXT] = _TAIL_CALL_GET_ANEXT, [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, + [GET_ITER_SELF] = _TAIL_CALL_GET_ITER_SELF, + [GET_ITER_VIRTUAL] = _TAIL_CALL_GET_ITER_VIRTUAL, [GET_LEN] = _TAIL_CALL_GET_LEN, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, @@ -1008,9 +1014,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1120,10 +1123,13 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_RANGE] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_TUPLE] = _TAIL_CALL_TRACE_RECORD, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_AITER] = _TAIL_CALL_TRACE_RECORD, [GET_ANEXT] = _TAIL_CALL_TRACE_RECORD, [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_SELF] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, @@ -1266,9 +1272,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Modules/_zstd/compressor.c b/Modules/_zstd/compressor.c index f90bc9c5ab5..8a3cd182ab1 100644 --- a/Modules/_zstd/compressor.c +++ b/Modules/_zstd/compressor.c @@ -74,7 +74,7 @@ zstd_contentsize_converter(PyObject *size, unsigned long long *p) if (PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Format(PyExc_ValueError, "size argument should be a positive int less " - "than %ull", ZSTD_CONTENTSIZE_ERROR); + "than %llu", ZSTD_CONTENTSIZE_ERROR); return 0; } return 0; @@ -83,7 +83,7 @@ zstd_contentsize_converter(PyObject *size, unsigned long long *p) *p = ZSTD_CONTENTSIZE_ERROR; PyErr_Format(PyExc_ValueError, "size argument should be a positive int less " - "than %ull", ZSTD_CONTENTSIZE_ERROR); + "than %llu", ZSTD_CONTENTSIZE_ERROR); return 0; } *p = pledged_size; diff --git a/Modules/_zstd/decompressor.c b/Modules/_zstd/decompressor.c index 0186ee92f5b..46682b483ad 100644 --- a/Modules/_zstd/decompressor.c +++ b/Modules/_zstd/decompressor.c @@ -111,6 +111,7 @@ _zstd_set_d_parameters(ZstdDecompressor *self, PyObject *options) int key_v = PyLong_AsInt(key); Py_DECREF(key); if (key_v == -1 && PyErr_Occurred()) { + Py_DECREF(value); return -1; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a86a7561271..b01e92eb887 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3053,8 +3053,10 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) len = 0; a = newarrayobject(type, len, descr); - if (a == NULL) + if (a == NULL) { + Py_XDECREF(it); return NULL; + } if (len > 0 && !array_Check(initial, state)) { Py_ssize_t i; @@ -3063,11 +3065,13 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PySequence_GetItem(initial, i); if (v == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } if (setarrayitem(a, i, v) != 0) { Py_DECREF(v); Py_DECREF(a); + Py_XDECREF(it); return NULL; } Py_DECREF(v); @@ -3079,6 +3083,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) v = array_array_frombytes((PyObject *)a, initial); if (v == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } Py_DECREF(v); @@ -3089,6 +3094,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) wchar_t *ustr = PyUnicode_AsWideCharString(initial, &n); if (ustr == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } @@ -3109,6 +3115,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_UCS4 *ustr = PyUnicode_AsUCS4Copy(initial); if (ustr == NULL) { Py_DECREF(a); + Py_XDECREF(it); return NULL; } @@ -3136,6 +3143,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return a; } } + Py_XDECREF(it); PyErr_SetString(PyExc_ValueError, "bad typecode (must be b, B, u, w, h, H, i, I, l, L, q, Q, f or d)"); return NULL; diff --git a/Modules/binascii.c b/Modules/binascii.c index b80bfbfffe4..7e6e9655f8d 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -244,6 +244,9 @@ static const _Py_ALIGNED_DEF(64, unsigned char) table_b2a_base85_a85[] = #define BASE85_A85_Z 0x00000000 #define BASE85_A85_Y 0x20202020 +/* 85**0 through 85**4, used for canonical encoding checks. */ +static const uint32_t pow85[] = {1, 85, 7225, 614125, 52200625}; + static const _Py_ALIGNED_DEF(64, unsigned char) table_a2b_base32[] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, @@ -729,6 +732,8 @@ binascii.a2b_base64 ignorechars: Py_buffer = NULL A byte string containing characters to ignore from the input when strict_mode is true. + canonical: bool = False + When set to true, reject non-zero padding bits per RFC 4648 section 3.5. Decode a line of base64 data. [clinic start generated code]*/ @@ -736,8 +741,8 @@ Decode a line of base64 data. static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, int padded, PyBytesObject *alphabet, - Py_buffer *ignorechars) -/*[clinic end generated code: output=525d840a299ff132 input=74a53dd3b23474b3]*/ + Py_buffer *ignorechars, int canonical) +/*[clinic end generated code: output=77c46dcbf4239527 input=c99096d071deeec8]*/ { assert(data->len >= 0); @@ -909,6 +914,16 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, goto error_end; } + /* https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + * Decoders MAY reject non-zero padding bits. */ + if (canonical && leftchar != 0) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Non-zero padding bits"); + } + goto error_end; + } + Py_XDECREF(table_obj); return PyBytesWriter_FinishWithPointer(writer, bin_data); @@ -1037,14 +1052,16 @@ binascii.a2b_ascii85 Expect data to be wrapped in '<~' and '~>' as in Adobe Ascii85. ignorechars: Py_buffer = b'' A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-canonical encodings. Decode Ascii85 data. [clinic start generated code]*/ static PyObject * binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, - int adobe, Py_buffer *ignorechars) -/*[clinic end generated code: output=599aa3e41095a651 input=f39abd11eab4bac0]*/ + int adobe, Py_buffer *ignorechars, int canonical) +/*[clinic end generated code: output=09b35f1eac531357 input=dd050604ed30199e]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1107,6 +1124,7 @@ binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, uint32_t leftchar = 0; int group_pos = 0; + int from_z = 0; /* true when current group came from 'z' shorthand */ for (; ascii_len > 0 || group_pos != 0; ascii_len--, ascii_data++) { /* Shift (in radix-85) data or padding into our buffer. */ unsigned char this_digit; @@ -1142,6 +1160,7 @@ binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, goto error; } leftchar = this_ch == 'y' ? BASE85_A85_Y : BASE85_A85_Z; + from_z = (this_ch == 'z'); group_pos = 5; } else if (!ignorechar(this_ch, ignorechars, ignorecache)) { @@ -1159,11 +1178,62 @@ binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, } /* Write current chunk. */ - Py_ssize_t chunk_len = ascii_len < 1 ? 3 + ascii_len : 4; - for (Py_ssize_t i = 0; i < chunk_len; i++) { + int chunk_len = ascii_len < 1 ? 3 + (int)ascii_len : 4; + + /* A final partial 5-tuple containing only one character is an + * encoding violation per the PLRM spec; reject unconditionally. */ + if (chunk_len == 0) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Incomplete Ascii85 group"); + } + goto error; + } + + for (int i = 0; i < chunk_len; i++) { *bin_data++ = (leftchar >> (24 - 8 * i)) & 0xff; } + if (canonical) { + /* The PLRM spec requires all-zero groups to use the 'z' + * abbreviation. Reject '!!!!!' (five zero digits). */ + if (chunk_len == 4 && leftchar == 0 && !from_z) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-canonical encoding, " + "use 'z' for all-zero groups"); + } + goto error; + } + /* Reject non-canonical partial groups. + * + * A partial group of N chars (2-4) encodes N-1 bytes. + * The decoder pads missing chars with digit 84 (the max). + * The encoder produces the unique N chars for those bytes + * by zero-padding the bytes to a uint32 and taking the + * leading N base-85 digits. Two encodings are equivalent + * iff they yield the same quotient when divided by + * 85**(5-N). */ + if (chunk_len < 4) { + int n_pad = 4 - chunk_len; + uint32_t canonical_top = + (leftchar >> (n_pad * 8)) << (n_pad * 8); + if (canonical_top / pow85[n_pad] + != leftchar / pow85[n_pad]) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-zero padding bits"); + } + goto error; + } + } + } + + from_z = 0; group_pos = 0; leftchar = 0; } @@ -1315,14 +1385,17 @@ binascii.a2b_base85 alphabet: PyBytesObject(c_default="NULL") = BASE85_ALPHABET ignorechars: Py_buffer = b'' A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-canonical encodings. Decode a line of Base85 data. [clinic start generated code]*/ static PyObject * binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet, Py_buffer *ignorechars) -/*[clinic end generated code: output=6a8d6eae798818d7 input=04d72a319712bdf3]*/ + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical) +/*[clinic end generated code: output=90dfef0c6b51e5f3 input=2819dc8aeffee5a2]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1403,11 +1476,41 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, } /* Write current chunk. */ - Py_ssize_t chunk_len = ascii_len < 1 ? 3 + ascii_len : 4; - for (Py_ssize_t i = 0; i < chunk_len; i++) { + int chunk_len = ascii_len < 1 ? 3 + (int)ascii_len : 4; + + /* A 1-char final group is an encoding violation (no conforming + * encoder produces it); reject unconditionally. */ + if (chunk_len == 0) { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Incomplete Base85 group"); + } + goto error; + } + + for (int i = 0; i < chunk_len; i++) { *bin_data++ = (leftchar >> (24 - 8 * i)) & 0xff; } + /* Reject non-canonical encodings in the final group. + * See the comment in a2b_ascii85 for the full explanation. */ + if (canonical && chunk_len < 4) { + int n_pad = 4 - chunk_len; + uint32_t canonical_top = + (leftchar >> (n_pad * 8)) << (n_pad * 8); + if (canonical_top / pow85[n_pad] + != leftchar / pow85[n_pad]) + { + state = get_binascii_state(module); + if (state != NULL) { + PyErr_SetString(state->Error, + "Non-zero padding bits"); + } + goto error; + } + } + group_pos = 0; leftchar = 0; } @@ -1535,14 +1638,17 @@ binascii.a2b_base32 alphabet: PyBytesObject(c_default="NULL") = BASE32_ALPHABET ignorechars: Py_buffer = b'' A byte string containing characters to ignore from the input. + canonical: bool = False + When set to true, reject non-zero padding bits per RFC 4648 section 3.5. Decode a line of base32 data. [clinic start generated code]*/ static PyObject * binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, - PyBytesObject *alphabet, Py_buffer *ignorechars) -/*[clinic end generated code: output=7dbbaa816d956b1c input=07a3721acdf9b688]*/ + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical) +/*[clinic end generated code: output=bc70f2bb6001fb55 input=5bfe6d1ea2f30e3b]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1723,6 +1829,16 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, goto error; } + /* https://datatracker.ietf.org/doc/html/rfc4648.html#section-3.5 + * Decoders MAY reject non-zero padding bits. */ + if (canonical && leftchar != 0) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Non-zero padding bits"); + } + goto error; + } + Py_XDECREF(table_obj); return PyBytesWriter_FinishWithPointer(writer, bin_data); diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index 21f4ee3201e..85edc6fbb58 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -92,7 +92,11 @@ PyDoc_STRVAR(_testinternalcapi_compiler_codegen__doc__, "compiler_codegen($module, /, ast, filename, optimize, compile_mode=0)\n" "--\n" "\n" -"Apply compiler code generation to an AST."); +"Apply compiler code generation to an AST.\n" +"\n" +"Return (instruction_sequence, metadata). metadata maps \"argcount\",\n" +"\"posonlyargcount\", \"kwonlyargcount\" to ints and \"consts\" to the list of\n" +"constants in LOAD_CONST index order (for use with optimize_cfg)."); #define _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF \ {"compiler_codegen", _PyCFunction_CAST(_testinternalcapi_compiler_codegen), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_compiler_codegen__doc__}, @@ -169,7 +173,10 @@ PyDoc_STRVAR(_testinternalcapi_optimize_cfg__doc__, "optimize_cfg($module, /, instructions, consts, nlocals)\n" "--\n" "\n" -"Apply compiler optimizations to an instruction list."); +"Apply compiler optimizations to an instruction list.\n" +"\n" +"consts must be a list aligned with LOAD_CONST opargs (the \"consts\" entry\n" +"from the metadata dict returned by compiler_codegen for the same unit)."); #define _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF \ {"optimize_cfg", _PyCFunction_CAST(_testinternalcapi_optimize_cfg), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_optimize_cfg__doc__}, @@ -392,4 +399,4 @@ get_next_dict_keys_version(PyObject *module, PyObject *Py_UNUSED(ignored)) { return get_next_dict_keys_version_impl(module); } -/*[clinic end generated code: output=fbd8b7e0cae8bac7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ecb5d7ac85b153fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 0a2d33c428d..ed695758ef9 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -119,7 +119,7 @@ exit: PyDoc_STRVAR(binascii_a2b_base64__doc__, "a2b_base64($module, data, /, *, strict_mode=,\n" " padded=True, alphabet=BASE64_ALPHABET,\n" -" ignorechars=)\n" +" ignorechars=, canonical=False)\n" "--\n" "\n" "Decode a line of base64 data.\n" @@ -132,7 +132,9 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__, " When set to false, padding in input is not required.\n" " ignorechars\n" " A byte string containing characters to ignore from the input when\n" -" strict_mode is true."); +" strict_mode is true.\n" +" canonical\n" +" When set to true, reject non-zero padding bits per RFC 4648 section 3.5."); #define BINASCII_A2B_BASE64_METHODDEF \ {"a2b_base64", _PyCFunction_CAST(binascii_a2b_base64), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base64__doc__}, @@ -140,7 +142,7 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__, static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, int padded, PyBytesObject *alphabet, - Py_buffer *ignorechars); + Py_buffer *ignorechars, int canonical); static PyObject * binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -148,7 +150,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -157,7 +159,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(strict_mode), &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(strict_mode), &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -166,20 +168,21 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "strict_mode", "padded", "alphabet", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "strict_mode", "padded", "alphabet", "ignorechars", "canonical", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base64", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[5]; + PyObject *argsbuf[6]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; int strict_mode = -1; int padded = 1; PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {NULL, NULL}; + int canonical = 0; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -220,11 +223,20 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[4], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[4]) { + if (PyObject_GetBuffer(args[4], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[5]); + if (canonical < 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base64_impl(module, &data, strict_mode, padded, alphabet, &ignorechars); + return_value = binascii_a2b_base64_impl(module, &data, strict_mode, padded, alphabet, &ignorechars, canonical); exit: /* Cleanup for data */ @@ -352,7 +364,7 @@ exit: PyDoc_STRVAR(binascii_a2b_ascii85__doc__, "a2b_ascii85($module, data, /, *, foldspaces=False, adobe=False,\n" -" ignorechars=b\'\')\n" +" ignorechars=b\'\', canonical=False)\n" "--\n" "\n" "Decode Ascii85 data.\n" @@ -362,14 +374,16 @@ PyDoc_STRVAR(binascii_a2b_ascii85__doc__, " adobe\n" " Expect data to be wrapped in \'<~\' and \'~>\' as in Adobe Ascii85.\n" " ignorechars\n" -" A byte string containing characters to ignore from the input."); +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-canonical encodings."); #define BINASCII_A2B_ASCII85_METHODDEF \ {"a2b_ascii85", _PyCFunction_CAST(binascii_a2b_ascii85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_ascii85__doc__}, static PyObject * binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, - int adobe, Py_buffer *ignorechars); + int adobe, Py_buffer *ignorechars, int canonical); static PyObject * binascii_a2b_ascii85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -377,7 +391,7 @@ binascii_a2b_ascii85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -386,7 +400,7 @@ binascii_a2b_ascii85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(foldspaces), &_Py_ID(adobe), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(foldspaces), &_Py_ID(adobe), &_Py_ID(ignorechars), &_Py_ID(canonical), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -395,19 +409,20 @@ binascii_a2b_ascii85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "foldspaces", "adobe", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "foldspaces", "adobe", "ignorechars", "canonical", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_ascii85", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; int foldspaces = 0; int adobe = 0; Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -438,11 +453,20 @@ binascii_a2b_ascii85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[3]) { + if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[4]); + if (canonical < 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_ascii85_impl(module, &data, foldspaces, adobe, &ignorechars); + return_value = binascii_a2b_ascii85_impl(module, &data, foldspaces, adobe, &ignorechars, canonical); exit: /* Cleanup for data */ @@ -573,20 +597,23 @@ exit: PyDoc_STRVAR(binascii_a2b_base85__doc__, "a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET,\n" -" ignorechars=b\'\')\n" +" ignorechars=b\'\', canonical=False)\n" "--\n" "\n" "Decode a line of Base85 data.\n" "\n" " ignorechars\n" -" A byte string containing characters to ignore from the input."); +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-canonical encodings."); #define BINASCII_A2B_BASE85_METHODDEF \ {"a2b_base85", _PyCFunction_CAST(binascii_a2b_base85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base85__doc__}, static PyObject * binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet, Py_buffer *ignorechars); + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical); static PyObject * binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -594,7 +621,7 @@ binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -603,7 +630,7 @@ binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -612,18 +639,19 @@ binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "alphabet", "ignorechars", "canonical", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base85", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -646,11 +674,20 @@ binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[2]) { + if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[3]); + if (canonical < 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base85_impl(module, &data, alphabet, &ignorechars); + return_value = binascii_a2b_base85_impl(module, &data, alphabet, &ignorechars, canonical); exit: /* Cleanup for data */ @@ -768,7 +805,7 @@ exit: PyDoc_STRVAR(binascii_a2b_base32__doc__, "a2b_base32($module, data, /, *, padded=True, alphabet=BASE32_ALPHABET,\n" -" ignorechars=b\'\')\n" +" ignorechars=b\'\', canonical=False)\n" "--\n" "\n" "Decode a line of base32 data.\n" @@ -776,14 +813,17 @@ PyDoc_STRVAR(binascii_a2b_base32__doc__, " padded\n" " When set to false, padding in input is not required.\n" " ignorechars\n" -" A byte string containing characters to ignore from the input."); +" A byte string containing characters to ignore from the input.\n" +" canonical\n" +" When set to true, reject non-zero padding bits per RFC 4648 section 3.5."); #define BINASCII_A2B_BASE32_METHODDEF \ {"a2b_base32", _PyCFunction_CAST(binascii_a2b_base32), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base32__doc__}, static PyObject * binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, - PyBytesObject *alphabet, Py_buffer *ignorechars); + PyBytesObject *alphabet, Py_buffer *ignorechars, + int canonical); static PyObject * binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -791,7 +831,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -800,7 +840,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), &_Py_ID(canonical), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -809,19 +849,20 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "padded", "alphabet", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "padded", "alphabet", "ignorechars", "canonical", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base32", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; int padded = 1; PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + int canonical = 0; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -853,11 +894,20 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[3]) { + if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + canonical = PyObject_IsTrue(args[4]); + if (canonical < 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base32_impl(module, &data, padded, alphabet, &ignorechars); + return_value = binascii_a2b_base32_impl(module, &data, padded, alphabet, &ignorechars, canonical); exit: /* Cleanup for data */ @@ -1634,4 +1684,4 @@ exit: return return_value; } -/*[clinic end generated code: output=2acab1ceb0058b1a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b41544f39b0ef681 input=a9049054013a1b77]*/ diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 822e1ce4bdc..51aee5afd35 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -1910,6 +1910,11 @@ _overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self, } #endif + if (bufobj->len < (Py_ssize_t)size) { + PyErr_SetString(PyExc_ValueError, "nbytes is greater than the length of the buffer"); + return NULL; + } + wsabuf.buf = bufobj->buf; wsabuf.len = size; diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 31b883fe8bd..0f0afe17513 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -503,6 +503,28 @@ my_StartElementHandler(void *userData, } } +static inline void +invalid_expat_handler_rv(const char *name) +{ + PyObject *exc = PyErr_GetRaisedException(); + assert(exc != NULL); + PyObject *note = PyUnicode_FromFormat("invalid '%s' event handler return value", name); + if (note == NULL) { + goto error; + } + int rc = _PyException_AddNote(exc, note); + Py_DECREF(note); + if (rc < 0) { + goto error; + }; + goto done; + +error: + PyErr_Clear(); +done: + PyErr_SetRaisedException(exc); +} + #define RC_HANDLER(RETURN_TYPE, NAME, PARAMS, \ INIT, PARSE_FORMAT, CONVERSION, \ RETURN_VARIABLE, GETUSERDATA) \ @@ -536,6 +558,9 @@ my_ ## NAME ## Handler PARAMS { \ } \ CONVERSION \ Py_DECREF(rv); \ + if (PyErr_Occurred()) { \ + invalid_expat_handler_rv(#NAME); \ + } \ return RETURN_VARIABLE; \ } diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index f67434ecdc9..9c5820fbe97 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1669,6 +1669,7 @@ decompress(ZlibDecompressor *self, uint8_t *data, return result; error: + self->zst.next_in = NULL; Py_XDECREF(result); return NULL; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 902144e8ec9..8a9d1b133af 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1536,9 +1536,9 @@ bytes_length(PyObject *self) return Py_SIZE(a); } -/* This is also used by PyBytes_Concat() */ -static PyObject * -bytes_concat(PyObject *a, PyObject *b) +/* This is also used by PyBytes_Concat() and the specializing interpreter. */ +PyObject * +_PyBytes_Concat(PyObject *a, PyObject *b) { Py_buffer va, vb; PyObject *result = NULL; @@ -1804,7 +1804,7 @@ bytes_buffer_getbuffer(PyObject *op, Py_buffer *view, int flags) static PySequenceMethods bytes_as_sequence = { bytes_length, /*sq_length*/ - bytes_concat, /*sq_concat*/ + _PyBytes_Concat, /*sq_concat*/ bytes_repeat, /*sq_repeat*/ bytes_item, /*sq_item*/ 0, /*sq_slice*/ @@ -3205,6 +3205,18 @@ Construct an immutable array of bytes from:\n\ static PyObject *bytes_iter(PyObject *seq); + +static _PyObjectIndexPair +bytes_iteritem(PyObject *obj, Py_ssize_t index) +{ + PyBytesObject *a = _PyBytes_CAST(obj); + if (index >= Py_SIZE(a)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + PyObject *l = _PyLong_FromUnsignedChar((unsigned char)a->ob_sval[index]); + return (_PyObjectIndexPair) { .object = l, .index = index + 1 }; +} + PyTypeObject PyBytes_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "bytes", @@ -3248,6 +3260,7 @@ PyTypeObject PyBytes_Type = { bytes_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_version_tag = _Py_TYPE_VERSION_BYTES, + ._tp_iteritem = bytes_iteritem, }; void @@ -3294,7 +3307,7 @@ PyBytes_Concat(PyObject **pv, PyObject *w) else { /* Multiple references, need to create new object */ PyObject *v; - v = bytes_concat(*pv, w); + v = _PyBytes_Concat(*pv, w); Py_SETREF(*pv, v); } } diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h index bd4c7a0e64f..d2f350a3487 100644 --- a/Objects/clinic/typevarobject.c.h +++ b/Objects/clinic/typevarobject.c.h @@ -517,13 +517,15 @@ paramspec_has_default(PyObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(typevartuple__doc__, -"typevartuple(name, *, default=typing.NoDefault)\n" +"typevartuple(name, *, bound=None, covariant=False, contravariant=False,\n" +" infer_variance=False, default=typing.NoDefault)\n" "--\n" "\n" "Create a new TypeVarTuple with the given name."); static PyObject * -typevartuple_impl(PyTypeObject *type, PyObject *name, +typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance, PyObject *default_value); static PyObject * @@ -532,7 +534,7 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 6 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -541,7 +543,7 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(name), &_Py_ID(default), }, + .ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), &_Py_ID(default), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -550,18 +552,22 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"name", "default", NULL}; + static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", "default", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "typevartuple", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[6]; PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1; PyObject *name; + PyObject *bound = Py_None; + int covariant = 0; + int contravariant = 0; + int infer_variance = 0; PyObject *default_value = &_Py_NoDefaultStruct; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, @@ -577,9 +583,42 @@ typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!noptargs) { goto skip_optional_kwonly; } - default_value = fastargs[1]; + if (fastargs[1]) { + bound = fastargs[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[2]) { + covariant = PyObject_IsTrue(fastargs[2]); + if (covariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[3]) { + contravariant = PyObject_IsTrue(fastargs[3]); + if (contravariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[4]) { + infer_variance = PyObject_IsTrue(fastargs[4]); + if (infer_variance < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + default_value = fastargs[5]; skip_optional_kwonly: - return_value = typevartuple_impl(type, name, default_value); + return_value = typevartuple_impl(type, name, bound, covariant, contravariant, infer_variance, default_value); exit: return return_value; @@ -764,4 +803,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=67ab9a5d1869f2c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2e7dd170924d92e5 input=a9049054013a1b77]*/ diff --git a/Objects/codeobject.c b/Objects/codeobject.c index f0be4a77b54..50ebe657a0e 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -574,8 +574,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) co->co_tlbc->entries[0] = co->co_code_adaptive; #endif int entry_point = 0; - while (entry_point < Py_SIZE(co) && - _PyCode_CODE(co)[entry_point].op.code != RESUME) { + while (entry_point < Py_SIZE(co)) { + if (_PyCode_CODE(co)[entry_point].op.code == RESUME && + (_PyCode_CODE(co)[entry_point].op.arg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_GEN_EXPR_START + ) { + break; + } entry_point++; } co->_co_firsttraceable = entry_point; @@ -1292,77 +1296,6 @@ _PyLineTable_NextAddressRange(PyCodeAddressRange *range) return 1; } -static int -emit_pair(PyObject **bytes, int *offset, int a, int b) -{ - Py_ssize_t len = PyBytes_GET_SIZE(*bytes); - if (*offset + 2 >= len) { - if (_PyBytes_Resize(bytes, len * 2) < 0) - return 0; - } - unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); - lnotab += *offset; - *lnotab++ = a; - *lnotab++ = b; - *offset += 2; - return 1; -} - -static int -emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset) -{ - while (bdelta > 255) { - if (!emit_pair(bytes, offset, 255, 0)) { - return 0; - } - bdelta -= 255; - } - while (ldelta > 127) { - if (!emit_pair(bytes, offset, bdelta, 127)) { - return 0; - } - bdelta = 0; - ldelta -= 127; - } - while (ldelta < -128) { - if (!emit_pair(bytes, offset, bdelta, -128)) { - return 0; - } - bdelta = 0; - ldelta += 128; - } - return emit_pair(bytes, offset, bdelta, ldelta); -} - -static PyObject * -decode_linetable(PyCodeObject *code) -{ - PyCodeAddressRange bounds; - PyObject *bytes; - int table_offset = 0; - int code_offset = 0; - int line = code->co_firstlineno; - bytes = PyBytes_FromStringAndSize(NULL, 64); - if (bytes == NULL) { - return NULL; - } - _PyCode_InitAddressRange(code, &bounds); - while (_PyLineTable_NextAddressRange(&bounds)) { - if (bounds.opaque.computed_line != line) { - int bdelta = bounds.ar_start - code_offset; - int ldelta = bounds.opaque.computed_line - line; - if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) { - Py_DECREF(bytes); - return NULL; - } - code_offset = bounds.ar_start; - line = bounds.opaque.computed_line; - } - } - _PyBytes_Resize(&bytes, table_offset); - return bytes; -} - typedef struct { PyObject_HEAD @@ -2735,18 +2668,6 @@ static PyMemberDef code_memberlist[] = { }; -static PyObject * -code_getlnotab(PyObject *self, void *closure) -{ - PyCodeObject *code = _PyCodeObject_CAST(self); - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "co_lnotab is deprecated, use co_lines instead.", - 1) < 0) { - return NULL; - } - return decode_linetable(code); -} - static PyObject * code_getvarnames(PyObject *self, void *closure) { @@ -2784,7 +2705,6 @@ code_getcode(PyObject *self, void *closure) } static PyGetSetDef code_getsetlist[] = { - {"co_lnotab", code_getlnotab, NULL, NULL}, {"_co_code_adaptive", code_getcodeadaptive, NULL, NULL}, // The following old names are kept for backward compatibility. {"co_varnames", code_getvarnames, NULL, NULL}, diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 67bc4319e0b..09db93b2d31 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1910,8 +1910,8 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash) return ix; } -static void -insert_split_value(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix) +void +_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix) { assert(can_modify_dict(mp)); assert(PyUnicode_CheckExact(key)); @@ -1951,7 +1951,7 @@ insertdict(PyDictObject *mp, if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) { ix = insert_split_key(mp->ma_keys, key, hash); if (ix != DKIX_EMPTY) { - insert_split_value(mp, key, value, ix); + _PyDict_InsertSplitValue(mp, key, value, ix); Py_DECREF(key); Py_DECREF(value); return 0; @@ -4714,7 +4714,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu PyObject *value = mp->ma_values->values[ix]; int already_present = value != NULL; if (!already_present) { - insert_split_value(mp, key, default_value, ix); + _PyDict_InsertSplitValue(mp, key, default_value, ix); value = default_value; } if (result) { @@ -5041,8 +5041,8 @@ dict___sizeof___impl(PyDictObject *self) return PyLong_FromSsize_t(_PyDict_SizeOf(self)); } -static PyObject * -dict_or(PyObject *self, PyObject *other) +PyObject * +_PyDict_Or(PyObject *self, PyObject *other) { if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; @@ -5077,12 +5077,12 @@ frozendict_or(PyObject *self, PyObject *other) } } - return dict_or(self, other); + return _PyDict_Or(self, other); } -static PyObject * -dict_ior(PyObject *self, PyObject *other) +PyObject * +_PyDict_IOr(PyObject *self, PyObject *other) { if (dict_update_arg(self, other)) { return NULL; @@ -5198,8 +5198,8 @@ static PySequenceMethods dict_as_sequence = { }; static PyNumberMethods dict_as_number = { - .nb_or = dict_or, - .nb_inplace_or = dict_ior, + .nb_or = _PyDict_Or, + .nb_inplace_or = _PyDict_IOr, }; static PyObject * @@ -8028,7 +8028,7 @@ PyDict_Watch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id); + FT_ATOMIC_OR_UINT64(((PyDictObject*)dict)->_ma_watcher_tag, (1LL << watcher_id)); return 0; } @@ -8043,7 +8043,7 @@ PyDict_Unwatch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->_ma_watcher_tag &= ~(1LL << watcher_id); + FT_ATOMIC_AND_UINT64(((PyDictObject*)dict)->_ma_watcher_tag, ~(1LL << watcher_id)); return 0; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index d47c78b933b..0fffd36ad46 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -8,6 +8,7 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_object_deferred.h" // _PyObject_SetDeferredRefcount() +#include "pycore_optimizer.h" // _Py_Executors_InvalidateDependency() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_stats.h" @@ -63,6 +64,13 @@ handle_func_event(PyFunction_WatchEvent event, PyFunctionObject *func, case PyFunction_EVENT_MODIFY_DEFAULTS: case PyFunction_EVENT_MODIFY_KWDEFAULTS: case PyFunction_EVENT_MODIFY_QUALNAME: +#if _Py_TIER2 + // Note: we only invalidate JIT code if a function version changes. + // Not when the function is deallocated. + // Function deallocation occurs frequently (think: lambdas), + // so we want to minimize dependency invalidation there. + _Py_Executors_InvalidateDependency(interp, func, 1); +#endif RARE_EVENT_INTERP_INC(interp, func_modification); break; default: diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 7aef56cf4e9..e3bc8eb2739 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -242,7 +242,6 @@ _Py_make_parameters(PyObject *args) len += needed; if (_PyTuple_Resize(¶meters, len) < 0) { Py_DECREF(subparams); - Py_DECREF(parameters); Py_XDECREF(tuple_args); return NULL; } @@ -650,7 +649,7 @@ ga_vectorcall(PyObject *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { gaobject *alias = (gaobject *) self; - PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames); + PyObject *obj = PyObject_Vectorcall(alias->origin, args, nargsf, kwnames); return set_orig_class(obj, self); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 2895833b4ff..d628889afc6 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -496,7 +496,7 @@ gen_close(PyObject *self, PyObject *args) } if (is_resume(frame->instr_ptr)) { - bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET()); + bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET(), frame); /* We can safely ignore the outermost try block * as it is automatically generated to handle * StopIteration. */ @@ -1110,9 +1110,6 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) return (PyObject *)gen; } -static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame); - PyObject * _Py_MakeCoro(PyFunctionObject *func) { @@ -1150,7 +1147,7 @@ _Py_MakeCoro(PyFunctionObject *func) assert(frame); assert(_PyFrame_IsIncomplete(frame)); frame = _PyFrame_GetFirstComplete(frame->previous); - PyObject *cr_origin = compute_cr_origin(origin_depth, frame); + PyObject *cr_origin = _PyCoro_ComputeOrigin(origin_depth, frame); ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); @@ -1535,8 +1532,8 @@ PyTypeObject _PyCoroWrapper_Type = { 0, /* tp_free */ }; -static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame) +PyObject * +_PyCoro_ComputeOrigin(int origin_depth, _PyInterpreterFrame *current_frame) { _PyInterpreterFrame *frame = current_frame; /* First count how many frames we have */ @@ -1581,7 +1578,7 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname) if (origin_depth == 0) { ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL; } else { - PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame()); + PyObject *cr_origin = _PyCoro_ComputeOrigin(origin_depth, _PyEval_GetFrame()); ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin; if (!cr_origin) { Py_DECREF(coro); diff --git a/Objects/listobject.c b/Objects/listobject.c index 5c9fd55bab1..685b30bb9ee 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -798,8 +798,8 @@ list_concat_lock_held(PyListObject *a, PyListObject *b) return (PyObject *)np; } -static PyObject * -list_concat(PyObject *aa, PyObject *bb) +PyObject * +_PyList_Concat(PyObject *aa, PyObject *bb) { if (!PyList_Check(bb)) { PyErr_Format(PyExc_TypeError, @@ -3617,7 +3617,7 @@ static PyMethodDef list_methods[] = { static PySequenceMethods list_as_sequence = { list_length, /* sq_length */ - list_concat, /* sq_concat */ + _PyList_Concat, /* sq_concat */ list_repeat, /* sq_repeat */ list_item, /* sq_item */ 0, /* sq_slice */ @@ -3913,6 +3913,13 @@ list_ass_subscript(PyObject *self, PyObject *item, PyObject *value) return res; } +static _PyObjectIndexPair +list_iteritem(PyObject *obj, Py_ssize_t index) +{ + PyObject *result = list_get_item_ref((PyListObject *)obj, index); + return (_PyObjectIndexPair) { .object = result, .index = index + 1 }; +} + static PyMappingMethods list_as_mapping = { list_length, list_subscript, @@ -3963,6 +3970,7 @@ PyTypeObject PyList_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = list_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_LIST, + ._tp_iteritem = list_iteritem, }; /*********************** List Iterator **************************/ diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt deleted file mode 100644 index 335e441cfde..00000000000 --- a/Objects/lnotab_notes.txt +++ /dev/null @@ -1,228 +0,0 @@ -Description of the internal format of the line number table in Python 3.10 -and earlier. - -(For 3.11 onwards, see InternalDocs/code_objects.md) - -Conceptually, the line number table consists of a sequence of triples: - start-offset (inclusive), end-offset (exclusive), line-number. - -Note that not all byte codes have a line number so we need handle `None` for the line-number. - -However, storing the above sequence directly would be very inefficient as we would need 12 bytes per entry. - -First, note that the end of one entry is the same as the start of the next, so we can overlap entries. -Second, we don't really need arbitrary access to the sequence, so we can store deltas. - -We just need to store (end - start, line delta) pairs. The start offset of the first entry is always zero. - -Third, most deltas are small, so we can use a single byte for each value, as long we allow several entries for the same line. - -Consider the following table - Start End Line - 0 6 1 - 6 50 2 - 50 350 7 - 350 360 No line number - 360 376 8 - 376 380 208 - -Stripping the redundant ends gives: - - End-Start Line-delta - 6 +1 - 44 +1 - 300 +5 - 10 No line number - 16 +1 - 4 +200 - - -Note that the end - start value is always positive. - -Finally, in order to fit into a single byte we need to convert start deltas to the range 0 <= delta <= 254, -and line deltas to the range -127 <= delta <= 127. -A line delta of -128 is used to indicate no line number. -Also note that a delta of zero indicates that there are no bytecodes in the given range, -which means we can use an invalid line number for that range. - -Final form: - - Start delta Line delta - 6 +1 - 44 +1 - 254 +5 - 46 0 - 10 -128 (No line number, treated as a delta of zero) - 16 +1 - 0 +127 (line 135, but the range is empty as no bytecodes are at line 135) - 4 +73 - -Iterating over the table. -------------------------- - -For the `co_lines` method we want to emit the full form, omitting the (350, 360, No line number) and empty entries. - -The code is as follows: - -def co_lines(code): - line = code.co_firstlineno - end = 0 - table_iter = iter(code.internal_line_table): - for sdelta, ldelta in table_iter: - if ldelta == 0: # No change to line number, just accumulate changes to end - end += sdelta - continue - start = end - end = start + sdelta - if ldelta == -128: # No valid line number -- skip entry - continue - line += ldelta - if end == start: # Empty range, omit. - continue - yield start, end, line - - - - -The historical co_lnotab format -------------------------------- - -prior to 3.10 code objects stored a field named co_lnotab. -This was an array of unsigned bytes disguised as a Python bytes object. - -The old co_lnotab did not account for the presence of bytecodes without a line number, -nor was it well suited to tracing as a number of workarounds were required. - -The old format can still be accessed via `code.co_lnotab`, which is lazily computed from the new format. - -Below is the description of the old co_lnotab format: - - -The array is conceptually a compressed list of - (bytecode offset increment, line number increment) -pairs. The details are important and delicate, best illustrated by example: - - byte code offset source code line number - 0 1 - 6 2 - 50 7 - 350 207 - 361 208 - -Instead of storing these numbers literally, we compress the list by storing only -the difference from one row to the next. Conceptually, the stored list might -look like: - - 0, 1, 6, 1, 44, 5, 300, 200, 11, 1 - -The above doesn't really work, but it's a start. An unsigned byte (byte code -offset) can't hold negative values, or values larger than 255, a signed byte -(line number) can't hold values larger than 127 or less than -128, and the -above example contains two such values. (Note that before 3.6, line number -was also encoded by an unsigned byte.) So we make two tweaks: - - (a) there's a deep assumption that byte code offsets increase monotonically, - and - (b) if byte code offset jumps by more than 255 from one row to the next, or if - source code line number jumps by more than 127 or less than -128 from one row - to the next, more than one pair is written to the table. In case #b, - there's no way to know from looking at the table later how many were written. - That's the delicate part. A user of co_lnotab desiring to find the source - line number corresponding to a bytecode address A should do something like - this: - - lineno = addr = 0 - for addr_incr, line_incr in co_lnotab: - addr += addr_incr - if addr > A: - return lineno - if line_incr >= 0x80: - line_incr -= 0x100 - lineno += line_incr - -(In C, this is implemented by PyCode_Addr2Line().) In order for this to work, -when the addr field increments by more than 255, the line # increment in each -pair generated must be 0 until the remaining addr increment is < 256. So, in -the example above, assemble_lnotab in compile.c should not (as was actually done -until 2.2) expand 300, 200 to - 255, 255, 45, 45, -but to - 255, 0, 45, 127, 0, 73. - -The above is sufficient to reconstruct line numbers for tracebacks, but not for -line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c -and maybe_call_line_trace() in ceval.c. - -*** Tracing *** - -To a first approximation, we want to call the tracing function when the line -number of the current instruction changes. Re-computing the current line for -every instruction is a little slow, though, so each time we compute the line -number we save the bytecode indices where it's valid: - - *instr_lb <= frame->f_lasti < *instr_ub - -is true so long as execution does not change lines. That is, *instr_lb holds -the first bytecode index of the current line, and *instr_ub holds the first -bytecode index of the next line. As long as the above expression is true, -maybe_call_line_trace() does not need to call PyCode_CheckLineNumber(). Note -that the same line may appear multiple times in the lnotab, either because the -bytecode jumped more than 255 indices between line number changes or because -the compiler inserted the same line twice. Even in that case, *instr_ub holds -the first index of the next line. - -However, we don't *always* want to call the line trace function when the above -test fails. - -Consider this code: - -1: def f(a): -2: while a: -3: print(1) -4: break -5: else: -6: print(2) - -which compiles to this: - - 2 0 SETUP_LOOP 26 (to 28) - >> 2 LOAD_FAST 0 (a) - 4 POP_JUMP_IF_FALSE 18 - - 3 6 LOAD_GLOBAL 0 (print) - 8 LOAD_CONST 1 (1) - 10 CALL_NO_KW 1 - 12 POP_TOP - - 4 14 BREAK_LOOP - 16 JUMP_ABSOLUTE 2 - >> 18 POP_BLOCK - - 6 20 LOAD_GLOBAL 0 (print) - 22 LOAD_CONST 2 (2) - 24 CALL_NO_KW 1 - 26 POP_TOP - >> 28 LOAD_CONST 0 (None) - 30 RETURN_VALUE - -If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 18 -and the co_lnotab will claim that execution has moved to line 4, which is wrong. -In this case, we could instead associate the POP_BLOCK with line 5, but that -would break jumps around loops without else clauses. - -We fix this by only calling the line trace function for a forward jump if the -co_lnotab indicates we have jumped to the *start* of a line, i.e. if the current -instruction offset matches the offset given for the start of a line by the -co_lnotab. For backward jumps, however, we always call the line trace function, -which lets a debugger stop on every evaluation of a loop guard (which usually -won't be the first opcode in a line). - -Why do we set f_lineno when tracing, and only just before calling the trace -function? Well, consider the code above when 'a' is true. If stepping through -this with 'n' in pdb, you would stop at line 1 with a "call" type event, then -line events on lines 2, 3, and 4, then a "return" type event -- but because the -code for the return actually falls in the range of the "line 6" opcodes, you -would be shown line 6 during this event. This is a change from the behaviour in -2.2 and before, and I've found it confusing in practice. By setting and using -f_lineno when tracing, one can report a line number different from that -suggested by f_lasti on this one occasion where it's desirable. diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 4cbbb7eb7cd..d0f414f7c42 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1676,6 +1676,10 @@ fix_error_int(const char *fmt) return -1; } +// UNPACK_TO_BOOL: Return 0 if PTR represents "false", and 1 otherwise. +static const _Bool bool_false = 0; +#define UNPACK_TO_BOOL(PTR) (memcmp((PTR), &bool_false, sizeof(_Bool)) != 0) + /* Accept integer objects or objects with an __index__() method. */ static long pylong_as_ld(PyObject *item) @@ -1811,7 +1815,7 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld; /* boolean */ - case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool; + case '?': ld = UNPACK_TO_BOOL(ptr); goto convert_bool; /* unsigned integers */ case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu; @@ -3029,7 +3033,7 @@ unpack_cmp(const char *p, const char *q, char fmt, case 'l': CMP_SINGLE(p, q, long); return equal; /* boolean */ - case '?': CMP_SINGLE(p, q, _Bool); return equal; + case '?': return UNPACK_TO_BOOL(p) == UNPACK_TO_BOOL(q); /* unsigned integers */ case 'H': CMP_SINGLE(p, q, unsigned short); return equal; diff --git a/Objects/object.c b/Objects/object.c index 4db22f372ec..4fa20470601 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -688,6 +688,8 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) ret = -1; } } + + _Py_LeaveRecursiveCall(); return ret; } @@ -2766,9 +2768,9 @@ _Py_SetImmortalUntracked(PyObject *op) return; } #ifdef Py_GIL_DISABLED - op->ob_tid = _Py_UNOWNED_TID; - op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL; - op->ob_ref_shared = 0; + _Py_atomic_store_uintptr_relaxed(&op->ob_tid, _Py_UNOWNED_TID); + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, _Py_IMMORTAL_REFCNT_LOCAL); + _Py_atomic_store_ssize_relaxed(&op->ob_ref_shared, 0); _Py_atomic_or_uint8(&op->ob_gc_bits, _PyGC_BITS_DEFERRED); #elif SIZEOF_VOID_P > 4 op->ob_flags = _Py_IMMORTAL_FLAGS; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index ee6320e6ca3..7757a102677 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -547,8 +547,8 @@ PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j) return tuple_slice((PyTupleObject *)op, i, j); } -static PyObject * -tuple_concat(PyObject *aa, PyObject *bb) +PyObject * +_PyTuple_Concat(PyObject *aa, PyObject *bb) { PyTupleObject *a = _PyTuple_CAST(aa); if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) { @@ -864,7 +864,7 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable) static PySequenceMethods tuple_as_sequence = { tuple_length, /* sq_length */ - tuple_concat, /* sq_concat */ + _PyTuple_Concat, /* sq_concat */ tuple_repeat, /* sq_repeat */ tuple_item, /* sq_item */ 0, /* sq_slice */ @@ -873,6 +873,17 @@ static PySequenceMethods tuple_as_sequence = { tuple_contains, /* sq_contains */ }; +static _PyObjectIndexPair +tuple_iteritem(PyObject *obj, Py_ssize_t index) +{ + if (index >= PyTuple_GET_SIZE(obj)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + PyObject *result = PyTuple_GET_ITEM(obj, index); + Py_INCREF(result); + return (_PyObjectIndexPair) { .object = result, .index = index + 1 }; +} + static PyObject* tuple_subscript(PyObject *op, PyObject* item) { @@ -1000,6 +1011,7 @@ PyTypeObject PyTuple_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = tuple_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_TUPLE, + ._tp_iteritem = tuple_iteritem, }; /* The following function breaks the notion that tuples are immutable: diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 08b95cfbc6c..fb3c7101410 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5878,7 +5878,13 @@ PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *token) PyObject * PyType_GetModuleByToken(PyTypeObject *type, const void *token) { - PyObject *mod = PyType_GetModuleByToken_DuringGC(type, token); + return Py_XNewRef(PyType_GetModuleByDef(type, (PyModuleDef *)token)); +} + +PyObject * +PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) +{ + PyObject *mod = PyType_GetModuleByToken_DuringGC(type, def); if (!mod) { PyErr_Format( PyExc_TypeError, @@ -5886,14 +5892,6 @@ PyType_GetModuleByToken(PyTypeObject *type, const void *token) type->tp_name); return NULL; } - return Py_NewRef(mod); -} - -PyObject * -PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) -{ - PyObject *mod = PyType_GetModuleByToken(type, def); - Py_XDECREF(mod); // return borrowed ref return mod; } diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index c2b8ee43119..cdc0ea42eac 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -36,8 +36,12 @@ typedef struct { typedef struct { PyObject_HEAD PyObject *name; + PyObject *bound; PyObject *default_value; PyObject *evaluate_default; + bool covariant; + bool contravariant; + bool infer_variance; } typevartupleobject; typedef struct { @@ -1524,6 +1528,7 @@ typevartuple_dealloc(PyObject *self) typevartupleobject *tvt = typevartupleobject_CAST(self); Py_XDECREF(tvt->name); + Py_XDECREF(tvt->bound); Py_XDECREF(tvt->default_value); Py_XDECREF(tvt->evaluate_default); PyObject_ClearManagedDict(self); @@ -1555,16 +1560,28 @@ static PyObject * typevartuple_repr(PyObject *self) { typevartupleobject *tvt = typevartupleobject_CAST(self); - return Py_NewRef(tvt->name); + + if (tvt->infer_variance) { + return Py_NewRef(tvt->name); + } + + char variance = tvt->covariant ? '+' : tvt->contravariant ? '-' : '~'; + return PyUnicode_FromFormat("%c%U", variance, tvt->name); } static PyMemberDef typevartuple_members[] = { {"__name__", _Py_T_OBJECT, offsetof(typevartupleobject, name), Py_READONLY}, + {"__bound__", _Py_T_OBJECT, offsetof(typevartupleobject, bound), Py_READONLY}, + {"__covariant__", Py_T_BOOL, offsetof(typevartupleobject, covariant), Py_READONLY}, + {"__contravariant__", Py_T_BOOL, offsetof(typevartupleobject, contravariant), Py_READONLY}, + {"__infer_variance__", Py_T_BOOL, offsetof(typevartupleobject, infer_variance), Py_READONLY}, {0} }; static typevartupleobject * -typevartuple_alloc(PyObject *name, PyObject *module, PyObject *default_value) +typevartuple_alloc(PyObject *name, PyObject *bound, PyObject *default_value, + bool covariant, bool contravariant, bool infer_variance, + PyObject *module) { PyTypeObject *tp = _PyInterpreterState_GET()->cached_objects.typevartuple_type; typevartupleobject *tvt = PyObject_GC_New(typevartupleobject, tp); @@ -1572,6 +1589,10 @@ typevartuple_alloc(PyObject *name, PyObject *module, PyObject *default_value) return NULL; } tvt->name = Py_NewRef(name); + tvt->bound = Py_XNewRef(bound); + tvt->covariant = covariant; + tvt->contravariant = contravariant; + tvt->infer_variance = infer_variance; tvt->default_value = Py_XNewRef(default_value); tvt->evaluate_default = NULL; _PyObject_GC_TRACK(tvt); @@ -1590,21 +1611,46 @@ typevartuple.__new__ name: object(subclass_of="&PyUnicode_Type") * + bound: object = None + covariant: bool = False + contravariant: bool = False + infer_variance: bool = False default as default_value: object(c_default="&_Py_NoDefaultStruct") = typing.NoDefault Create a new TypeVarTuple with the given name. [clinic start generated code]*/ static PyObject * -typevartuple_impl(PyTypeObject *type, PyObject *name, +typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance, PyObject *default_value) -/*[clinic end generated code: output=9d6b76dfe95aae51 input=e149739929a866d0]*/ +/*[clinic end generated code: output=40bc9ca10f64e392 input=56e28c725a8da40b]*/ { - PyObject *module = caller(); - if (module == NULL) { + if (covariant && contravariant) { + PyErr_SetString(PyExc_ValueError, "Bivariant types are not supported."); return NULL; } - PyObject *result = (PyObject *)typevartuple_alloc(name, module, default_value); + if (infer_variance && (covariant || contravariant)) { + PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); + return NULL; + } + if (Py_IsNone(bound)) { + bound = NULL; + } + if (bound != NULL) { + bound = type_check(bound, "Bound must be a type."); + if (bound == NULL) { + return NULL; + } + } + PyObject *module = caller(); + if (module == NULL) { + Py_XDECREF(bound); + return NULL; + } + PyObject *result = (PyObject *)typevartuple_alloc( + name, bound, default_value, covariant, contravariant, infer_variance, module); + Py_XDECREF(bound); Py_DECREF(module); return result; } @@ -1688,6 +1734,7 @@ typevartuple_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(Py_TYPE(self)); typevartupleobject *tvt = typevartupleobject_CAST(self); Py_VISIT(tvt->name); + Py_VISIT(tvt->bound); Py_VISIT(tvt->default_value); Py_VISIT(tvt->evaluate_default); return PyObject_VisitManagedDict(self, visit, arg); @@ -1698,6 +1745,7 @@ typevartuple_clear(PyObject *self) { typevartupleobject *tvt = typevartupleobject_CAST(self); Py_CLEAR(tvt->name); + Py_CLEAR(tvt->bound); Py_CLEAR(tvt->default_value); Py_CLEAR(tvt->evaluate_default); PyObject_ClearManagedDict(self); @@ -1829,7 +1877,7 @@ PyObject * _Py_make_typevartuple(PyThreadState *Py_UNUSED(ignored), PyObject *v) { assert(PyUnicode_Check(v)); - return (PyObject *)typevartuple_alloc(v, NULL, NULL); + return (PyObject *)typevartuple_alloc(v, NULL, NULL, false, false, true, NULL); } static PyObject * diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index a0a26a75129..9aee7120c81 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -589,6 +589,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) { #define CHECK(expr) \ do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0) +#ifdef Py_GIL_DISABLED +# define CHECK_IF_GIL(expr) (void)(expr) +# define CHECK_IF_FT(expr) CHECK(expr) +#else +# define CHECK_IF_GIL(expr) CHECK(expr) +# define CHECK_IF_FT(expr) (void)(expr) +#endif + assert(op != NULL); CHECK(PyUnicode_Check(op)); @@ -669,11 +677,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) /* Check interning state */ #ifdef Py_DEBUG - // Note that we do not check `_Py_IsImmortal(op)`, since stable ABI - // extensions can make immortal strings mortal (but with a high enough - // refcount). - // The other way is extremely unlikely (worth a potential failed assertion - // in a debug build), so we do check `!_Py_IsImmortal(op)`. + // Note that we do not check `_Py_IsImmortal(op)` in the GIL-enabled build + // since stable ABI extensions can make immortal strings mortal (but with a + // high enough refcount). switch (PyUnicode_CHECK_INTERNED(op)) { case SSTATE_NOT_INTERNED: if (ascii->state.statically_allocated) { @@ -683,18 +689,20 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) // are static but use SSTATE_NOT_INTERNED } else { - CHECK(!_Py_IsImmortal(op)); + CHECK_IF_GIL(!_Py_IsImmortal(op)); } break; case SSTATE_INTERNED_MORTAL: CHECK(!ascii->state.statically_allocated); - CHECK(!_Py_IsImmortal(op)); + CHECK_IF_GIL(!_Py_IsImmortal(op)); break; case SSTATE_INTERNED_IMMORTAL: CHECK(!ascii->state.statically_allocated); + CHECK_IF_FT(_Py_IsImmortal(op)); break; case SSTATE_INTERNED_IMMORTAL_STATIC: CHECK(ascii->state.statically_allocated); + CHECK_IF_FT(_Py_IsImmortal(op)); break; default: Py_UNREACHABLE(); @@ -13982,6 +13990,20 @@ unicode_subtype_new(PyTypeObject *type, PyObject *unicode) return NULL; } +static _PyObjectIndexPair +unicode_iteritem(PyObject *obj, Py_ssize_t index) +{ + if (index >= PyUnicode_GET_LENGTH(obj)) { + return (_PyObjectIndexPair) { .object = NULL, .index = index }; + } + const void *data = PyUnicode_DATA(obj); + int kind = PyUnicode_KIND(obj); + Py_UCS4 ch = PyUnicode_READ(kind, data, index); + PyObject *result = unicode_char(ch); + index = (result == NULL) ? -1 : index + 1; + return (_PyObjectIndexPair) { .object = result, .index = index }; +} + void _PyUnicode_ExactDealloc(PyObject *op) { @@ -14047,6 +14069,7 @@ PyTypeObject PyUnicode_Type = { unicode_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_vectorcall = unicode_vectorcall, + ._tp_iteritem = unicode_iteritem, }; /* Initialize the Unicode implementation */ @@ -14193,6 +14216,18 @@ immortalize_interned(PyObject *s) FT_ATOMIC_STORE_UINT8(_PyUnicode_STATE(s).interned, SSTATE_INTERNED_IMMORTAL); } +#ifdef Py_GIL_DISABLED +static bool +can_immortalize_safely(PyObject *s) +{ + if (_Py_IsOwnedByCurrentThread(s) || _Py_IsImmortal(s)) { + return true; + } + Py_ssize_t shared = _Py_atomic_load_ssize(&s->ob_ref_shared); + return _Py_REF_IS_MERGED(shared); +} +#endif + static /* non-null */ PyObject* intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, bool immortalize) @@ -14221,11 +14256,16 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, // no, go on break; case SSTATE_INTERNED_MORTAL: +#ifndef Py_GIL_DISABLED // yes but we might need to make it immortal if (immortalize) { immortalize_interned(s); } return s; +#else + // not fully interned yet; fall through to the locking path + break; +#endif default: // all done return s; @@ -14290,6 +14330,23 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */, Py_DECREF(r); } #endif + +#ifdef Py_GIL_DISABLED + // Immortalization writes to the refcount fields non-atomically. That + // races with Py_INCREF / Py_DECREF on the thread that owns `s`. If we + // don't own it (and its refcount hasn't been merged), intern a copy + // we own instead. + if (!can_immortalize_safely(s)) { + PyObject *copy = _PyUnicode_Copy(s); + if (copy == NULL) { + PyErr_Clear(); + return s; + } + Py_DECREF(s); + s = copy; + } +#endif + FT_MUTEX_LOCK(INTERN_MUTEX); PyObject *t; { diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index cb806459596..38236922a52 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -310,6 +310,26 @@ $(IntDir)codecs.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h + + encodings + $(IntDir)encodings.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.h + + + encodings.aliases + $(IntDir)encodings.aliases.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.aliases.h + + + encodings.utf_8 + $(IntDir)encodings.utf_8.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.utf_8.h + + + encodings._win_cp_codecs + $(IntDir)encodings._win_cp_codecs.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings._win_cp_codecs.h + io $(IntDir)io.g.h @@ -355,6 +375,11 @@ $(IntDir)stat.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h + + linecache + $(IntDir)linecache.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\linecache.h + importlib.util $(IntDir)importlib.util.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 6dcf0e87129..73861dbb0c9 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -537,6 +537,18 @@ Python Files + + Python Files + + + Python Files + + + Python Files + + + Python Files + Python Files @@ -564,6 +576,9 @@ Python Files + + Python Files + Python Files diff --git a/PCbuild/build.bat b/PCbuild/build.bat index 8fb2f096c93..9d2f032f5a9 100644 --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -170,16 +170,20 @@ if "%do_pgo%"=="true" ( del /s "%dir%\*.pgc" del /s "%dir%\..\Lib\*.pyc" set conf=PGUpdate - if "%clean%"=="false" ( - echo on - call "%dir%\..\python.bat" %pgo_job% - @echo off - call :Kill - set target=Build - ) + if "%clean%"=="false" goto :RunPgoJob ) goto :Build +:RunPgoJob +echo on +call "%dir%\..\python.bat" %pgo_job% +@echo off +set pgo_errorlevel=%ERRORLEVEL% +call :Kill +if %pgo_errorlevel% NEQ 0 exit /B %pgo_errorlevel% +set target=Build +goto :Build + :Kill echo on %MSBUILD% "%dir%\pythoncore.vcxproj" /t:KillPython %verbose%^ diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 94ae718d58c..f79608e1d58 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -12,8 +12,9 @@ $(IntDir.Replace(`\\`, `\`)) $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_frozen\ $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)$(ArchName)_$(Configuration)\zlib-ng\ - $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration) - $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration)\ + $(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument\ + $(GeneratedJitStencilsDir.Replace(`\\`, `\`)) $(ProjectName) $(TargetName)$(PyDebugExt) false diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 61bee29c0af..07305add81d 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -115,6 +115,9 @@ version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) zlib-ng$(PyDebugExt).lib;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o;%(AdditionalDependencies) + $(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o;%(AdditionalDependencies) @@ -359,6 +362,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 664788e69af..629f063861d 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -156,6 +156,9 @@ Include + + Include + Include diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 41af9cacfb9..9552e73ef6a 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -35,6 +35,9 @@ <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-aarch64-pc-windows-msvc.h" Condition="$(Platform) == 'ARM64'"/> <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-i686-pc-windows-msvc.h" Condition="$(Platform) == 'Win32'"/> <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-x86_64-pc-windows-msvc.h" Condition="$(Platform) == 'x64'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o" Condition="$(Platform) == 'ARM64'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o" Condition="$(Platform) == 'Win32'"/> + <_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o" Condition="$(Platform) == 'x64'"/> <_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\optimizer_bytecodes.c;"/> <_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\optimizer_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/> <_SbomSources Include="$(PySourcePath)PCbuild\get_externals.bat" /> @@ -129,7 +132,7 @@ x86_64-pc-windows-msvc $(JITArgs) --debug - + diff --git a/Parser/parser.c b/Parser/parser.c index f853d309de9..c55c081dfc3 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -9066,7 +9066,7 @@ complex_number_rule(Parser *p) return _res; } -// signed_number: NUMBER | '-' NUMBER +// signed_number: NUMBER | '+' NUMBER | '-' NUMBER static expr_ty signed_number_rule(Parser *p) { @@ -9107,6 +9107,33 @@ signed_number_rule(Parser *p) D(fprintf(stderr, "%*c%s signed_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NUMBER")); } + { // '+' NUMBER + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + Token * _literal; + expr_ty number; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (number = _PyPegen_number_token(p)) // NUMBER + ) + { + D(fprintf(stderr, "%*c+ signed_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + _res = number; + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s signed_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' NUMBER")); + } { // '-' NUMBER if (p->error_indicator) { p->level--; @@ -9149,7 +9176,7 @@ signed_number_rule(Parser *p) return _res; } -// signed_real_number: real_number | '-' real_number +// signed_real_number: real_number | '+' real_number | '-' real_number static expr_ty signed_real_number_rule(Parser *p) { @@ -9190,6 +9217,33 @@ signed_real_number_rule(Parser *p) D(fprintf(stderr, "%*c%s signed_real_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "real_number")); } + { // '+' real_number + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' real_number")); + Token * _literal; + expr_ty real; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (real = real_number_rule(p)) // real_number + ) + { + D(fprintf(stderr, "%*c+ signed_real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' real_number")); + _res = real; + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s signed_real_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' real_number")); + } { // '-' real_number if (p->error_indicator) { p->level--; @@ -9275,7 +9329,7 @@ real_number_rule(Parser *p) return _res; } -// imaginary_number: NUMBER +// imaginary_number: NUMBER | '+' NUMBER static expr_ty imaginary_number_rule(Parser *p) { @@ -9312,6 +9366,33 @@ imaginary_number_rule(Parser *p) D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NUMBER")); } + { // '+' NUMBER + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + Token * _literal; + expr_ty imag; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' + && + (imag = _PyPegen_number_token(p)) // NUMBER + ) + { + D(fprintf(stderr, "%*c+ imaginary_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); + _res = _PyPegen_ensure_imaginary ( p , imag ); + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' NUMBER")); + } _res = NULL; done: p->level--; diff --git a/Android/README.md b/Platforms/Android/README.md similarity index 63% rename from Android/README.md rename to Platforms/Android/README.md index 0004f26e72b..d6f95c365c6 100644 --- a/Android/README.md +++ b/Platforms/Android/README.md @@ -11,7 +11,6 @@ # Python for Android [here](https://docs.python.org/3/using/android.html), which will provide a much easier experience. - ## Prerequisites If you already have an Android SDK installed, export the `ANDROID_HOME` @@ -25,7 +24,7 @@ ## Prerequisites `android-sdk/cmdline-tools/latest`. * `export ANDROID_HOME=/path/to/android-sdk` -The `android.py` script will automatically use the SDK's `sdkmanager` to install +The `Platforms/Android` script will automatically use the SDK's `sdkmanager` to install any packages it needs. The script also requires the following commands to be on the `PATH`: @@ -33,7 +32,6 @@ ## Prerequisites * `curl` * `java` (or set the `JAVA_HOME` environment variable) - ## Building Python can be built for Android on any POSIX platform supported by the Android @@ -43,29 +41,28 @@ ## Building help produce a "host" Python for Android. So make sure you have all the usual tools and libraries needed to build Python for your development machine. -The easiest way to do a build is to use the `android.py` script. You can either +The easiest way to do a build is to use the `Platforms/Android` script. You can either have it perform the entire build process from start to finish in one step, or you can do it in discrete steps that mirror running `configure` and `make` for each of the two builds of Python you end up producing. -The discrete steps for building via `android.py` are: +The discrete steps for building via `Platforms/Android` are: ```sh -./android.py configure-build -./android.py make-build -./android.py configure-host HOST -./android.py make-host HOST +python3 Platforms/Android configure-build +python3 Platforms/Android make-build +python3 Platforms/Android configure-host HOST +python3 Platforms/Android make-host HOST ``` `HOST` identifies which architecture to build. To see the possible values, run -`./android.py configure-host --help`. +`python3 Platforms/Android configure-host --help`. To do all steps in a single command, run: ```sh -./android.py build HOST +python3 Platforms/Android build HOST ``` - In the end you should have a build Python in `cross-build/build`, and a host Python in `cross-build/HOST`. @@ -75,17 +72,16 @@ ## Building `configure`, you can do: ```sh -./android.py build HOST -- -C --with-pydebug +python3 Platforms/Android build HOST -- -C --with-pydebug ``` - ## Packaging After building an architecture as described in the section above, you can package it for release with this command: ```sh -./android.py package HOST +python3 Platforms/Android package HOST ``` `HOST` is defined in the section above. @@ -93,25 +89,16 @@ ## Packaging This will generate a tarball in `cross-build/HOST/dist`, whose structure is similar to the `Android` directory of the CPython source tree. - ## Testing -The Python test suite can be run on Linux, macOS, or Windows. +Tests can be run on Linux, macOS, or Windows, using either an Android emulator +or a physical device. On Linux, the emulator needs access to the KVM virtualization interface. This may require adding your user to a group, or changing your udev rules. On GitHub Actions, the test script will do this automatically using the commands shown [here](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/). -You can run the test suite either: - -* Within the CPython repository, after doing a build as described above. On - Windows, you won't be able to do the build on the same machine, so you'll have - to copy the `cross-build/HOST/prefix` directory from somewhere else. - -* Or by taking a release package built using the `package` command, extracting - it wherever you want, and using its own copy of `android.py`. - The test script supports the following modes: * In `--connected` mode, it runs on a device or emulator you have already @@ -120,7 +107,7 @@ ## Testing script like this: ```sh - ./android.py test --connected emulator-5554 + python3 Platforms/Android test --connected emulator-5554 ``` * In `--managed` mode, it uses a temporary headless emulator defined in the @@ -131,29 +118,55 @@ ## Testing to our minimum and maximum supported Android versions. For example: ```sh - ./android.py test --managed maxVersion + python3 Platforms/Android test --managed maxVersion ``` By default, the only messages the script will show are Python's own stdout and stderr. Add the `-v` option to also show Gradle output, and non-Python logcat messages. -Any other arguments on the `android.py test` command line will be passed through -to `python -m test` – use `--` to separate them from android.py's own options. +### Testing Python + +You can run the test suite by doing a build as described above, and then running +`python3 Platforms/Android test`. On Windows, you won't be able to do the build +on the same machine, so you'll have to copy the `cross-build/HOST/prefix` directory +from somewhere else. + +Extra arguments on the `Platforms/Android test` command line will be passed through +to `python -m test` – use `--` to separate them from `Platforms/Android`'s own options. See the [Python Developer's Guide](https://devguide.python.org/testing/run-write-tests/) for common options – most of them will work on Android, except for those that involve subprocesses, such as `-j`. -Every time you run `android.py test`, changes in pure-Python files in the +Every time you run `python3 Platforms/Android test`, changes in pure-Python files in the repository's `Lib` directory will be picked up immediately. Changes in C files, and architecture-specific files such as sysconfigdata, will not take effect -until you re-run `android.py make-host` or `build`. +until you re-run `python3 Platforms/Android make-host` or `build`. -The testbed app can also be used to test third-party packages. For more details, -run `android.py test --help`, paying attention to the options `--site-packages`, -`--cwd`, `-c` and `-m`. +### Testing a third-party package +The `Platforms/Android` script is also included as `android.py` in the root of a +release package (i.e., the one built using `Platforms/Android package`). + +You can use this script to test third-party packages by taking a release +package, extracting it wherever you want, and using the `android.py` script to +run the test suite for your third-party package. + +Any argument that can be passed to `python3 Platforms/Android test` can also be +passed to `android.py`. The following options will be of particular use when +configuring the execution of a third-party test suite: + +* `--cwd`: the directory of content to copy into the testbed app as the working + directory. +* `--site-packages`: the directory to copy into the testbed app to use as site + packages. + +Extra arguments on the `android.py test` command line will be passed through to +Python – use `--` to separate them from `android.py`'s own options. You must include +either a `-c` or `-m` argument to specify how the test suite should be started. + +For more details, run `android.py test --help`. ## Using in your own app diff --git a/Android/android.py b/Platforms/Android/__main__.py similarity index 97% rename from Android/android.py rename to Platforms/Android/__main__.py index adcc7c708d9..315632ea12c 100755 --- a/Android/android.py +++ b/Platforms/Android/__main__.py @@ -24,8 +24,11 @@ SCRIPT_NAME = Path(__file__).name +if SCRIPT_NAME.startswith("__"): + SCRIPT_NAME = "Platforms/Android" + ANDROID_DIR = Path(__file__).resolve().parent -PYTHON_DIR = ANDROID_DIR.parent +PYTHON_DIR = ANDROID_DIR.parent.parent in_source_tree = ( ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists() ) @@ -393,17 +396,6 @@ def setup_testbed(): os.chmod(out_path, 0o755) -# run_testbed will build the app automatically, but it's useful to have this as -# a separate command to allow running the app outside of this script. -def build_testbed(context): - setup_sdk() - setup_testbed() - run( - [gradlew, "--console", "plain", "packageDebug", "packageDebugAndroidTest"], - cwd=TESTBED_DIR, - ) - - # Work around a bug involving sys.exit and TaskGroups # (https://github.com/python/cpython/issues/101515). def exit(*args): @@ -645,6 +637,10 @@ async def gradle_task(context): task_prefix = "connected" env["ANDROID_SERIAL"] = context.connected + # Ensure that CROSS_BUILD_DIR is in the Gradle environment, regardless + # of whether it was set by environment variable or `--cross-build-dir`. + env["CROSS_BUILD_DIR"] = CROSS_BUILD_DIR + if context.ci_mode: context.args[0:0] = [ # See _add_ci_python_opts in libregrtest/main.py. @@ -763,7 +759,7 @@ def package(context): prefix_dir = subdir(context.host, "prefix") version = package_version(prefix_dir) - with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir: + with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir: temp_dir = Path(temp_dir) # Include all tracked files from the Android directory. @@ -772,7 +768,10 @@ def package(context): cwd=ANDROID_DIR, capture_output=True, text=True, log=False, ).stdout.splitlines(): src = ANDROID_DIR / line - dst = temp_dir / line + # "__main__.py" is renamed "android.py" for distribution purpose + dst = temp_dir / { + "__main__.py": "android.py" + }.get(line, line) dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(src, dst, follow_symlinks=False) @@ -838,7 +837,7 @@ def ci(context): "emulator on this platform." ) else: - with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir: + with TemporaryDirectory(prefix=SCRIPT_NAME.replace("/", "-")) as temp_dir: print("::group::Tests") # Prove the package is self-contained by using it to run the tests. @@ -873,49 +872,6 @@ def parse_args(): def add_parser(*args, **kwargs): parser = subcommands.add_parser(*args, **kwargs) parser.add_argument( - "-v", "--verbose", action="count", default=0, - help="Show verbose output. Use twice to be even more verbose.") - return parser - - # Subcommands - build = add_parser( - "build", - help="Run configure and make for the selected target" - ) - configure_build = add_parser( - "configure-build", help="Run `configure` for the build Python") - make_build = add_parser( - "make-build", help="Run `make` for the build Python") - configure_host = add_parser( - "configure-host", help="Run `configure` for Android") - make_host = add_parser( - "make-host", help="Run `make` for Android") - - clean = add_parser( - "clean", - help="Delete build directories for the selected target" - ) - - add_parser("build-testbed", help="Build the testbed app") - test = add_parser("test", help="Run the testbed app") - package = add_parser("package", help="Make a release package") - ci = add_parser("ci", help="Run build, package and test") - env = add_parser("env", help="Print environment variables") - - # Common arguments - # --cross-build-dir argument - for cmd in [ - clean, - configure_build, - make_build, - configure_host, - make_host, - build, - package, - test, - ci, - ]: - cmd.add_argument( "--cross-build-dir", action="store", default=os.environ.get("CROSS_BUILD_DIR"), @@ -927,7 +883,36 @@ def add_parser(*args, **kwargs): "with the CROSS_BUILD_DIR environment variable." ), ) + parser.add_argument( + "-v", "--verbose", action="count", default=0, + help="Show verbose output. Use twice to be even more verbose.") + return parser + # Subcommands + build = add_parser( + "build", + help="Run configure and make for the selected target" + ) + configure_build = add_parser( + "configure-build", help="Run `configure` for the build Python") + add_parser( + "make-build", help="Run `make` for the build Python") + configure_host = add_parser( + "configure-host", help="Run `configure` for Android") + make_host = add_parser( + "make-host", help="Run `make` for Android") + + clean = add_parser( + "clean", + help="Delete build directories for the selected target" + ) + + test = add_parser("test", help="Run the testbed app") + package = add_parser("package", help="Make a release package") + ci = add_parser("ci", help="Run build, package and test") + env = add_parser("env", help="Print environment variables") + + # Common arguments # --cache-dir option for cmd in [configure_host, build, ci]: cmd.add_argument( @@ -1032,7 +1017,6 @@ def main(): "make-host": make_host_python, "build": build_targets, "clean": clean_targets, - "build-testbed": build_testbed, "test": run_testbed, "package": package, "ci": ci, diff --git a/Android/android-env.sh b/Platforms/Android/android-env.sh similarity index 100% rename from Android/android-env.sh rename to Platforms/Android/android-env.sh diff --git a/Android/testbed/.gitignore b/Platforms/Android/testbed/.gitignore similarity index 100% rename from Android/testbed/.gitignore rename to Platforms/Android/testbed/.gitignore diff --git a/Android/testbed/.idea/inspectionProfiles/Project_Default.xml b/Platforms/Android/testbed/.idea/inspectionProfiles/Project_Default.xml similarity index 100% rename from Android/testbed/.idea/inspectionProfiles/Project_Default.xml rename to Platforms/Android/testbed/.idea/inspectionProfiles/Project_Default.xml diff --git a/Android/testbed/app/.gitignore b/Platforms/Android/testbed/app/.gitignore similarity index 100% rename from Android/testbed/app/.gitignore rename to Platforms/Android/testbed/app/.gitignore diff --git a/Android/testbed/app/build.gradle.kts b/Platforms/Android/testbed/app/build.gradle.kts similarity index 99% rename from Android/testbed/app/build.gradle.kts rename to Platforms/Android/testbed/app/build.gradle.kts index b58edc04a92..e51398fce81 100644 --- a/Android/testbed/app/build.gradle.kts +++ b/Platforms/Android/testbed/app/build.gradle.kts @@ -7,8 +7,8 @@ plugins { } val ANDROID_DIR = file("../..") -val PYTHON_DIR = ANDROID_DIR.parentFile!! -val PYTHON_CROSS_DIR = file("$PYTHON_DIR/cross-build") +val PYTHON_DIR = ANDROID_DIR.parentFile.parentFile!! +val PYTHON_CROSS_DIR = file(System.getenv("CROSS_BUILD_DIR") ?: "$PYTHON_DIR/cross-build") val inSourceTree = ( ANDROID_DIR.name == "Android" && file("$PYTHON_DIR/pyconfig.h.in").exists() ) diff --git a/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt b/Platforms/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt similarity index 100% rename from Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt rename to Platforms/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt diff --git a/Android/testbed/app/src/main/AndroidManifest.xml b/Platforms/Android/testbed/app/src/main/AndroidManifest.xml similarity index 100% rename from Android/testbed/app/src/main/AndroidManifest.xml rename to Platforms/Android/testbed/app/src/main/AndroidManifest.xml diff --git a/Android/testbed/app/src/main/c/CMakeLists.txt b/Platforms/Android/testbed/app/src/main/c/CMakeLists.txt similarity index 100% rename from Android/testbed/app/src/main/c/CMakeLists.txt rename to Platforms/Android/testbed/app/src/main/c/CMakeLists.txt diff --git a/Android/testbed/app/src/main/c/main_activity.c b/Platforms/Android/testbed/app/src/main/c/main_activity.c similarity index 100% rename from Android/testbed/app/src/main/c/main_activity.c rename to Platforms/Android/testbed/app/src/main/c/main_activity.c diff --git a/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt b/Platforms/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt similarity index 100% rename from Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt rename to Platforms/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt diff --git a/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/Platforms/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png rename to Platforms/Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/Android/testbed/app/src/main/res/layout/activity_main.xml b/Platforms/Android/testbed/app/src/main/res/layout/activity_main.xml similarity index 100% rename from Android/testbed/app/src/main/res/layout/activity_main.xml rename to Platforms/Android/testbed/app/src/main/res/layout/activity_main.xml diff --git a/Android/testbed/app/src/main/res/values/strings.xml b/Platforms/Android/testbed/app/src/main/res/values/strings.xml similarity index 100% rename from Android/testbed/app/src/main/res/values/strings.xml rename to Platforms/Android/testbed/app/src/main/res/values/strings.xml diff --git a/Android/testbed/build.gradle.kts b/Platforms/Android/testbed/build.gradle.kts similarity index 100% rename from Android/testbed/build.gradle.kts rename to Platforms/Android/testbed/build.gradle.kts diff --git a/Android/testbed/gradle.properties b/Platforms/Android/testbed/gradle.properties similarity index 100% rename from Android/testbed/gradle.properties rename to Platforms/Android/testbed/gradle.properties diff --git a/Android/testbed/gradle/wrapper/gradle-wrapper.properties b/Platforms/Android/testbed/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from Android/testbed/gradle/wrapper/gradle-wrapper.properties rename to Platforms/Android/testbed/gradle/wrapper/gradle-wrapper.properties diff --git a/Android/testbed/settings.gradle.kts b/Platforms/Android/testbed/settings.gradle.kts similarity index 100% rename from Android/testbed/settings.gradle.kts rename to Platforms/Android/testbed/settings.gradle.kts diff --git a/Platforms/emscripten/README.md b/Platforms/emscripten/README.md index 017bb3c8977..ce230c4b74a 100644 --- a/Platforms/emscripten/README.md +++ b/Platforms/emscripten/README.md @@ -186,8 +186,8 @@ #### In the browser are not shipped. All other modules are bundled as pre-compiled ``pyc`` files. - In-memory file system (MEMFS) is not persistent and limited. -- Test modules are disabled by default. Use ``--enable-test-modules`` build - test modules like ``_testcapi``. +- Test modules are built by default. Use ``--disable-test-modules`` to disable + building test modules like ``_testcapi``. ## Detecting Emscripten builds diff --git a/Platforms/emscripten/web_example/index.html b/Platforms/emscripten/web_example/index.html index 9c89c9c0ed3..3a207b92015 100644 --- a/Platforms/emscripten/web_example/index.html +++ b/Platforms/emscripten/web_example/index.html @@ -663,9 +663,9 @@

Simple REPL for Python WASM

The simple REPL provides a limited Python experience in the browser. - Tools/wasm/README.md + Platforms/emscripten/README.md contains a list of known limitations and issues. Networking, subprocesses, and threading are not available. @@ -679,9 +679,9 @@

Simple REPL for Python WASM

your browser instead of using server.py as described in - Tools/wasm/README.md + Platforms/emscripten/README.md .

diff --git a/Programs/_testembed.c b/Programs/_testembed.c index d4d2a7131cc..285f4f091b2 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -2000,6 +2000,8 @@ static int test_init_main(void) config._init_main = 0; init_from_config_clear(&config); + assert(Py_IsInitialized() == 0); + /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */ int res = PyRun_SimpleString( "import sys; " @@ -2203,6 +2205,52 @@ static int test_init_in_background_thread(void) return PyThread_join_thread(handle); } +/* gh-146302: Py_IsInitialized() must not return true during site import. */ +static int _initialized_during_site_import = -1; /* -1 = not observed */ + +static int hook_check_initialized_on_site_import( + const char *event, PyObject *args, void *userData) +{ + if (strcmp(event, "import") == 0 && args != NULL) { + PyObject *name = PyTuple_GetItem(args, 0); + if (name != NULL && PyUnicode_Check(name) + && PyUnicode_CompareWithASCIIString(name, "site") == 0 + && _initialized_during_site_import == -1) + { + _initialized_during_site_import = Py_IsInitialized(); + } + } + return 0; +} + +static int test_isinitialized_false_during_site_import(void) +{ + _initialized_during_site_import = -1; + + /* Register audit hook before initialization */ + PySys_AddAuditHook(hook_check_initialized_on_site_import, NULL); + + _testembed_initialize(); + + if (_initialized_during_site_import == -1) { + error("audit hook never observed site import"); + Py_Finalize(); + return 1; + } + if (_initialized_during_site_import != 0) { + error("Py_IsInitialized() was true during site import"); + Py_Finalize(); + return 1; + } + if (!Py_IsInitialized()) { + error("Py_IsInitialized() was false after Py_Initialize()"); + return 1; + } + + Py_Finalize(); + return 0; +} + #ifndef MS_WINDOWS #include "test_frozenmain.h" // M_test_frozenmain @@ -2693,6 +2741,7 @@ static struct TestCase TestCases[] = { {"test_init_use_frozen_modules", test_init_use_frozen_modules}, {"test_init_main_interpreter_settings", test_init_main_interpreter_settings}, {"test_init_in_background_thread", test_init_in_background_thread}, + {"test_isinitialized_false_during_site_import", test_isinitialized_false_during_site_import}, // Audit {"test_open_code_hook", test_open_code_hook}, diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index d550740b110..28e08e42f5c 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,7 +1,7 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, - 0,0,0,0,0,243,186,0,0,0,128,0,0,0,93,0, + 0,0,0,0,0,243,188,0,0,0,128,0,0,0,93,0, 81,1,72,0,115,0,93,0,81,1,72,4,115,1,92,2, 31,0,81,2,50,1,0,0,0,0,0,0,29,0,92,2, 31,0,81,3,92,0,79,6,0,0,0,0,0,0,0,0, @@ -9,31 +9,31 @@ unsigned char M_test_frozenmain[] = { 0,0,29,0,92,1,79,8,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,31,0,50,0,0,0, 0,0,0,0,81,4,42,26,0,0,0,0,0,0,0,0, - 0,0,115,5,81,7,70,0,68,24,0,0,115,6,92,2, - 31,0,81,5,92,6,12,0,81,6,92,5,92,6,42,26, - 0,0,0,0,0,0,0,0,0,0,12,0,48,4,50,1, - 0,0,0,0,0,0,29,0,74,26,0,0,9,0,28,0, - 81,1,33,0,41,8,233,0,0,0,0,78,122,18,70,114, - 111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100, - 122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102, - 105,103,122,7,99,111,110,102,105,103,32,122,2,58,32,41, - 5,218,12,112,114,111,103,114,97,109,95,110,97,109,101,218, - 10,101,120,101,99,117,116,97,98,108,101,218,15,117,115,101, - 95,101,110,118,105,114,111,110,109,101,110,116,218,17,99,111, - 110,102,105,103,117,114,101,95,99,95,115,116,100,105,111,218, - 14,98,117,102,102,101,114,101,100,95,115,116,100,105,111,41, - 7,218,3,115,121,115,218,17,95,116,101,115,116,105,110,116, - 101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116, - 218,4,97,114,103,118,218,11,103,101,116,95,99,111,110,102, - 105,103,115,114,3,0,0,0,218,3,107,101,121,169,0,243, - 0,0,0,0,218,18,116,101,115,116,95,102,114,111,122,101, - 110,109,97,105,110,46,112,121,218,8,60,109,111,100,117,108, - 101,62,114,18,0,0,0,1,0,0,0,115,94,0,0,0, - 241,3,1,1,1,243,8,0,1,11,219,0,24,225,0,5, - 208,6,26,212,0,27,217,0,5,128,106,144,35,151,40,145, - 40,212,0,27,216,9,26,215,9,38,210,9,38,211,9,40, - 168,24,213,9,50,128,6,243,2,6,12,2,128,67,241,14, - 0,5,10,136,71,144,67,144,53,152,2,152,54,160,35,157, - 59,152,45,208,10,40,214,4,41,243,15,6,12,2,114,16, - 0,0,0, + 0,0,115,5,81,7,70,0,0,0,68,24,0,0,115,6, + 92,2,31,0,81,5,92,6,12,0,81,6,92,5,92,6, + 42,26,0,0,0,0,0,0,0,0,0,0,12,0,48,4, + 50,1,0,0,0,0,0,0,29,0,74,26,0,0,9,0, + 28,0,81,1,33,0,41,8,233,0,0,0,0,78,122,18, + 70,114,111,122,101,110,32,72,101,108,108,111,32,87,111,114, + 108,100,122,8,115,121,115,46,97,114,103,118,218,6,99,111, + 110,102,105,103,122,7,99,111,110,102,105,103,32,122,2,58, + 32,41,5,218,12,112,114,111,103,114,97,109,95,110,97,109, + 101,218,10,101,120,101,99,117,116,97,98,108,101,218,15,117, + 115,101,95,101,110,118,105,114,111,110,109,101,110,116,218,17, + 99,111,110,102,105,103,117,114,101,95,99,95,115,116,100,105, + 111,218,14,98,117,102,102,101,114,101,100,95,115,116,100,105, + 111,41,7,218,3,115,121,115,218,17,95,116,101,115,116,105, + 110,116,101,114,110,97,108,99,97,112,105,218,5,112,114,105, + 110,116,218,4,97,114,103,118,218,11,103,101,116,95,99,111, + 110,102,105,103,115,114,3,0,0,0,218,3,107,101,121,169, + 0,243,0,0,0,0,218,18,116,101,115,116,95,102,114,111, + 122,101,110,109,97,105,110,46,112,121,218,8,60,109,111,100, + 117,108,101,62,114,18,0,0,0,1,0,0,0,115,94,0, + 0,0,241,3,1,1,1,243,8,0,1,11,219,0,24,225, + 0,5,208,6,26,212,0,27,217,0,5,128,106,144,35,151, + 40,145,40,212,0,27,216,9,26,215,9,38,210,9,38,211, + 9,40,168,24,213,9,50,128,6,244,2,6,12,2,128,67, + 241,14,0,5,10,136,71,144,67,144,53,152,2,152,54,160, + 35,157,59,152,45,208,10,40,214,4,41,243,15,6,12,2, + 114,16,0,0,0, }; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index fec64e1ff9d..16413d784cc 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1840,15 +1840,17 @@ hash as builtin_hash obj: object / -Return the hash value for the given object. +Return the integer hash value for the given object. -Two objects that compare equal must also have the same hash value, but the -reverse is not necessarily true. +Two objects that compare equal must also have the same hash value, but +the reverse is not necessarily true. Hash values may differ between +Python processes. Not all objects are hashable; calling hash() on an +unhashable object raises TypeError. [clinic start generated code]*/ static PyObject * builtin_hash(PyObject *module, PyObject *obj) -/*[clinic end generated code: output=237668e9d7688db7 input=58c48be822bf9c54]*/ +/*[clinic end generated code: output=237668e9d7688db7 input=70a242ff65f6717c]*/ { Py_hash_t x; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index a7d2d652e68..59db0eb399b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -199,7 +199,7 @@ dummy_func( } } - op(_LOAD_BYTECODE, (--)) { + replaced op(_LOAD_BYTECODE, (--)) { #ifdef Py_GIL_DISABLED if (frame->tlbc_index != ((_PyThreadStateImpl *)tstate)->tlbc_index) { @@ -381,11 +381,6 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(value, _PyUnicode_ExactDealloc); } - tier2 op(_POP_TWO, (nos, tos --)) { - PyStackRef_CLOSE(tos); - PyStackRef_CLOSE(nos); - } - op(_POP_TOP_OPARG, (args[oparg] -- )) { _PyStackRef_CloseStack(args, oparg); DEAD(args); @@ -900,6 +895,53 @@ dummy_func( INPUTS_DEAD(); } + // Float true division --- not specialized at tier 1, emitted by the + // tier 2 optimizer when both operands are known floats. + tier2 op(_BINARY_OP_TRUEDIV_FLOAT, (left, right -- res, l, r)) { + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyFloat_CheckExact(left_o)); + assert(PyFloat_CheckExact(right_o)); + STAT_INC(BINARY_OP, hit); + double divisor = ((PyFloatObject *)right_o)->ob_fval; + if (divisor == 0.0) { + PyErr_SetString(PyExc_ZeroDivisionError, + "float division by zero"); + ERROR_NO_POP(); + } + double dres = ((PyFloatObject *)left_o)->ob_fval / divisor; + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(d); + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, (left, right -- res, l, r)) { + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + ERROR_NO_POP(); + } + res = left; + l = PyStackRef_NULL; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) { + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + ERROR_NO_POP(); + } + res = right; + l = left; + r = PyStackRef_NULL; + INPUTS_DEAD(); + } + pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); @@ -966,14 +1008,32 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(temp); } + tier2 op(_GUARD_BINARY_OP_EXTEND_LHS, (descr/4, left, right -- left, right)) { + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + EXIT_IF(Py_TYPE(left_o) != d->lhs_type); + } + + tier2 op(_GUARD_BINARY_OP_EXTEND_RHS, (descr/4, left, right -- left, right)) { + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + EXIT_IF(Py_TYPE(right_o) != d->rhs_type); + } + op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); - int res = d->guard(left_o, right_o); - EXIT_IF(!res); + assert(d != NULL); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); + EXIT_IF(!match); } op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { @@ -988,6 +1048,14 @@ dummy_func( if (res_o == NULL) { ERROR_NO_POP(); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + // The JIT and tier 2 optimizer assume that float results from + // binary operations are always uniquely referenced (refcount == 1). + // If this assertion fails, update the optimizer to stop marking + // float results as unique in optimizer_bytecodes.c. + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); + res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -2752,6 +2820,11 @@ dummy_func( } } + op(_GUARD_TYPE, (type/4, owner -- owner)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + EXIT_IF(tp != (PyTypeObject *)type); + } + op(_CHECK_MANAGED_OBJECT_HAS_VALUES, (owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_dictoffset < 0); @@ -2924,14 +2997,12 @@ dummy_func( _LOAD_ATTR_CLASS + _PUSH_NULL_CONDITIONAL; - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + EXIT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; - EXIT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED); - EXIT_IF(code->co_kwonlyargcount); - EXIT_IF(code->co_argcount != 1); EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); @@ -2945,40 +3016,38 @@ dummy_func( _RECORD_TOS_TYPE + _GUARD_TYPE_VERSION + _CHECK_PEP_523 + - unused/2 + _LOAD_ATTR_PROPERTY_FRAME + _SAVE_RETURN_OFFSET + _PUSH_FRAME; - inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused)) { - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - + op(_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, (func_version/2, getattribute/4, owner -- new_frame)) { assert((oparg & 1) == 0); - DEOPT_IF(IS_PEP523_HOOKED(tstate)); - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - DEOPT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(cls->tp_version_tag) != type_version); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; assert(func_version != 0); - DEOPT_IF(f->func_version != func_version); + EXIT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; + pushed_frame->localsplus[0] = owner; DEAD(owner); - // Manipulate stack directly because we exit with DISPATCH_INLINED(). - SYNC_SP(); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = INSTRUCTION_SIZE; - DISPATCH_INLINED(new_frame); + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } + macro(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) = + unused/1 + + _RECORD_TOS_TYPE + + _GUARD_TYPE_VERSION + + _CHECK_PEP_523 + + _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + + _SAVE_RETURN_OFFSET + + _PUSH_FRAME; + op(_GUARD_DORV_NO_DICT, (owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); @@ -3016,6 +3085,7 @@ dummy_func( macro(STORE_ATTR_INSTANCE_VALUE) = unused/1 + + _RECORD_TOS_TYPE + _LOCK_OBJECT + _GUARD_TYPE_VERSION_LOCKED + _GUARD_DORV_NO_DICT + @@ -3459,7 +3529,7 @@ dummy_func( int og_oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); } opcode = og_opcode; @@ -3590,16 +3660,71 @@ dummy_func( values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); } - inst(GET_ITER, (iterable -- iter, index_or_null)) { - #ifdef Py_STATS - _Py_GatherStats_GetIter(iterable); - #endif + family(GET_ITER, INLINE_CACHE_ENTRIES_GET_ITER) = { + GET_ITER_SELF, + GET_ITER_VIRTUAL, + }; + + specializing op(_SPECIALIZE_GET_ITER, (counter/1, iterable -- iterable)) { + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _Py_Specialize_GetIter(iterable, next_instr); + DISPATCH_SAME_OPARG(); + } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ + } + + op(_GET_ITER, (iterable -- iter, index_or_null)) { _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); DEAD(iterable); ERROR_IF(PyStackRef_IsError(result)); iter = result; } + macro(GET_ITER) = + _RECORD_TOS_TYPE + + _SPECIALIZE_GET_ITER + + _GET_ITER; + + op(_GUARD_ITERATOR, (iterable -- iterable)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + EXIT_IF(tp->tp_iter != PyObject_SelfIter); + STAT_INC(GET_ITER, hit); + } + + macro(GET_ITER_SELF) = + _RECORD_TOS_TYPE + + unused/1 + + _GUARD_ITERATOR + + PUSH_NULL; + + op(_GUARD_ITER_VIRTUAL, (iterable -- iterable)) { + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + EXIT_IF(tp->_tp_iteritem == NULL); + STAT_INC(GET_ITER, hit); + } + + op(_PUSH_TAGGED_ZERO, ( -- zero)) { + zero = PyStackRef_TagInt(0); + } + + macro(GET_ITER_VIRTUAL) = + _RECORD_TOS_TYPE + + unused/1 + + _GUARD_ITER_VIRTUAL + + _PUSH_TAGGED_ZERO; + + op(_GET_ITER_TRAD, (iterable -- iter, index_or_null)) { + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + PyStackRef_CLOSE(iterable); + ERROR_IF(iter_o == NULL); + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; + } + // Most members of this family are "secretly" super-instructions. // When the loop is exhausted, they jump, and the jump target is // always END_FOR, which pops two values off the stack. @@ -3611,6 +3736,7 @@ dummy_func( FOR_ITER_TUPLE, FOR_ITER_RANGE, FOR_ITER_GEN, + FOR_ITER_VIRTUAL, }; specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter, null_or_index -- iter, null_or_index)) { @@ -3638,6 +3764,8 @@ dummy_func( next = item; } + macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; + op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); if (!PyStackRef_IsValid(item)) { @@ -3651,9 +3779,51 @@ dummy_func( next = item; } + op(_GUARD_NOS_ITER_VIRTUAL, (iter, null_or_index -- iter, null_or_index)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + EXIT_IF(Py_TYPE(iter_o)->_tp_iteritem == NULL); + } - macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; + replaced op(_FOR_ITER_VIRTUAL, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + ERROR_NO_POP(); + } + // Jump forward by oparg and skip the following END_FOR + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + macro(FOR_ITER_VIRTUAL) = + unused/1 + // Skip over the counter + _GUARD_NOS_ITER_VIRTUAL + + _FOR_ITER_VIRTUAL; + + op(_FOR_ITER_VIRTUAL_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + ERROR_NO_POP(); + } + /* iterator ended normally */ + /* The translator sets the deopt target just past the matching END_FOR */ + EXIT_IF(true); + } + next = PyStackRef_FromPyObjectSteal(next_o); + null_or_index = PyStackRef_TagInt(index); + } inst(INSTRUMENTED_FOR_ITER, (unused/1, iter, null_or_index -- iter, null_or_index, next)) { _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); @@ -3891,6 +4061,7 @@ dummy_func( } macro(LOAD_SPECIAL) = + _RECORD_TOS_TYPE + _INSERT_NULL + _LOAD_SPECIAL; @@ -4503,15 +4674,23 @@ dummy_func( POP_TOP + _CHECK_PERIODIC_AT_END; - op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); EXIT_IF(!PyStackRef_IsNull(self_or_null)); EXIT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version); + } + + op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; PyFunctionObject *init_func = (PyFunctionObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init); PyCodeObject *code = (PyCodeObject *)init_func->func_code; @@ -4556,7 +4735,8 @@ dummy_func( _RECORD_CALLABLE + unused/1 + _CHECK_PEP_523 + - _CHECK_AND_ALLOCATE_OBJECT + + _CHECK_OBJECT + + _ALLOCATE_OBJECT + _CREATE_INIT_FRAME + _PUSH_FRAME; @@ -4570,34 +4750,41 @@ dummy_func( DEAD(should_be_none); } - op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- res)) { + op(_GUARD_CALLABLE_BUILTIN_CLASS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); EXIT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; + EXIT_IF(tp->tp_vectorcall == NULL); + } + + op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - EXIT_IF(tp->tp_vectorcall == NULL); STAT_INC(CALL, hit); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_BUILTIN_CLASS) = _RECORD_CALLABLE + unused/1 + unused/2 + + _GUARD_CALLABLE_BUILTIN_CLASS + _CALL_BUILTIN_CLASS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; op(_GUARD_CALLABLE_BUILTIN_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { @@ -4618,8 +4805,6 @@ dummy_func( if (!PyStackRef_IsNull(self_or_null)) { args--; } - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -4640,6 +4825,7 @@ dummy_func( unused/1 + unused/2 + _GUARD_CALLABLE_BUILTIN_O + + _CHECK_RECURSION_LIMIT + _CALL_BUILTIN_O + POP_TOP + POP_TOP + @@ -4689,7 +4875,7 @@ dummy_func( EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS)); } - op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int total_args = oparg; _PyStackRef *arguments = args; @@ -4698,12 +4884,13 @@ dummy_func( total_args++; } STAT_INC(CALL, hit); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_BUILTIN_FAST_WITH_KEYWORDS) = @@ -4712,6 +4899,8 @@ dummy_func( unused/2 + _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS + _CALL_BUILTIN_FAST_WITH_KEYWORDS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; macro(CALL_LEN) = @@ -4904,7 +5093,7 @@ dummy_func( EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); } - op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; @@ -4918,36 +5107,38 @@ dummy_func( assert(self != NULL); STAT_INC(CALL, hit); PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc, self, arguments, total_args ); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } - tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, (callable, args[oparg], cfunc/4 -- res)) { - PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); - assert(self != NULL); + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, (callable, self_st, args[oparg], cfunc/4 -- callable, self_st, args[oparg])) { + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); STAT_INC(CALL, hit); volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc_v, self, - args, - oparg + args - 1, + oparg + 1 ); - DEAD(args); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) = @@ -4956,6 +5147,8 @@ dummy_func( unused/2 + _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { @@ -5042,7 +5235,7 @@ dummy_func( EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); } - op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) { + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; @@ -5056,36 +5249,39 @@ dummy_func( assert(self != NULL); STAT_INC(CALL, hit); PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc, self, arguments, total_args ); - DEAD(args); - DEAD(self_or_null); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } - tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, (callable, args[oparg], cfunc/4 -- res)) { - PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, (callable, self_st, args[oparg], cfunc/4 -- callable, self_st, args[oparg])) { + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); assert(self != NULL); STAT_INC(CALL, hit); volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc_v, self, - args, - oparg + args - 1, + oparg + 1 ); - DEAD(args); - DEAD(callable); - ERROR_IF(res_o == NULL); - res = PyStackRef_FromPyObjectSteal(res_o); + if (res_o == NULL) { + ERROR_NO_POP(); + } + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + PyStackRef_CLOSE(temp); } macro(CALL_METHOD_DESCRIPTOR_FAST) = @@ -5093,6 +5289,8 @@ dummy_func( unused/2 + _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST + _CALL_METHOD_DESCRIPTOR_FAST + + _POP_TOP_OPARG + + POP_TOP + _CHECK_PERIODIC_AT_END; // Cache layout: counter/1, func_version/2 @@ -5226,6 +5424,7 @@ dummy_func( } macro(CALL_KW_PY) = + _RECORD_CALLABLE_KW + unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_FUNCTION_VERSION_KW + @@ -5256,6 +5455,7 @@ dummy_func( } macro(CALL_KW_BOUND_METHOD) = + _RECORD_CALLABLE_KW + unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_METHOD_VERSION_KW + @@ -5651,7 +5851,7 @@ dummy_func( DEAD(rhs); } - macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP + POP_TOP + POP_TOP; + macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _RECORD_TOS_TYPE + _RECORD_NOS_TYPE + unused/4 + _BINARY_OP + POP_TOP + POP_TOP; pure replicate(2:4) inst(SWAP, (bottom, unused[oparg-2], top -- bottom, unused[oparg-2], top)) { @@ -5903,54 +6103,10 @@ dummy_func( value = PyStackRef_FromPyObjectNew(ptr); } - tier2 pure op (_POP_TOP_LOAD_CONST_INLINE, (ptr/4, pop -- value)) { - PyStackRef_CLOSE(pop); - value = PyStackRef_FromPyObjectNew(ptr); - } - tier2 pure op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { value = PyStackRef_FromPyObjectBorrow(ptr); } - tier2 op(_POP_CALL, (callable, null --)) { - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_CALL_ONE, (callable, null, pop --)) { - PyStackRef_CLOSE(pop); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_CALL_TWO, (callable, null, pop1, pop2 --)) { - PyStackRef_CLOSE(pop2); - PyStackRef_CLOSE(pop1); - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(callable); - } - - tier2 op(_POP_TOP_LOAD_CONST_INLINE_BORROW, (ptr/4, pop -- value)) { - PyStackRef_CLOSE(pop); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_POP_TWO_LOAD_CONST_INLINE_BORROW, (ptr/4, pop1, pop2 -- value)) { - PyStackRef_CLOSE(pop2); - PyStackRef_CLOSE(pop1); - value = PyStackRef_FromPyObjectBorrow(ptr); - } - - tier2 op(_INSERT_2_LOAD_CONST_INLINE_BORROW, (ptr/4, left, right -- res, l, r)) { - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - INPUTS_DEAD(); - } - tier2 op(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { res = PyStackRef_FromPyObjectBorrow(ptr); a = arg; @@ -6148,6 +6304,10 @@ dummy_func( RECORD_VALUE(PyStackRef_AsPyObjectBorrow(nos)); } + tier2 op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) { + RECORD_VALUE(Py_TYPE(PyStackRef_AsPyObjectBorrow(nos))); + } + tier2 op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) { PyObject *obj = PyStackRef_AsPyObjectBorrow(nos); if (PyGen_Check(obj)) { @@ -6178,11 +6338,14 @@ dummy_func( RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); } + tier2 op(_RECORD_CALLABLE_KW, (func, self, args[oparg], kwnames -- func, self, args[oparg], kwnames)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } + tier2 op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (Py_TYPE(callable_o) == &PyMethod_Type) { - PyObject *func = ((PyMethodObject *)callable_o)->im_func; - RECORD_VALUE(func); + RECORD_VALUE(callable_o); } } @@ -6365,7 +6528,10 @@ dummy_func( ERROR_IF(err < 0); DISPATCH(); } - Py_CLEAR(tracer->prev_state.recorded_value); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + Py_CLEAR(tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -6375,15 +6541,19 @@ dummy_func( tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; diff --git a/Python/ceval.c b/Python/ceval.c index 3f024ad67f2..506ea591c38 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -832,7 +832,7 @@ _Py_BuiltinCallFast_StackRef( } PyObject * -_Py_BuiltinCallFastWithKeywords_StackRefSteal( +_Py_BuiltinCallFastWithKeywords_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args) @@ -840,8 +840,7 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyCFunctionFastWithKeywords cfunc = @@ -849,20 +848,11 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( res = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_PyCallMethodDescriptorFast_StackRefSteal( +_PyCallMethodDescriptorFast_StackRef( _PyStackRef callable, PyCFunctionFast cfunc, PyObject *self, @@ -872,28 +862,18 @@ _PyCallMethodDescriptorFast_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); res = cfunc(self, (args_o + 1), total_args - 1); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_PyCallMethodDescriptorFastWithKeywords_StackRefSteal( +_PyCallMethodDescriptorFastWithKeywords_StackRef( _PyStackRef callable, PyCFunctionFastWithKeywords cfunc, PyObject *self, @@ -903,28 +883,18 @@ _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); res = cfunc(self, (args_o + 1), total_args-1, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } PyObject * -_Py_CallBuiltinClass_StackRefSteal( +_Py_CallBuiltinClass_StackRef( _PyStackRef callable, _PyStackRef *arguments, int total_args) @@ -932,22 +902,12 @@ _Py_CallBuiltinClass_StackRefSteal( PyObject *res; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - res = NULL; - goto cleanup; + return NULL; } PyTypeObject *tp = (PyTypeObject *)PyStackRef_AsPyObjectBorrow(callable); res = tp->tp_vectorcall((PyObject *)tp, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); -cleanup: - // arguments is a pointer into the GC visible stack, - // so we must NULL out values as we clear them. - for (int i = total_args-1; i >= 0; i--) { - _PyStackRef tmp = arguments[i]; - arguments[i] = PyStackRef_NULL; - PyStackRef_CLOSE(tmp); - } - PyStackRef_CLOSE(callable); return res; } @@ -1155,7 +1115,7 @@ _PyStackRef _PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from) { PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { + if (tp->_tp_iteritem != NULL) { /* Leave iterable on stack and pushed tagged 0 */ *index_or_null = PyStackRef_TagInt(0); return iterable; @@ -1345,7 +1305,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } #ifdef _Py_TIER2 #ifdef _Py_JIT -_PyJitEntryFuncPtr _Py_jit_entry = _Py_LazyJitShim; +_PyJitEntryFuncPtr _Py_jit_entry = _PyJIT; #else _PyJitEntryFuncPtr _Py_jit_entry = _PyTier2Interpreter; #endif @@ -2446,15 +2406,16 @@ void _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RAISE)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_RAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RAISE); } bool -_PyEval_NoToolsForUnwind(PyThreadState *tstate) { - return no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND); +_PyEval_NoToolsForUnwind(PyThreadState *tstate, _PyInterpreterFrame *frame) +{ + return no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND); } @@ -3737,36 +3698,24 @@ _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *na return value; } -static _PyStackRef -foriter_next(PyObject *seq, _PyStackRef index) -{ - assert(PyStackRef_IsTaggedInt(index)); - assert(PyTuple_CheckExact(seq) || PyList_CheckExact(seq)); - intptr_t i = PyStackRef_UntagInt(index); - if (PyTuple_CheckExact(seq)) { - size_t size = PyTuple_GET_SIZE(seq); - if ((size_t)i >= size) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, i)); - } - PyObject *item = _PyList_GetItemRef((PyListObject *)seq, i); - if (item == NULL) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectSteal(item); -} - _PyStackRef _PyForIter_VirtualIteratorNext(PyThreadState* tstate, _PyInterpreterFrame* frame, _PyStackRef iter, _PyStackRef* index_ptr) { PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); _PyStackRef index = *index_ptr; if (PyStackRef_IsTaggedInt(index)) { - *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); - return foriter_next(iter_o, index); + intptr_t i = PyStackRef_UntagInt(index); + assert(i >= 0); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, i); + i = next_index.index; + PyObject *next = next_index.object; + if (next == NULL) { + return i < 0 ? PyStackRef_ERROR : PyStackRef_NULL; + } + *index_ptr = PyStackRef_TagInt(i); + return PyStackRef_FromPyObjectSteal(next); } - PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); - if (next_o == NULL) { + PyObject *next = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); + if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr); @@ -3778,7 +3727,7 @@ _PyStackRef _PyForIter_VirtualIteratorNext(PyThreadState* tstate, _PyInterpreter } return PyStackRef_NULL; } - return PyStackRef_FromPyObjectSteal(next_o); + return PyStackRef_FromPyObjectSteal(next); } /* Check if a 'cls' provides the given special method. */ diff --git a/Python/ceval.h b/Python/ceval.h index bb5f7ddb857..0437ab85c5a 100644 --- a/Python/ceval.h +++ b/Python/ceval.h @@ -367,7 +367,7 @@ no_tools_for_global_event(PyThreadState *tstate, int event) static inline bool no_tools_for_local_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event) { - assert(event < _PY_MONITORING_LOCAL_EVENTS); + assert(event < _PY_MONITORING_UNGROUPED_EVENTS); _PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring; if (data) { return data->active_monitors.tools[event] == 0; @@ -382,7 +382,7 @@ monitor_handled(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *exc) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { return 0; } return _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc); @@ -393,7 +393,7 @@ monitor_throw(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_THROW)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_THROW)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_THROW); @@ -403,7 +403,7 @@ static void monitor_reraise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_RERAISE)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_RERAISE)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RERAISE); @@ -431,7 +431,7 @@ monitor_unwind(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr) { - if (no_tools_for_global_event(tstate, PY_MONITORING_EVENT_PY_UNWIND)) { + if (no_tools_for_local_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND)) { return; } do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_PY_UNWIND); diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index ad790c03865..a7d63fd3b82 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -220,14 +220,14 @@ do { \ DISPATCH_GOTO_NON_TRACING(); \ } -#define DISPATCH_INLINED(NEW_FRAME) \ - do { \ - assert(tstate->interp->eval_frame == NULL); \ - _PyFrame_SetStackPointer(frame, stack_pointer); \ - assert((NEW_FRAME)->previous == frame); \ - frame = tstate->current_frame = (NEW_FRAME); \ - CALL_STAT_INC(inlined_py_calls); \ - JUMP_TO_LABEL(start_frame); \ +#define DISPATCH_INLINED(NEW_FRAME) \ + do { \ + assert(!IS_PEP523_HOOKED(tstate)); \ + _PyFrame_SetStackPointer(frame, stack_pointer); \ + assert((NEW_FRAME)->previous == frame); \ + frame = tstate->current_frame = (NEW_FRAME); \ + CALL_STAT_INC(inlined_py_calls); \ + JUMP_TO_LABEL(start_frame); \ } while (0) /* Tuple access macros */ @@ -563,6 +563,30 @@ gen_try_set_executing(PyGenObject *gen) ->ob_fval = _dres; \ } while (0) +// Inplace float true division. Sets _divop_err to 1 on zero division. +// Caller must check _divop_err and call ERROR_NO_POP() if set. +#define FLOAT_INPLACE_DIVOP(left, right, TARGET) \ + int _divop_err = 0; \ + do { \ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); \ + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); \ + assert(PyFloat_CheckExact(left_o)); \ + assert(PyFloat_CheckExact(right_o)); \ + assert(_PyObject_IsUniquelyReferenced( \ + PyStackRef_AsPyObjectBorrow(TARGET))); \ + STAT_INC(BINARY_OP, hit); \ + double _divisor = ((PyFloatObject *)right_o)->ob_fval; \ + if (_divisor == 0.0) { \ + PyErr_SetString(PyExc_ZeroDivisionError, \ + "float division by zero"); \ + _divop_err = 1; \ + break; \ + } \ + double _dres = ((PyFloatObject *)left_o)->ob_fval / _divisor; \ + ((PyFloatObject *)PyStackRef_AsPyObjectBorrow(TARGET)) \ + ->ob_fval = _dres; \ + } while (0) + // Inplace compact int operation. TARGET is expected to be uniquely // referenced at the optimizer level, but at runtime it may be a // cached small int singleton. We check _Py_IsImmortal on TARGET @@ -604,4 +628,3 @@ gen_try_set_executing(PyGenObject *gen) (PyLongObject *)PyStackRef_AsPyObjectBorrow(left), \ (PyLongObject *)PyStackRef_AsPyObjectBorrow(right)); \ } - diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index c8c141f863d..e6b845cd375 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -826,10 +826,12 @@ PyDoc_STRVAR(builtin_hash__doc__, "hash($module, obj, /)\n" "--\n" "\n" -"Return the hash value for the given object.\n" +"Return the integer hash value for the given object.\n" "\n" -"Two objects that compare equal must also have the same hash value, but the\n" -"reverse is not necessarily true."); +"Two objects that compare equal must also have the same hash value, but\n" +"the reverse is not necessarily true. Hash values may differ between\n" +"Python processes. Not all objects are hashable; calling hash() on an\n" +"unhashable object raises TypeError."); #define BUILTIN_HASH_METHODDEF \ {"hash", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__}, @@ -1380,4 +1382,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=1c3327da8885bb8e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f1fc836a63d89826 input=a9049054013a1b77]*/ diff --git a/Python/codegen.c b/Python/codegen.c index aca590d055f..389e7cf85d3 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -1130,10 +1130,10 @@ codegen_annotations_in_scope(compiler *c, location loc, Py_ssize_t *annotations_len) { RETURN_IF_ERROR( - codegen_argannotations(c, args->args, annotations_len, loc)); + codegen_argannotations(c, args->posonlyargs, annotations_len, loc)); RETURN_IF_ERROR( - codegen_argannotations(c, args->posonlyargs, annotations_len, loc)); + codegen_argannotations(c, args->args, annotations_len, loc)); if (args->vararg && args->vararg->annotation) { RETURN_IF_ERROR( @@ -1224,12 +1224,17 @@ codegen_wrap_in_stopiteration_handler(compiler *c) { NEW_JUMP_TARGET_LABEL(c, handler); - /* Insert SETUP_CLEANUP just before RESUME */ + /* Insert SETUP_CLEANUP just after the initial RETURN_GENERATOR; POP_TOP */ instr_sequence *seq = INSTR_SEQUENCE(c); int resume = 0; - while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RESUME) { + while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RETURN_GENERATOR) { resume++; + assert(resume < seq->s_used); } + resume++; + assert(_PyInstructionSequence_GetInstruction(seq, resume).i_opcode == POP_TOP); + resume++; + assert(resume < seq->s_used); RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( seq, resume, @@ -4977,10 +4982,14 @@ codegen_comprehension(compiler *c, expr_ty e, int type, RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( INSTR_SEQUENCE(c), 0, - LOAD_FAST, 0, LOC(outermost->iter))); + RESUME, RESUME_AT_GEN_EXPR_START, NO_LOCATION)); RETURN_IF_ERROR( _PyInstructionSequence_InsertInstruction( INSTR_SEQUENCE(c), 1, + LOAD_FAST, 0, LOC(outermost->iter))); + RETURN_IF_ERROR( + _PyInstructionSequence_InsertInstruction( + INSTR_SEQUENCE(c), 2, outermost->is_async ? GET_AITER : GET_ITER, 0, LOC(outermost->iter))); iter_state = ITERATOR_ON_STACK; diff --git a/Python/compile.c b/Python/compile.c index 365b118cc71..eb9fc827bea 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -297,6 +297,19 @@ compiler_set_qualname(compiler *c) base = Py_NewRef(parent->u_metadata.u_qualname); } } + if (u->u_ste->ste_function_name != NULL) { + PyObject *tmp = base; + base = PyUnicode_FromFormat("%U.%U", + base, + u->u_ste->ste_function_name); + Py_DECREF(tmp); + if (base == NULL) { + return ERROR; + } + } + } + else if (u->u_ste->ste_function_name != NULL) { + base = Py_NewRef(u->u_ste->ste_function_name); } if (base != NULL) { @@ -1645,6 +1658,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, { PyObject *res = NULL; PyObject *metadata = NULL; + PyObject *consts_list = NULL; if (!PyAST_Check(ast)) { PyErr_SetString(PyExc_TypeError, "expected an AST"); @@ -1699,12 +1713,23 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, } if (_PyInstructionSequence_ApplyLabelMap(_PyCompile_InstrSequence(c)) < 0) { - return NULL; + goto finally; } + + /* After AddReturnAtEnd: co_consts indices match the final instruction stream. */ + consts_list = consts_dict_keys_inorder(umd->u_consts); + if (consts_list == NULL) { + goto finally; + } + if (PyDict_SetItemString(metadata, "consts", consts_list) < 0) { + goto finally; + } + /* Allocate a copy of the instruction sequence on the heap */ res = _PyTuple_FromPair((PyObject *)_PyCompile_InstrSequence(c), metadata); finally: + Py_XDECREF(consts_list); Py_XDECREF(metadata); _PyCompile_ExitScope(c); compiler_free(c); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ed050570909..93d39bee1b9 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -93,7 +93,7 @@ break; } - /* _LOAD_BYTECODE is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ + /* _LOAD_BYTECODE is not a viable micro-op for tier 2 because it is replaced */ case _RESUME_CHECK_r00: { CHECK_CURRENT_CACHED_VALUES(0); @@ -2497,34 +2497,6 @@ break; } - case _POP_TWO_r20: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef tos; - _PyStackRef nos; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - tos = _stack_item_1; - nos = _stack_item_0; - stack_pointer[0] = nos; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(tos); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(nos); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _POP_TOP_OPARG_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6029,6 +6001,241 @@ break; } + case _BINARY_OP_TRUEDIV_FLOAT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyFloat_CheckExact(left_o)); + assert(PyFloat_CheckExact(right_o)); + STAT_INC(BINARY_OP, hit); + double divisor = ((PyFloatObject *)right_o)->ob_fval; + if (divisor == 0.0) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyErr_SetString(PyExc_ZeroDivisionError, + "float division by zero"); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + double dres = ((PyFloatObject *)left_o)->ob_fval / divisor; + PyObject *d = PyFloat_FromDouble(dres); + if (d == NULL) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(d); + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + stack_pointer[0] = right; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_DIVOP(left, right, left); + if (_divop_err) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = left; + l = PyStackRef_NULL; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + stack_pointer[0] = right; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + FLOAT_INPLACE_DIVOP(left, right, right); + if (_divop_err) { + stack_pointer[0] = left; + stack_pointer[1] = right; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = right; + l = left; + r = PyStackRef_NULL; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_ADD_UNICODE_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6188,6 +6395,216 @@ break; } + case _GUARD_BINARY_OP_EXTEND_LHS_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + left = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + left = _stack_item_0; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_LHS_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef left; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + left = _stack_item_1; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->lhs_type != NULL); + if (Py_TYPE(left_o) != d->lhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = left; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = left; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + right = stack_pointer[-1]; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = stack_pointer[-2]; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = stack_pointer[-1]; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = right; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + right = _stack_item_2; + PyObject *descr = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; + assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); + assert(d && d->guard == NULL && d->rhs_type != NULL); + if (Py_TYPE(right_o) != d->rhs_type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = right; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = right; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_BINARY_OP_EXTEND_r22: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6202,15 +6619,17 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); stack_pointer[0] = left; stack_pointer[1] = right; stack_pointer += 2; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UOP_STAT_INC(uopcode, miss); _tos_cache1 = right; _tos_cache0 = left; @@ -6258,6 +6677,9 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -10849,6 +11271,95 @@ break; } + case _GUARD_TYPE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + owner = stack_pointer[-1]; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + owner = _stack_item_0; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + owner = _stack_item_1; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TYPE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + owner = _stack_item_2; + PyObject *type = (PyObject *)CURRENT_OPERAND0_64(); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + if (tp != (PyTypeObject *)type) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CHECK_MANAGED_OBJECT_HAS_VALUES_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -11478,6 +11989,41 @@ break; } + case _LOAD_ATTR_PROPERTY_FRAME_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _LOAD_ATTR_PROPERTY_FRAME_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -11486,29 +12032,18 @@ _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); owner = _stack_item_0; - PyObject *fget = (PyObject *)CURRENT_OPERAND0_64(); + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } - if (code->co_kwonlyargcount) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } - if (code->co_argcount != 1) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = owner; @@ -11520,6 +12055,131 @@ pushed_frame->localsplus[0] = owner; new_frame = PyStackRef_Wrap(pushed_frame); _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + oparg = CURRENT_OPARG(); + owner = _stack_item_1; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache1 = new_frame; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + oparg = CURRENT_OPARG(); + owner = _stack_item_2; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache2 = new_frame; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + oparg = CURRENT_OPARG(); + owner = _stack_item_0; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *getattribute = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = owner; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(1); @@ -11527,8 +12187,6 @@ break; } - /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 because it has too many cache entries */ - case _GUARD_DORV_NO_DICT_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -13051,9 +13709,6 @@ _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); iterable = _stack_item_0; - #ifdef Py_STATS - _Py_GatherStats_GetIter(iterable); - #endif stack_pointer[0] = iterable; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -13077,6 +13732,256 @@ break; } + case _GUARD_ITERATOR_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + iterable = _stack_item_0; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iterable = _stack_item_1; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITERATOR_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iterable = _stack_item_2; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + iterable = _stack_item_0; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache0 = iterable; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iterable = _stack_item_1; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache1 = iterable; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_ITER_VIRTUAL_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iterable = _stack_item_2; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(GET_ITER, hit); + _tos_cache2 = iterable; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + zero = PyStackRef_TagInt(0); + _tos_cache0 = zero; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + _PyStackRef _stack_item_0 = _tos_cache0; + zero = PyStackRef_TagInt(0); + _tos_cache1 = zero; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _PUSH_TAGGED_ZERO_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef zero; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + zero = PyStackRef_TagInt(0); + _tos_cache2 = zero; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GET_ITER_TRAD_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iterable; + _PyStackRef iter; + _PyStackRef index_or_null; + _PyStackRef _stack_item_0 = _tos_cache0; + iterable = _stack_item_0; + stack_pointer[0] = iterable; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; + _tos_cache1 = index_or_null; + _tos_cache0 = iter; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + /* _FOR_ITER is not a viable micro-op for tier 2 because it is replaced */ case _FOR_ITER_TIER_TWO_r23: { @@ -13123,6 +14028,145 @@ break; } + case _GUARD_NOS_ITER_VIRTUAL_r02: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = stack_pointer[-1]; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r12: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + iter = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_0; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + iter = _stack_item_0; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_NOS_ITER_VIRTUAL_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef iter; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + iter = _stack_item_1; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = iter; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = iter; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + /* _FOR_ITER_VIRTUAL is not a viable micro-op for tier 2 because it is replaced */ + + case _FOR_ITER_VIRTUAL_TIER_TWO_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef null_or_index; + _PyStackRef iter; + _PyStackRef next; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + null_or_index = _stack_item_1; + iter = _stack_item_0; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + stack_pointer[0] = iter; + stack_pointer[1] = null_or_index; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + if (true) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = null_or_index; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JUMP_TO_JUMP_TARGET(); + } + } + next = PyStackRef_FromPyObjectSteal(next_o); + null_or_index = PyStackRef_TagInt(index); + _tos_cache2 = next; + _tos_cache1 = null_or_index; + _tos_cache0 = iter; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 because it is instrumented */ case _ITER_CHECK_LIST_r02: { @@ -16326,7 +17370,7 @@ break; } - case _CHECK_AND_ALLOCATE_OBJECT_r00: { + case _CHECK_OBJECT_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef self_or_null; @@ -16352,6 +17396,23 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _ALLOCATE_OBJECT_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -16455,16 +17516,11 @@ break; } - case _CALL_BUILTIN_CLASS_r01: { + case _GUARD_CALLABLE_BUILTIN_CLASS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef *args; - _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -16473,37 +17529,53 @@ JUMP_TO_JUMP_TARGET(); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CALL_BUILTIN_CLASS_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef self_or_null; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -16558,11 +17630,6 @@ if (!PyStackRef_IsNull(self_or_null)) { args--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -16674,13 +17741,12 @@ break; } - case _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01: { + case _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; @@ -16693,21 +17759,22 @@ } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -17534,13 +18601,12 @@ break; } - case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01: { + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; @@ -17558,7 +18624,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc, self, @@ -17567,58 +18633,60 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01: { + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; + _PyStackRef self_st; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; - callable = stack_pointer[-1 - oparg]; + self_st = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); - PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); - assert(self != NULL); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc_v, self, - args, - oparg + args - 1, + oparg + 1 ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -17793,13 +18861,12 @@ break; } - case _CALL_METHOD_DESCRIPTOR_FAST_r01: { + case _CALL_METHOD_DESCRIPTOR_FAST_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; _PyStackRef self_or_null; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; @@ -17817,7 +18884,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc, self, @@ -17826,58 +18893,61 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } - case _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01: { + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef *args; + _PyStackRef self_st; _PyStackRef callable; - _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; - callable = stack_pointer[-1 - oparg]; + self_st = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); - PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc_v, self, - args, - oparg + args - 1, + oparg + 1 ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - res = PyStackRef_FromPyObjectSteal(res_o); - _tos_cache0 = res; + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + _tos_cache0 = PyStackRef_ZERO_BITS; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } @@ -21225,26 +22295,6 @@ break; } - case _POP_TOP_LOAD_CONST_INLINE_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - pop = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectNew(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _LOAD_CONST_INLINE_BORROW_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -21287,224 +22337,6 @@ break; } - case _POP_CALL_r20: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - null = _stack_item_1; - callable = _stack_item_0; - (void)null; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_ONE_r30: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop = _stack_item_2; - null = _stack_item_1; - callable = _stack_item_0; - stack_pointer[0] = callable; - stack_pointer[1] = null; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_CALL_TWO_r30: { - CHECK_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop2; - _PyStackRef pop1; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - pop2 = _stack_item_2; - pop1 = _stack_item_1; - null = _stack_item_0; - callable = stack_pointer[-1]; - stack_pointer[0] = null; - stack_pointer[1] = pop1; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop2); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop1); - stack_pointer = _PyFrame_GetStackPointer(frame); - (void)null; - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - _tos_cache0 = PyStackRef_ZERO_BITS; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_TOP_LOAD_CONST_INLINE_BORROW_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - pop = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _POP_TWO_LOAD_CONST_INLINE_BORROW_r21: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef pop2; - _PyStackRef pop1; - _PyStackRef value; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - pop2 = _stack_item_1; - pop1 = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - stack_pointer[0] = pop1; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop2); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(pop1); - stack_pointer = _PyFrame_GetStackPointer(frame); - value = PyStackRef_FromPyObjectBorrow(ptr); - _tos_cache0 = value; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r03: { - CHECK_CURRENT_CACHED_VALUES(0); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r13: { - CHECK_CURRENT_CACHED_VALUES(1); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - _PyStackRef _stack_item_0 = _tos_cache0; - right = _stack_item_0; - left = stack_pointer[-1]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW_r23: { - CHECK_CURRENT_CACHED_VALUES(2); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - _PyStackRef right; - _PyStackRef left; - _PyStackRef res; - _PyStackRef l; - _PyStackRef r; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - right = _stack_item_1; - left = _stack_item_0; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0_64(); - res = PyStackRef_FromPyObjectBorrow(ptr); - l = left; - r = right; - _tos_cache2 = r; - _tos_cache1 = l; - _tos_cache0 = res; - SET_CURRENT_CACHED_VALUES(3); - assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); - break; - } - case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/flowgraph.c b/Python/flowgraph.c index e988f445100..2cb2d32a410 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -6,6 +6,7 @@ #include "pycore_intrinsics.h" #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_long.h" // _PY_IS_SMALL_INT() +#include "pycore_hashtable.h" // _Py_hashtable_t #include "pycore_opcode_utils.h" #include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc @@ -963,7 +964,7 @@ label_exception_targets(basicblock *entryblock) { } else if (instr->i_opcode == RESUME) { instr->i_except = handler; - if (instr->i_oparg != RESUME_AT_FUNC_START) { + if (instr->i_oparg != RESUME_AT_FUNC_START && instr->i_oparg != RESUME_AT_GEN_EXPR_START) { assert(last_yield_except_depth >= 0); if (last_yield_except_depth == 1) { instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK; @@ -1309,6 +1310,14 @@ get_const_value(int opcode, int oparg, PyObject *co_consts) PyObject *constant = NULL; assert(loads_const(opcode)); if (opcode == LOAD_CONST) { + assert(PyList_Check(co_consts)); + Py_ssize_t n = PyList_GET_SIZE(co_consts); + if (oparg < 0 || oparg >= n) { + PyErr_Format(PyExc_ValueError, + "LOAD_CONST index %d is out of range for consts (len=%zd)", + oparg, n); + return NULL; + } constant = PyList_GET_ITEM(co_consts, oparg); } if (opcode == LOAD_SMALL_INT) { @@ -1325,30 +1334,38 @@ get_const_value(int opcode, int oparg, PyObject *co_consts) // Steals a reference to newconst. static int -add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache) +add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) { Py_DECREF(newconst); return -1; } - Py_ssize_t index; - for (index = 0; index < PyList_GET_SIZE(consts); index++) { - if (PyList_GET_ITEM(consts, index) == newconst) { - break; - } + _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(consts_index, (void *)newconst); + if (entry != NULL) { + Py_DECREF(newconst); + return (int)(uintptr_t)entry->value; } - if (index == PyList_GET_SIZE(consts)) { - if ((size_t)index >= (size_t)INT_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, "too many constants"); - Py_DECREF(newconst); - return -1; - } - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return -1; - } + + Py_ssize_t index = PyList_GET_SIZE(consts); + if ((size_t)index >= (size_t)INT_MAX - 1) { + PyErr_SetString(PyExc_OverflowError, "too many constants"); + Py_DECREF(newconst); + return -1; } + if (PyList_Append(consts, newconst)) { + Py_DECREF(newconst); + return -1; + } + + if (_Py_hashtable_set(consts_index, (void *)newconst, (void *)(uintptr_t)index) < 0) { + PyList_SetSlice(consts, index, index + 1, NULL); + Py_DECREF(newconst); + PyErr_NoMemory(); + return -1; + } + Py_DECREF(newconst); return (int)index; } @@ -1424,7 +1441,8 @@ maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst, /* Steals reference to "newconst" */ static int instr_make_load_const(cfg_instr *instr, PyObject *newconst, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { int res = maybe_instr_make_load_smallint(instr, newconst, consts, const_cache); if (res < 0) { @@ -1434,7 +1452,7 @@ instr_make_load_const(cfg_instr *instr, PyObject *newconst, if (res > 0) { return SUCCESS; } - int oparg = add_const(newconst, consts, const_cache); + int oparg = add_const(newconst, consts, const_cache, consts_index); RETURN_IF_ERROR(oparg); INSTR_SET_OP1(instr, LOAD_CONST, oparg); return SUCCESS; @@ -1447,7 +1465,8 @@ instr_make_load_const(cfg_instr *instr, PyObject *newconst, Called with codestr pointing to the first LOAD_CONST. */ static int -fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { /* Pre-conditions */ assert(PyDict_CheckExact(const_cache)); @@ -1484,7 +1503,7 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const } nop_out(const_instrs, seq_size); - return instr_make_load_const(instr, const_tuple, consts, const_cache); + return instr_make_load_const(instr, const_tuple, consts, const_cache, consts_index); } /* Replace: @@ -1502,7 +1521,8 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const */ static int fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -1554,7 +1574,7 @@ fold_constant_intrinsic_list_to_tuple(basicblock *bb, int i, nop_out(&instr, 1); } assert(consts_found == 0); - return instr_make_load_const(intrinsic, newconst, consts, const_cache); + return instr_make_load_const(intrinsic, newconst, consts, const_cache, consts_index); } if (expect_append) { @@ -1590,7 +1610,8 @@ Optimize lists and sets for: */ static int optimize_lists_and_sets(basicblock *bb, int i, int nextop, - PyObject *consts, PyObject *const_cache) + PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -1640,7 +1661,7 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop, Py_SETREF(const_result, frozenset); } - int index = add_const(const_result, consts, const_cache); + int index = add_const(const_result, consts, const_cache, consts_index); RETURN_IF_ERROR(index); nop_out(const_instrs, seq_size); @@ -1837,7 +1858,8 @@ eval_const_binop(PyObject *left, int op, PyObject *right) } static int -fold_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_const_binop(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { #define BINOP_OPERAND_COUNT 2 assert(PyDict_CheckExact(const_cache)); @@ -1879,7 +1901,7 @@ fold_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) } nop_out(operands_instrs, BINOP_OPERAND_COUNT); - return instr_make_load_const(binop, newconst, consts, const_cache); + return instr_make_load_const(binop, newconst, consts, const_cache, consts_index); } static PyObject * @@ -1925,7 +1947,8 @@ eval_const_unaryop(PyObject *operand, int opcode, int oparg) } static int -fold_const_unaryop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) +fold_const_unaryop(basicblock *bb, int i, PyObject *consts, + PyObject *const_cache, _Py_hashtable_t *consts_index) { #define UNARYOP_OPERAND_COUNT 1 assert(PyDict_CheckExact(const_cache)); @@ -1962,7 +1985,7 @@ fold_const_unaryop(basicblock *bb, int i, PyObject *consts, PyObject *const_cach assert(PyBool_Check(newconst)); } nop_out(&operand_instr, UNARYOP_OPERAND_COUNT); - return instr_make_load_const(unaryop, newconst, consts, const_cache); + return instr_make_load_const(unaryop, newconst, consts, const_cache, consts_index); } #define VISITED (-1) @@ -2157,7 +2180,8 @@ apply_static_swaps(basicblock *block, int i) } static int -basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *consts) +basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, + PyObject *consts, _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -2167,6 +2191,9 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * cfg_instr *inst = &bb->b_instr[i]; if (inst->i_opcode == LOAD_CONST) { PyObject *constant = get_const_value(inst->i_opcode, inst->i_oparg, consts); + if (constant == NULL) { + return ERROR; + } int res = maybe_instr_make_load_smallint(inst, constant, consts, const_cache); Py_DECREF(constant); if (res < 0) { @@ -2272,7 +2299,7 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * return ERROR; } cnt = PyBool_FromLong(is_true); - int index = add_const(cnt, consts, const_cache); + int index = add_const(cnt, consts, const_cache, consts_index); if (index < 0) { return ERROR; } @@ -2286,15 +2313,17 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject * } static int -optimize_load_const(PyObject *const_cache, cfg_builder *g, PyObject *consts) { +optimize_load_const(PyObject *const_cache, cfg_builder *g, PyObject *consts, + _Py_hashtable_t *consts_index) { for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - RETURN_IF_ERROR(basicblock_optimize_load_const(const_cache, b, consts)); + RETURN_IF_ERROR(basicblock_optimize_load_const(const_cache, b, consts, consts_index)); } return SUCCESS; } static int -optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) +optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts, + _Py_hashtable_t *consts_index) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); @@ -2334,11 +2363,11 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) continue; } } - RETURN_IF_ERROR(fold_tuple_of_constants(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_tuple_of_constants(bb, i, consts, const_cache, consts_index)); break; case BUILD_LIST: case BUILD_SET: - RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache)); + RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache, consts_index)); break; case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NONE: @@ -2473,7 +2502,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) _Py_FALLTHROUGH; case UNARY_INVERT: case UNARY_NEGATIVE: - RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index)); break; case CALL_INTRINSIC_1: if (oparg == INTRINSIC_LIST_TO_TUPLE) { @@ -2481,15 +2510,15 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) INSTR_SET_OP0(inst, NOP); } else { - RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_constant_intrinsic_list_to_tuple(bb, i, consts, const_cache, consts_index)); } } else if (oparg == INTRINSIC_UNARY_POSITIVE) { - RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index)); } break; case BINARY_OP: - RETURN_IF_ERROR(fold_const_binop(bb, i, consts, const_cache)); + RETURN_IF_ERROR(fold_const_binop(bb, i, consts, const_cache, consts_index)); break; } } @@ -2534,16 +2563,17 @@ remove_redundant_nops_and_jumps(cfg_builder *g) NOPs. Later those NOPs are removed. */ static int -optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstlineno) +optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, + _Py_hashtable_t *consts_index, int firstlineno) { assert(PyDict_CheckExact(const_cache)); RETURN_IF_ERROR(check_cfg(g)); RETURN_IF_ERROR(inline_small_or_no_lineno_blocks(g->g_entryblock)); RETURN_IF_ERROR(remove_unreachable(g->g_entryblock)); RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno)); - RETURN_IF_ERROR(optimize_load_const(const_cache, g, consts)); + RETURN_IF_ERROR(optimize_load_const(const_cache, g, consts, consts_index)); for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { - RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts)); + RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts, consts_index)); } RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock)); RETURN_IF_ERROR(remove_unreachable(g->g_entryblock)); @@ -3663,7 +3693,33 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache, RETURN_IF_ERROR(label_exception_targets(g->g_entryblock)); /** Optimization **/ - RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache, firstlineno)); + + _Py_hashtable_t *consts_index = _Py_hashtable_new( + _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct); + if (consts_index == NULL) { + PyErr_NoMemory(); + return ERROR; + } + + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(consts); i++) { + PyObject *item = PyList_GET_ITEM(consts, i); + if (_Py_hashtable_get_entry(consts_index, (void *)item) != NULL) { + continue; + } + if (_Py_hashtable_set(consts_index, (void *)item, + (void *)(uintptr_t)i) < 0) { + _Py_hashtable_destroy(consts_index); + PyErr_NoMemory(); + return ERROR; + } + } + + int ret = optimize_cfg(g, consts, const_cache, consts_index, firstlineno); + + _Py_hashtable_destroy(consts_index); + + RETURN_IF_ERROR(ret); + RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts)); RETURN_IF_ERROR( add_checks_for_loads_of_uninitialized_variables( @@ -4064,6 +4120,10 @@ _PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals) PyErr_SetString(PyExc_ValueError, "expected an instruction sequence"); return NULL; } + if (!PyList_Check(consts)) { + PyErr_SetString(PyExc_TypeError, "consts must be a list"); + return NULL; + } PyObject *const_cache = PyDict_New(); if (const_cache == NULL) { return NULL; diff --git a/Python/frozen.c b/Python/frozen.c index 15d256b6743..1fae26f8dbc 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -46,6 +46,10 @@ #include "frozen_modules/zipimport.h" #include "frozen_modules/abc.h" #include "frozen_modules/codecs.h" +#include "frozen_modules/encodings.h" +#include "frozen_modules/encodings.aliases.h" +#include "frozen_modules/encodings.utf_8.h" +#include "frozen_modules/encodings._win_cp_codecs.h" #include "frozen_modules/io.h" #include "frozen_modules/_collections_abc.h" #include "frozen_modules/_sitebuiltins.h" @@ -55,6 +59,7 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" +#include "frozen_modules/linecache.h" #include "frozen_modules/importlib.util.h" #include "frozen_modules/importlib.machinery.h" #include "frozen_modules/runpy.h" @@ -76,6 +81,10 @@ static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false}, {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false}, + {"encodings", _Py_M__encodings, (int)sizeof(_Py_M__encodings), true}, + {"encodings.aliases", _Py_M__encodings_aliases, (int)sizeof(_Py_M__encodings_aliases), false}, + {"encodings.utf_8", _Py_M__encodings_utf_8, (int)sizeof(_Py_M__encodings_utf_8), false}, + {"encodings._win_cp_codecs", _Py_M__encodings__win_cp_codecs, (int)sizeof(_Py_M__encodings__win_cp_codecs), false}, {"io", _Py_M__io, (int)sizeof(_Py_M__io), false}, /* stdlib - startup, with site */ @@ -88,6 +97,9 @@ static const struct _frozen stdlib_modules[] = { {"site", _Py_M__site, (int)sizeof(_Py_M__site), false}, {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false}, + /* pythonrun - interactive */ + {"linecache", _Py_M__linecache, (int)sizeof(_Py_M__linecache), false}, + /* runpy - run module with -m */ {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false}, {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false}, diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 2a2751e8a84..dccee0e4a3b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -342,11 +342,13 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr; assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); - assert(d && d->guard); + assert(d != NULL); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = d->guard(left_o, right_o); + int match = (d->guard != NULL) + ? d->guard(left_o, right_o) + : (Py_TYPE(left_o) == d->lhs_type && Py_TYPE(right_o) == d->rhs_type); stack_pointer = _PyFrame_GetStackPointer(frame); - if (!res) { + if (!match) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); @@ -367,6 +369,9 @@ if (res_o == NULL) { JUMP_TO_LABEL(error); } + assert(d->result_type == NULL || Py_TYPE(res_o) == d->result_type); + assert(!d->result_unique || Py_REFCNT(res_o) == 1 || _Py_IsImmortal(res_o)); + assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1); res = PyStackRef_FromPyObjectSteal(res_o); l = left; r = right; @@ -1897,7 +1902,7 @@ JUMP_TO_PREDICTED(CALL); } } - // _CHECK_AND_ALLOCATE_OBJECT + // _CHECK_OBJECT { self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; @@ -1919,6 +1924,13 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _ALLOCATE_OBJECT + { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + assert(PyStackRef_IsNull(self_or_null)); + assert(PyType_Check(callable_o)); + PyTypeObject *tp = (PyTypeObject *)callable_o; assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); @@ -2276,13 +2288,11 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - // _CALL_BUILTIN_CLASS + // _GUARD_CALLABLE_BUILTIN_CLASS { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (!PyType_Check(callable_o)) { @@ -2291,36 +2301,57 @@ JUMP_TO_PREDICTED(CALL); } PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall == NULL) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } + // _CALL_BUILTIN_CLASS + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null)) { arguments--; total_args++; } - if (tp->tp_vectorcall == NULL) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( + PyObject *res_o = _Py_CallBuiltinClass_StackRef( callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2433,7 +2464,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS @@ -2463,20 +2494,36 @@ } STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); + PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + args = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2532,6 +2579,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_BUILTIN_O { args = &stack_pointer[-oparg]; @@ -2539,11 +2594,6 @@ if (!PyStackRef_IsNull(self_or_null)) { args--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; @@ -3792,7 +3842,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST @@ -3844,7 +3894,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFast_StackRef( callable, cfunc, self, @@ -3853,17 +3903,32 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3888,7 +3953,7 @@ _PyStackRef callable; _PyStackRef self_or_null; _PyStackRef *args; - _PyStackRef res; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS @@ -3941,7 +4006,7 @@ STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); - PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRef( callable, cfunc, self, @@ -3950,17 +4015,32 @@ ); stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -2 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_LABEL(error); } - res = PyStackRef_FromPyObjectSteal(res_o); + _PyStackRef temp = callable; + callable = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2 - oparg] = callable; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(temp); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP_OPARG + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef_CloseStack(args, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = self_or_null; + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_AT_END { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); int err = check_periodics(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -5833,7 +5913,7 @@ int og_oparg = (oparg & ~255) | executor->vm_data.oparg; next_instr = this_instr; if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[og_opcode]]) { PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); } opcode = og_opcode; @@ -6299,6 +6379,58 @@ DISPATCH(); } + TARGET(FOR_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = FOR_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef null_or_index; + _PyStackRef next; + /* Skip 1 cache entry */ + // _GUARD_NOS_ITER_VIRTUAL + { + iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (Py_TYPE(iter_o)->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + } + // _FOR_ITER_VIRTUAL + { + null_or_index = stack_pointer[-1]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + Py_ssize_t index = PyStackRef_UntagInt(null_or_index); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyObjectIndexPair next_index = Py_TYPE(iter_o)->_tp_iteritem(iter_o, index); + stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *next_o = next_index.object; + index = next_index.index; + if (next_o == NULL) { + if (index < 0) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg + 1); + DISPATCH(); + } + null_or_index = PyStackRef_TagInt(index); + next = PyStackRef_FromPyObjectSteal(next_o); + } + stack_pointer[-1] = null_or_index; + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_AITER) { #if _Py_TAIL_CALL_INTERP int opcode = GET_AITER; @@ -6419,22 +6551,41 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(GET_ITER); + PREDICTED_GET_ITER:; + _Py_CODEUNIT* const this_instr = next_instr - 2; + (void)this_instr; _PyStackRef iterable; _PyStackRef iter; _PyStackRef index_or_null; - iterable = stack_pointer[-1]; - #ifdef Py_STATS - _Py_GatherStats_GetIter(iterable); - #endif - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (PyStackRef_IsError(result)) { - JUMP_TO_LABEL(pop_1_error); + // _SPECIALIZE_GET_ITER + { + iterable = stack_pointer[-1]; + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + #if ENABLE_SPECIALIZATION + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_GetIter(iterable, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH_SAME_OPARG(); + } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION */ + } + // _GET_ITER + { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsError(result)) { + JUMP_TO_LABEL(pop_1_error); + } + iter = result; } - iter = result; stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; stack_pointer += 1; @@ -6442,6 +6593,76 @@ DISPATCH(); } + TARGET(GET_ITER_SELF) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_SELF; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_SELF); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef res; + /* Skip 1 cache entry */ + // _GUARD_ITERATOR + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->tp_iter != PyObject_SelfIter) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_NULL + { + res = PyStackRef_NULL; + } + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + + TARGET(GET_ITER_VIRTUAL) { + #if _Py_TAIL_CALL_INTERP + int opcode = GET_ITER_VIRTUAL; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_VIRTUAL); + static_assert(INLINE_CACHE_ENTRIES_GET_ITER == 1, "incorrect cache size"); + _PyStackRef iterable; + _PyStackRef zero; + /* Skip 1 cache entry */ + // _GUARD_ITER_VIRTUAL + { + iterable = stack_pointer[-1]; + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)); + if (tp->_tp_iteritem == NULL) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + STAT_INC(GET_ITER, hit); + } + // _PUSH_TAGGED_ZERO + { + zero = PyStackRef_TagInt(0); + } + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(GET_LEN) { #if _Py_TAIL_CALL_INTERP int opcode = GET_LEN; @@ -8232,50 +8453,81 @@ INSTRUCTION_STATS(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); _PyStackRef owner; + _PyStackRef new_frame; /* Skip 1 cache entry */ - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - uint32_t func_version = read_u32(&this_instr[4].cache); - PyObject *getattribute = read_obj(&this_instr[6].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert((oparg & 1) == 0); - if (IS_PEP523_HOOKED(tstate)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _GUARD_TYPE_VERSION + { + owner = stack_pointer[-1]; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); + assert(type_version != 0); + if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - PyTypeObject *cls = Py_TYPE(owner_o); - assert(type_version != 0); - if (FT_ATOMIC_LOAD_UINT_RELAXED(cls->tp_version_tag) != type_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _CHECK_PEP_523 + { + if (IS_PEP523_HOOKED(tstate)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } } - assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); - PyFunctionObject *f = (PyFunctionObject *)getattribute; - assert(func_version != 0); - if (f->func_version != func_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME + { + uint32_t func_version = read_u32(&this_instr[4].cache); + PyObject *getattribute = read_obj(&this_instr[6].cache); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + assert(func_version != 0); + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + assert(code->co_argcount == 2); + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } + STAT_INC(LOAD_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked( + tstate, PyStackRef_FromPyObjectNew(f), 2, frame); + pushed_frame->localsplus[0] = owner; + pushed_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); + new_frame = PyStackRef_Wrap(pushed_frame); } - PyCodeObject *code = (PyCodeObject *)f->func_code; - assert(code->co_argcount == 2); - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); + // _SAVE_RETURN_OFFSET + { + #if TIER_ONE + frame->return_offset = (uint16_t)(next_instr - this_instr); + #endif + #if TIER_TWO + frame->return_offset = oparg; + #endif } - STAT_INC(LOAD_ATTR, hit); - PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); - _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( - tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - new_frame->localsplus[0] = owner; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); - frame->return_offset = 10u ; - DISPATCH_INLINED(new_frame); + // _PUSH_FRAME + { + assert(!IS_PEP523_HOOKED(tstate)); + _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(temp->previous == frame || temp->previous->previous == frame); + CALL_STAT_INC(inlined_py_calls); + frame = tstate->current_frame = temp; + tstate->py_recursion_remaining--; + LOAD_SP(); + LOAD_IP(0); + LLTRACE_RESUME_FRAME(); + } + DISPATCH(); } TARGET(LOAD_ATTR_INSTANCE_VALUE) { @@ -8764,29 +9016,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UPDATE_MISS_STATS(LOAD_ATTR); + assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); + JUMP_TO_PREDICTED(LOAD_ATTR); + } PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -12239,9 +12481,12 @@ } DISPATCH(); } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_CLEAR(tracer->prev_state.recorded_value); - stack_pointer = _PyFrame_GetStackPointer(frame); + for (int i = 0; i < tracer->prev_state.recorded_count; i++) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_CLEAR(tracer->prev_state.recorded_values[i]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + tracer->prev_state.recorded_count = 0; tracer->prev_state.instr = next_instr; PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable); if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) { @@ -12252,14 +12497,18 @@ tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + // Branch opcodes use the cache for branch history, not + // specialization counters. Don't reset it. + && !IS_CONDITIONAL_JUMP_OPCODE(opcode)) { (&next_instr[1])->counter = trigger_backoff_counter(); } - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[opcode]; - if (record_func_index) { - _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_func_index]; - doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[opcode]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr doesnt_escape = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + doesnt_escape(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); } + tracer->prev_state.recorded_count = record_entry->count; DISPATCH_GOTO_NON_TRACING(); #else (void)prev_instr; @@ -12865,6 +13114,9 @@ JUMP_TO_LABEL(error); DISPATCH(); } + #if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2) + Py_GCC_ATTRIBUTE((unused)) + #endif LABEL(stop_tracing) { #if _Py_TIER2 diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 256e2a3d3a2..51bcbfdb3b6 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -185,6 +185,12 @@ opcode_has_event(int opcode) ); } +uint8_t +_PyCode_Deinstrument(uint8_t opcode) +{ + return DE_INSTRUMENT[opcode]; +} + static inline bool is_instrumented(int opcode) { @@ -197,7 +203,7 @@ is_instrumented(int opcode) static inline bool monitors_equals(_Py_LocalMonitors a, _Py_LocalMonitors b) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (a.tools[i] != b.tools[i]) { return false; } @@ -210,7 +216,7 @@ static inline _Py_LocalMonitors monitors_sub(_Py_LocalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] & ~b.tools[i]; } return res; @@ -221,7 +227,7 @@ static inline _Py_LocalMonitors monitors_and(_Py_LocalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] & b.tools[i]; } return res; @@ -237,7 +243,7 @@ static inline _Py_LocalMonitors local_union(_Py_GlobalMonitors a, _Py_LocalMonitors b) { _Py_LocalMonitors res; - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { res.tools[i] = a.tools[i] | b.tools[i]; } return res; @@ -246,7 +252,7 @@ local_union(_Py_GlobalMonitors a, _Py_LocalMonitors b) static inline bool monitors_are_empty(_Py_LocalMonitors m) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (m.tools[i]) { return false; } @@ -257,7 +263,7 @@ monitors_are_empty(_Py_LocalMonitors m) static inline bool multiple_tools(_Py_LocalMonitors *m) { - for (int i = 0; i < _PY_MONITORING_LOCAL_EVENTS; i++) { + for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { if (_Py_popcount32(m->tools[i]) > 1) { return true; } @@ -269,7 +275,7 @@ static inline _PyMonitoringEventSet get_local_events(_Py_LocalMonitors *m, int tool_id) { _PyMonitoringEventSet result = 0; - for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { if ((m->tools[e] >> tool_id) & 1) { result |= (1 << e); } @@ -330,12 +336,6 @@ _PyInstruction_GetLength(PyCodeObject *code, int offset) return 1 + _PyOpcode_Caches[inst.op.code]; } -static inline uint8_t -get_original_opcode(_PyCoLineInstrumentationData *line_data, int index) -{ - return line_data->data[index*line_data->bytes_per_entry]; -} - static inline uint8_t * get_original_opcode_ptr(_PyCoLineInstrumentationData *line_data, int index) { @@ -401,7 +401,7 @@ dump_instrumentation_data_lines(PyCodeObject *code, _PyCoLineInstrumentationData fprintf(out, ", lines = NULL"); } else { - int opcode = get_original_opcode(lines, i); + int opcode = _PyCode_GetOriginalOpcode(lines, i); int line_delta = get_line_delta(lines, i); if (opcode == 0) { fprintf(out, ", lines = {original_opcode = No LINE (0), line_delta = %d)", line_delta); @@ -453,7 +453,7 @@ static void dump_local_monitors(const char *prefix, _Py_LocalMonitors monitors, FILE*out) { fprintf(out, "%s monitors:\n", prefix); - for (int event = 0; event < _PY_MONITORING_LOCAL_EVENTS; event++) { + for (int event = 0; event < _PY_MONITORING_UNGROUPED_EVENTS; event++) { fprintf(out, " Event %d: Tools %x\n", event, monitors.tools[event]); } } @@ -571,7 +571,7 @@ sanity_check_instrumentation(PyCodeObject *code) } if (opcode == INSTRUMENTED_LINE) { CHECK(data->lines); - opcode = get_original_opcode(data->lines, i); + opcode = _PyCode_GetOriginalOpcode(data->lines, i); CHECK(valid_opcode(opcode)); CHECK(opcode != END_FOR); CHECK(opcode != RESUME); @@ -588,7 +588,7 @@ sanity_check_instrumentation(PyCodeObject *code) * *and* we are executing a INSTRUMENTED_LINE instruction * that has de-instrumented itself, then we will execute * an invalid INSTRUMENTED_INSTRUCTION */ - CHECK(get_original_opcode(data->lines, i) != INSTRUMENTED_INSTRUCTION); + CHECK(_PyCode_GetOriginalOpcode(data->lines, i) != INSTRUMENTED_INSTRUCTION); } if (opcode == INSTRUMENTED_INSTRUCTION) { CHECK(data->per_instruction_opcodes[i] != 0); @@ -603,7 +603,7 @@ sanity_check_instrumentation(PyCodeObject *code) } CHECK(active_monitors.tools[event] != 0); } - if (data->lines && get_original_opcode(data->lines, i)) { + if (data->lines && _PyCode_GetOriginalOpcode(data->lines, i)) { int line1 = compute_line(code, get_line_delta(data->lines, i)); int line2 = _PyCode_CheckLineNumber(i*sizeof(_Py_CODEUNIT), &range); CHECK(line1 == line2); @@ -655,7 +655,7 @@ _Py_GetBaseCodeUnit(PyCodeObject *code, int i) return inst; } if (opcode == INSTRUMENTED_LINE) { - opcode = get_original_opcode(code->_co_monitoring->lines, i); + opcode = _PyCode_GetOriginalOpcode(code->_co_monitoring->lines, i); } if (opcode == INSTRUMENTED_INSTRUCTION) { opcode = code->_co_monitoring->per_instruction_opcodes[i]; @@ -714,7 +714,7 @@ de_instrument_line(PyCodeObject *code, _Py_CODEUNIT *bytecode, _PyCoMonitoringDa return; } _PyCoLineInstrumentationData *lines = monitoring->lines; - int original_opcode = get_original_opcode(lines, i); + int original_opcode = _PyCode_GetOriginalOpcode(lines, i); if (original_opcode == INSTRUMENTED_INSTRUCTION) { set_original_opcode(lines, i, monitoring->per_instruction_opcodes[i]); } @@ -1102,8 +1102,10 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, event == PY_MONITORING_EVENT_C_RETURN); event = PY_MONITORING_EVENT_CALL; } + assert(_PY_MONITORING_IS_UNGROUPED_EVENT(event)); + CHECK(debug_check_sanity(interp, code)); if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { - CHECK(debug_check_sanity(interp, code)); + /* Instrumented events use per-instruction tool bitmaps. */ if (code->_co_monitoring->tools) { tools = code->_co_monitoring->tools[i]; } @@ -1112,7 +1114,9 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, } } else { - tools = interp->monitors.tools[event]; + /* Other (non-instrumented) events are not tied to specific instructions; + * use the code-object-level active_monitors bitmap instead. */ + tools = code->_co_monitoring->active_monitors.tools[event]; } return tools; } @@ -1139,6 +1143,25 @@ static const char *const event_names [] = { [PY_MONITORING_EVENT_STOP_ITERATION] = "STOP_ITERATION", }; +/* Disable an "other" (non-instrumented) event (e.g. PY_UNWIND) for a single + * tool on this code object. Must be called with the world stopped or the + * code lock held. */ +static void +remove_local_tool(PyCodeObject *code, PyInterpreterState *interp, + int event, int tool) +{ + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(_PY_MONITORING_IS_UNGROUPED_EVENT(event)); + assert(!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); + assert(code->_co_monitoring); + code->_co_monitoring->local_monitors.tools[event] &= ~(1 << tool); + /* Recompute active_monitors for this event as the union of global and + * (now updated) local monitors. */ + code->_co_monitoring->active_monitors.tools[event] = + interp->monitors.tools[event] | + code->_co_monitoring->local_monitors.tools[event]; +} + static int call_instrumentation_vector( _Py_CODEUNIT *instr, PyThreadState *tstate, int event, @@ -1183,7 +1206,18 @@ call_instrumentation_vector( } else { /* DISABLE */ - if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + _PyEval_StopTheWorld(interp); + remove_tools(code, offset, event, 1 << tool); + _PyEval_StartTheWorld(interp); + } + else if (_PY_MONITORING_IS_UNGROUPED_EVENT(event)) { + /* Other (non-instrumented) event: disable for this code object. */ + _PyEval_StopTheWorld(interp); + remove_local_tool(code, interp, event, tool); + _PyEval_StartTheWorld(interp); + } + else { PyErr_Format(PyExc_ValueError, "Cannot disable %s events. Callback removed.", event_names[event]); @@ -1192,12 +1226,6 @@ call_instrumentation_vector( err = -1; break; } - else { - PyInterpreterState *interp = tstate->interp; - _PyEval_StopTheWorld(interp); - remove_tools(code, offset, event, 1 << tool); - _PyEval_StartTheWorld(interp); - } } } Py_DECREF(arg2_obj); @@ -1391,7 +1419,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, Py_DECREF(line_obj); uint8_t original_opcode; done: - original_opcode = get_original_opcode(line_data, i); + original_opcode = _PyCode_GetOriginalOpcode(line_data, i); assert(original_opcode != 0); assert(original_opcode != INSTRUMENTED_LINE); assert(_PyOpcode_Deopt[original_opcode] == original_opcode); @@ -1464,7 +1492,7 @@ initialize_tools(PyCodeObject *code) int opcode = instr->op.code; assert(opcode != ENTER_EXECUTOR); if (opcode == INSTRUMENTED_LINE) { - opcode = get_original_opcode(code->_co_monitoring->lines, i); + opcode = _PyCode_GetOriginalOpcode(code->_co_monitoring->lines, i); } if (opcode == INSTRUMENTED_INSTRUCTION) { opcode = code->_co_monitoring->per_instruction_opcodes[i]; @@ -1681,7 +1709,7 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { - for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { + for (int j = 0; j < _PY_MONITORING_UNGROUPED_EVENTS; j++) { local_monitors->tools[j] &= ~(1 << i); } } @@ -1849,7 +1877,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) if (removed_line_tools) { _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; for (int i = code->_co_firsttraceable; i < code_len;) { - if (get_original_opcode(line_data, i)) { + if (_PyCode_GetOriginalOpcode(line_data, i)) { remove_line_tools(code, i, removed_line_tools); } i += _PyInstruction_GetLength(code, i); @@ -1876,7 +1904,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) if (new_line_tools) { _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; for (int i = code->_co_firsttraceable; i < code_len;) { - if (get_original_opcode(line_data, i)) { + if (_PyCode_GetOriginalOpcode(line_data, i)) { add_line_tools(code, i, new_line_tools); } i += _PyInstruction_GetLength(code, i); @@ -1977,7 +2005,7 @@ static void set_local_events(_Py_LocalMonitors *m, int tool_id, _PyMonitoringEventSet events) { assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); - for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { uint8_t *tools = &m->tools[e]; int val = (events >> e) & 1; *tools &= ~(1 << tool_id); @@ -2037,7 +2065,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); PyInterpreterState *interp = _PyInterpreterState_GET(); - assert(events < (1 << _PY_MONITORING_LOCAL_EVENTS)); + assert(events < (1 << _PY_MONITORING_UNGROUPED_EVENTS)); if (code->_co_firsttraceable >= Py_SIZE(code)) { PyErr_Format(PyExc_SystemError, "cannot instrument shim code object '%U'", code->co_name); return -1; @@ -2373,7 +2401,7 @@ monitoring_get_local_events_impl(PyObject *module, int tool_id, _PyMonitoringEventSet event_set = 0; _PyCoMonitoringData *data = ((PyCodeObject *)code)->_co_monitoring; if (data != NULL) { - for (int e = 0; e < _PY_MONITORING_LOCAL_EVENTS; e++) { + for (int e = 0; e < _PY_MONITORING_UNGROUPED_EVENTS; e++) { if ((data->local_monitors.tools[e] >> tool_id) & 1) { event_set |= (1 << e); } @@ -2416,7 +2444,7 @@ monitoring_set_local_events_impl(PyObject *module, int tool_id, event_set &= ~(1 << PY_MONITORING_EVENT_BRANCH); event_set |= (1 << PY_MONITORING_EVENT_BRANCH_RIGHT) | (1 << PY_MONITORING_EVENT_BRANCH_LEFT); } - if (event_set < 0 || event_set >= (1 << _PY_MONITORING_LOCAL_EVENTS)) { + if (event_set < 0 || event_set >= (1 << _PY_MONITORING_UNGROUPED_EVENTS)) { PyErr_Format(PyExc_ValueError, "invalid local event set 0x%x", event_set); return NULL; } diff --git a/Python/jit.c b/Python/jit.c index d56ff6ad156..26e01b25d48 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -60,8 +60,6 @@ jit_error(const char *message) PyErr_Format(PyExc_RuntimeWarning, "JIT %s (%d)", message, hint); } -static size_t _Py_jit_shim_size = 0; - static int address_in_executor_array(_PyExecutorObject **ptrs, size_t count, uintptr_t addr) { @@ -104,13 +102,6 @@ _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr) if (interp == NULL) { return 0; } - if (_Py_jit_entry != _Py_LazyJitShim && _Py_jit_shim_size != 0) { - uintptr_t start = (uintptr_t)_Py_jit_entry; - uintptr_t end = start + _Py_jit_shim_size; - if (addr >= start && addr < end) { - return 1; - } - } if (address_in_executor_array(interp->executor_ptrs, interp->executor_count, addr)) { return 1; } @@ -355,6 +346,14 @@ patch_aarch64_12(unsigned char *location, uint64_t value) set_bits(loc32, 10, value, shift, 12); } +// Relaxable 12-bit low part of an absolute address. +// Usually paired with patch_aarch64_21rx (below). +void +patch_aarch64_12x(unsigned char *location, uint64_t value) +{ + patch_aarch64_12(location, value); +} + // 16-bit low part of an absolute address. void patch_aarch64_16a(unsigned char *location, uint64_t value) @@ -415,6 +414,14 @@ patch_aarch64_21r(unsigned char *location, uint64_t value) set_bits(loc32, 5, value, 2, 19); } +// Relaxable 21-bit count of pages between this page and an absolute address's +// page. Usually paired with patch_aarch64_12x (above). +void +patch_aarch64_21rx(unsigned char *location, uint64_t value) +{ + patch_aarch64_21r(location, value); +} + // 21-bit relative branch. void patch_aarch64_19r(unsigned char *location, uint64_t value) @@ -445,6 +452,56 @@ patch_aarch64_26r(unsigned char *location, uint64_t value) set_bits(loc32, 0, value, 2, 26); } +// A pair of patch_aarch64_21rx and patch_aarch64_12x. +void +patch_aarch64_33rx(unsigned char *location_a, unsigned char *location_b, uint64_t value) +{ + uint32_t *loc32_a = (uint32_t *)location_a; + uint32_t *loc32_b = (uint32_t *)location_b; + // Try to relax the pair of GOT loads into an immediate value: + assert(IS_AARCH64_ADRP(*loc32_a)); + assert(IS_AARCH64_LDR_OR_STR(*loc32_b)); + unsigned char reg = get_bits(*loc32_a, 0, 5); + // There should be only one register involved: + assert(reg == get_bits(*loc32_a, 0, 5)); // ldr's output register. + assert(reg == get_bits(*loc32_b, 5, 5)); // ldr's input register. + uint64_t relaxed = *(uint64_t *)value; + if (relaxed < (1UL << 16)) { + // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; nop + *loc32_a = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; + *loc32_b = 0xD503201F; + return; + } + if (relaxed < (1ULL << 32)) { + // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; movk reg, YYY + *loc32_a = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; + *loc32_b = 0xF2A00000 | (get_bits(relaxed, 16, 16) << 5) | reg; + return; + } + int64_t page_delta = (relaxed >> 12) - ((uintptr_t)location_a >> 12); + if (page_delta >= -(1L << 20) && + page_delta < (1L << 20)) + { + // adrp reg, AAA; ldr reg, [reg + BBB] -> adrp reg, AAA; add reg, reg, BBB + patch_aarch64_21rx(location_a, relaxed); + *loc32_b = 0x91000000 | get_bits(relaxed, 0, 12) << 10 | reg << 5 | reg; + return; + } + relaxed = value - (uintptr_t)location_a; + if ((relaxed & 0x3) == 0 && + (int64_t)relaxed >= -(1L << 19) && + (int64_t)relaxed < (1L << 19)) + { + // adrp reg, AAA; ldr reg, [reg + BBB] -> ldr reg, XXX; nop + *loc32_a = 0x58000000 | (get_bits(relaxed, 2, 19) << 5) | reg; + *loc32_b = 0xD503201F; + return; + } + // Couldn't do it. Just patch the two instructions normally: + patch_aarch64_21rx(location_a, value); + patch_aarch64_12x(location_b, value); +} + // Relaxable 32-bit relative address. void patch_x86_64_32rx(unsigned char *location, uint64_t value) @@ -661,75 +718,6 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz return 0; } -/* One-off compilation of the jit entry shim - * We compile this once only as it effectively a normal - * function, but we need to use the JIT because it needs - * to understand the jit-specific calling convention. - * Don't forget to call _PyJIT_Fini later! - */ -static _PyJitEntryFuncPtr -compile_shim(void) -{ - _PyExecutorObject dummy; - const StencilGroup *group; - size_t code_size = 0; - size_t data_size = 0; - jit_state state = {0}; - group = &shim; - code_size += group->code_size; - data_size += group->data_size; - combine_symbol_mask(group->trampoline_mask, state.trampolines.mask); - combine_symbol_mask(group->got_mask, state.got_symbols.mask); - // Round up to the nearest page: - size_t page_size = get_page_size(); - assert((page_size & (page_size - 1)) == 0); - size_t code_padding = DATA_ALIGN - ((code_size + state.trampolines.size) & (DATA_ALIGN - 1)); - size_t padding = page_size - ((code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size) & (page_size - 1)); - size_t total_size = code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size + padding; - unsigned char *memory = jit_alloc(total_size); - if (memory == NULL) { - return NULL; - } - unsigned char *code = memory; - state.trampolines.mem = memory + code_size; - unsigned char *data = memory + code_size + state.trampolines.size + code_padding; - state.got_symbols.mem = data + data_size; - // Compile the shim, which handles converting between the native - // calling convention and the calling convention used by jitted code - // (which may be different for efficiency reasons). - group = &shim; - group->emit(code, data, &dummy, NULL, &state); - code += group->code_size; - data += group->data_size; - assert(code == memory + code_size); - assert(data == memory + code_size + state.trampolines.size + code_padding + data_size); - if (mark_executable(memory, total_size)) { - jit_free(memory, total_size); - return NULL; - } - _Py_jit_shim_size = total_size; - return (_PyJitEntryFuncPtr)memory; -} - -static PyMutex lazy_jit_mutex = { 0 }; - -_Py_CODEUNIT * -_Py_LazyJitShim( - _PyExecutorObject *executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate -) { - PyMutex_Lock(&lazy_jit_mutex); - if (_Py_jit_entry == _Py_LazyJitShim) { - _PyJitEntryFuncPtr shim = compile_shim(); - if (shim == NULL) { - PyMutex_Unlock(&lazy_jit_mutex); - Py_FatalError("Cannot allocate core JIT code"); - } - _Py_jit_entry = shim; - } - PyMutex_Unlock(&lazy_jit_mutex); - return _Py_jit_entry(executor, frame, stack_pointer, tstate); -} - // Free executor's memory allocated with _PyJIT_Compile void _PyJIT_Free(_PyExecutorObject *executor) @@ -746,22 +734,4 @@ _PyJIT_Free(_PyExecutorObject *executor) } } -// Free shim memory allocated with compile_shim -void -_PyJIT_Fini(void) -{ - PyMutex_Lock(&lazy_jit_mutex); - unsigned char *memory = (unsigned char *)_Py_jit_entry; - size_t size = _Py_jit_shim_size; - if (size) { - _Py_jit_entry = _Py_LazyJitShim; - _Py_jit_shim_size = 0; - if (jit_free(memory, size)) { - PyErr_FormatUnraisable("Exception ignored while " - "freeing JIT entry code"); - } - } - PyMutex_Unlock(&lazy_jit_mutex); -} - #endif // _Py_JIT diff --git a/Python/lock.c b/Python/lock.c index 752a5899e08..af136fefd29 100644 --- a/Python/lock.c +++ b/Python/lock.c @@ -248,7 +248,16 @@ _PyRawMutex_LockSlow(_PyRawMutex *m) // Wait for us to be woken up. Note that we still have to lock the // mutex ourselves: it is NOT handed off to us. - _PySemaphore_Wait(&waiter.sema, -1); + // + // Loop until we observe an actual wakeup. A return of Py_PARK_INTR + // could otherwise let us exit _PySemaphore_Wait and destroy + // `waiter.sema` while _PyRawMutex_UnlockSlow's matching + // _PySemaphore_Wakeup is still pending, since the unlocker has + // already CAS-removed us from the waiter list without any handshake. + int res; + do { + res = _PySemaphore_Wait(&waiter.sema, -1); + } while (res != Py_PARK_OK); } _PySemaphore_Destroy(&waiter.sema); diff --git a/Python/marshal.c b/Python/marshal.c index b60a36e128c..dace22da0d4 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -382,7 +382,6 @@ static int w_ref(PyObject *v, char *flag, WFILE *p) { _Py_hashtable_entry_t *entry; - int w; if (p->version < 3 || p->hashtable == NULL) return 0; /* not writing object references */ @@ -399,20 +398,28 @@ w_ref(PyObject *v, char *flag, WFILE *p) entry = _Py_hashtable_get_entry(p->hashtable, v); if (entry != NULL) { /* write the reference index to the stream */ - w = (int)(uintptr_t)entry->value; + uintptr_t w = (uintptr_t)entry->value; + if (w & 0x80000000LU) { + PyErr_Format(PyExc_ValueError, "cannot marshal recursion %T objects", v); + goto err; + } /* we don't store "long" indices in the dict */ - assert(0 <= w && w <= 0x7fffffff); + assert(w <= 0x7fffffff); w_byte(TYPE_REF, p); - w_long(w, p); + w_long((int)w, p); return 1; } else { - size_t s = p->hashtable->nentries; + size_t w = p->hashtable->nentries; /* we don't support long indices */ - if (s >= 0x7fffffff) { + if (w >= 0x7fffffff) { PyErr_SetString(PyExc_ValueError, "too many objects"); goto err; } - w = (int)s; + // Corresponding code should call w_complete() after + // writing the object. + if (PyCode_Check(v) || PySlice_Check(v) || PyFrozenDict_CheckExact(v)) { + w |= 0x80000000LU; + } if (_Py_hashtable_set(p->hashtable, Py_NewRef(v), (void *)(uintptr_t)w) < 0) { Py_DECREF(v); @@ -426,6 +433,27 @@ w_ref(PyObject *v, char *flag, WFILE *p) return 1; } +static void +w_complete(PyObject *v, WFILE *p) +{ + if (p->version < 3 || p->hashtable == NULL) { + return; + } + if (_PyObject_IsUniquelyReferenced(v)) { + return; + } + + _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(p->hashtable, v); + if (entry == NULL) { + return; + } + assert(entry != NULL); + uintptr_t w = (uintptr_t)entry->value; + assert(w & 0x80000000LU); + w &= ~0x80000000LU; + entry->value = (void *)(uintptr_t)w; +} + static void w_complex_object(PyObject *v, char flag, WFILE *p); @@ -599,6 +627,9 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(value, p); } w_object((PyObject *)NULL, p); + if (PyFrozenDict_CheckExact(v)) { + w_complete(v, p); + } } else if (PyAnySet_CheckExact(v)) { PyObject *value; @@ -684,6 +715,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(co->co_linetable, p); w_object(co->co_exceptiontable, p); Py_DECREF(co_code); + w_complete(v, p); } else if (PyObject_CheckBuffer(v)) { /* Write unknown bytes-like objects as a bytes object */ @@ -709,6 +741,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_object(slice->start, p); w_object(slice->stop, p); w_object(slice->step, p); + w_complete(v, p); } else { W_TYPE(TYPE_UNKNOWN, p); @@ -1433,9 +1466,19 @@ r_object(RFILE *p) case TYPE_DICT: case TYPE_FROZENDICT: v = PyDict_New(); - R_REF(v); - if (v == NULL) + if (v == NULL) { break; + } + if (type == TYPE_DICT) { + R_REF(v); + } + else { + idx = r_ref_reserve(flag, p); + if (idx < 0) { + Py_CLEAR(v); + break; + } + } for (;;) { PyObject *key, *val; key = r_object(p); @@ -1458,13 +1501,7 @@ r_object(RFILE *p) Py_CLEAR(v); } if (type == TYPE_FROZENDICT && v != NULL) { - PyObject *frozendict = PyFrozenDict_New(v); - if (frozendict != NULL) { - Py_SETREF(v, frozendict); - } - else { - Py_CLEAR(v); - } + Py_SETREF(v, PyFrozenDict_New(v)); } retval = v; break; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 48fe9c14f4e..d99b618c839 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -178,6 +178,9 @@ static void *opcode_targets_table[256] = { &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_FOR_ITER_VIRTUAL, + &&TARGET_GET_ITER_SELF, + &&TARGET_GET_ITER_VIRTUAL, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -230,9 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -473,9 +473,9 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -621,10 +621,13 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_FOR_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_SELF(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER_VIRTUAL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS); @@ -862,10 +865,13 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST, [FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE, [FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_FOR_ITER_VIRTUAL, [GET_AITER] = _TAIL_CALL_GET_AITER, [GET_ANEXT] = _TAIL_CALL_GET_ANEXT, [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, + [GET_ITER_SELF] = _TAIL_CALL_GET_ITER_SELF, + [GET_ITER_VIRTUAL] = _TAIL_CALL_GET_ITER_VIRTUAL, [GET_LEN] = _TAIL_CALL_GET_LEN, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, [IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME, @@ -1008,9 +1014,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1120,10 +1123,13 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [FOR_ITER_LIST] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_RANGE] = _TAIL_CALL_TRACE_RECORD, [FOR_ITER_TUPLE] = _TAIL_CALL_TRACE_RECORD, + [FOR_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_AITER] = _TAIL_CALL_TRACE_RECORD, [GET_ANEXT] = _TAIL_CALL_TRACE_RECORD, [GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD, [GET_ITER] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_SELF] = _TAIL_CALL_TRACE_RECORD, + [GET_ITER_VIRTUAL] = _TAIL_CALL_TRACE_RECORD, [GET_LEN] = _TAIL_CALL_TRACE_RECORD, [IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD, [IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD, @@ -1266,9 +1272,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [214] = _TAIL_CALL_UNKNOWN_OPCODE, - [215] = _TAIL_CALL_UNKNOWN_OPCODE, - [216] = _TAIL_CALL_UNKNOWN_OPCODE, [217] = _TAIL_CALL_UNKNOWN_OPCODE, [218] = _TAIL_CALL_UNKNOWN_OPCODE, [219] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer.c b/Python/optimizer.c index f09bf778587..a389c0f4072 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -496,8 +496,10 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = { [_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST, [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, [_FOR_ITER] = _FOR_ITER_TIER_TWO, + [_FOR_ITER_VIRTUAL] = _FOR_ITER_VIRTUAL_TIER_TWO, [_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO, [_CHECK_PERIODIC_AT_END] = _TIER2_RESUME_CHECK, + [_LOAD_BYTECODE] = _NOP, }; static const uint8_t @@ -549,8 +551,6 @@ dynamic_exit_uop[MAX_UOP_ID + 1] = { }; -#define CONFIDENCE_RANGE 1000 -#define CONFIDENCE_CUTOFF 333 #ifdef Py_DEBUG #define DPRINTF(level, ...) \ @@ -598,6 +598,54 @@ add_to_trace( ((uint32_t)((INSTR) - ((_Py_CODEUNIT *)(CODE)->co_code_adaptive))) +/* Branch penalty: 0 for a fully biased branch and FITNESS_BRANCH_BALANCED for + * a balanced or fully off-trace branch. This keeps any single branch from + * consuming more than one balanced-branch cost. + */ +static inline int +compute_branch_penalty(uint16_t history) +{ + bool branch_taken = history & 1; + int taken_count = _Py_popcount32((uint32_t)history); + int on_trace_count = branch_taken ? taken_count : 16 - taken_count; + int off_trace = 16 - on_trace_count; + int penalty = off_trace * FITNESS_BRANCH_BALANCED / 8; + if (penalty > FITNESS_BRANCH_BALANCED) { + penalty = FITNESS_BRANCH_BALANCED; + } + return penalty; +} + +/* Compute exit quality for the current trace position. + * Higher values mean better places to stop the trace. */ +static inline int32_t +compute_exit_quality(_Py_CODEUNIT *target_instr, int opcode, + const _PyJitTracerState *tracer) +{ + if (target_instr == tracer->initial_state.close_loop_instr) { + return EXIT_QUALITY_CLOSE_LOOP; + } + else if (target_instr->op.code == ENTER_EXECUTOR) { + return EXIT_QUALITY_ENTER_EXECUTOR; + } + else if (opcode == JUMP_BACKWARD_JIT || + opcode == JUMP_BACKWARD || + opcode == JUMP_BACKWARD_NO_INTERRUPT) { + return EXIT_QUALITY_BACKWARD_EDGE; + } + else if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { + return EXIT_QUALITY_SPECIALIZABLE; + } + return EXIT_QUALITY_DEFAULT; +} + +/* Frame penalty: (MAX_ABSTRACT_FRAME_DEPTH-1) pushes exhaust fitness. */ +static inline int32_t +compute_frame_penalty(uint16_t fitness_initial) +{ + return (int32_t)fitness_initial / (MAX_ABSTRACT_FRAME_DEPTH - 1) + 1; +} + static int is_terminator(const _PyUOpInstruction *uop) { @@ -734,13 +782,11 @@ _PyJit_translate_single_bytecode_to_trace( DPRINTF(2, "Unsupported: oparg too large\n"); unsupported: { - // Rewind to previous instruction and replace with _EXIT_TRACE. _PyUOpInstruction *curr = uop_buffer_last(trace); while (curr->opcode != _SET_IP && uop_buffer_length(trace) > 2) { trace->next--; curr = uop_buffer_last(trace); } - assert(curr->opcode == _SET_IP || uop_buffer_length(trace) == 2); if (curr->opcode == _SET_IP) { int32_t old_target = (int32_t)uop_get_target(curr); curr->opcode = _DEOPT; @@ -763,11 +809,28 @@ _PyJit_translate_single_bytecode_to_trace( return 1; } + // Stop the trace if fitness has dropped below the exit quality threshold. + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + int32_t eq = compute_exit_quality(target_instr, opcode, tracer); + DPRINTF(3, "Fitness check: %s(%d) fitness=%d, exit_quality=%d, depth=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq, ts->frame_depth); + + if (ts->fitness < eq) { + // Heuristic exit: leave operand1=0 so the side exit increments chain_depth. + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); + OPT_STAT_INC(fitness_terminated_traces); + DPRINTF(2, "Fitness terminated: %s(%d) fitness=%d < exit_quality=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq); + goto done; + } + + // Snapshot remaining space so the later fitness charge reflects all buffer + // space this bytecode consumed, including reserved tail slots. + int32_t remaining_before = uop_buffer_remaining_space(trace); + // One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT trace->end -= 2; - const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; - assert(opcode != ENTER_EXECUTOR && opcode != EXTENDED_ARG); assert(!_PyErr_Occurred(tstate)); @@ -788,13 +851,11 @@ _PyJit_translate_single_bytecode_to_trace( // _GUARD_IP leads to an exit. trace->end -= needs_guard_ip; +#if Py_DEBUG + const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; int space_needed = expansion->nuops + needs_guard_ip + 2 + (!OPCODE_HAS_NO_SAVE_IP(opcode)); - if (uop_buffer_remaining_space(trace) < space_needed) { - DPRINTF(2, "No room for expansions and guards (need %d, got %d)\n", - space_needed, uop_buffer_remaining_space(trace)); - OPT_STAT_INC(trace_too_long); - goto done; - } + assert(uop_buffer_remaining_space(trace) > space_needed); +#endif ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target); @@ -816,6 +877,12 @@ _PyJit_translate_single_bytecode_to_trace( assert(jump_happened ? (next_instr == computed_jump_instr) : (next_instr == computed_next_instr)); uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened]; ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code)); + int bp = compute_branch_penalty(target_instr[1].cache); + tracer->translator_state.fitness -= bp; + DPRINTF(3, " branch penalty: -%d (history=0x%04x, taken=%d) -> fitness=%d\n", + bp, target_instr[1].cache, jump_happened, + tracer->translator_state.fitness); + break; } case JUMP_BACKWARD_JIT: @@ -823,29 +890,9 @@ _PyJit_translate_single_bytecode_to_trace( case JUMP_BACKWARD_NO_JIT: case JUMP_BACKWARD: ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target); - _Py_FALLTHROUGH; - case JUMP_BACKWARD_NO_INTERRUPT: - { - if ((next_instr != tracer->initial_state.close_loop_instr) && - (next_instr != tracer->initial_state.start_instr) && - uop_buffer_length(&tracer->code_buffer) > CODE_SIZE_NO_PROGRESS && - // For side exits, we don't want to terminate them early. - tracer->initial_state.exit == NULL && - // These are coroutines, and we want to unroll those usually. - opcode != JUMP_BACKWARD_NO_INTERRUPT) { - // We encountered a JUMP_BACKWARD but not to the top of our own loop. - // We don't want to continue tracing as we might get stuck in the - // inner loop. Instead, end the trace where the executor of the - // inner loop might start and let the traces rejoin. - OPT_STAT_INC(inner_loop); - ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - uop_buffer_last(trace)->operand1 = true; // is_control_flow - DPRINTF(2, "JUMP_BACKWARD not to top ends trace %p %p %p\n", next_instr, - tracer->initial_state.close_loop_instr, tracer->initial_state.start_instr); - goto done; - } break; - } + case JUMP_BACKWARD_NO_INTERRUPT: + break; case RESUME: case RESUME_CHECK: @@ -866,6 +913,7 @@ _PyJit_translate_single_bytecode_to_trace( assert(nuops > 0); uint32_t orig_oparg = oparg; // For OPARG_TOP/BOTTOM uint32_t orig_target = target; + int record_idx = 0; for (int i = 0; i < nuops; i++) { oparg = orig_oparg; target = orig_target; @@ -945,9 +993,43 @@ _PyJit_translate_single_bytecode_to_trace( assert(next->op.code == STORE_FAST); operand = next->op.arg; } + else if (uop == _PUSH_FRAME) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + ts_depth->frame_depth++; + assert(ts_depth->frame_depth < MAX_ABSTRACT_FRAME_DEPTH); + int32_t frame_penalty = compute_frame_penalty(tstate->interp->opt_config.fitness_initial); + ts_depth->fitness -= frame_penalty; + DPRINTF(3, " _PUSH_FRAME: depth=%d, penalty=-%d -> fitness=%d\n", + ts_depth->frame_depth, frame_penalty, + ts_depth->fitness); + } + else if (uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + int32_t frame_penalty = compute_frame_penalty(tstate->interp->opt_config.fitness_initial); + if (ts_depth->frame_depth <= 0) { + // Returning past the traced root is normal for guarded + // caller continuation. Charge a small penalty so these + // paths still terminate. + int32_t underflow_penalty = frame_penalty / 4; + ts_depth->fitness -= underflow_penalty; + DPRINTF(3, " %s: underflow penalty=-%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], underflow_penalty, + ts_depth->fitness); + } + else { + // Symmetric with push: net-zero frame impact. + ts_depth->fitness += frame_penalty; + ts_depth->frame_depth--; + DPRINTF(3, " %s: return reward=+%d, depth=%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], frame_penalty, + ts_depth->frame_depth, + ts_depth->fitness); + } + } else if (_PyUop_Flags[uop] & HAS_RECORDS_VALUE_FLAG) { - PyObject *recorded_value = tracer->prev_state.recorded_value; - tracer->prev_state.recorded_value = NULL; + PyObject *recorded_value = tracer->prev_state.recorded_values[record_idx]; + tracer->prev_state.recorded_values[record_idx] = NULL; + record_idx++; operand = (uintptr_t)recorded_value; } // All other instructions @@ -986,13 +1068,20 @@ _PyJit_translate_single_bytecode_to_trace( ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); goto done; } - DPRINTF(2, "Trace continuing\n"); + // Charge fitness by trace-buffer capacity consumed for this bytecode, + // including both emitted uops and tail reservations. + { + int32_t slots_used = remaining_before - uop_buffer_remaining_space(trace); + tracer->translator_state.fitness -= slots_used; + DPRINTF(3, " per-insn cost: -%d -> fitness=%d\n", slots_used, + tracer->translator_state.fitness); + } + DPRINTF(2, "Trace continuing (fitness=%d)\n", tracer->translator_state.fitness); return 1; done: DPRINTF(2, "Trace done\n"); if (!is_terminator(uop_buffer_last(trace))) { ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - uop_buffer_last(trace)->operand1 = true; // is_control_flow } return 0; } @@ -1060,15 +1149,26 @@ _PyJit_TryInitializeTracing( tracer->prev_state.instr_frame = frame; tracer->prev_state.instr_oparg = oparg; tracer->prev_state.instr_stacklevel = tracer->initial_state.stack_depth; - tracer->prev_state.recorded_value = NULL; - uint8_t record_func_index = _PyOpcode_RecordFunctionIndices[curr_instr->op.code]; - if (record_func_index) { - _Py_RecordFuncPtr record_func = _PyOpcode_RecordFunctions[record_func_index]; - record_func(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); + tracer->prev_state.recorded_count = 0; + for (int i = 0; i < MAX_RECORDED_VALUES; i++) { + tracer->prev_state.recorded_values[i] = NULL; } + const _PyOpcodeRecordEntry *record_entry = &_PyOpcode_RecordEntries[curr_instr->op.code]; + for (int i = 0; i < record_entry->count; i++) { + _Py_RecordFuncPtr record_func = _PyOpcode_RecordFunctions[record_entry->indices[i]]; + record_func(frame, stack_pointer, oparg, &tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = record_entry->count; assert(curr_instr->op.code == JUMP_BACKWARD_JIT || curr_instr->op.code == RESUME_CHECK_JIT || (exit != NULL)); tracer->initial_state.jump_backward_instr = curr_instr; + const _PyOptimizationConfig *cfg = &tstate->interp->opt_config; + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + ts->fitness = cfg->fitness_initial; + ts->frame_depth = 0; + DPRINTF(3, "Fitness init: chain_depth=%d, fitness=%d\n", + chain_depth, ts->fitness); + tracer->is_tracing = true; return 1; } @@ -1117,7 +1217,10 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) Py_CLEAR(tracer->initial_state.func); Py_CLEAR(tracer->initial_state.executor); Py_CLEAR(tracer->prev_state.instr_code); - Py_CLEAR(tracer->prev_state.recorded_value); + for (int i = 0; i < MAX_RECORDED_VALUES; i++) { + Py_CLEAR(tracer->prev_state.recorded_values[i]); + } + tracer->prev_state.recorded_count = 0; uop_buffer_init(buffer, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); tracer->is_tracing = false; } diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index ada104ea65d..095bcfc639b 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -119,14 +119,15 @@ static int get_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - return (d->_ma_watcher_tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS)-1); + uint64_t tag = FT_ATOMIC_LOAD_UINT64_RELAXED(d->_ma_watcher_tag); + return (tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS) - 1); } static void increment_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - d->_ma_watcher_tag += (1 << DICT_MAX_WATCHERS); + FT_ATOMIC_ADD_UINT64(d->_ma_watcher_tag, (1 << DICT_MAX_WATCHERS)); } /* The first two dict watcher IDs are reserved for CPython, @@ -256,6 +257,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_get_probable_type _Py_uop_sym_get_probable_type #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) #define sym_set_non_null(SYM) _Py_uop_sym_set_non_null(ctx, SYM) #define sym_set_type(SYM, TYPE) _Py_uop_sym_set_type(ctx, SYM, TYPE) @@ -282,8 +284,6 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_get_probable_func_code _Py_uop_sym_get_probable_func_code #define sym_get_probable_value _Py_uop_sym_get_probable_value #define sym_set_stack_depth(DEPTH, SP) _Py_uop_sym_set_stack_depth(ctx, DEPTH, SP) -#define sym_get_func_version _Py_uop_sym_get_func_version -#define sym_set_func_version _Py_uop_sym_set_func_version /* Comparison oparg masks */ #define COMPARE_LT_MASK 2 @@ -397,8 +397,10 @@ lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction if (suffix != _NOP) { ADD_OP(suffix, 2, 0); } - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } return sym_new_const(ctx, lookup); } } @@ -466,10 +468,13 @@ lookup_super_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, if (suffix != _NOP) { ADD_OP(suffix, 2, 0); } - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)su_type); - _Py_BloomFilter_Add(dependencies, su_type); - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)obj_type); - _Py_BloomFilter_Add(dependencies, obj_type); + // if obj_type is immutable, then all its superclasses are immutable + if ((obj_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)su_type); + _Py_BloomFilter_Add(dependencies, su_type); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)obj_type); + _Py_BloomFilter_Add(dependencies, obj_type); + } return sym_new_const_steal(ctx, lookup); } @@ -677,9 +682,7 @@ const uint16_t op_without_push[MAX_UOP_ID + 1] = { [_LOAD_FAST] = _NOP, [_LOAD_FAST_BORROW] = _NOP, [_LOAD_SMALL_INT] = _NOP, - [_POP_TOP_LOAD_CONST_INLINE] = _POP_TOP, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _POP_TOP, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TWO, + [_PUSH_NULL] = _NOP, }; const bool op_skip[MAX_UOP_ID + 1] = { @@ -695,16 +698,6 @@ const uint16_t op_without_pop[MAX_UOP_ID + 1] = { [_POP_TOP_INT] = _NOP, [_POP_TOP_FLOAT] = _NOP, [_POP_TOP_UNICODE] = _NOP, - [_POP_TOP_LOAD_CONST_INLINE] = _LOAD_CONST_INLINE, - [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _LOAD_CONST_INLINE_BORROW, - [_POP_TWO] = _POP_TOP, - [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TOP_LOAD_CONST_INLINE_BORROW, - [_POP_CALL_TWO] = _POP_CALL_ONE, - [_POP_CALL_ONE] = _POP_CALL, -}; - -const uint16_t op_without_pop_null[MAX_UOP_ID + 1] = { - [_POP_CALL] = _POP_TOP, }; @@ -739,10 +732,10 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) default: { // Cancel out pushes and pops, repeatedly. So: - // _LOAD_FAST + _POP_TWO_LOAD_CONST_INLINE_BORROW + _POP_TOP + // _LOAD_FAST + _POP_TOP + _POP_TOP + _LOAD_CONST_INLINE_BORROW + _POP_TOP // ...becomes: - // _NOP + _POP_TOP + _NOP - while (op_without_pop[opcode] || op_without_pop_null[opcode]) { + // _NOP + _NOP + _POP_TOP + _NOP + _NOP + while (op_without_pop[opcode]) { _PyUOpInstruction *last = &buffer[pc - 1]; while (op_skip[last->opcode]) { last--; @@ -755,14 +748,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) pc = (int)(last - buffer); } } - else if (last->opcode == _PUSH_NULL) { - // Handle _POP_CALL separately. - // This looks for a preceding _PUSH_NULL instruction and - // simplifies to _POP_TOP. - last->opcode = _NOP; - opcode = buffer[pc].opcode = op_without_pop_null[opcode]; - assert(opcode); - } else { break; } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 50005d4e968..daebef4a043 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -20,6 +20,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_new_null _Py_uop_sym_new_null #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_get_type _Py_uop_sym_get_type #define sym_has_type _Py_uop_sym_has_type #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) @@ -134,6 +135,31 @@ dummy_func(void) { assert(!PyJitRef_IsUnique(value)); } + op(_GUARD_TYPE_VERSION_LOCKED, (type_version/2, owner -- owner)) { + assert(type_version); + if (sym_matches_type_version(owner, type_version)) { + ADD_OP(_NOP, 0, 0); + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + // Promote the probable type version to a known one. + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } + } + } + op(_STORE_ATTR_INSTANCE_VALUE, (offset/1, value, owner -- o)) { (void)offset; (void)value; @@ -210,6 +236,10 @@ dummy_func(void) { } else { sym_set_const(owner, type); + if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, type); + _Py_BloomFilter_Add(dependencies, type); + } } } } @@ -219,20 +249,20 @@ dummy_func(void) { assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - // add watcher so that whenever the type changes we invalidate this - PyTypeObject *type = _PyType_LookupByVersion(type_version); - // if the type is null, it was not found in the cache (there was a conflict) - // with the key, in which case we can't trust the version - if (type) { - // if the type version was set properly, then add a watcher - // if it wasn't this means that the type version was previously set to something else - // and we set the owner to bottom, so we don't need to add a watcher because we must have - // already added one earlier. - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } } @@ -259,7 +289,56 @@ dummy_func(void) { bool rhs_int = sym_matches_type(rhs, &PyLong_Type); bool lhs_float = sym_matches_type(lhs, &PyFloat_Type); bool rhs_float = sym_matches_type(rhs, &PyFloat_Type); - if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { + bool is_truediv = (oparg == NB_TRUE_DIVIDE + || oparg == NB_INPLACE_TRUE_DIVIDE); + bool is_remainder = (oparg == NB_REMAINDER + || oparg == NB_INPLACE_REMAINDER); + // Promote probable-float operands to known floats via speculative + // guards. _RECORD_TOS_TYPE / _RECORD_NOS_TYPE in the BINARY_OP macro + // record the observed operand type during tracing, which + // sym_get_probable_type reads here. Applied only to ops where + // narrowing unlocks a meaningful downstream win: + // - NB_TRUE_DIVIDE: enables the specialized float path below. + // - NB_REMAINDER: lets the float result type propagate. + // NB_POWER is excluded: speculative guards there regressed + // test_power_type_depends_on_input_values (GH-127844). + if (is_truediv || is_remainder) { + if (!sym_has_type(rhs) + && sym_get_probable_type(rhs) == &PyFloat_Type) { + ADD_OP(_GUARD_TOS_FLOAT, 0, 0); + sym_set_type(rhs, &PyFloat_Type); + rhs_float = true; + } + if (!sym_has_type(lhs) + && sym_get_probable_type(lhs) == &PyFloat_Type) { + ADD_OP(_GUARD_NOS_FLOAT, 0, 0); + sym_set_type(lhs, &PyFloat_Type); + lhs_float = true; + } + } + if (is_truediv && lhs_float && rhs_float) { + if (PyJitRef_IsUnique(lhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + l = sym_new_null(ctx); + r = rhs; + } + else if (PyJitRef_IsUnique(rhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + l = lhs; + r = sym_new_null(ctx); + } + else { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + l = lhs; + r = rhs; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (is_truediv + && (lhs_int || lhs_float) && (rhs_int || rhs_float)) { + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { // There's something other than an int or float involved: res = sym_new_unknown(ctx); } @@ -282,7 +361,7 @@ dummy_func(void) { } else if (lhs_float) { // Case C: - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else if (!sym_is_const(ctx, rhs)) { // Case A or B... can't know without the sign of the RHS: @@ -290,21 +369,18 @@ dummy_func(void) { } else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) { // Case B: - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else { // Case A: res = sym_new_type(ctx, &PyLong_Type); } } - else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { - res = sym_new_type(ctx, &PyFloat_Type); - } else if (lhs_int && rhs_int) { res = sym_new_type(ctx, &PyLong_Type); } else { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } } @@ -409,6 +485,46 @@ dummy_func(void) { r = right; } + op(_GUARD_BINARY_OP_EXTEND_LHS, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->lhs_type != NULL); + if (sym_matches_type(left, d->lhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(left, d->lhs_type); + } + + op(_GUARD_BINARY_OP_EXTEND_RHS, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->rhs_type != NULL); + if (sym_matches_type(right, d->rhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(right, d->rhs_type); + } + + op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) { + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->guard == NULL) { + /* guard == NULL means the check is purely a type test against + lhs_type/rhs_type, so eliminate it when types are already known. */ + assert(d->lhs_type != NULL && d->rhs_type != NULL); + bool lhs_known = sym_matches_type(left, d->lhs_type); + bool rhs_known = sym_matches_type(right, d->rhs_type); + if (lhs_known && rhs_known) { + ADD_OP(_NOP, 0, 0); + } + else if (lhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_RHS, 0, (uintptr_t)d); + sym_set_type(right, d->rhs_type); + } + else if (rhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_LHS, 0, (uintptr_t)d); + sym_set_type(left, d->lhs_type); + } + } + } + op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; if (d != NULL && d->result_type != NULL) { @@ -710,6 +826,16 @@ dummy_func(void) { r = right; } + op(_IS_NONE, (value -- b)) { + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } + } + op(_CONTAINS_OP, (left, right -- b, l, r)) { b = sym_new_type(ctx, &PyBool_Type); l = left; @@ -731,6 +857,10 @@ dummy_func(void) { b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenDict_Type)) { + REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, b); + } } op(_LOAD_CONST, (-- value)) { @@ -953,30 +1083,83 @@ dummy_func(void) { _LOAD_CONST_INLINE, _SWAP); } - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { - // + 1 for _SAVE_RETURN_OFFSET - // FIX ME -- This needs a version check and function watcher - PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code; + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; + new_frame = PyJitRef_WrapInvalid(f); + } + + op(_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME, (func_version/2, getattribute/4, owner -- new_frame)) { + PyFunctionObject *func = (PyFunctionObject *)getattribute; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, func); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); + if (f == NULL) { + break; + } + PyObject *name = get_co_name(ctx, oparg >> 1); + f->locals[0] = owner; + f->locals[1] = sym_new_const(ctx, name); + f->func = func; new_frame = PyJitRef_WrapInvalid(f); } op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + callable = sym_new_not_null(ctx); + sym_set_recorded_value(callable, method->im_func); + self_or_null = sym_new_not_null(ctx); + sym_set_recorded_value(self_or_null, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } } op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - if (sym_get_func_version(callable) == func_version) { - REPLACE_OP(this_instr, _NOP, 0, 0); + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; } - else { - sym_set_func_version(ctx, callable, func_version); + // Guarded on this, so it can be promoted. + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); + } + + op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) { + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; } + // Guarded on this, so it can be promoted. + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); } op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] -- callable, null, unused[oparg])) { @@ -986,6 +1169,42 @@ dummy_func(void) { ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; } + else { + // Guarding on the bound method, safe to promote. + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } + sym_set_type(callable, &PyMethod_Type); + } + + op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable, null, unused[oparg], unused -- callable, null, unused[oparg], unused)) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + assert(PyMethod_Check(method)); + ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); + uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; + } + else { + // Guarding on the bound method, safe to promote. + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } sym_set_type(callable, &PyMethod_Type); } @@ -1024,6 +1243,30 @@ dummy_func(void) { } } + op(_EXPAND_METHOD, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + } + + op(_EXPAND_METHOD_KW, (callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) { + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + } + op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { (void)args; callable = sym_new_not_null(ctx); @@ -1042,10 +1285,39 @@ dummy_func(void) { ex_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, func_st, NULL, 0)); } - op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { - (void)type_version; - (void)args; - callable = sym_new_not_null(ctx); + op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + PyObject *probable_callable = sym_get_probable_value(callable); + assert(probable_callable != NULL); + PyObject *const_callable = sym_get_const(ctx, callable); + bool is_probable = const_callable == NULL && probable_callable != NULL; + PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable; + if (sym_is_null(self_or_null) && + callable_o != NULL && + PyType_Check(callable_o) && + ((PyTypeObject *)callable_o)->tp_version_tag == type_version) { + // Probable types need the guard. + if (!is_probable) { + ADD_OP(_NOP, 0, 0); + } + else { + // Promote the probable type, as we have + // guarded on it. + sym_set_const(callable, callable_o); + } + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; + PyObject *init = cls->_spec_cache.init; + assert(init != NULL); + assert(PyFunction_Check(init)); + callable = sym_new_const(ctx, init); + PyType_Watch(TYPE_WATCHER_ID, callable_o); + _Py_BloomFilter_Add(dependencies, callable_o);; + } + else { + callable = sym_new_not_null(ctx); + } + } + + op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { self_or_null = sym_new_not_null(ctx); } @@ -1124,9 +1396,46 @@ dummy_func(void) { } op(_GET_ITER, (iterable -- iter, index_or_null)) { - if (sym_matches_type(iterable, &PyTuple_Type) || sym_matches_type(iterable, &PyList_Type)) { + bool is_coro = false; + bool is_trad = false; // has `tp_iter` slot + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (oparg == GET_ITER_YIELD_FROM_NO_CHECK) { + if (tp == &PyCoro_Type) { + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_PUSH_NULL, 0, 0); + is_coro = true; + } + } + if (tp != NULL && + tp->_tp_iteritem == NULL && + tp->tp_iter != NULL && + tp->tp_iter != PyObject_SelfIter && + tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE + ) { + assert(tp != &PyCoro_Type); + is_trad = true; + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_GET_ITER_TRAD, 0, 0); + } + if (is_coro) { + assert(!is_trad); iter = iterable; - index_or_null = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); + } + else if (is_trad) { + iter = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); } else { iter = sym_new_not_null(ctx); @@ -1134,6 +1443,42 @@ dummy_func(void) { } } + op(_GUARD_ITERATOR, (iterable -- iterable)) { + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->tp_iter == PyObject_SelfIter) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + } + + op(_GUARD_ITER_VIRTUAL, (iterable -- iterable)) { + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->_tp_iteritem != NULL) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + } + op(_FOR_ITER_GEN_FRAME, (iter, unused -- iter, unused, gen_frame)) { _Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, iter, NULL, 0); if (new_frame == NULL) { @@ -1169,6 +1514,27 @@ dummy_func(void) { (void)framesize; } + op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } + } + + op(_CHECK_IS_NOT_PY_CALLABLE_EX, (func_st, unused, unused, unused -- func_st, unused, unused, unused)) { + PyTypeObject *type = sym_get_type(func_st); + if (type && type != &PyFunction_Type) { + ADD_OP(_NOP, 0, 0); + } + } + + op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) { + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } + } + op(_PUSH_FRAME, (new_frame -- )) { SYNC_SP(); if (!CURRENT_FRAME_IS_INIT_SHIM()) { @@ -1215,11 +1581,11 @@ dummy_func(void) { } op(_ITER_CHECK_RANGE, (iter, null_or_index -- iter, null_or_index)) { - if (sym_matches_type(iter, &PyRange_Type)) { + if (sym_matches_type(iter, &PyRangeIter_Type)) { ADD_OP(_NOP, 0, 0); } else { - sym_set_type(iter, &PyRange_Type); + sym_set_type(iter, &PyRangeIter_Type); } } @@ -1227,13 +1593,13 @@ dummy_func(void) { next = sym_new_type(ctx, &PyLong_Type); } - op(_CALL_TYPE_1, (unused, unused, arg -- res, a)) { + op(_CALL_TYPE_1, (callable, null, arg -- res, a)) { PyObject* type = (PyObject *)sym_get_type(arg); if (type) { res = sym_new_const(ctx, type); ADD_OP(_SWAP, 3, 0); - ADD_OP(_POP_TOP, 0, 0); - ADD_OP(_POP_TOP, 0, 0); + optimize_pop_top(ctx, this_instr, callable); + optimize_pop_top(ctx, this_instr, null); ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type); ADD_OP(_SWAP, 2, 0); } @@ -1256,7 +1622,7 @@ dummy_func(void) { a = arg; } - op(_CALL_ISINSTANCE, (unused, unused, instance, cls -- res)) { + op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { // the result is always a bool, but sometimes we can // narrow it down to True or False res = sym_new_type(ctx, &PyBool_Type); @@ -1272,7 +1638,10 @@ dummy_func(void) { out = Py_True; } sym_set_const(res, out); - ADD_OP(_POP_CALL_TWO, 0, 0); + optimize_pop_top(ctx, this_instr, cls); + optimize_pop_top(ctx, this_instr, instance); + optimize_pop_top(ctx, this_instr, null); + optimize_pop_top(ctx, this_instr, callable); ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); } } @@ -1284,6 +1653,19 @@ dummy_func(void) { none = sym_new_const(ctx, Py_None); } + op(_GUARD_CALLABLE_BUILTIN_CLASS, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyType_Type)) { + PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall != NULL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyType_Type); + } + } + op(_GUARD_CALLABLE_BUILTIN_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyCFunction_Type) && @@ -1325,6 +1707,10 @@ dummy_func(void) { } } + op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + callable = sym_new_not_null(ctx); + } + op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, c, s)) { res = sym_new_not_null(ctx); c = callable; @@ -1344,6 +1730,10 @@ dummy_func(void) { callable = sym_new_not_null(ctx); } + op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { + callable = sym_new_not_null(ctx); + } + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && @@ -1454,26 +1844,26 @@ dummy_func(void) { } } - op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) && sym_is_not_null(self_or_null)) { PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; PyCFunction cfunc = method->d_method->ml_meth; - ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg + 1, (uintptr_t)cfunc); + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg, (uintptr_t)cfunc); } - res = sym_new_not_null(ctx); + callable = sym_new_not_null(ctx); } - op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) { + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) && sym_is_not_null(self_or_null)) { PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; PyCFunction cfunc = method->d_method->ml_meth; - ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg + 1, (uintptr_t)cfunc); + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg, (uintptr_t)cfunc); } - res = sym_new_not_null(ctx); + callable = sym_new_not_null(ctx); } op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { @@ -1614,8 +2004,30 @@ dummy_func(void) { } op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) { - method_and_self[0] = sym_new_not_null(ctx); - method_and_self[1] = sym_new_unknown(ctx); + bool optimized = false; + PyTypeObject *type = sym_get_probable_type(method_and_self[1]); + if (type != NULL) { + PyObject *name = _Py_SpecialMethods[oparg].name; + PyObject *descr = _PyType_Lookup(type, name); + if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) { + ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag); + bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)descr); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, method_and_self[0]); + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } + method_and_self[0] = sym_new_const(ctx, descr); + optimized = true; + } + } + if (!optimized) { + method_and_self[0] = sym_new_not_null(ctx); + method_and_self[1] = sym_new_unknown(ctx); + } } op(_JUMP_TO_TOP, (--)) { @@ -2125,6 +2537,11 @@ dummy_func(void) { sym_set_recorded_value(nos, (PyObject *)this_instr->operand0); } + op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) { + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(nos, tp); + } + op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) { sym_set_recorded_value(value, (PyObject *)this_instr->operand0); } @@ -2133,6 +2550,14 @@ dummy_func(void) { sym_set_recorded_value(func, (PyObject *)this_instr->operand0); } + op(_RECORD_CALLABLE_KW, (func, self, args[oparg], kwnames -- func, self, args[oparg], kwnames)) { + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); + } + + op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) { + sym_set_recorded_value(callable, (PyObject *)this_instr->operand0); + } + op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) { PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0; assert(func == NULL || PyFunction_Check(func)); @@ -2150,7 +2575,8 @@ dummy_func(void) { if (co->co_version == version) { _Py_BloomFilter_Add(dependencies, co); // Functions derive their version from code objects. - if (sym_get_func_version(ctx->frame->callable) == version) { + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version == version) { REPLACE_OP(this_instr, _NOP, 0, 0); } } @@ -2183,7 +2609,8 @@ dummy_func(void) { op(_GUARD_IP__PUSH_FRAME, (ip/4 --)) { (void)ip; stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); - if (sym_get_func_version(ctx->frame->callable) != 0 && + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version != 0 && // We can remove this guard for simple function call targets. (((PyCodeObject *)ctx->frame->func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 34b535538a5..c3c889e9de9 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -165,13 +165,6 @@ break; } - case _POP_TWO: { - CHECK_STACK_BOUNDS(-2); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - case _POP_TOP_OPARG: { JitOptRef *args; args = &stack_pointer[-oparg]; @@ -645,8 +638,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -715,8 +710,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -785,8 +782,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -1114,6 +1113,54 @@ break; } + case _BINARY_OP_TRUEDIV_FLOAT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _BINARY_OP_ADD_UNICODE: { JitOptRef right; JitOptRef left; @@ -1163,7 +1210,55 @@ break; } + case _GUARD_BINARY_OP_EXTEND_LHS: { + JitOptRef left; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->lhs_type != NULL); + if (sym_matches_type(left, d->lhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(left, d->lhs_type); + break; + } + + case _GUARD_BINARY_OP_EXTEND_RHS: { + JitOptRef right; + right = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + assert(d != NULL && d->guard == NULL && d->rhs_type != NULL); + if (sym_matches_type(right, d->rhs_type)) { + ADD_OP(_NOP, 0, 0); + } + sym_set_type(right, d->rhs_type); + break; + } + case _GUARD_BINARY_OP_EXTEND: { + JitOptRef right; + JitOptRef left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + PyObject *descr = (PyObject *)this_instr->operand0; + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->guard == NULL) { + assert(d->lhs_type != NULL && d->rhs_type != NULL); + bool lhs_known = sym_matches_type(left, d->lhs_type); + bool rhs_known = sym_matches_type(right, d->rhs_type); + if (lhs_known && rhs_known) { + ADD_OP(_NOP, 0, 0); + } + else if (lhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_RHS, 0, (uintptr_t)d); + sym_set_type(right, d->rhs_type); + } + else if (rhs_known) { + ADD_OP(_GUARD_BINARY_OP_EXTEND_LHS, 0, (uintptr_t)d); + sym_set_type(left, d->lhs_type); + } + } break; } @@ -1510,8 +1605,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2071,7 +2168,7 @@ case _LOAD_GLOBAL_MODULE: { JitOptRef res; uint16_t version = (uint16_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)index; PyObject *cnst = NULL; if (ctx->frame->func != NULL) { @@ -2118,7 +2215,7 @@ case _LOAD_GLOBAL_BUILTINS: { JitOptRef res; uint16_t version = (uint16_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)version; (void)index; PyObject *cnst = NULL; @@ -2428,19 +2525,54 @@ assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - PyTypeObject *type = _PyType_LookupByVersion(type_version); - if (type) { - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } break; } case _GUARD_TYPE_VERSION_LOCKED: { + JitOptRef owner; + owner = stack_pointer[-1]; + uint32_t type_version = (uint32_t)this_instr->operand0; + assert(type_version); + if (sym_matches_type_version(owner, type_version)) { + ADD_OP(_NOP, 0, 0); + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } + } + break; + } + + case _GUARD_TYPE: { break; } @@ -2471,7 +2603,7 @@ JitOptRef o; owner = stack_pointer[-1]; uint32_t dict_version = (uint32_t)this_instr->operand0; - uint16_t index = (uint16_t)this_instr->operand0; + uint16_t index = (uint16_t)this_instr->operand1; (void)dict_version; (void)index; attr = PyJitRef_NULL; @@ -2555,6 +2687,10 @@ } else { sym_set_const(owner, type); + if ((((PyTypeObject *)type)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, type); + _Py_BloomFilter_Add(dependencies, type); + } } } break; @@ -2578,19 +2714,55 @@ JitOptRef owner; JitOptRef new_frame; owner = stack_pointer[-1]; - PyObject *fget = (PyObject *)this_instr->operand0; - PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *fget = (PyObject *)this_instr->operand1; + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; new_frame = PyJitRef_WrapInvalid(f); stack_pointer[-1] = new_frame; break; } - /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */ + case _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME: { + JitOptRef owner; + JitOptRef new_frame; + owner = stack_pointer[-1]; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *getattribute = (PyObject *)this_instr->operand1; + PyFunctionObject *func = (PyFunctionObject *)getattribute; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, func); + PyCodeObject *co = (PyCodeObject *)func->func_code; + _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); + if (f == NULL) { + break; + } + PyObject *name = get_co_name(ctx, oparg >> 1); + f->locals[0] = owner; + f->locals[1] = sym_new_const(ctx, name); + f->func = func; + new_frame = PyJitRef_WrapInvalid(f); + stack_pointer[-1] = new_frame; + break; + } case _GUARD_DORV_NO_DICT: { break; @@ -2690,8 +2862,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _POP_TWO_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _POP_TOP + _POP_TOP + _LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_POP_TOP, 0, 0); + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); } } CHECK_STACK_BOUNDS(-1); @@ -2761,8 +2935,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2834,8 +3010,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2896,8 +3074,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -2976,8 +3156,10 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -3083,8 +3265,10 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -3116,6 +3300,53 @@ b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenDict_Type)) { + if ( + sym_is_safe_const(ctx, left) && + sym_is_safe_const(ctx, right) + ) { + JitOptRef left_sym = left; + JitOptRef right_sym = right; + _PyStackRef left = sym_get_const_as_stackref(ctx, left_sym); + _PyStackRef right = sym_get_const_as_stackref(ctx, right_sym); + _PyStackRef b_stackref; + _PyStackRef l_stackref; + _PyStackRef r_stackref; + /* Start of uop copied from bytecodes for constant evaluation */ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyAnyDict_CheckExact(right_o)); + STAT_INC(CONTAINS_OP, hit); + int res = PyDict_Contains(right_o, left_o); + if (res < 0) { + JUMP_TO_LABEL(error); + } + b_stackref = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; + l_stackref = left; + r_stackref = right; + /* End of uop copied from bytecodes for constant evaluation */ + (void)l_stackref; + (void)r_stackref; + b = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(b_stackref)); + if (sym_is_const(ctx, b)) { + PyObject *result = sym_get_const(ctx, b); + if (_Py_IsImmortal(result)) { + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); + } + } + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = b; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = b; stack_pointer[-1] = l; @@ -3167,8 +3398,16 @@ /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ case _IS_NONE: { + JitOptRef value; JitOptRef b; - b = sym_new_not_null(ctx); + value = stack_pointer[-1]; + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } stack_pointer[-1] = b; break; } @@ -3267,9 +3506,46 @@ JitOptRef iter; JitOptRef index_or_null; iterable = stack_pointer[-1]; - if (sym_matches_type(iterable, &PyTuple_Type) || sym_matches_type(iterable, &PyList_Type)) { + bool is_coro = false; + bool is_trad = false; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (oparg == GET_ITER_YIELD_FROM_NO_CHECK) { + if (tp == &PyCoro_Type) { + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_PUSH_NULL, 0, 0); + is_coro = true; + } + } + if (tp != NULL && + tp->_tp_iteritem == NULL && + tp->tp_iter != NULL && + tp->tp_iter != PyObject_SelfIter && + tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE + ) { + assert(tp != &PyCoro_Type); + is_trad = true; + if (!definite) { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + ADD_OP(_GET_ITER_TRAD, 0, 0); + } + if (is_coro) { + assert(!is_trad); iter = iterable; - index_or_null = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); + } + else if (is_trad) { + iter = sym_new_not_null(ctx); + index_or_null = sym_new_null(ctx); } else { iter = sym_new_not_null(ctx); @@ -3283,6 +3559,71 @@ break; } + case _GUARD_ITERATOR: { + JitOptRef iterable; + iterable = stack_pointer[-1]; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->tp_iter == PyObject_SelfIter) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + break; + } + + case _GUARD_ITER_VIRTUAL: { + JitOptRef iterable; + iterable = stack_pointer[-1]; + bool definite = true; + PyTypeObject *tp = sym_get_type(iterable); + if (tp == NULL) { + definite = false; + tp = sym_get_probable_type(iterable); + } + if (tp != NULL && tp->_tp_iteritem != NULL) { + if (definite) { + ADD_OP(_NOP, 0, 0); + } + else { + ADD_OP(_GUARD_TYPE, 0, (uintptr_t)tp); + sym_set_type(iterable, tp); + } + } + break; + } + + case _PUSH_TAGGED_ZERO: { + JitOptRef zero; + zero = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[0] = zero; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _GET_ITER_TRAD: { + JitOptRef iter; + JitOptRef index_or_null; + iter = sym_new_not_null(ctx); + index_or_null = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-1] = iter; + stack_pointer[0] = index_or_null; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + /* _FOR_ITER is not a viable micro-op for tier 2 */ case _FOR_ITER_TIER_TWO: { @@ -3295,6 +3636,22 @@ break; } + case _GUARD_NOS_ITER_VIRTUAL: { + break; + } + + /* _FOR_ITER_VIRTUAL is not a viable micro-op for tier 2 */ + + case _FOR_ITER_VIRTUAL_TIER_TWO: { + JitOptRef next; + next = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[0] = next; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ case _ITER_CHECK_LIST: { @@ -3356,11 +3713,11 @@ case _ITER_CHECK_RANGE: { JitOptRef iter; iter = stack_pointer[-2]; - if (sym_matches_type(iter, &PyRange_Type)) { + if (sym_matches_type(iter, &PyRangeIter_Type)) { ADD_OP(_NOP, 0, 0); } else { - sym_set_type(iter, &PyRange_Type); + sym_set_type(iter, &PyRangeIter_Type); } break; } @@ -3416,8 +3773,30 @@ case _LOAD_SPECIAL: { JitOptRef *method_and_self; method_and_self = &stack_pointer[-2]; - method_and_self[0] = sym_new_not_null(ctx); - method_and_self[1] = sym_new_unknown(ctx); + bool optimized = false; + PyTypeObject *type = sym_get_probable_type(method_and_self[1]); + if (type != NULL) { + PyObject *name = _Py_SpecialMethods[oparg].name; + PyObject *descr = _PyType_Lookup(type, name); + if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) { + ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag); + bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE); + ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE, + 0, (uintptr_t)descr); + ADD_OP(_SWAP, 3, 0); + optimize_pop_top(ctx, this_instr, method_and_self[0]); + if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); + _Py_BloomFilter_Add(dependencies, type); + } + method_and_self[0] = sym_new_const(ctx, descr); + optimized = true; + } + } + if (!optimized) { + method_and_self[0] = sym_new_not_null(ctx); + method_and_self[1] = sym_new_unknown(ctx); + } break; } @@ -3579,12 +3958,14 @@ JitOptRef callable; callable = stack_pointer[-2 - oparg]; uint32_t func_version = (uint32_t)this_instr->operand0; - if (sym_get_func_version(callable) == func_version) { - REPLACE_OP(this_instr, _NOP, 0, 0); - } - else { - sym_set_func_version(ctx, callable, func_version); + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; } + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); break; } @@ -3602,15 +3983,48 @@ ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; } + else { + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } sym_set_type(callable, &PyMethod_Type); break; } case _EXPAND_METHOD: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + stack_pointer[-2 - oparg] = callable; + stack_pointer[-1 - oparg] = self_or_null; break; } case _CHECK_IS_NOT_PY_CALLABLE: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -3639,8 +4053,18 @@ JitOptRef callable; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + callable = sym_new_not_null(ctx); + sym_set_recorded_value(callable, method->im_func); + self_or_null = sym_new_not_null(ctx); + sym_set_recorded_value(self_or_null, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } stack_pointer[-2 - oparg] = callable; stack_pointer[-1 - oparg] = self_or_null; break; @@ -3781,15 +4205,19 @@ case _CALL_TYPE_1: { JitOptRef arg; + JitOptRef null; + JitOptRef callable; JitOptRef res; JitOptRef a; arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; PyObject* type = (PyObject *)sym_get_type(arg); if (type) { res = sym_new_const(ctx, type); ADD_OP(_SWAP, 3, 0); - ADD_OP(_POP_TOP, 0, 0); - ADD_OP(_POP_TOP, 0, 0); + optimize_pop_top(ctx, this_instr, callable); + optimize_pop_top(ctx, this_instr, null); ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type); ADD_OP(_SWAP, 2, 0); } @@ -3869,19 +4297,47 @@ break; } - case _CHECK_AND_ALLOCATE_OBJECT: { - JitOptRef *args; + case _CHECK_OBJECT: { JitOptRef self_or_null; JitOptRef callable; - args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; uint32_t type_version = (uint32_t)this_instr->operand0; - (void)type_version; - (void)args; - callable = sym_new_not_null(ctx); - self_or_null = sym_new_not_null(ctx); + PyObject *probable_callable = sym_get_probable_value(callable); + assert(probable_callable != NULL); + PyObject *const_callable = sym_get_const(ctx, callable); + bool is_probable = const_callable == NULL && probable_callable != NULL; + PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable; + if (sym_is_null(self_or_null) && + callable_o != NULL && + PyType_Check(callable_o) && + ((PyTypeObject *)callable_o)->tp_version_tag == type_version) { + if (!is_probable) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_const(callable, callable_o); + } + PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; + PyObject *init = cls->_spec_cache.init; + assert(init != NULL); + assert(PyFunction_Check(init)); + callable = sym_new_const(ctx, init); + stack_pointer[-2 - oparg] = callable; + PyType_Watch(TYPE_WATCHER_ID, callable_o); + _Py_BloomFilter_Add(dependencies, callable_o);; + } + else { + callable = sym_new_not_null(ctx); + } stack_pointer[-2 - oparg] = callable; + break; + } + + case _ALLOCATE_OBJECT: { + JitOptRef self_or_null; + self_or_null = stack_pointer[-1 - oparg]; + self_or_null = sym_new_not_null(ctx); stack_pointer[-1 - oparg] = self_or_null; break; } @@ -3920,13 +4376,27 @@ break; } + case _GUARD_CALLABLE_BUILTIN_CLASS: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && sym_matches_type(callable, &PyType_Type)) { + PyTypeObject *tp = (PyTypeObject *)callable_o; + if (tp->tp_vectorcall != NULL) { + ADD_OP(_NOP, 0, 0); + } + } + else { + sym_set_type(callable, &PyType_Type); + } + break; + } + case _CALL_BUILTIN_CLASS: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; break; } @@ -4022,12 +4492,10 @@ } case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; break; } @@ -4110,9 +4578,13 @@ case _CALL_ISINSTANCE: { JitOptRef cls; JitOptRef instance; + JitOptRef null; + JitOptRef callable; JitOptRef res; cls = stack_pointer[-1]; instance = stack_pointer[-2]; + null = stack_pointer[-3]; + callable = stack_pointer[-4]; res = sym_new_type(ctx, &PyBool_Type); PyTypeObject *inst_type = sym_get_type(instance); PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); @@ -4122,7 +4594,10 @@ out = Py_True; } sym_set_const(res, out); - ADD_OP(_POP_CALL_TWO, 0, 0); + optimize_pop_top(ctx, this_instr, cls); + optimize_pop_top(ctx, this_instr, instance); + optimize_pop_top(ctx, this_instr, null); + optimize_pop_top(ctx, this_instr, callable); ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out); } CHECK_STACK_BOUNDS(-3); @@ -4302,7 +4777,6 @@ case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { JitOptRef self_or_null; JitOptRef callable; - JitOptRef res; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); @@ -4310,23 +4784,14 @@ && sym_is_not_null(self_or_null)) { PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; PyCFunction cfunc = method->d_method->ml_meth; - ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg + 1, (uintptr_t)cfunc); + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg, (uintptr_t)cfunc); } - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; break; } case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-oparg); - stack_pointer[-1 - oparg] = res; - stack_pointer += -oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -4455,7 +4920,6 @@ case _CALL_METHOD_DESCRIPTOR_FAST: { JitOptRef self_or_null; JitOptRef callable; - JitOptRef res; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); @@ -4463,23 +4927,14 @@ && sym_is_not_null(self_or_null)) { PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; PyCFunction cfunc = method->d_method->ml_meth; - ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg + 1, (uintptr_t)cfunc); + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg, (uintptr_t)cfunc); } - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1 - oparg); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + callable = sym_new_not_null(ctx); + stack_pointer[-2 - oparg] = callable; break; } case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: { - JitOptRef res; - res = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-oparg); - stack_pointer[-1 - oparg] = res; - stack_pointer += -oparg; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } @@ -4504,18 +4959,72 @@ } case _CHECK_FUNCTION_VERSION_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *func = sym_get_probable_value(callable); + if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + sym_set_const(callable, func); + _Py_BloomFilter_Add(dependencies, func); break; } case _CHECK_METHOD_VERSION_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + uint32_t func_version = (uint32_t)this_instr->operand0; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + assert(PyMethod_Check(method)); + ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version); + uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func; + } + else { + PyObject *bound_method = sym_get_probable_value(callable); + if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) { + PyMethodObject *method = (PyMethodObject *)bound_method; + PyObject *func = method->im_func; + if (PyFunction_Check(func) && + ((PyFunctionObject *)func)->func_version == func_version) { + _Py_BloomFilter_Add(dependencies, func); + sym_set_const(callable, bound_method); + } + } + } + sym_set_type(callable, &PyMethod_Type); break; } case _EXPAND_METHOD_KW: { + JitOptRef self_or_null; + JitOptRef callable; + self_or_null = stack_pointer[-2 - oparg]; + callable = stack_pointer[-3 - oparg]; + if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) { + PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable); + callable = sym_new_const(ctx, method->im_func); + self_or_null = sym_new_const(ctx, method->im_self); + } + else { + callable = sym_new_not_null(ctx); + self_or_null = sym_new_not_null(ctx); + } + stack_pointer[-3 - oparg] = callable; + stack_pointer[-2 - oparg] = self_or_null; break; } case _CHECK_IS_NOT_PY_CALLABLE_KW: { + JitOptRef callable; + callable = stack_pointer[-3 - oparg]; + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -4552,6 +5061,12 @@ } case _CHECK_IS_NOT_PY_CALLABLE_EX: { + JitOptRef func_st; + func_st = stack_pointer[-4]; + PyTypeObject *type = sym_get_type(func_st); + if (type && type != &PyFunction_Type) { + ADD_OP(_NOP, 0, 0); + } break; } @@ -4700,8 +5215,10 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result - ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + ADD_OP(_SWAP, 3, 0); + ADD_OP(_SWAP, 2, 0); } } CHECK_STACK_BOUNDS(1); @@ -4716,7 +5233,47 @@ bool rhs_int = sym_matches_type(rhs, &PyLong_Type); bool lhs_float = sym_matches_type(lhs, &PyFloat_Type); bool rhs_float = sym_matches_type(rhs, &PyFloat_Type); - if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { + bool is_truediv = (oparg == NB_TRUE_DIVIDE + || oparg == NB_INPLACE_TRUE_DIVIDE); + bool is_remainder = (oparg == NB_REMAINDER + || oparg == NB_INPLACE_REMAINDER); + if (is_truediv || is_remainder) { + if (!sym_has_type(rhs) + && sym_get_probable_type(rhs) == &PyFloat_Type) { + ADD_OP(_GUARD_TOS_FLOAT, 0, 0); + sym_set_type(rhs, &PyFloat_Type); + rhs_float = true; + } + if (!sym_has_type(lhs) + && sym_get_probable_type(lhs) == &PyFloat_Type) { + ADD_OP(_GUARD_NOS_FLOAT, 0, 0); + sym_set_type(lhs, &PyFloat_Type); + lhs_float = true; + } + } + if (is_truediv && lhs_float && rhs_float) { + if (PyJitRef_IsUnique(lhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + l = sym_new_null(ctx); + r = rhs; + } + else if (PyJitRef_IsUnique(rhs)) { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + l = lhs; + r = sym_new_null(ctx); + } + else { + ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + l = lhs; + r = rhs; + } + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (is_truediv + && (lhs_int || lhs_float) && (rhs_int || rhs_float)) { + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); + } + else if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { res = sym_new_unknown(ctx); } else if (oparg == NB_POWER || oparg == NB_INPLACE_POWER) { @@ -4724,26 +5281,23 @@ res = sym_new_unknown(ctx); } else if (lhs_float) { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else if (!sym_is_const(ctx, rhs)) { res = sym_new_unknown(ctx); } else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } else { res = sym_new_type(ctx, &PyLong_Type); } } - else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { - res = sym_new_type(ctx, &PyFloat_Type); - } else if (lhs_int && rhs_int) { res = sym_new_type(ctx, &PyLong_Type); } else { - res = sym_new_type(ctx, &PyFloat_Type); + res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; @@ -4932,13 +5486,6 @@ break; } - case _POP_TOP_LOAD_CONST_INLINE: { - JitOptRef value; - value = sym_new_not_null(ctx); - stack_pointer[-1] = value; - break; - } - case _LOAD_CONST_INLINE_BORROW: { JitOptRef value; PyObject *ptr = (PyObject *)this_instr->operand0; @@ -4950,60 +5497,6 @@ break; } - case _POP_CALL: { - CHECK_STACK_BOUNDS(-2); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_ONE: { - CHECK_STACK_BOUNDS(-3); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_CALL_TWO: { - CHECK_STACK_BOUNDS(-4); - stack_pointer += -4; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _POP_TOP_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - value = sym_new_not_null(ctx); - stack_pointer[-1] = value; - break; - } - - case _POP_TWO_LOAD_CONST_INLINE_BORROW: { - JitOptRef value; - value = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-1); - stack_pointer[-2] = value; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - - case _INSERT_2_LOAD_CONST_INLINE_BORROW: { - JitOptRef res; - JitOptRef l; - JitOptRef r; - res = sym_new_not_null(ctx); - l = sym_new_not_null(ctx); - r = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(1); - stack_pointer[-2] = res; - stack_pointer[-1] = l; - stack_pointer[0] = r; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - break; - } - case _SHUFFLE_3_LOAD_CONST_INLINE_BORROW: { JitOptRef res; JitOptRef a; @@ -5063,7 +5556,8 @@ PyCodeObject *co = get_current_code_object(ctx); if (co->co_version == version) { _Py_BloomFilter_Add(dependencies, co); - if (sym_get_func_version(ctx->frame->callable) == version) { + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version == version) { REPLACE_OP(this_instr, _NOP, 0, 0); } } @@ -5104,7 +5598,8 @@ PyObject *ip = (PyObject *)this_instr->operand0; (void)ip; stack_pointer = sym_set_stack_depth((int)this_instr->operand1, stack_pointer); - if (sym_get_func_version(ctx->frame->callable) != 0 && + PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, ctx->frame->callable); + if (func != NULL && func->func_version != 0 && // We can remove this guard for simple function call targets. (((PyCodeObject *)ctx->frame->func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { @@ -5165,6 +5660,14 @@ break; } + case _RECORD_NOS_TYPE: { + JitOptRef nos; + nos = stack_pointer[-2]; + PyTypeObject *tp = (PyTypeObject *)this_instr->operand0; + sym_set_recorded_type(nos, tp); + break; + } + case _RECORD_NOS_GEN_FUNC: { JitOptRef nos; nos = stack_pointer[-2]; @@ -5197,7 +5700,17 @@ break; } + case _RECORD_CALLABLE_KW: { + JitOptRef func; + func = stack_pointer[-3 - oparg]; + sym_set_recorded_value(func, (PyObject *)this_instr->operand0); + break; + } + case _RECORD_BOUND_METHOD: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + sym_set_recorded_value(callable, (PyObject *)this_instr->operand0); break; } diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index 6230b894869..79f81482d24 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -35,12 +35,12 @@ NULL | | RECORDED_VALUE* | TYPE_VERSION | | | | | | | | <- Anything below this level has a known type. | KNOWN_CLASS--+ | | | -| | | | | | PREDICATE RECORDED_VALUE(known type) -| | | INT* | | | | -| | | | | | | | <- Anything below this level has a known truthiness. -| | | | FUNC_VERSION | | | -| TUPLE | | | TRUTHINESS | | -| | | | | | | | <- Anything below this level is a known constant. +| | | | | PREDICATE RECORDED_VALUE(known type) +| | | INT* | | | +| | | | | | | <- Anything below this level has a known truthiness. +| | | | | | | +| TUPLE | | TRUTHINESS | | +| | | | | | | <- Anything below this level is a known constant. | KNOWN_VALUE--+-------+----+------+ | | <- Anything below this level is unreachable. BOTTOM @@ -101,9 +101,6 @@ _PyUOpSymPrint(JitOptRef ref) case JIT_SYM_TYPE_VERSION_TAG: printf("", sym->version.version, (void *)sym); break; - case JIT_SYM_FUNC_VERSION_TAG: - printf("", sym->func_version.func_version); - break; case JIT_SYM_KNOWN_CLASS_TAG: printf("<%s at %p>", sym->cls.type->tp_name, (void *)sym); break; @@ -325,11 +322,6 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ) sym_set_bottom(ctx, sym); } return; - case JIT_SYM_FUNC_VERSION_TAG: - if (typ != &PyFunction_Type) { - sym_set_bottom(ctx, sym); - } - return; case JIT_SYM_KNOWN_VALUE_TAG: if (Py_TYPE(sym->value.value) != typ) { Py_CLEAR(sym->value.value); @@ -433,12 +425,6 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver return false; } return true; - case JIT_SYM_FUNC_VERSION_TAG: - if (version != PyFunction_Type.tp_version_tag) { - sym_set_bottom(ctx, sym); - return false; - } - return true; case JIT_SYM_BOTTOM_TAG: return false; case JIT_SYM_NON_NULL_TAG: @@ -486,87 +472,6 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver Py_UNREACHABLE(); } -bool -_Py_uop_sym_set_func_version(JitOptContext *ctx, JitOptRef ref, uint32_t version) -{ - JitOptSymbol *sym = PyJitRef_Unwrap(ref); - JitSymType tag = sym->tag; - switch(tag) { - case JIT_SYM_NULL_TAG: - sym_set_bottom(ctx, sym); - return false; - case JIT_SYM_KNOWN_CLASS_TAG: - if (sym->cls.type != &PyFunction_Type) { - sym_set_bottom(ctx, sym); - return false; - } - sym->tag = JIT_SYM_FUNC_VERSION_TAG; - sym->version.version = version; - return true; - case JIT_SYM_KNOWN_VALUE_TAG: - if (Py_TYPE(sym->value.value) != &PyFunction_Type || - ((PyFunctionObject *)sym->value.value)->func_version != version) { - Py_CLEAR(sym->value.value); - sym_set_bottom(ctx, sym); - return false; - } - return true; - case JIT_SYM_TYPE_VERSION_TAG: - if (sym->version.version != PyFunction_Type.tp_version_tag) { - sym_set_bottom(ctx, sym); - return false; - } - sym->tag = JIT_SYM_FUNC_VERSION_TAG; - sym->version.version = version; - return true; - case JIT_SYM_FUNC_VERSION_TAG: - if (sym->func_version.func_version != version) { - sym_set_bottom(ctx, sym); - return false; - } - return true; - case JIT_SYM_BOTTOM_TAG: - return false; - case JIT_SYM_NON_NULL_TAG: - case JIT_SYM_UNKNOWN_TAG: - sym->tag = JIT_SYM_FUNC_VERSION_TAG; - sym->func_version.func_version = version; - return true; - case JIT_SYM_RECORDED_GEN_FUNC_TAG: - case JIT_SYM_COMPACT_INT: - case JIT_SYM_TUPLE_TAG: - case JIT_SYM_PREDICATE_TAG: - case JIT_SYM_TRUTHINESS_TAG: - sym_set_bottom(ctx, sym); - return false; - case JIT_SYM_RECORDED_VALUE_TAG: { - PyObject *val = sym->recorded_value.value; - if (Py_TYPE(val) != &PyFunction_Type || - ((PyFunctionObject *)sym->recorded_value.value)->func_version != version) { - sym_set_bottom(ctx, sym); - return false; - } - // Promote to known value, as we have guarded/checked on it. - sym->tag = JIT_SYM_KNOWN_VALUE_TAG; - // New ownership. We need to NewRef here, as - // it's originally kept alive by the trace buffer. - sym->value.value = Py_NewRef(val); - return true; - } - case JIT_SYM_RECORDED_TYPE_TAG: - if (sym->recorded_type.type == &PyFunction_Type) { - sym->tag = JIT_SYM_FUNC_VERSION_TAG; - sym->func_version.func_version = version; - return true; - } - else { - sym_set_bottom(ctx, sym); - return false; - } - } - Py_UNREACHABLE(); -} - void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val) { @@ -612,14 +517,6 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val) } make_const(sym, const_val); return; - case JIT_SYM_FUNC_VERSION_TAG: - if (Py_TYPE(const_val) != &PyFunction_Type || - ((PyFunctionObject *)const_val)->func_version != sym->func_version.func_version) { - sym_set_bottom(ctx, sym); - return; - } - make_const(sym, const_val); - return; case JIT_SYM_BOTTOM_TAG: return; case JIT_SYM_RECORDED_VALUE_TAG: @@ -783,6 +680,7 @@ _Py_uop_sym_get_type(JitOptRef ref) case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: case JIT_SYM_RECORDED_TYPE_TAG: + case JIT_SYM_RECORDED_GEN_FUNC_TAG: return NULL; case JIT_SYM_RECORDED_VALUE_TAG: if (sym->recorded_value.known_type) { @@ -795,8 +693,6 @@ _Py_uop_sym_get_type(JitOptRef ref) return Py_TYPE(sym->value.value); case JIT_SYM_TYPE_VERSION_TAG: return _PyType_LookupByVersion(sym->version.version); - case JIT_SYM_FUNC_VERSION_TAG: - return &PyFunction_Type; case JIT_SYM_TUPLE_TAG: return &PyTuple_Type; case JIT_SYM_PREDICATE_TAG: @@ -804,8 +700,6 @@ _Py_uop_sym_get_type(JitOptRef ref) return &PyBool_Type; case JIT_SYM_COMPACT_INT: return &PyLong_Type; - case JIT_SYM_RECORDED_GEN_FUNC_TAG: - return &PyGen_Type; } Py_UNREACHABLE(); } @@ -821,7 +715,6 @@ _Py_uop_sym_get_probable_type(JitOptRef ref) case JIT_SYM_NON_NULL_TAG: case JIT_SYM_UNKNOWN_TAG: case JIT_SYM_TYPE_VERSION_TAG: - case JIT_SYM_FUNC_VERSION_TAG: case JIT_SYM_TUPLE_TAG: case JIT_SYM_PREDICATE_TAG: case JIT_SYM_TRUTHINESS_TAG: @@ -830,7 +723,7 @@ _Py_uop_sym_get_probable_type(JitOptRef ref) case JIT_SYM_KNOWN_VALUE_TAG: return _Py_uop_sym_get_type(ref); case JIT_SYM_RECORDED_GEN_FUNC_TAG: - return NULL; + return &PyGen_Type; case JIT_SYM_RECORDED_VALUE_TAG: return Py_TYPE(sym->recorded_value.value); case JIT_SYM_RECORDED_TYPE_TAG: @@ -854,8 +747,6 @@ _Py_uop_sym_get_type_version(JitOptRef ref) return 0; case JIT_SYM_TYPE_VERSION_TAG: return sym->version.version; - case JIT_SYM_FUNC_VERSION_TAG: - return PyFunction_Type.tp_version_tag; case JIT_SYM_KNOWN_CLASS_TAG: return sym->cls.version; case JIT_SYM_KNOWN_VALUE_TAG: @@ -873,37 +764,6 @@ _Py_uop_sym_get_type_version(JitOptRef ref) Py_UNREACHABLE(); } -uint32_t -_Py_uop_sym_get_func_version(JitOptRef ref) -{ - JitOptSymbol *sym = PyJitRef_Unwrap(ref); - JitSymType tag = sym->tag; - switch(tag) { - case JIT_SYM_NULL_TAG: - case JIT_SYM_BOTTOM_TAG: - case JIT_SYM_NON_NULL_TAG: - case JIT_SYM_UNKNOWN_TAG: - case JIT_SYM_RECORDED_VALUE_TAG: - case JIT_SYM_RECORDED_TYPE_TAG: - case JIT_SYM_TYPE_VERSION_TAG: - case JIT_SYM_KNOWN_CLASS_TAG: - case JIT_SYM_TUPLE_TAG: - case JIT_SYM_PREDICATE_TAG: - case JIT_SYM_TRUTHINESS_TAG: - case JIT_SYM_COMPACT_INT: - case JIT_SYM_RECORDED_GEN_FUNC_TAG: - return 0; - case JIT_SYM_FUNC_VERSION_TAG: - return sym->func_version.func_version; - case JIT_SYM_KNOWN_VALUE_TAG: - if (Py_TYPE(sym->value.value) == &PyFunction_Type) { - return ((PyFunctionObject *)sym->value.value)->func_version; - } - return 0; - } - Py_UNREACHABLE(); -} - bool _Py_uop_sym_has_type(JitOptRef sym) @@ -936,7 +796,6 @@ _Py_uop_sym_get_probable_value(JitOptRef ref) case JIT_SYM_UNKNOWN_TAG: case JIT_SYM_RECORDED_TYPE_TAG: case JIT_SYM_TYPE_VERSION_TAG: - case JIT_SYM_FUNC_VERSION_TAG: case JIT_SYM_TUPLE_TAG: case JIT_SYM_PREDICATE_TAG: case JIT_SYM_TRUTHINESS_TAG: @@ -1006,8 +865,6 @@ _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) return -1; case JIT_SYM_KNOWN_VALUE_TAG: break; - case JIT_SYM_FUNC_VERSION_TAG: - return 1; case JIT_SYM_TUPLE_TAG: return sym->tuple.length != 0; case JIT_SYM_TRUTHINESS_TAG: @@ -1156,7 +1013,6 @@ _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef ref) sym_set_bottom(ctx, sym); } return; - case JIT_SYM_FUNC_VERSION_TAG: case JIT_SYM_TUPLE_TAG: case JIT_SYM_PREDICATE_TAG: case JIT_SYM_TRUTHINESS_TAG: @@ -1344,7 +1200,6 @@ _Py_uop_sym_set_recorded_value(JitOptContext *ctx, JitOptRef ref, PyObject *valu case JIT_SYM_PREDICATE_TAG: case JIT_SYM_TRUTHINESS_TAG: case JIT_SYM_COMPACT_INT: - case JIT_SYM_FUNC_VERSION_TAG: return; } Py_UNREACHABLE(); @@ -1368,9 +1223,6 @@ _Py_uop_sym_set_recorded_gen_func(JitOptContext *ctx, JitOptRef ref, PyFunctionO case JIT_SYM_PREDICATE_TAG: case JIT_SYM_TRUTHINESS_TAG: case JIT_SYM_COMPACT_INT: - case JIT_SYM_FUNC_VERSION_TAG: - sym_set_bottom(ctx, sym); - return; case JIT_SYM_BOTTOM_TAG: return; case JIT_SYM_NON_NULL_TAG: @@ -1465,7 +1317,6 @@ _Py_uop_sym_set_recorded_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *t case JIT_SYM_TRUTHINESS_TAG: case JIT_SYM_COMPACT_INT: case JIT_SYM_RECORDED_GEN_FUNC_TAG: - case JIT_SYM_FUNC_VERSION_TAG: return; } Py_UNREACHABLE(); @@ -2129,15 +1980,6 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "43 is not an int"); TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref_int) == val_43, "43 isn't 43"); - // Test func version's important transitions. - JitOptRef func_version = _Py_uop_sym_new_not_null(ctx); - TEST_PREDICATE(_Py_uop_sym_get_func_version(func_version) == 0, "func version should be unset"); - _Py_uop_sym_set_func_version(ctx, func_version, 172); - TEST_PREDICATE(_Py_uop_sym_get_func_version(func_version) == 172, "func version should be set"); - func_version = _Py_uop_sym_new_type(ctx, &PyFunction_Type); - _Py_uop_sym_set_func_version(ctx, func_version, 192); - TEST_PREDICATE(_Py_uop_sym_get_func_version(func_version) == 192, "func version should be set"); - // Test recorded values /* Test that recorded values aren't treated as known values*/ @@ -2211,7 +2053,8 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) /* Test that recorded type aren't treated as known values*/ JitOptRef rg1 = _Py_uop_sym_new_unknown(ctx); _Py_uop_sym_set_recorded_gen_func(ctx, rg1, func); - TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator"); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg1) == &PyGen_Type, "recorded gen func not treated as generator"); TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg1) == NULL, "recorded gen func is treated as known value"); /* Test that setting type narrows correctly */ @@ -2219,13 +2062,15 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) JitOptRef rg2 = _Py_uop_sym_new_unknown(ctx); _Py_uop_sym_set_recorded_gen_func(ctx, rg2, func); _Py_uop_sym_set_type(ctx, rg2, &PyGen_Type); - TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator"); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg2, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg2) == &PyGen_Type, "recorded gen func not treated as generator"); TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg2) == NULL, "known type is treated as known value"); JitOptRef rg3 = _Py_uop_sym_new_unknown(ctx); _Py_uop_sym_set_recorded_gen_func(ctx, rg3, func); _Py_uop_sym_set_type_version(ctx, rg3, PyGen_Type.tp_version_tag); - TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator"); + TEST_PREDICATE(!_Py_uop_sym_matches_type(rg3, &PyGen_Type), "recorded gen func treated as generator"); + TEST_PREDICATE(_Py_uop_sym_get_probable_type(rg3) == &PyGen_Type, "recorded gen func not treated as generator"); TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg3) == NULL, "recorded value with type is treated as known"); /* Test contradictions */ diff --git a/Python/parking_lot.c b/Python/parking_lot.c index 99c1ad848be..8823d77719c 100644 --- a/Python/parking_lot.c +++ b/Python/parking_lot.c @@ -61,7 +61,9 @@ _PySemaphore_Init(_PySemaphore *sema) NULL // unnamed ); if (!sema->platform_sem) { - Py_FatalError("parking_lot: CreateSemaphore failed"); + _Py_FatalErrorFormat(__func__, + "parking_lot: CreateSemaphore failed (error: %u)", + GetLastError()); } #elif defined(_Py_USE_SEMAPHORES) if (sem_init(&sema->platform_sem, /*pshared=*/0, /*value=*/0) < 0) { @@ -141,8 +143,8 @@ _PySemaphore_Wait(_PySemaphore *sema, PyTime_t timeout) } else { _Py_FatalErrorFormat(__func__, - "unexpected error from semaphore: %u (error: %u)", - wait, GetLastError()); + "unexpected error from semaphore: %u (error: %u, handle: %p)", + wait, GetLastError(), sema->platform_sem); } #elif defined(_Py_USE_SEMAPHORES) int err; @@ -230,7 +232,9 @@ _PySemaphore_Wakeup(_PySemaphore *sema) { #if defined(MS_WINDOWS) if (!ReleaseSemaphore(sema->platform_sem, 1, NULL)) { - Py_FatalError("parking_lot: ReleaseSemaphore failed"); + _Py_FatalErrorFormat(__func__, + "parking_lot: ReleaseSemaphore failed (error: %u, handle: %p)", + GetLastError(), sema->platform_sem); } #elif defined(_Py_USE_SEMAPHORES) int err = sem_post(&sema->platform_sem); diff --git a/Python/preconfig.c b/Python/preconfig.c index 0fdc0a87317..2c8c18284c1 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -928,7 +928,7 @@ _PyPreConfig_Write(const PyPreConfig *src_config) return status; } - if (_PyRuntime.core_initialized) { + if (_Py_IsCoreInitialized()) { /* bpo-34008: Calling this functions after Py_Initialize() ignores the new configuration. */ return _PyStatus_OK(); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8be9e6d7373..0a88e32bb6b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -37,9 +37,6 @@ #include "pycore_uniqueid.h" // _PyObject_FinalizeUniqueIdPool() #include "pycore_warnings.h" // _PyWarnings_InitState() #include "pycore_weakref.h" // _PyWeakref_GET_REF() -#ifdef _Py_JIT -#include "pycore_jit.h" // _PyJIT_Fini() -#endif #if defined(PYMALLOC_USE_HUGEPAGES) && defined(MS_WINDOWS) #include @@ -170,13 +167,13 @@ int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \ int _Py_IsCoreInitialized(void) { - return _PyRuntime.core_initialized; + return _PyRuntimeState_GetCoreInitialized(&_PyRuntime); } int Py_IsInitialized(void) { - return _PyRuntime.initialized; + return _PyRuntimeState_GetInitialized(&_PyRuntime); } @@ -530,7 +527,7 @@ static PyStatus pycore_init_runtime(_PyRuntimeState *runtime, const PyConfig *config) { - if (runtime->initialized) { + if (_PyRuntimeState_GetInitialized(runtime)) { return _PyStatus_ERR("main interpreter already initialized"); } @@ -1032,7 +1029,7 @@ pyinit_config(_PyRuntimeState *runtime, } /* Only when we get here is the runtime core fully initialized */ - runtime->core_initialized = 1; + _PyRuntimeState_SetCoreInitialized(runtime, 1); return _PyStatus_OK(); } @@ -1359,7 +1356,7 @@ init_interp_main(PyThreadState *tstate) * or pure Python code in the standard library won't work. */ if (is_main_interp) { - interp->runtime->initialized = 1; + _PyRuntimeState_SetInitialized(interp->runtime, 1); } return _PyStatus_OK(); } @@ -1471,8 +1468,6 @@ init_interp_main(PyThreadState *tstate) Py_XDECREF(warnings_module); } Py_XDECREF(warnoptions); - - interp->runtime->initialized = 1; } if (config->site_import) { @@ -1568,6 +1563,10 @@ init_interp_main(PyThreadState *tstate) assert(!_PyErr_Occurred(tstate)); + if (is_main_interp) { + _PyRuntimeState_SetInitialized(interp->runtime, 1); + } + return _PyStatus_OK(); } @@ -1587,11 +1586,11 @@ static PyStatus pyinit_main(PyThreadState *tstate) { PyInterpreterState *interp = tstate->interp; - if (!interp->runtime->core_initialized) { + if (!_PyRuntimeState_GetCoreInitialized(interp->runtime)) { return _PyStatus_ERR("runtime core not initialized"); } - if (interp->runtime->initialized) { + if (_PyRuntimeState_GetInitialized(interp->runtime)) { return pyinit_main_reconfigure(tstate); } @@ -1639,19 +1638,12 @@ Py_InitializeFromConfig(const PyConfig *config) void Py_InitializeEx(int install_sigs) { - PyStatus status; - - status = _PyRuntime_Initialize(); - if (_PyStatus_EXCEPTION(status)) { - Py_ExitStatusException(status); - } - _PyRuntimeState *runtime = &_PyRuntime; - - if (runtime->initialized) { + if (Py_IsInitialized()) { /* bpo-33932: Calling Py_Initialize() twice does nothing. */ return; } + PyStatus status; PyConfig config; _PyConfig_InitCompatConfig(&config); @@ -2352,7 +2344,7 @@ _Py_Finalize(_PyRuntimeState *runtime) int status = 0; /* Bail out early if already finalized (or never initialized). */ - if (!runtime->initialized) { + if (!_PyRuntimeState_GetInitialized(runtime)) { return status; } @@ -2387,8 +2379,8 @@ _Py_Finalize(_PyRuntimeState *runtime) when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ _PyInterpreterState_SetFinalizing(tstate->interp, tstate); _PyRuntimeState_SetFinalizing(runtime, tstate); - runtime->initialized = 0; - runtime->core_initialized = 0; + _PyRuntimeState_SetInitialized(runtime, 0); + _PyRuntimeState_SetCoreInitialized(runtime, 0); // XXX Call something like _PyImport_Disable() here? @@ -2536,11 +2528,6 @@ _Py_Finalize(_PyRuntimeState *runtime) finalize_interp_clear(tstate); -#ifdef _Py_JIT - /* Free JIT shim memory */ - _PyJIT_Fini(); -#endif - #ifdef Py_TRACE_REFS /* Display addresses (& refcnts) of all objects still alive. * An address can be used to find the repr of the object, printed @@ -2614,7 +2601,7 @@ new_interpreter(PyThreadState **tstate_p, } _PyRuntimeState *runtime = &_PyRuntime; - if (!runtime->initialized) { + if (!_PyRuntimeState_GetInitialized(runtime)) { return _PyStatus_ERR("Py_Initialize must be called first"); } @@ -3454,10 +3441,10 @@ fatal_error_dump_runtime(int fd, _PyRuntimeState *runtime) _Py_DumpHexadecimal(fd, (uintptr_t)finalizing, sizeof(finalizing) * 2); PUTS(fd, ")"); } - else if (runtime->initialized) { + else if (_PyRuntimeState_GetInitialized(runtime)) { PUTS(fd, "initialized"); } - else if (runtime->core_initialized) { + else if (_PyRuntimeState_GetCoreInitialized(runtime)) { PUTS(fd, "core initialized"); } else if (runtime->preinitialized) { diff --git a/Python/pystate.c b/Python/pystate.c index 143175da0f4..2df24597e65 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -330,8 +330,8 @@ init_runtime(_PyRuntimeState *runtime, { assert(!runtime->preinitializing); assert(!runtime->preinitialized); - assert(!runtime->core_initialized); - assert(!runtime->initialized); + assert(!_PyRuntimeState_GetCoreInitialized(runtime)); + assert(!_PyRuntimeState_GetInitialized(runtime)); assert(!runtime->_initialized); runtime->open_code_hook = open_code_hook; @@ -489,11 +489,6 @@ free_interpreter(PyInterpreterState *interp) static inline int check_interpreter_whence(long); #endif -extern _Py_CODEUNIT * -_Py_LazyJitShim( - struct _PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate -); - /* Get the interpreter state to a minimal consistent state. Further init happens in pylifecycle.c before it can be used. All fields not initialized here are expected to be zeroed out, @@ -635,6 +630,11 @@ init_interpreter(PyInterpreterState *interp, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); + // Trace fitness configuration + init_policy(&interp->opt_config.fitness_initial, + "PYTHON_JIT_FITNESS_INITIAL", + FITNESS_INITIAL, EXIT_QUALITY_CLOSE_LOOP, UOP_MAX_TRACE_LENGTH - 1); + interp->opt_config.specialization_enabled = !is_env_enabled("PYTHON_SPECIALIZATION_OFF"); interp->opt_config.uops_optimize_enabled = !is_env_disabled("PYTHON_UOPS_OPTIMIZE"); if (interp != &runtime->_main_interpreter) { @@ -3026,9 +3026,32 @@ _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, RARE_EVENT_INC(set_eval_frame_func); _PyEval_StopTheWorld(interp); interp->eval_frame = eval_frame; + // reset when evaluator is reset + interp->eval_frame_allow_specialization = 0; _PyEval_StartTheWorld(interp); } +void +_PyInterpreterState_SetEvalFrameAllowSpecialization(PyInterpreterState *interp, + int allow_specialization) +{ + if (allow_specialization == interp->eval_frame_allow_specialization) { + return; + } + _Py_Executors_InvalidateAll(interp, 1); + RARE_EVENT_INC(set_eval_frame_func); + _PyEval_StopTheWorld(interp); + interp->eval_frame_allow_specialization = allow_specialization; + _PyEval_StartTheWorld(interp); +} + +int +_PyInterpreterState_IsSpecializationEnabled(PyInterpreterState *interp) +{ + return interp->eval_frame == NULL + || interp->eval_frame_allow_specialization; +} + const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp) diff --git a/Python/pystats.c b/Python/pystats.c index a057ad88456..2fac2db1b73 100644 --- a/Python/pystats.c +++ b/Python/pystats.c @@ -274,6 +274,7 @@ print_optimization_stats(FILE *out, OptimizationStats *stats) fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence); fprintf(out, "Optimization unknown callee: %" PRIu64 "\n", stats->unknown_callee); fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated); + fprintf(out, "Optimization fitness terminated: %" PRIu64 "\n", stats->fitness_terminated_traces); print_histogram(out, "Trace length", stats->trace_length_hist); print_histogram(out, "Trace run length", stats->trace_run_length_hist); diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 14d5719313a..645bb013581 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -67,6 +67,7 @@ _Py_hexlify_simd(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) const v16u8 mask_0f = v16u8_splat(0x0f); const v16u8 ascii_0 = v16u8_splat('0'); const v16u8 offset = v16u8_splat('a' - '0' - 10); /* 0x27 */ + const v16u8 four = v16u8_splat(4); const v16s8 nine = v16s8_splat(9); Py_ssize_t i = 0; @@ -78,7 +79,7 @@ _Py_hexlify_simd(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) memcpy(&data, src + i, 16); /* Extract high and low nibbles using vector operators */ - v16u8 hi = (data >> 4) & mask_0f; + v16u8 hi = (data >> four) & mask_0f; v16u8 lo = data & mask_0f; /* Compare > 9 using signed comparison for efficient codegen. diff --git a/Python/record_functions.c.h b/Python/record_functions.c.h index 33fd2f19b12..dff13bfb45e 100644 --- a/Python/record_functions.c.h +++ b/Python/record_functions.c.h @@ -27,6 +27,13 @@ void _PyOpcode_RecordFunction_NOS(_PyInterpreterFrame *frame, _PyStackRef *stack Py_INCREF(*recorded_value); } +void _PyOpcode_RecordFunction_NOS_TYPE(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef nos; + nos = stack_pointer[-2]; + *recorded_value = (PyObject *)Py_TYPE(PyStackRef_AsPyObjectBorrow(nos)); + Py_INCREF(*recorded_value); +} + void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { _PyStackRef nos; nos = stack_pointer[-2]; @@ -69,13 +76,19 @@ void _PyOpcode_RecordFunction_CALLABLE(_PyInterpreterFrame *frame, _PyStackRef * Py_INCREF(*recorded_value); } +void _PyOpcode_RecordFunction_CALLABLE_KW(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { + _PyStackRef func; + func = stack_pointer[-3 - oparg]; + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); +} + void _PyOpcode_RecordFunction_BOUND_METHOD(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) { _PyStackRef callable; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); if (Py_TYPE(callable_o) == &PyMethod_Type) { - PyObject *func = ((PyMethodObject *)callable_o)->im_func; - *recorded_value = (PyObject *)func; + *recorded_value = (PyObject *)callable_o; Py_INCREF(*recorded_value); } } @@ -91,42 +104,54 @@ void _PyOpcode_RecordFunction_CODE(_PyInterpreterFrame *frame, _PyStackRef *stac #define _RECORD_NOS_GEN_FUNC_INDEX 4 #define _RECORD_CALLABLE_INDEX 5 #define _RECORD_BOUND_METHOD_INDEX 6 -#define _RECORD_4OS_INDEX 7 -const uint8_t _PyOpcode_RecordFunctionIndices[256] = { - [TO_BOOL_ALWAYS_TRUE] = _RECORD_TOS_TYPE_INDEX, - [BINARY_OP_SUBSCR_GETITEM] = _RECORD_NOS_INDEX, - [SEND_GEN] = _RECORD_3OS_GEN_FUNC_INDEX, - [LOAD_SUPER_ATTR_METHOD] = _RECORD_NOS_INDEX, - [LOAD_ATTR_INSTANCE_VALUE] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_PROPERTY] = _RECORD_TOS_TYPE_INDEX, - [STORE_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX, - [STORE_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX, - [FOR_ITER_GEN] = _RECORD_NOS_GEN_FUNC_INDEX, - [LOAD_ATTR_METHOD_WITH_VALUES] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_METHOD_NO_DICT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = _RECORD_TOS_TYPE_INDEX, - [LOAD_ATTR_METHOD_LAZY_DICT] = _RECORD_TOS_TYPE_INDEX, - [CALL_PY_GENERAL] = _RECORD_CALLABLE_INDEX, - [CALL_BOUND_METHOD_GENERAL] = _RECORD_BOUND_METHOD_INDEX, - [CALL_NON_PY_GENERAL] = _RECORD_CALLABLE_INDEX, - [CALL_BOUND_METHOD_EXACT_ARGS] = _RECORD_BOUND_METHOD_INDEX, - [CALL_PY_EXACT_ARGS] = _RECORD_CALLABLE_INDEX, - [CALL_ALLOC_AND_ENTER_INIT] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_CLASS] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_O] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_FAST] = _RECORD_CALLABLE_INDEX, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_O] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = _RECORD_CALLABLE_INDEX, - [CALL_METHOD_DESCRIPTOR_NOARGS] = _RECORD_CALLABLE_INDEX, - [CALL_EX_PY] = _RECORD_4OS_INDEX, +#define _RECORD_CALLABLE_KW_INDEX 7 +#define _RECORD_4OS_INDEX 8 +#define _RECORD_NOS_TYPE_INDEX 9 + +const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = { + [TO_BOOL_ALWAYS_TRUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [BINARY_OP_SUBSCR_GETITEM] = {1, {_RECORD_NOS_INDEX}}, + [SEND_GEN] = {1, {_RECORD_3OS_GEN_FUNC_INDEX}}, + [LOAD_SUPER_ATTR_METHOD] = {1, {_RECORD_NOS_INDEX}}, + [LOAD_ATTR_INSTANCE_VALUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_WITH_HINT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_SLOT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_PROPERTY] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_INSTANCE_VALUE] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_WITH_HINT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [STORE_ATTR_SLOT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER_SELF] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [GET_ITER_VIRTUAL] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [FOR_ITER_GEN] = {1, {_RECORD_NOS_GEN_FUNC_INDEX}}, + [LOAD_SPECIAL] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_NO_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [LOAD_ATTR_METHOD_LAZY_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}}, + [CALL_PY_GENERAL] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BOUND_METHOD_GENERAL] = {1, {_RECORD_BOUND_METHOD_INDEX}}, + [CALL_NON_PY_GENERAL] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BOUND_METHOD_EXACT_ARGS] = {1, {_RECORD_BOUND_METHOD_INDEX}}, + [CALL_PY_EXACT_ARGS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_ALLOC_AND_ENTER_INIT] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_CLASS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_O] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_FAST] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_O] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_METHOD_DESCRIPTOR_NOARGS] = {1, {_RECORD_CALLABLE_INDEX}}, + [CALL_KW_PY] = {1, {_RECORD_CALLABLE_KW_INDEX}}, + [CALL_KW_BOUND_METHOD] = {1, {_RECORD_CALLABLE_KW_INDEX}}, + [CALL_EX_PY] = {1, {_RECORD_4OS_INDEX}}, + [BINARY_OP] = {2, {_RECORD_TOS_TYPE_INDEX, _RECORD_NOS_TYPE_INDEX}}, }; -const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[8] = { +const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[10] = { [0] = NULL, [_RECORD_TOS_TYPE_INDEX] = _PyOpcode_RecordFunction_TOS_TYPE, [_RECORD_NOS_INDEX] = _PyOpcode_RecordFunction_NOS, @@ -134,5 +159,7 @@ const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[8] = { [_RECORD_NOS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_NOS_GEN_FUNC, [_RECORD_CALLABLE_INDEX] = _PyOpcode_RecordFunction_CALLABLE, [_RECORD_BOUND_METHOD_INDEX] = _PyOpcode_RecordFunction_BOUND_METHOD, + [_RECORD_CALLABLE_KW_INDEX] = _PyOpcode_RecordFunction_CALLABLE_KW, [_RECORD_4OS_INDEX] = _PyOpcode_RecordFunction_4OS, + [_RECORD_NOS_TYPE_INDEX] = _PyOpcode_RecordFunction_NOS_TYPE, }; diff --git a/Python/specialize.c b/Python/specialize.c index bfa7b8148e4..793bac58adf 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2,6 +2,7 @@ #include "opcode.h" +#include "pycore_bytesobject.h" // _PyBytes_Concat #include "pycore_code.h" #include "pycore_critical_section.h" #include "pycore_descrobject.h" // _PyMethodWrapper_Type @@ -9,7 +10,8 @@ #include "pycore_function.h" // _PyFunction_GetVersionForCurrentState() #include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE #include "pycore_lazyimportobject.h" // PyLazyImport_CheckExact -#include "pycore_list.h" // _PyListIterObject +#include "pycore_list.h" // _PyListIterObject, _PyList_Concat +#include "pycore_tuple.h" // _PyTuple_Concat #include "pycore_long.h" // _PyLong_IsNonNegativeCompact() #include "pycore_moduleobject.h" #include "pycore_object.h" @@ -836,7 +838,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); return -1; } @@ -846,8 +848,13 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } #endif + uint32_t func_version = function_get_version(fget, LOAD_ATTR); + if (func_version == 0) { + return -1; + } assert(tp_version != 0); write_u32(lm_cache->type_version, tp_version); + write_u32(lm_cache->keys_version, func_version); /* borrowed */ write_ptr(lm_cache->descr, fget); specialize(instr, LOAD_ATTR_PROPERTY); @@ -915,7 +922,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); return -1; } @@ -1733,7 +1740,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, PyCodeObject *code = (PyCodeObject *)func->func_code; int kind = function_kind(code); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523); return -1; } @@ -1776,7 +1783,7 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, PyCodeObject *code = (PyCodeObject *)func->func_code; int kind = function_kind(code); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523); return -1; } @@ -2039,7 +2046,7 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs) return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS; } - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { /* Don't specialize if PEP 523 is active */ Py_DECREF(descriptor); return SPEC_FAIL_OTHER; @@ -2115,6 +2122,56 @@ is_compactlong(PyObject *v) _PyLong_IsCompact((PyLongObject *)v); } +/* sequence * int helpers: bypass PyNumber_Multiply dispatch overhead + by calling sq_repeat directly with PyLong_AsSsize_t. */ + +static inline PyObject * +seq_int_multiply(PyObject *seq, PyObject *n, + ssizeargfunc repeat) +{ + Py_ssize_t count = PyLong_AsSsize_t(n); + if (count == -1 && PyErr_Occurred()) { + return NULL; + } + return repeat(seq, count); +} + +static PyObject * +str_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyUnicode_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_str_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyUnicode_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +bytes_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyBytes_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_bytes_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyBytes_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +tuple_int_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(lhs, rhs, PyTuple_Type.tp_as_sequence->sq_repeat); +} + +static PyObject * +int_tuple_multiply(PyObject *lhs, PyObject *rhs) +{ + return seq_int_multiply(rhs, lhs, PyTuple_Type.tp_as_sequence->sq_repeat); +} + static int compactlongs_guard(PyObject *lhs, PyObject *rhs) { @@ -2205,25 +2262,63 @@ LONG_FLOAT_ACTION(compactlong_float_true_div, /) #undef LONG_FLOAT_ACTION static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = { - /* long-long arithmetic */ - {NB_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1}, - {NB_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1}, - {NB_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1}, - {NB_INPLACE_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1}, - {NB_INPLACE_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1}, - {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1}, + /* long-long arithmetic: guards also check _PyLong_IsCompact, so + type alone is not sufficient to eliminate the guard. */ + {NB_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL}, + {NB_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL}, + {NB_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL}, + {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL}, - /* float-long arithemetic */ - {NB_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1}, - {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1}, - {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1}, - {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1}, + /* float-long arithmetic: guards also check NaN and compactness. */ + {NB_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1, NULL, NULL}, + {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1, NULL, NULL}, + {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1, NULL, NULL}, + {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1, NULL, NULL}, - /* float-float arithmetic */ - {NB_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1}, - {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1}, - {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1}, - {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1}, + /* long-float arithmetic: guards also check NaN and compactness. */ + {NB_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1, NULL, NULL}, + {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1, NULL, NULL}, + {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1, NULL, NULL}, + {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1, NULL, NULL}, + + /* list-list concatenation: _PyList_Concat always allocates a new list */ + {NB_ADD, NULL, _PyList_Concat, &PyList_Type, 1, &PyList_Type, &PyList_Type}, + /* tuple-tuple concatenation: _PyTuple_Concat has a zero-length shortcut + that can return one of the operands, so the result is not guaranteed + to be a freshly allocated object. */ + {NB_ADD, NULL, _PyTuple_Concat, &PyTuple_Type, 0, &PyTuple_Type, &PyTuple_Type}, + + /* str * int / int * str: call unicode_repeat directly. + unicode_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type}, + {NB_INPLACE_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type}, + + /* bytes + bytes: bytes_concat may return an operand when one side + is empty, so result is not always unique. */ + {NB_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type}, + {NB_INPLACE_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type}, + + /* bytes * int / int * bytes: call bytes_repeat directly. + bytes_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type}, + {NB_INPLACE_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type}, + + /* tuple * int / int * tuple: call tuple_repeat directly. + tuple_repeat returns the original when n == 1. */ + {NB_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type}, + {NB_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type}, + {NB_INPLACE_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type}, + {NB_INPLACE_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type}, + + /* dict | dict */ + {NB_OR, NULL, _PyDict_Or, &PyDict_Type, 1, &PyDict_Type, &PyDict_Type}, + {NB_INPLACE_OR, NULL, _PyDict_IOr, &PyDict_Type, 0, &PyDict_Type, &PyDict_Type}, }; static int @@ -2233,7 +2328,13 @@ binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg, size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr); for (size_t i = 0; i < n; i++) { _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i]; - if (d->oparg == oparg && d->guard(lhs, rhs)) { + if (d->oparg != oparg) { + continue; + } + int match = (d->guard != NULL) + ? d->guard(lhs, rhs) + : (Py_TYPE(lhs) == d->lhs_type && Py_TYPE(rhs) == d->rhs_type); + if (match) { *descr = d; return 1; } @@ -2348,7 +2449,7 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type; if (kind == SIMPLE_FUNCTION && fcode->co_argcount == 2 && - !_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */ + _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET()) && /* Don't specialize if PEP 523 is active */ _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version)) { specialize(instr, BINARY_OP_SUBSCR_GETITEM); @@ -2606,7 +2707,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR ); /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { goto failure; } specialize(instr, FOR_ITER_GEN); @@ -2614,20 +2715,24 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT } } else { - if (tp == &PyList_Type) { -#ifdef Py_GIL_DISABLED - // Only specialize for lists owned by this thread or shared - if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { - goto failure; + if (tp->_tp_iteritem != NULL) { + if (tp == &PyList_Type) { + #ifdef Py_GIL_DISABLED + // Only specialize for lists owned by this thread or shared + if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { + goto failure; + } + #endif + specialize(instr, FOR_ITER_LIST); + return; + } + else if (tp == &PyTuple_Type) { + specialize(instr, FOR_ITER_TUPLE); + return; } -#endif - specialize(instr, FOR_ITER_LIST); - return; - } - else if (tp == &PyTuple_Type) { - specialize(instr, FOR_ITER_TUPLE); - return; } + specialize(instr, FOR_ITER_VIRTUAL); + return; } failure: SPECIALIZATION_FAIL(FOR_ITER, @@ -2645,7 +2750,7 @@ _Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr) PyTypeObject *tp = Py_TYPE(receiver); if (tp == &PyGen_Type || tp == &PyCoro_Type) { /* Don't specialize if PEP 523 is active */ - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER); goto failure; } @@ -2668,7 +2773,7 @@ _Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr) if (Py_TYPE(func) == &PyFunction_Type && ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) { - if (_PyInterpreterState_GET()->eval_frame) { + if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) { goto failure; } specialize(instr, CALL_EX_PY); @@ -2822,6 +2927,23 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr) return; } +void +_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr) +{ + assert(ENABLE_SPECIALIZATION); + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp->_tp_iteritem != NULL) { + specialize(instr, GET_ITER_VIRTUAL); + return; + } + if (tp->tp_iter == PyObject_SelfIter) { + specialize(instr, GET_ITER_SELF); + return; + } + SPECIALIZATION_FAIL(GET_ITER, + tp == &PyCoro_Type ? SPEC_FAIL_ITER_COROUTINE : SPEC_FAIL_OTHER); + unspecialize(instr); +} void _Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame) diff --git a/Python/symtable.c b/Python/symtable.c index 4b695e4b258..2263a2d8db9 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -108,6 +108,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = Py_NewRef(name); + ste->ste_function_name = NULL; ste->ste_symbols = NULL; ste->ste_varnames = NULL; @@ -186,6 +187,7 @@ ste_dealloc(PyObject *op) ste->ste_table = NULL; Py_XDECREF(ste->ste_id); Py_XDECREF(ste->ste_name); + Py_XDECREF(ste->ste_function_name); Py_XDECREF(ste->ste_symbols); Py_XDECREF(ste->ste_varnames); Py_XDECREF(ste->ste_children); @@ -2918,6 +2920,7 @@ symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ (void *)a, LOCATION(o))) { return 0; } + Py_XSETREF(st->st_cur->ste_function_name, Py_NewRef(function_ste->ste_name)); if (is_in_class || current_type == ClassBlock) { st->st_cur->ste_can_see_class_scope = 1; if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(o))) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 408d04684a9..1ee0b3bec68 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -34,6 +34,7 @@ Data members: #include "pycore_pymem.h" // _PyMem_DefaultRawFree() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystats.h" // _Py_PrintSpecializationStats() +#include "pycore_runtime.h" // _PyRuntimeState_Get*() #include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags() #include "pycore_sysmodule.h" // export _PySys_GetSizeOf() #include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal() @@ -471,7 +472,7 @@ PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData) PySys_AddAuditHook() can be called before Python is initialized. */ _PyRuntimeState *runtime = &_PyRuntime; PyThreadState *tstate; - if (runtime->initialized) { + if (_PyRuntimeState_GetInitialized(runtime)) { tstate = _PyThreadState_GET(); } else { diff --git a/Tools/build/freeze_modules.py b/Tools/build/freeze_modules.py index 3c43f7e3bbe..b8b17ceb4f4 100644 --- a/Tools/build/freeze_modules.py +++ b/Tools/build/freeze_modules.py @@ -50,10 +50,10 @@ ('stdlib - startup, without site (python -S)', [ 'abc', 'codecs', - # For now we do not freeze the encodings, due # to the noise all - # those extra modules add to the text printed during the build. - # (See https://github.com/python/cpython/pull/28398#pullrequestreview-756856469.) - #'', + '', + 'encodings.aliases', + 'encodings.utf_8', + 'encodings._win_cp_codecs', 'io', ]), ('stdlib - startup, with site', [ @@ -66,6 +66,9 @@ 'site', 'stat', ]), + ('pythonrun - interactive', [ + 'linecache', + ]), ('runpy - run module with -m', [ "importlib.util", "importlib.machinery", diff --git a/Tools/build/generate_levenshtein_examples.py b/Tools/build/generate_levenshtein_examples.py index 30dcc7cf1a1..2396c8040ca 100644 --- a/Tools/build/generate_levenshtein_examples.py +++ b/Tools/build/generate_levenshtein_examples.py @@ -13,7 +13,7 @@ _CASE_COST = 1 -def _substitution_cost(ch_a, ch_b): +def _substitution_cost(ch_a: str, ch_b: str) -> int: if ch_a == ch_b: return 0 if ch_a.lower() == ch_b.lower(): @@ -22,7 +22,7 @@ def _substitution_cost(ch_a, ch_b): @lru_cache(None) -def levenshtein(a, b): +def levenshtein(a: str, b: str) -> int: if not a or not b: return (len(a) + len(b)) * _MOVE_COST option1 = levenshtein(a[:-1], b[:-1]) + _substitution_cost(a[-1], b[-1]) @@ -31,7 +31,7 @@ def levenshtein(a, b): return min(option1, option2, option3) -def main(): +def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('output_path', metavar='FILE', type=str) parser.add_argument('--overwrite', dest='overwrite', action='store_const', @@ -48,7 +48,7 @@ def main(): ) return - examples = set() + examples: set[tuple[str, str, int]] = set() # Create a lot of non-empty examples, which should end up with a Gauss-like # distribution for even costs (moves) and odd costs (case substitutions). while len(examples) < 9990: diff --git a/Tools/build/mypy.ini b/Tools/build/mypy.ini index 7d341afd1cd..5465e2d4b61 100644 --- a/Tools/build/mypy.ini +++ b/Tools/build/mypy.ini @@ -9,6 +9,7 @@ files = Tools/build/consts_getter.py, Tools/build/deepfreeze.py, Tools/build/generate-build-details.py, + Tools/build/generate_levenshtein_examples.py, Tools/build/generate_sbom.py, Tools/build/generate_stdlib_module_names.py, Tools/build/verify_ensurepip_wheels.py, diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index d645d2b6150..74ca5628240 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -357,7 +357,7 @@ Modules/_testclinic.c - TestClass - ################################## ## global non-objects to fix in builtin modules -# +Objects/memoryobject.c - bool_false - ################################## diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 6ba9c43ef1f..414ca18be46 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -1132,7 +1132,7 @@ def add_macro( macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop] ) -> None: parts: list[Part] = [] - first = True + seen_real_uop = False for part in macro.uops: match part: case parser.OpName(): @@ -1144,12 +1144,15 @@ def add_macro( f"No Uop named {part.name}", macro.tokens[0] ) uop = uops[part.name] - if uop.properties.records_value and not first: - raise analysis_error( - f"Recording uop {part.name} must be first in macro", - macro.tokens[0]) + if uop.properties.records_value: + if seen_real_uop: + raise analysis_error( + f"Recording uop {part.name} must precede all " + f"non-recording, non-specializing uops in macro", + macro.tokens[0]) + elif "specializing" not in uop.annotations: + seen_real_uop = True parts.append(uop) - first = False case parser.CacheEffect(): parts.append(Skip(part.size)) case _: diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index 72cad9f98b9..784e1a8a2d1 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -250,12 +250,16 @@ def replace_opcode_if_evaluates_pure( }, 2: { # (a, b -- res), usually for binary ops - 0: [("_POP_TWO_LOAD_CONST_INLINE_BORROW", + 0: [("_POP_TOP", "0, 0"), + ("_POP_TOP", "0, 0"), + ("_LOAD_CONST_INLINE_BORROW", "0, (uintptr_t)result")], # (left, right -- res, left, right) # usually for binary ops with passthrough references - 2: [("_INSERT_2_LOAD_CONST_INLINE_BORROW", - "0, (uintptr_t)result")], + 2: [("_LOAD_CONST_INLINE_BORROW", + "0, (uintptr_t)result"), + ("_SWAP", "3, 0"), + ("_SWAP", "2, 0")], }, } @@ -408,6 +412,7 @@ def write_uop( args.append(input.name) out.emit(f'DEBUG_PRINTF({", ".join(args)});\n') if override: + idx = 0 for cache in uop.caches: if cache.name != "unused": if cache.size == 4: @@ -415,7 +420,8 @@ def write_uop( else: type = f"uint{cache.size*16}_t " cast = f"uint{cache.size*16}_t" - out.emit(f"{type}{cache.name} = ({cast})this_instr->operand0;\n") + out.emit(f"{type}{cache.name} = ({cast})this_instr->operand{idx};\n") + idx += 1 if override: emitter = OptimizerEmitter(out, {}, uop, stack.copy()) # No reference management of inputs needed. diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py index 4ec46d8cac6..ccf8bf64952 100644 --- a/Tools/cases_generator/parser.py +++ b/Tools/cases_generator/parser.py @@ -70,7 +70,6 @@ def parse_files(filenames: list[str]) -> list[AstNode]: assert node is not None result.append(node) # type: ignore[arg-type] if not psr.eof(): - pprint.pprint(result) psr.backup() raise psr.make_syntax_error( f"Extra stuff at the end of {filename}", psr.next(True) diff --git a/Tools/cases_generator/record_function_generator.py b/Tools/cases_generator/record_function_generator.py index 58d948f198c..d7ae0ebf79f 100644 --- a/Tools/cases_generator/record_function_generator.py +++ b/Tools/cases_generator/record_function_generator.py @@ -25,6 +25,9 @@ DEFAULT_OUTPUT = ROOT / "Python/recorder_functions.c.h" +# Must match MAX_RECORDED_VALUES in Include/internal/pycore_optimizer.h. +MAX_RECORDED_VALUES = 3 + class RecorderEmitter(Emitter): def __init__(self, out: CWriter): @@ -81,27 +84,35 @@ def generate_recorder_functions(filenames: list[str], analysis: Analysis, out: C def generate_recorder_tables(analysis: Analysis, out: CWriter) -> None: record_function_indexes: dict[str, int] = dict() - record_table: dict[str, str] = {} + record_table: dict[str, list[str]] = {} index = 1 for inst in analysis.instructions.values(): if not inst.properties.records_value: continue + records: list[str] = [] for part in inst.parts: if not part.properties.records_value: continue if part.name not in record_function_indexes: record_function_indexes[part.name] = index index += 1 - record_table[inst.name] = part.name - break + records.append(part.name) + if records: + if len(records) > MAX_RECORDED_VALUES: + raise ValueError( + f"Instruction {inst.name} has {len(records)} recording ops, " + f"exceeds MAX_RECORDED_VALUES ({MAX_RECORDED_VALUES})" + ) + record_table[inst.name] = records func_count = len(record_function_indexes) for name, index in record_function_indexes.items(): out.emit(f"#define {name}_INDEX {index}\n") - args = "_PyJitTracerState *tracer, _PyInterpreterFrame *frame, _PyStackRef *stackpointer, int oparg" - out.emit("const uint8_t _PyOpcode_RecordFunctionIndices[256] = {\n") - for inst_name, record_name in record_table.items(): - out.emit(f" [{inst_name}] = {record_name}_INDEX,\n") + out.emit("\n") + out.emit("const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = {\n") + for inst_name, record_names in record_table.items(): + indices = ", ".join(f"{name}_INDEX" for name in record_names) + out.emit(f" [{inst_name}] = {{{len(record_names)}, {{{indices}}}}},\n") out.emit("};\n\n") out.emit(f"const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[{func_count+1}] = {{\n") out.emit(" [0] = NULL,\n") diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py index 0334bec724d..d2fa749e141 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -203,6 +203,10 @@ def generate_tier1_labels( emitter.emit("\n") # Emit tail-callable labels as function defintions for name, label in analysis.labels.items(): + if name == 'stop_tracing': + emitter.emit("#if _Py_TAIL_CALL_INTERP && !defined(_Py_TIER2)\n") + emitter.emit("Py_GCC_ATTRIBUTE((unused))\n") + emitter.emit("#endif\n") emitter.emit(f"LABEL({name})\n") storage = Storage(Stack(), [], [], 0, False) if label.spilled: diff --git a/Tools/check-c-api-docs/ignored_c_api.txt b/Tools/check-c-api-docs/ignored_c_api.txt index f3a3612b849..dfec0524cfe 100644 --- a/Tools/check-c-api-docs/ignored_c_api.txt +++ b/Tools/check-c-api-docs/ignored_c_api.txt @@ -18,8 +18,6 @@ Py_HasFileSystemDefaultEncoding Py_UTF8Mode # pyhash.h Py_HASH_EXTERNAL -# modsupport.h -PyABIInfo_FREETHREADING_AGNOSTIC # object.h Py_INVALID_SIZE # pyexpat.h diff --git a/Tools/jit/README.md b/Tools/jit/README.md index 8eadb3349ba..9361f39dcc6 100644 --- a/Tools/jit/README.md +++ b/Tools/jit/README.md @@ -9,7 +9,12 @@ ## Installing LLVM The JIT compiler does not require end users to install any third-party dependencies, but part of it must be *built* using LLVM[^why-llvm]. You are *not* required to build the rest of CPython using LLVM, or even the same version of LLVM (in fact, this is uncommon). -LLVM version 21 is the officially supported version. You can modify if needed using the `LLVM_VERSION` env var during configure. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. +LLVM version 21 is the officially supported version. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-21`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. + +You can customize the LLVM configuration using environment variables before running configure: + +- LLVM_VERSION: Specify a different LLVM version (default: 21) +- LLVM_TOOLS_INSTALL_DIR: Point to a specific LLVM installation prefix when multiple installations exist (the tools are expected in `

/bin`) It's easy to install all of the required tools: @@ -62,7 +67,7 @@ ### Windows ### Dev Containers -If you are working on CPython in a [Codespaces instance](https://devguide.python.org/getting-started/setup-building/#using-codespaces), there's no +If you are working on CPython in a [Codespaces instance](https://devguide.python.org/getting-started/setup-building/#using-codespaces), there's no need to install LLVM as the Fedora 43 base image includes LLVM 21 out of the box. ## Building @@ -81,3 +86,8 @@ ## Miscellaneous [^pep-744]: [PEP 744](https://peps.python.org/pep-0744/) [^why-llvm]: Clang is specifically needed because it's the only C compiler with support for guaranteed tail calls (`musttail`), which are required by CPython's continuation-passing-style approach to JIT compilation. Since LLVM also includes other functionalities we need (namely, object file parsing and disassembly), it's convenient to only support one toolchain at this time. + +### Understanding JIT behavior + +The [example_trace_dump.py](./example_trace_dump.py) script will (when configured as described in the script) dump out the +executors for a range of tiny programs to show the behavior of the JIT front-end. \ No newline at end of file diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py index a4aaacdf412..601752bf1f6 100644 --- a/Tools/jit/_llvm.py +++ b/Tools/jit/_llvm.py @@ -80,7 +80,18 @@ async def _get_brew_llvm_prefix(llvm_version: str, *, echo: bool = False) -> str @_async_cache -async def _find_tool(tool: str, llvm_version: str, *, echo: bool = False) -> str | None: +async def _find_tool( + tool: str, + llvm_version: str, + llvm_tools_install_dir: str | None, + *, + echo: bool = False, +) -> str | None: + # Explicitly defined LLVM installation location + if llvm_tools_install_dir: + path = os.path.join(llvm_tools_install_dir, "bin", tool) + if await _check_tool_version(path, llvm_version, echo=echo): + return path # Unversioned executables: path = tool if await _check_tool_version(path, llvm_version, echo=echo): @@ -114,10 +125,11 @@ async def maybe_run( args: typing.Iterable[str], echo: bool = False, llvm_version: str = _LLVM_VERSION, + llvm_tools_install_dir: str | None = None, ) -> str | None: """Run an LLVM tool if it can be found. Otherwise, return None.""" - path = await _find_tool(tool, llvm_version, echo=echo) + path = await _find_tool(tool, llvm_version, llvm_tools_install_dir, echo=echo) return path and await _run(path, args, echo=echo) @@ -126,10 +138,17 @@ async def run( args: typing.Iterable[str], echo: bool = False, llvm_version: str = _LLVM_VERSION, + llvm_tools_install_dir: str | None = None, ) -> str: """Run an LLVM tool if it can be found. Otherwise, raise RuntimeError.""" - output = await maybe_run(tool, args, echo=echo, llvm_version=llvm_version) + output = await maybe_run( + tool, + args, + echo=echo, + llvm_version=llvm_version, + llvm_tools_install_dir=llvm_tools_install_dir, + ) if output is None: raise RuntimeError(f"Can't find {tool}-{llvm_version}!") return output diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index ef28e0c0dde..f192783a559 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -99,6 +99,9 @@ class InstructionKind(enum.Enum): RETURN = enum.auto() SMALL_CONST_1 = enum.auto() SMALL_CONST_2 = enum.auto() + SMALL_CONST_MASK = enum.auto() + LARGE_CONST_1 = enum.auto() + LARGE_CONST_2 = enum.auto() OTHER = enum.auto() @@ -107,6 +110,7 @@ class Instruction: kind: InstructionKind name: str text: str + register: str | None target: str | None def is_branch(self) -> bool: @@ -115,7 +119,11 @@ def is_branch(self) -> bool: def update_target(self, target: str) -> "Instruction": assert self.target is not None return Instruction( - self.kind, self.name, self.text.replace(self.target, target), target + self.kind, + self.name, + self.text.replace(self.target, target), + self.register, + target, ) def update_name_and_target(self, name: str, target: str) -> "Instruction": @@ -124,6 +132,7 @@ def update_name_and_target(self, name: str, target: str) -> "Instruction": self.kind, name, self.text.replace(self.name, name).replace(self.target, target), + self.register, target, ) @@ -193,8 +202,12 @@ class Optimizer: globals: set[str] = dataclasses.field(default_factory=set) _re_small_const_1 = _RE_NEVER_MATCH _re_small_const_2 = _RE_NEVER_MATCH + _re_small_const_mask = _RE_NEVER_MATCH + _re_large_const_1 = _RE_NEVER_MATCH + _re_large_const_2 = _RE_NEVER_MATCH const_reloc = "" _frame_pointer_modify: typing.ClassVar[re.Pattern[str]] = _RE_NEVER_MATCH + label_index: int = 0 def __post_init__(self) -> None: # Split the code into a linked list of basic blocks. A basic block is an @@ -255,6 +268,7 @@ def _preprocess(self, text: str) -> str: def _parse_instruction(self, line: str) -> Instruction: target = None + reg = None if match := self._re_branch.match(line): target = match["target"] name = match["instruction"] @@ -276,15 +290,34 @@ def _parse_instruction(self, line: str) -> Instruction: elif match := self._re_small_const_1.match(line): target = match["value"] name = match["instruction"] + reg = match["register"] kind = InstructionKind.SMALL_CONST_1 elif match := self._re_small_const_2.match(line): target = match["value"] name = match["instruction"] + reg = match["register"] kind = InstructionKind.SMALL_CONST_2 + elif match := self._re_small_const_mask.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + if reg.startswith("w"): + reg = "x" + reg[1:] + kind = InstructionKind.SMALL_CONST_MASK + elif match := self._re_large_const_1.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + kind = InstructionKind.LARGE_CONST_1 + elif match := self._re_large_const_2.match(line): + target = match["value"] + name = match["instruction"] + reg = match["register"] + kind = InstructionKind.LARGE_CONST_2 else: name, *_ = line.split(" ") kind = InstructionKind.OTHER - return Instruction(kind, name, line, target) + return Instruction(kind, name, line, reg, target) def _invert_branch(self, inst: Instruction, target: str) -> Instruction | None: assert inst.is_branch() @@ -487,73 +520,13 @@ def _fixup_external_labels(self) -> None: name = target[len(self.symbol_prefix) :] label = f"{self.symbol_prefix}{reloc}_JIT_RELOCATION_{name}_JIT_RELOCATION_{index}:" block.instructions[-1] = Instruction( - InstructionKind.OTHER, "", label, None + InstructionKind.OTHER, "", label, None, None ) block.instructions.append(branch.update_target("0")) - def _make_temp_label(self, index: int) -> Instruction: - marker = f"jit_temp_{index}:" - return Instruction(InstructionKind.OTHER, "", marker, None) - def _fixup_constants(self) -> None: - if not self.supports_small_constants: - return - index = 0 - for block in self._blocks(): - fixed: list[Instruction] = [] - small_const_index = -1 - for inst in block.instructions: - if inst.kind == InstructionKind.SMALL_CONST_1: - marker = f"jit_pending_{inst.target}{index}:" - fixed.append(self._make_temp_label(index)) - index += 1 - small_const_index = len(fixed) - fixed.append(inst) - elif inst.kind == InstructionKind.SMALL_CONST_2: - if small_const_index < 0: - fixed.append(inst) - continue - small_const_1 = fixed[small_const_index] - if not self._small_consts_match(small_const_1, inst): - small_const_index = -1 - fixed.append(inst) - continue - assert small_const_1.target is not None - if small_const_1.target.endswith("16"): - fixed[small_const_index] = self._make_temp_label(index) - index += 1 - else: - assert small_const_1.target.endswith("32") - patch_kind, replacement = self._small_const_1(small_const_1) - if replacement is not None: - label = f"{self.const_reloc}{patch_kind}_JIT_RELOCATION_CONST{small_const_1.target[:-3]}_JIT_RELOCATION_{index}:" - index += 1 - fixed[small_const_index - 1] = Instruction( - InstructionKind.OTHER, "", label, None - ) - fixed[small_const_index] = replacement - patch_kind, replacement = self._small_const_2(inst) - if replacement is not None: - assert inst.target is not None - label = f"{self.const_reloc}{patch_kind}_JIT_RELOCATION_CONST{inst.target[:-3]}_JIT_RELOCATION_{index}:" - index += 1 - fixed.append( - Instruction(InstructionKind.OTHER, "", label, None) - ) - fixed.append(replacement) - small_const_index = -1 - else: - fixed.append(inst) - block.instructions = fixed - - def _small_const_1(self, inst: Instruction) -> tuple[str, Instruction | None]: - raise NotImplementedError() - - def _small_const_2(self, inst: Instruction) -> tuple[str, Instruction | None]: - raise NotImplementedError() - - def _small_consts_match(self, inst1: Instruction, inst2: Instruction) -> bool: - raise NotImplementedError() + "Fixup loading of constants. Overridden by OptimizerAArch64" + pass def _validate(self) -> None: for block in self._blocks(): @@ -602,52 +575,200 @@ class OptimizerAArch64(Optimizer): # pylint: disable = too-few-public-methods supports_small_constants = True _re_small_const_1 = re.compile( - r"\s*(?Padrp)\s+.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + r"\s*(?Padrp)\s+(?Px\d\d?),.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" ) _re_small_const_2 = re.compile( - r"\s*(?Pldr)\s+.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + r"\s*(?Pldr)\s+(?Px\d\d?),.*(?P_JIT_OP(ARG|ERAND(0|1))_(16|32)).*" + ) + _re_small_const_mask = re.compile( + r"\s*(?Pand)\s+[xw]\d\d?, *(?P[xw]\d\d?).*(?P0xffff)" + ) + _re_large_const_1 = re.compile( + r"\s*(?Padrp)\s+(?Px\d\d?),.*:got:(?P[_A-Za-z0-9]+).*" + ) + _re_large_const_2 = re.compile( + r"\s*(?Pldr)\s+(?Px\d\d?),.*:got_lo12:(?P[_A-Za-z0-9]+).*" ) const_reloc = "CUSTOM_AARCH64_CONST" _frame_pointer_modify = re.compile(r"\s*stp\s+x29.*") - def _get_reg(self, inst: Instruction) -> str: - _, rest = inst.text.split(inst.name) - reg, *_ = rest.split(",") - return reg.strip() + def _make_temp_label(self, note: object = None) -> Instruction: + marker = f"jit_temp_{self.label_index}:" + if note is not None: + marker = f"{marker[:-1]}_{note}:" + self.label_index += 1 + return Instruction(InstructionKind.OTHER, "", marker, None, None) - def _small_const_1(self, inst: Instruction) -> tuple[str, Instruction | None]: - assert inst.kind is InstructionKind.SMALL_CONST_1 - assert inst.target is not None - if "16" in inst.target: - return "", None - pre, _ = inst.text.split(inst.name) - return "16a", Instruction( - InstructionKind.OTHER, "movz", f"{pre}movz {self._get_reg(inst)}, 0", None + def _both_registers_same(self, inst: Instruction) -> bool: + reg = inst.register + assert reg is not None + if reg not in inst.text: + reg = "w" + reg[1:] + return inst.text.count(reg) == 2 + + def _fixup_small_constant_pair( + self, output: list[Instruction], label_index: int, inst: Instruction + ) -> str | None: + first = output[label_index + 1] + reg = first.register + if reg is None or inst.register != reg: + output.append( + Instruction(InstructionKind.OTHER, "", "# registers differ", None, None) + ) + output.append(inst) + return None + assert first.target is not None + if first.target != inst.target: + output.append( + Instruction(InstructionKind.OTHER, "", "# targets differ", None, None) + ) + output.append(inst) + return None + if not self._both_registers_same(inst): + output.append( + Instruction( + InstructionKind.OTHER, "", "# not same register", None, None + ) + ) + output.append(inst) + return None + pre, _ = first.text.split(first.name) + output[label_index + 1] = Instruction( + InstructionKind.OTHER, + "movz", + f"{pre}movz {reg}, 0", + reg, + None, ) - - def _small_const_2(self, inst: Instruction) -> tuple[str, Instruction | None]: - assert inst.kind is InstructionKind.SMALL_CONST_2 - assert inst.target is not None - pre, _ = inst.text.split(inst.name) - if "16" in inst.target: - return "16a", Instruction( - InstructionKind.OTHER, - "movz", - f"{pre}movz {self._get_reg(inst)}, 0", - None, + label_text = f"{self.const_reloc}16a_JIT_RELOCATION_CONST{first.target[:-3]}_JIT_RELOCATION_{self.label_index}:" + self.label_index += 1 + output[label_index] = Instruction( + InstructionKind.OTHER, "", label_text, None, None + ) + assert first.target.endswith("16") or first.target.endswith("32") + if first.target.endswith("32"): + label_text = f"{self.const_reloc}16b_JIT_RELOCATION_CONST{first.target[:-3]}_JIT_RELOCATION_{self.label_index}:" + self.label_index += 1 + output.append( + Instruction(InstructionKind.OTHER, "", label_text, None, None) ) + pre, _ = inst.text.split(inst.name) + output.append( + Instruction( + InstructionKind.OTHER, + "movk", + f"{pre}movk {reg}, 0, lsl #16", + reg, + None, + ) + ) + return reg + + def may_use_reg(self, inst: Instruction, reg: str | None) -> bool: + "Return False if `reg` is not explicitly used by this instruction" + if reg is None: + return False + assert reg.startswith("w") or reg.startswith("x") + xreg = f"x{reg[1:]}" + wreg = f"w{reg[1:]}" + if wreg in inst.text: + return True + if xreg in inst.text: + # Exclude false positives like 0x80 for x8 + count = inst.text.count(xreg) + number_count = inst.text.count("0" + xreg) + return count > number_count + return False + + def _fixup_large_constant_pair( + self, output: list[Instruction], label_index: int, inst: Instruction + ) -> None: + first = output[label_index + 1] + reg = first.register + if reg is None or inst.register != reg: + output.append(inst) + return + assert first.target is not None + if first.target != inst.target: + output.append(inst) + return + label = f"{self.const_reloc}33a_JIT_PAIR_{first.target}_JIT_PAIR_{self.label_index}:" + output[label_index] = Instruction(InstructionKind.OTHER, "", label, None, None) + label = ( + f"{self.const_reloc}33b_JIT_PAIR_{inst.target}_JIT_PAIR_{self.label_index}:" + ) + self.label_index += 1 + output.append(Instruction(InstructionKind.OTHER, "", label, None, None)) + output.append(inst) + + def _fixup_mask(self, output: list[Instruction], inst: Instruction) -> None: + if self._both_registers_same(inst): + # Nop + pass else: - return "16b", Instruction( - InstructionKind.OTHER, - "movk", - f"{pre}movk {self._get_reg(inst)}, 0, lsl #16", - None, - ) + output.append(inst) - def _small_consts_match(self, inst1: Instruction, inst2: Instruction) -> bool: - reg1 = self._get_reg(inst1) - reg2 = self._get_reg(inst2) - return reg1 == reg2 + def _fixup_constants(self) -> None: + for block in self._blocks(): + fixed: list[Instruction] = [] + small_const_part: dict[str, int | None] = {} + small_const_whole: dict[str, str | None] = {} + large_const_part: dict[str, int | None] = {} + for inst in block.instructions: + if inst.kind == InstructionKind.SMALL_CONST_1: + assert inst.register is not None + small_const_part[inst.register] = len(fixed) + small_const_whole[inst.register] = None + large_const_part[inst.register] = None + fixed.append(self._make_temp_label(inst.register)) + fixed.append(inst) + elif inst.kind == InstructionKind.SMALL_CONST_2: + assert inst.register is not None + index = small_const_part.get(inst.register) + small_const_part[inst.register] = None + if index is None: + fixed.append(inst) + continue + small_const_whole[inst.register] = self._fixup_small_constant_pair( + fixed, index, inst + ) + small_const_part[inst.register] = None + elif inst.kind == InstructionKind.SMALL_CONST_MASK: + assert inst.register is not None + reg = small_const_whole.get(inst.register) + if reg is not None: + self._fixup_mask(fixed, inst) + else: + fixed.append(inst) + elif inst.kind == InstructionKind.LARGE_CONST_1: + assert inst.register is not None + small_const_part[inst.register] = None + small_const_whole[inst.register] = None + large_const_part[inst.register] = len(fixed) + fixed.append(self._make_temp_label()) + fixed.append(inst) + elif inst.kind == InstructionKind.LARGE_CONST_2: + assert inst.register is not None + small_const_part[inst.register] = None + small_const_whole[inst.register] = None + index = large_const_part.get(inst.register) + large_const_part[inst.register] = None + if index is None: + fixed.append(inst) + continue + self._fixup_large_constant_pair(fixed, index, inst) + else: + for reg in small_const_part: + if self.may_use_reg(inst, reg): + small_const_part[reg] = None + for reg in small_const_whole: + if self.may_use_reg(inst, reg): + small_const_whole[reg] = None + for reg in small_const_part: + if self.may_use_reg(inst, reg): + large_const_part[reg] = None + fixed.append(inst) + block.instructions = fixed class OptimizerX86(Optimizer): # pylint: disable = too-few-public-methods diff --git a/Tools/jit/_stencils.py b/Tools/jit/_stencils.py index 55a4aece542..e2ae3d988fc 100644 --- a/Tools/jit/_stencils.py +++ b/Tools/jit/_stencils.py @@ -57,11 +57,12 @@ class HoleValue(enum.Enum): _PATCH_FUNCS = { # aarch64-apple-darwin: "ARM64_RELOC_BRANCH26": "patch_aarch64_26r", - "ARM64_RELOC_GOT_LOAD_PAGE21": "patch_aarch64_21r", - "ARM64_RELOC_GOT_LOAD_PAGEOFF12": "patch_aarch64_12", + "ARM64_RELOC_GOT_LOAD_PAGE21": "patch_aarch64_21rx", + "ARM64_RELOC_GOT_LOAD_PAGEOFF12": "patch_aarch64_12x", "ARM64_RELOC_PAGE21": "patch_aarch64_21r", "ARM64_RELOC_PAGEOFF12": "patch_aarch64_12", "ARM64_RELOC_UNSIGNED": "patch_64", + # custom aarch64, both darwin and linux: "CUSTOM_AARCH64_BRANCH19": "patch_aarch64_19r", "CUSTOM_AARCH64_CONST16a": "patch_aarch64_16a", "CUSTOM_AARCH64_CONST16b": "patch_aarch64_16b", @@ -70,21 +71,21 @@ class HoleValue(enum.Enum): # aarch64-pc-windows-msvc: "IMAGE_REL_ARM64_BRANCH19": "patch_aarch64_19r", "IMAGE_REL_ARM64_BRANCH26": "patch_aarch64_26r", - "IMAGE_REL_ARM64_PAGEBASE_REL21": "patch_aarch64_21r", + "IMAGE_REL_ARM64_PAGEBASE_REL21": "patch_aarch64_21rx", "IMAGE_REL_ARM64_PAGEOFFSET_12A": "patch_aarch64_12", - "IMAGE_REL_ARM64_PAGEOFFSET_12L": "patch_aarch64_12", + "IMAGE_REL_ARM64_PAGEOFFSET_12L": "patch_aarch64_12x", # i686-pc-windows-msvc: "IMAGE_REL_I386_DIR32": "patch_32", "IMAGE_REL_I386_REL32": "patch_x86_64_32rx", # aarch64-unknown-linux-gnu: "R_AARCH64_ABS64": "patch_64", "R_AARCH64_ADD_ABS_LO12_NC": "patch_aarch64_12", - "R_AARCH64_ADR_GOT_PAGE": "patch_aarch64_21r", + "R_AARCH64_ADR_GOT_PAGE": "patch_aarch64_21rx", "R_AARCH64_ADR_PREL_PG_HI21": "patch_aarch64_21r", "R_AARCH64_CALL26": "patch_aarch64_26r", "R_AARCH64_CONDBR19": "patch_aarch64_19r", "R_AARCH64_JUMP26": "patch_aarch64_26r", - "R_AARCH64_LD64_GOT_LO12_NC": "patch_aarch64_12", + "R_AARCH64_LD64_GOT_LO12_NC": "patch_aarch64_12x", "R_AARCH64_MOVW_UABS_G0_NC": "patch_aarch64_16a", "R_AARCH64_MOVW_UABS_G1_NC": "patch_aarch64_16b", "R_AARCH64_MOVW_UABS_G2_NC": "patch_aarch64_16c", @@ -165,14 +166,30 @@ class Hole: custom_location: str = "" custom_value: str = "" func: str = dataclasses.field(init=False) + offset2: int = -1 + void: bool = False # Convenience method: replace = dataclasses.replace def __post_init__(self) -> None: self.func = _PATCH_FUNCS[self.kind] + def fold(self, other: typing.Self) -> None: + """Combine two holes into a single hole.""" + assert ( + self.func == "patch_aarch64_12x" and other.func == "patch_aarch64_21rx" + ), (self.func, other.func) + assert self.value == other.value + assert self.symbol == other.symbol + assert self.addend == other.addend + self.func = "patch_aarch64_33rx" + self.offset2 = other.offset + other.void = True + def as_c(self, where: str) -> str: """Dump this hole as a call to a patch_* function.""" + if self.void: + return "" if self.custom_location: location = self.custom_location else: @@ -194,6 +211,9 @@ def as_c(self, where: str) -> str: value += f"{_signed(self.addend):#x}" if self.need_state: return f"{self.func}({location}, {value}, state);" + if self.offset2 >= 0: + first_location = f"{where} + {self.offset2:#x}" + return f"{self.func}({first_location}, {location}, {value});" return f"{self.func}({location}, {value});" @@ -238,6 +258,10 @@ class StencilGroup: _got_entries: set[int] = dataclasses.field(default_factory=set, init=False) def convert_labels_to_relocations(self) -> None: + holes_by_offset: dict[int, Hole] = {} + first_in_pair: dict[str, Hole] = {} + for hole in self.code.holes: + holes_by_offset[hole.offset] = hole for name, hole_plus in self.symbols.items(): if isinstance(name, str) and "_JIT_RELOCATION_" in name: _, offset = hole_plus @@ -247,6 +271,16 @@ def convert_labels_to_relocations(self) -> None: int(offset), typing.cast(_schema.HoleKind, reloc), value, symbol, 0 ) self.code.holes.append(hole) + elif isinstance(name, str) and "_JIT_PAIR_" in name: + _, offset = hole_plus + reloc, target, index = name.split("_JIT_PAIR_") + if offset in holes_by_offset: + hole = holes_by_offset[offset] + if "33a" in reloc: + first_in_pair[index] = hole + elif "33b" in reloc and index in first_in_pair: + first = first_in_pair[index] + hole.fold(first) def process_relocations(self, known_symbols: dict[str, int]) -> None: """Fix up all GOT and internal relocations for this stencil group.""" diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index ea0a9722c3c..15cac3de3fe 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -53,9 +53,16 @@ class _Target(typing.Generic[_S, _R]): cflags: str = "" frame_pointers: bool = False llvm_version: str = _llvm._LLVM_VERSION + llvm_tools_install_dir: str | None = None known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve() + def _compile_args(self) -> list[str]: + return list(self.args) + + def _shim_compile_args(self) -> list[str]: + return [] + def _get_nop(self) -> bytes: if re.fullmatch(r"aarch64-.*", self.triple): nop = b"\x1f\x20\x03\xd5" @@ -85,7 +92,11 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: group = _stencils.StencilGroup() args = ["--disassemble", "--reloc", f"{path}"] output = await _llvm.maybe_run( - "llvm-objdump", args, echo=self.verbose, llvm_version=self.llvm_version + "llvm-objdump", + args, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) if output is not None: # Make sure that full paths don't leak out (for reproducibility): @@ -105,7 +116,11 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: f"{path}", ] output = await _llvm.run( - "llvm-readobj", args, echo=self.verbose, llvm_version=self.llvm_version + "llvm-readobj", + args, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) # --elf-output-style=JSON is only *slightly* broken on Mach-O... output = output.replace("PrivateExtern\n", "\n") @@ -130,12 +145,8 @@ def _handle_relocation( ) -> _stencils.Hole: raise NotImplementedError(type(self)) - async def _compile( - self, opname: str, c: pathlib.Path, tempdir: pathlib.Path - ) -> _stencils.StencilGroup: - s = tempdir / f"{opname}.s" - o = tempdir / f"{opname}.o" - args_s = [ + def _base_clang_args(self, opname: str, tempdir: pathlib.Path) -> list[str]: + return [ f"--target={self.triple}", "-DPy_BUILD_CORE_MODULE", "-D_DEBUG" if self.debug else "-DNDEBUG", @@ -158,48 +169,88 @@ async def _compile( # generates better code than -O2 (and -O2 usually generates better # code than -O3). As a nice benefit, it uses less memory too: "-Os", - "-S", # Shorten full absolute file paths in the generated code (like the # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # This debug info isn't necessary, and bloats out the JIT'ed code. - # We *may* be able to re-enable this, process it, and JIT it for a - # nicer debugging experience... but that needs a lot more research: - "-fno-asynchronous-unwind-tables", # Don't call built-in functions that we can't find or patch: "-fno-builtin", # Don't call stack-smashing canaries that we can't find or patch: "-fno-stack-protector", "-std=c11", + ] + + async def _build_stencil_group( + self, opname: str, c: pathlib.Path, tempdir: pathlib.Path + ) -> _stencils.StencilGroup: + s = tempdir / f"{opname}.s" + o = tempdir / f"{opname}.o" + args_s = self._base_clang_args(opname, tempdir) + args_s += [ + "-S", + # Stencils do not need unwind info, and the optimizer does not + # preserve .cfi_* directives correctly. On Darwin, + # -fno-asynchronous-unwind-tables alone still leaves synchronous + # unwind directives in the assembly, so disable both forms here. + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", "-o", f"{s}", f"{c}", ] - is_shim = opname == "shim" if self.frame_pointers: - frame_pointer = "all" if is_shim else "reserved" - args_s += ["-Xclang", f"-mframe-pointer={frame_pointer}"] - args_s += self.args + args_s += ["-Xclang", "-mframe-pointer=reserved"] + args_s += self._compile_args() # Allow user-provided CFLAGS to override any defaults args_s += shlex.split(self.cflags) await _llvm.run( - "clang", args_s, echo=self.verbose, llvm_version=self.llvm_version + "clang", + args_s, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) - if not is_shim: - self.optimizer( - s, - label_prefix=self.label_prefix, - symbol_prefix=self.symbol_prefix, - re_global=self.re_global, - frame_pointers=self.frame_pointers, - ).run() + self.optimizer( + s, + label_prefix=self.label_prefix, + symbol_prefix=self.symbol_prefix, + re_global=self.re_global, + frame_pointers=self.frame_pointers, + ).run() args_o = [f"--target={self.triple}", "-c", "-o", f"{o}", f"{s}"] await _llvm.run( - "clang", args_o, echo=self.verbose, llvm_version=self.llvm_version + "clang", + args_o, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, ) return await self._parse(o) + async def _build_shim_object(self, output: pathlib.Path) -> None: + with tempfile.TemporaryDirectory() as tempdir: + work = pathlib.Path(tempdir).resolve() + args_o = self._base_clang_args("shim", work) + args_o += self._shim_compile_args() + args_o += [ + "-c", + # The linked shim is a real function in the final binary, so + # keep unwind info for debuggers and stack walkers. + "-fasynchronous-unwind-tables", + ] + if self.frame_pointers: + args_o += ["-Xclang", "-mframe-pointer=all"] + args_o += self._compile_args() + args_o += shlex.split(self.cflags) + args_o += ["-o", f"{output}", f"{TOOLS_JIT / 'shim.c'}"] + await _llvm.run( + "clang", + args_o, + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, + ) + async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: generated_cases = PYTHON_EXECUTOR_CASES_C_H.read_text() cases_and_opnames = sorted( @@ -208,11 +259,12 @@ async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: ) ) tasks = [] + # If you need to see the generated assembly files, + # uncomment line below (and comment out line below that) + # with tempfile.TemporaryDirectory("-stencils-assembly", delete=False) as tempdir: with tempfile.TemporaryDirectory() as tempdir: work = pathlib.Path(tempdir).resolve() async with asyncio.TaskGroup() as group: - coro = self._compile("shim", TOOLS_JIT / "shim.c", work) - tasks.append(group.create_task(coro, name="shim")) template = TOOLS_JIT_TEMPLATE_C.read_text() for case, opname in cases_and_opnames: # Write out a copy of the template with *only* this case @@ -222,7 +274,7 @@ async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: # all of the other cases): c = work / f"{opname}.c" c.write_text(template.replace("CASE", case)) - coro = self._compile(opname, c, work) + coro = self._build_stencil_group(opname, c, work) tasks.append(group.create_task(coro, name=opname)) stencil_groups = {task.get_name(): task.result() for task in tasks} for stencil_group in stencil_groups.values(): @@ -236,8 +288,9 @@ def build( comment: str = "", force: bool = False, jit_stencils: pathlib.Path, + jit_shim_object: pathlib.Path, ) -> None: - """Build jit_stencils.h in the given directory.""" + """Build jit_stencils.h and the shim object in the given directory.""" jit_stencils.parent.mkdir(parents=True, exist_ok=True) if not self.stable: warning = f"JIT support for {self.triple} is still experimental!" @@ -251,8 +304,10 @@ def build( not force and jit_stencils.exists() and jit_stencils.read_text().startswith(digest) + and jit_shim_object.exists() ): return + ASYNCIO_RUNNER.run(self._build_shim_object(jit_shim_object)) stencil_groups = ASYNCIO_RUNNER.run(self._build_stencils()) jit_stencils_new = jit_stencils.parent / "jit_stencils.h.new" try: @@ -276,6 +331,13 @@ def build( class _COFF( _Target[_schema.COFFSection, _schema.COFFRelocation] ): # pylint: disable = too-few-public-methods + def _shim_compile_args(self) -> list[str]: + # The linked shim is part of pythoncore, not a shared extension. + # On Windows, Py_BUILD_CORE_MODULE makes public APIs import from + # pythonXY.lib, which creates a self-dependency when linking + # pythoncore.dll. Build the shim with builtin/core semantics. + return ["-UPy_BUILD_CORE_MODULE", "-DPy_BUILD_CORE_BUILTIN"] + def _handle_section( self, section: _schema.COFFSection, group: _stencils.StencilGroup ) -> None: @@ -376,6 +438,10 @@ class _COFF64(_COFF): symbol_prefix = "" re_global = re.compile(r'\s*\.def\s+(?P