Skip to content

gh-119786: [doc] more consistent syntax in InternalDocs #125815

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 21, 2024
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
3 changes: 1 addition & 2 deletions InternalDocs/adaptive.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ although these are not fundamental and may change:

## Example family

The `LOAD_GLOBAL` instruction (in
[Python/bytecodes.c](https://github.com/python/cpython/blob/main/Python/bytecodes.c))
The `LOAD_GLOBAL` instruction (in [Python/bytecodes.c](../Python/bytecodes.c))
already has an adaptive family that serves as a relatively simple example.

The `LOAD_GLOBAL` instruction performs adaptive specialization,
Expand Down
418 changes: 194 additions & 224 deletions InternalDocs/compiler.md

Large diffs are not rendered by default.

28 changes: 12 additions & 16 deletions InternalDocs/exception_handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,16 @@ Handling Exceptions
-------------------

At runtime, when an exception occurs, the interpreter calls
``get_exception_handler()`` in
[Python/ceval.c](https://github.com/python/cpython/blob/main/Python/ceval.c)
`get_exception_handler()` in [Python/ceval.c](../Python/ceval.c)
to look up the offset of the current instruction in the exception
table. If it finds a handler, control flow transfers to it. Otherwise, the
exception bubbles up to the caller, and the caller's frame is
checked for a handler covering the `CALL` instruction. This
repeats until a handler is found or the topmost frame is reached.
If no handler is found, then the interpreter function
(``_PyEval_EvalFrameDefault()``) returns NULL. During unwinding,
(`_PyEval_EvalFrameDefault()`) returns NULL. During unwinding,
the traceback is constructed as each frame is added to it by
``PyTraceBack_Here()``, which is in
[Python/traceback.c](https://github.com/python/cpython/blob/main/Python/traceback.c).
`PyTraceBack_Here()`, which is in [Python/traceback.c](../Python/traceback.c).

Along with the location of an exception handler, each entry of the
exception table also contains the stack depth of the `try` instruction
Expand Down Expand Up @@ -174,22 +172,20 @@ which is then encoded as:

for a total of five bytes.

The code to construct the exception table is in ``assemble_exception_table()``
in [Python/assemble.c](https://github.com/python/cpython/blob/main/Python/assemble.c).
The code to construct the exception table is in `assemble_exception_table()`
in [Python/assemble.c](../Python/assemble.c).

The interpreter's function to lookup the table by instruction offset is
``get_exception_handler()`` in
[Python/ceval.c](https://github.com/python/cpython/blob/main/Python/ceval.c).
The Python function ``_parse_exception_table()`` in
[Lib/dis.py](https://github.com/python/cpython/blob/main/Lib/dis.py)
`get_exception_handler()` in [Python/ceval.c](../Python/ceval.c).
The Python function `_parse_exception_table()` in [Lib/dis.py](../Lib/dis.py)
returns the exception table content as a list of namedtuple instances.

Exception Chaining Implementation
---------------------------------

[Exception chaining](https://docs.python.org/dev/tutorial/errors.html#exception-chaining)
refers to setting the ``__context__`` and ``__cause__`` fields of an exception as it is
being raised. The ``__context__`` field is set by ``_PyErr_SetObject()`` in
[Python/errors.c](https://github.com/python/cpython/blob/main/Python/errors.c)
(which is ultimately called by all ``PyErr_Set*()`` functions).
The ``__cause__`` field (explicit chaining) is set by the ``RAISE_VARARGS`` bytecode.
refers to setting the `__context__` and `__cause__` fields of an exception as it is
being raised. The `__context__` field is set by `_PyErr_SetObject()` in
[Python/errors.c](../Python/errors.c) (which is ultimately called by all
`PyErr_Set*()` functions). The `__cause__` field (explicit chaining) is set by
the `RAISE_VARARGS` bytecode.
18 changes: 8 additions & 10 deletions InternalDocs/frames.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@ of three conceptual sections:
globals dict, code object, instruction pointer, stack depth, the
previous frame, etc.

The definition of the ``_PyInterpreterFrame`` struct is in
[Include/internal/pycore_frame.h](https://github.com/python/cpython/blob/main/Include/internal/pycore_frame.h).
The definition of the `_PyInterpreterFrame` struct is in
[Include/internal/pycore_frame.h](../Include/internal/pycore_frame.h).

# Allocation

Python semantics allows frames to outlive the activation, so they need to
be allocated outside the C call stack. To reduce overhead and improve locality
of reference, most frames are allocated contiguously in a per-thread stack
(see ``_PyThreadState_PushFrame`` in
[Python/pystate.c](https://github.com/python/cpython/blob/main/Python/pystate.c)).
(see `_PyThreadState_PushFrame` in [Python/pystate.c](../Python/pystate.c)).

Frames of generators and coroutines are embedded in the generator and coroutine
objects, so are not allocated in the per-thread stack. See ``PyGenObject`` in
[Include/internal/pycore_genobject.h](https://github.com/python/cpython/blob/main/Include/internal/pycore_genobject.h).
objects, so are not allocated in the per-thread stack. See `PyGenObject` in
[Include/internal/pycore_genobject.h](../Include/internal/pycore_genobject.h).

## Layout

Expand Down Expand Up @@ -82,16 +81,15 @@ frames for each activation, but with low runtime overhead.

### Generators and Coroutines

Generators (objects of type ``PyGen_Type``, ``PyCoro_Type`` or
``PyAsyncGen_Type``) have a `_PyInterpreterFrame` embedded in them, so
Generators (objects of type `PyGen_Type`, `PyCoro_Type` or
`PyAsyncGen_Type`) have a `_PyInterpreterFrame` embedded in them, so
that they can be created with a single memory allocation.
When such an embedded frame is iterated or awaited, it can be linked with
frames on the per-thread stack via the linkage fields.

If a frame object associated with a generator outlives the generator, then
the embedded `_PyInterpreterFrame` is copied into the frame object (see
``take_ownership()`` in
[Python/frame.c](https://github.com/python/cpython/blob/main/Python/frame.c)).
`take_ownership()` in [Python/frame.c](../Python/frame.c)).

### Field names

Expand Down
Loading