Skip to content

Commit

Permalink
gh-100227: Move next_keys_version to PyInterpreterState (gh-102335)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently committed Mar 9, 2023
1 parent 66ff374 commit 5e5acd2
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 13 deletions.
3 changes: 2 additions & 1 deletion Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);

/* Gets a version number unique to the current state of the keys of dict, if possible.
* Returns the version number, or zero if it was not possible to get a version number. */
extern uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys);
extern uint32_t _PyDictKeys_GetVersionForCurrentState(
PyInterpreterState *interp, PyDictKeysObject *dictkeys);

extern size_t _PyDict_KeysSize(PyDictKeysObject *keys);

Expand Down
4 changes: 3 additions & 1 deletion Include/internal/pycore_dict_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct _Py_dict_runtime_state {
* It is incremented each time that a dictionary is created and each
* time that a dictionary is modified. */
uint64_t global_version;
uint32_t next_keys_version;
};


Expand All @@ -30,13 +29,16 @@ struct _Py_dict_runtime_state {
#define DICT_MAX_WATCHERS 8

struct _Py_dict_state {
uint32_t next_keys_version;

#if PyDict_MAXFREELIST > 0
/* Dictionary reuse scheme to save calls to malloc and free */
PyDictObject *free_list[PyDict_MAXFREELIST];
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
int numfree;
int keys_numfree;
#endif

PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
};

Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ extern PyTypeObject _PyExc_MemoryError;
.float_format = _py_float_format_unknown, \
.double_format = _py_float_format_unknown, \
}, \
.dict_state = { \
.next_keys_version = 2, \
}, \
.types = { \
.next_version_tag = 1, \
}, \
Expand Down Expand Up @@ -113,6 +110,9 @@ extern PyTypeObject _PyExc_MemoryError;
}, \
}, \
.dtoa = _dtoa_state_INIT(&(INTERP)), \
.dict_state = { \
.next_keys_version = 2, \
}, \
.func_state = { \
.next_version = 1, \
}, \
Expand Down
7 changes: 4 additions & 3 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5655,15 +5655,16 @@ _PyDictKeys_DecRef(PyDictKeysObject *keys)
dictkeys_decref(keys);
}

uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys)
uint32_t _PyDictKeys_GetVersionForCurrentState(PyInterpreterState *interp,
PyDictKeysObject *dictkeys)
{
if (dictkeys->dk_version != 0) {
return dictkeys->dk_version;
}
if (_PyRuntime.dict_state.next_keys_version == 0) {
if (interp->dict_state.next_keys_version == 0) {
return 0;
}
uint32_t v = _PyRuntime.dict_state.next_keys_version++;
uint32_t v = interp->dict_state.next_keys_version++;
dictkeys->dk_version = v;
return v;
}
Expand Down
16 changes: 11 additions & 5 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,8 @@ specialize_module_load_attr(
SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(dict->ma_keys);
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(
_PyInterpreterState_GET(), dict->ma_keys);
if (keys_version == 0) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
Expand Down Expand Up @@ -1063,7 +1064,8 @@ PyObject *descr, DescriptorClassification kind)
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED);
return 0;
}
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(keys);
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(
_PyInterpreterState_GET(), keys);
if (keys_version == 0) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return 0;
Expand Down Expand Up @@ -1134,12 +1136,14 @@ _Py_Specialize_LoadGlobal(
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
goto fail;
}
PyInterpreterState *interp = _PyInterpreterState_GET();
if (index != DKIX_EMPTY) {
if (index != (uint16_t)index) {
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
goto fail;
}
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(globals_keys);
uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(
interp, globals_keys);
if (keys_version == 0) {
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
goto fail;
Expand Down Expand Up @@ -1167,12 +1171,14 @@ _Py_Specialize_LoadGlobal(
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
goto fail;
}
uint32_t globals_version = _PyDictKeys_GetVersionForCurrentState(globals_keys);
uint32_t globals_version = _PyDictKeys_GetVersionForCurrentState(
interp, globals_keys);
if (globals_version == 0) {
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
goto fail;
}
uint32_t builtins_version = _PyDictKeys_GetVersionForCurrentState(builtin_keys);
uint32_t builtins_version = _PyDictKeys_GetVersionForCurrentState(
interp, builtin_keys);
if (builtins_version == 0) {
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
goto fail;
Expand Down

0 comments on commit 5e5acd2

Please sign in to comment.