-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-115999: Specialize CALL_KW
in free-threaded builds
#127713
Conversation
`_PY_FRAME_KW` pushes a pointer to the new frame onto the stack for consumption by the next uop. When pushing the frame fails, we do not want to push the result, `NULL`, to the stack because it is not a valid stackref. This works in the default build because `PyStackRef_NULL` and `NULL` are the same value, so the `PyStackRef_XCLOSE()` in the error handler ignores it. In the free-threaded build the values are not the same; `PyStackRef_XCLOSE()` will attempt to decref a null pointer.
!buildbot nogil refleak |
🤖 New build scheduled with the buildbot fleet by @mpage for commit b22403e 🤖 The command will test the builders whose names match following regular expression: The builders matched are:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
!buildbot nogil refleak |
🤖 New build scheduled with the buildbot fleet by @mpage for commit aef38b1 🤖 The command will test the builders whose names match following regular expression: The builders matched are:
|
The
CALL_KW
family was already thread-safe. Only one change to fix a bug in_PY_FRAME_KW
was needed:_PY_FRAME_KW
pushes a pointer to the new frame onto the stack for consumption by the next uop. When pushing the frame fails, we do not want to push the result,NULL
, to the stack because it is not a valid stackref. This works in the default build becausePyStackRef_NULL
andNULL
are the same value, so thePyStackRef_XCLOSE()
in the error handler ignores it. In the free-threaded build the values are not the same, causingPyStackRef_XCLOSE()
to decref a null pointer.Single-threaded performance
Performance looks neutral on both builds. I think this is still worth merging to keep the two builds consistent, however.
Scalability
Scalability looks roughly unchanged:
Thread safety
The specialized instructions are composed of the follow uops, whose thread-safety is documented below.
_CALL_KW_NON_PY
- Tuples are immutable; it's fine to read their size non-atomically._CHECK_FUNCTION_VERSION_KW
- This uop guards that the top of the stack is a function and that its version matches the version stored in the inline cache. Instructions assume that if the guard passes, the version, and any properties verified by the version, will not change for the remainder of the instruction execution, assuming there are no escaping calls in between the guard and the code that relies on the guard. This property is preserved in free-threaded builds: the world is stopped whenever a function's version changes._CHECK_IS_NOT_PY_CALLABLE_KW
- Performs type checks._CHECK_METHOD_VERSION_KW
- This loads a function from a PyMethodObject and guards that its version matches what is stored in the cache. PyMethodObjects are immutable; their fields can be accessed non-atomically. The thread safety of function version guards was already documented above._CHECK_PEP_523
- Thread safety was addressed as part ofCALL
._CHECK_PERIODIC
- Thread safety was previously addressed as part of the 3.13 release._EXPAND_METHOD_KW
- Only loads from PyMethodObjects and performs type checks._PUSH_FRAME
- Only manipulateststate->current_frame
and fields that are not read by other threads._PY_FRAME_KW
- Loads immutable fields (tuple size, code flags) or fields that require stopping the world to modify (function code) and uses thread-safe APIs._SAVE_RETURN_OFFSET
- Stores only to the frame's return_offset which is not read by other threads.Specialization only looks at properties that require stopping the world to update (i.e. instance type,
eval_frame
,func_code
, and the function version) and contains no escaping calls.--disable-gil
builds #115999