bpo-46836: Move PyFrameObject to pycore_frame.h by vstinner · Pull Request #31530 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Doc/c-api/veryhigh.rst
68 changes: 34 additions & 34 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -832,40 +832,40 @@ Porting to Python 3.11
which are not available in the limited C API.
(Contributed by Victor Stinner in :issue:`46007`.)

* Changes of the private :c:type:`PyFrameObject` structure members.
* The :c:type:`PyFrameObject` structure member has been moved to the internal C
API headers.

While the documentation notes that the fields of ``PyFrameObject`` are
subject to change at any time, they have been stable for a long time
and were used in several popular extensions.
In Python 3.11, the frame struct was reorganized to allow performance
optimizations. Rather than reading the fields directly, extensions should
use functions:
While the documentation notes that the :c:type:`PyFrameObject` fields are
subject to change at any time, they have been stable for a long time and were
used in several popular extensions.

* ``f_code``: removed, use :c:func:`PyFrame_GetCode` instead.
Warning: the function returns a :term:`strong reference`, need to call
:c:func:`Py_DECREF`.
* ``f_back``: changed (see below), use :c:func:`PyFrame_GetBack`.
* ``f_builtins``: removed,
use ``PyObject_GetAttrString((PyObject*)frame, "f_builtins")``.
* ``f_globals``: removed,
use ``PyObject_GetAttrString((PyObject*)frame, "f_globals")``.
* ``f_locals``: removed,
use ``PyObject_GetAttrString((PyObject*)frame, "f_locals")``.
* ``f_lasti``: removed,
use ``PyObject_GetAttrString((PyObject*)frame, "f_lasti")``.
Code using ``f_lasti`` with ``PyCode_Addr2Line()`` should use
In Python 3.11, the frame struct was reorganized to allow performance
optimizations. Some fields were removed entirely, as they were details of the
old implementation.

:c:type:`PyFrameObject` fields:

* ``f_back``: use :c:func:`PyFrame_GetBack`.
* ``f_blockstack``: removed.
* ``f_builtins``: use ``PyObject_GetAttrString((PyObject*)frame, "f_builtins")``.
* ``f_code``: use :c:func:`PyFrame_GetCode`.
* ``f_gen``: removed.
* ``f_globals``: use ``PyObject_GetAttrString((PyObject*)frame, "f_globals")``.
* ``f_iblock``: removed.
* ``f_lasti``: use ``PyObject_GetAttrString((PyObject*)frame, "f_lasti")``.
Code using ``f_lasti`` with ``PyCode_Addr2Line()`` must use
:c:func:`PyFrame_GetLineNumber` instead.

The following fields were removed entirely, as they were details
of the old implementation:

* ``f_valuesstack``
* ``f_stackdepth``
* ``f_gen``
* ``f_iblock``
* ``f_state``
* ``f_blockstack``
* ``f_localsplus``
* ``f_lineno``: use :c:func:`PyFrame_GetLineNumber`
* ``f_locals``: use ``PyObject_GetAttrString((PyObject*)frame, "f_locals")``.
* ``f_stackdepth``: removed.
* ``f_state``: no public API (renamed to ``f_frame.f_state``).
* ``f_trace``: no public API.
* ``f_trace_lines``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_lines")``
(it also be modified).
* ``f_trace_opcodes``: use ``PyObject_GetAttrString((PyObject*)frame, "f_trace_opcodes")``
(it also be modified).
* ``f_localsplus``: no public API (renamed to ``f_frame.localsplus``).
* ``f_valuestack``: removed.

The Python frame object is now created lazily. A side effect is that the
``f_back`` member must not be accessed directly, since its value is now also
Expand All @@ -892,9 +892,9 @@ Porting to Python 3.11
}
#endif

Or use `the pythoncapi_compat project
<https://github.com/pythoncapi/pythoncapi_compat>`__ to get these APIs
on older Python versions.
Or use the `pythoncapi_compat project
<https://github.com/pythoncapi/pythoncapi_compat>`__ to get these two
functions on older Python versions.

* Changes of the :c:type:`PyThreadState` structure members:

Expand Down
13 changes: 0 additions & 13 deletions Include/cpython/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,6 @@
# error "this header file must not be included directly"
#endif

struct _frame {
PyObject_HEAD
PyFrameObject *f_back; /* previous frame, or NULL */
struct _interpreter_frame *f_frame; /* points to the frame data */
PyObject *f_trace; /* Trace function */
int f_lineno; /* Current line number. Only valid if non-zero */
char f_trace_lines; /* Emit per-line trace events? */
char f_trace_opcodes; /* Emit per-opcode trace events? */
char f_owns_frame; /* This frame owns the frame */
/* The frame data, if this frame object owns the frame */
PyObject *_f_frame_data[1];
};

/* Standard object interface */

PyAPI_DATA(PyTypeObject) PyFrame_Type;
Expand Down
12 changes: 12 additions & 0 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ extern "C" {

#include <stdbool.h>

struct _frame {
PyObject_HEAD
PyFrameObject *f_back; /* previous frame, or NULL */
struct _interpreter_frame *f_frame; /* points to the frame data */
PyObject *f_trace; /* Trace function */
int f_lineno; /* Current line number. Only valid if non-zero */
char f_trace_lines; /* Emit per-line trace events? */
char f_trace_opcodes; /* Emit per-opcode trace events? */
char f_owns_frame; /* This frame owns the frame */
/* The frame data, if this frame object owns the frame */
PyObject *_f_frame_data[1];
};

/* runtime lifecycle */

Expand Down