-
-
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
Why do we have two counters for function versions? #116916
Comments
I think there is no reason to have two function versions. However it came it about, we should remove one of the versions. |
gvanrossum
added a commit
that referenced
this issue
Mar 18, 2024
Somehow we ended up with two separate counter variables tracking "the next function version". Most likely this was a historical accident where an old branch was updated incorrectly. This PR merges the two counters into a single one: `interp->func_state.next_version`.
vstinner
pushed a commit
to vstinner/cpython
that referenced
this issue
Mar 20, 2024
…6918) Somehow we ended up with two separate counter variables tracking "the next function version". Most likely this was a historical accident where an old branch was updated incorrectly. This PR merges the two counters into a single one: `interp->func_state.next_version`.
adorilson
pushed a commit
to adorilson/cpython
that referenced
this issue
Mar 25, 2024
…6918) Somehow we ended up with two separate counter variables tracking "the next function version". Most likely this was a historical accident where an old branch was updated incorrectly. This PR merges the two counters into a single one: `interp->func_state.next_version`.
diegorusso
pushed a commit
to diegorusso/cpython
that referenced
this issue
Apr 17, 2024
…6918) Somehow we ended up with two separate counter variables tracking "the next function version". Most likely this was a historical accident where an old branch was updated incorrectly. This PR merges the two counters into a single one: `interp->func_state.next_version`.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In the interpreter state there are two separate counters that are used to generate unique versions for code and function objects. Both counters share the following properties:
1
0
, it remains zero, and no new versions can be allocated (in this case the specializer will just give up -- hopefully this never happens in real code, creating four billion code objects is just hard to imagine)There are two ways that a function object obtains a version:
MAKE_FUNCTION
bytecode. In this case it gets the version from the code object. (See below.)func.__code__
or a few other attributes, the function version is reset, and if the specializer later needs a function version, a new version number is taken frominterp->func_state.next_version
by_PyFunction_GetVersionForCurrentState()
.Code objects obtain a version when they are created from
interp->next_func_version
.I believe there's a scenario where two unrelated function objects could end up with the same version:
interp->next_func_version
;__code__
attribute modified, and then obtains a fresh version frominterp->func_state.next_version
, which somehow has the same value as the other counter had -- this should be possible because the counters are managed independently.I looked a bit into the history, and it looks like in 3.11 there was only a static global
next_func_version
in funcobject.c, which was used by_PyFunction_GetVersionForCurrentState()
. In 3.12 the current structure exists, exceptnext_func_version
is still a static global (func_state
however is an interpreter member). It seems that this was introduced by gh-98525 (commit: fb713b2). Was it intentional to use two separate counters? If so, what was the rationale? (If it had to do with deepfreeze, that rationale is now gone, as we no longer use it.)Linked PRs
The text was updated successfully, but these errors were encountered: