gh-116916: Remove separate next_func_version counter (#116918)

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`.
This commit is contained in:
Guido van Rossum 2024-03-18 11:11:10 -07:00 committed by GitHub
parent 76d0868907
commit 7e1f38f2de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 7 additions and 9 deletions

View File

@ -245,7 +245,6 @@ struct _is {
uint16_t optimizer_side_threshold; uint16_t optimizer_side_threshold;
uint32_t next_func_version;
_rare_events rare_events; _rare_events rare_events;
PyDict_WatchCallback builtins_dict_watcher; PyDict_WatchCallback builtins_dict_watcher;

View File

@ -415,9 +415,9 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->co_ncellvars = ncellvars; co->co_ncellvars = ncellvars;
co->co_nfreevars = nfreevars; co->co_nfreevars = nfreevars;
PyInterpreterState *interp = _PyInterpreterState_GET(); PyInterpreterState *interp = _PyInterpreterState_GET();
co->co_version = interp->next_func_version; co->co_version = interp->func_state.next_version;
if (interp->next_func_version != 0) { if (interp->func_state.next_version != 0) {
interp->next_func_version++; interp->func_state.next_version++;
} }
co->_co_monitoring = NULL; co->_co_monitoring = NULL;
co->_co_instrumentation_version = 0; co->_co_instrumentation_version = 0;

View File

@ -236,8 +236,9 @@ How does a function's `func_version` field get initialized?
- A new version is allocated by `_PyFunction_GetVersionForCurrentState` - A new version is allocated by `_PyFunction_GetVersionForCurrentState`
when the specializer needs a version and the version is 0. when the specializer needs a version and the version is 0.
The latter allocates versions using a counter in the interpreter state; The latter allocates versions using a counter in the interpreter state,
when the counter wraps around to 0, no more versions are allocated. `interp->func_state.next_version`.
When the counter wraps around to 0, no more versions are allocated.
There is one other special case: functions with a non-standard There is one other special case: functions with a non-standard
`vectorcall` field are not given a version. `vectorcall` field are not given a version.
@ -247,8 +248,7 @@ Code object versions
-------------------- --------------------
So where to code objects get their `co_version`? So where to code objects get their `co_version`?
There is a per-interpreter counter, `next_func_version`. They share the same counter, `interp->func_state.next_version`.
This is initialized to 1 when the interpreter is created.
Code objects get a new `co_version` allocated from this counter upon Code objects get a new `co_version` allocated from this counter upon
creation. Since code objects are nominally immutable, `co_version` can creation. Since code objects are nominally immutable, `co_version` can

View File

@ -630,7 +630,6 @@ init_interpreter(PyInterpreterState *interp,
interp->sys_profile_initialized = false; interp->sys_profile_initialized = false;
interp->sys_trace_initialized = false; interp->sys_trace_initialized = false;
(void)_Py_SetOptimizer(interp, NULL); (void)_Py_SetOptimizer(interp, NULL);
interp->next_func_version = 1;
interp->executor_list_head = NULL; interp->executor_list_head = NULL;
if (interp != &runtime->_main_interpreter) { if (interp != &runtime->_main_interpreter) {
/* Fix the self-referential, statically initialized fields. */ /* Fix the self-referential, statically initialized fields. */