gh-91053: Add an optional callback that is invoked whenever a function is modified#97834
gh-91053: Add an optional callback that is invoked whenever a function is modified#97834mpage wants to merge 152 commits into
Conversation
JIT compilers may need to invalidate compiled code when a function is modified (e.g. if its code object is modified). This adds the ability to set a callback that, when set, is called each time a function is modified.
|
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
|
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
The primary use case for this is a JIT, which will be per-runtime, not per-interpreter, so move the callback onto the runtime.
|
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
… be deleted This should would across platforms and implementations.
|
pyperformance results for the updated version where the callback is stored on the interpreter state still look perf-neutral: https://gist.github.com/mpage/26d2efdf0f6f166cf536c1ee9e5841a9 I wrote a microbenchmark to attempt to measure the overhead this imposes on function creation when no callback is set: https://gist.github.com/mpage/b3006c3b490460272d7a95438345b3f3 The overhead looks like it's small enough to be lost in the noise. Happy to use a different benchmark or a quieter machine if one is available. Upstream: This PR with no modified callback set: |
carljm
left a comment
There was a problem hiding this comment.
You should also add documentation for the new API in Doc/c-api/function.rst; don't forget the versionadded tag which I missed in the original dict watchers PR, too, and also add mention in Doc/whatsnew/3.12.rst.
Also it's worth running your added tests with -R just to ensure no accidental refleaks; CI won't catch that until post-land.
| * | ||
| * Pass NULL to clear the callback. | ||
| */ | ||
| PyAPI_FUNC(void) PyFunction_SetEventCallback(PyFunction_EventCallback callback); |
There was a problem hiding this comment.
I think we are going to want to support multiple watchers (up to 8, to match dict and type watchers), which means the API here should look like int PyFunction_AddWatcher which gives you back an id 0-7 (or -1 and sets an exception if there are no more watcher IDs available), and also PyFunction_ClearWatcher(int watcher_id) to clear a watcher. Can look at the dict watcher API in Include/cpython/dictobject.h and Python/dictobject.c to make it as parallel as we can. (Obviously with the difference that here we aren't doing per-function watching so there's no equivalent to PyDict_Watch API.)
| struct callable_cache callable_cache; | ||
|
|
||
|
|
||
| PyFunction_EventCallback func_event_callback; |
There was a problem hiding this comment.
So this will be PyFunction_EventCallback func_event_callbacks[FUNC_MAX_WATCHERS]; or similar.
| void | ||
| PyFunction_SetEventCallback(PyFunction_EventCallback callback) | ||
| { | ||
| PyThreadState *tstate = _PyThreadState_GET(); |
There was a problem hiding this comment.
You can also do PyInterpreterState *interp = _PyInterpreterState_GET(); directly since that's all you're using.
…yncioTestCase (python#93369) Lay the foundation for further work in `asyncio.test_streams`.
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Doc: Add references to PEP 686.
…eError suggestions (python#97022) Relevant tests moved from test_exceptions to test_traceback to be able to compare both implementations. Co-authored-by: Carl Friedrich Bolz-Tereick <cfbolz@gmx.de>
|
Ugh I botched rebasing this. Sorry for the noise everyone. Will open a new PR. |
|
@mpage once there's been some reviews you should always merge from main, never rebase |
JIT compilers may need to invalidate compiled code when a function is modified (e.g. if its code object is modified). This adds the ability to set a callback that, when set, is called each time a function is modified.
Pyperformance results look neutral: https://gist.github.com/mpage/0ffeaa76fa759c8230e91415eec44be3