mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
gh-124296: Remove private dictionary version tag (PEP 699) (#124472)
This commit is contained in:
parent
60ff67d010
commit
5aa91c56bf
13 changed files with 35 additions and 354 deletions
|
|
@ -877,7 +877,7 @@ new_dict(PyInterpreterState *interp,
|
|||
mp->ma_keys = keys;
|
||||
mp->ma_values = values;
|
||||
mp->ma_used = used;
|
||||
mp->ma_version_tag = DICT_NEXT_VERSION(interp);
|
||||
mp->_ma_watcher_tag = 0;
|
||||
ASSERT_CONSISTENT(mp);
|
||||
return (PyObject *)mp;
|
||||
}
|
||||
|
|
@ -1678,8 +1678,7 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
mp->ma_keys->dk_version = 0;
|
||||
|
||||
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
|
||||
|
|
@ -1698,7 +1697,6 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
STORE_VALUE(ep, value);
|
||||
STORE_HASH(ep, hash);
|
||||
}
|
||||
mp->ma_version_tag = new_version;
|
||||
STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
|
||||
STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
|
||||
assert(mp->ma_keys->dk_usable >= 0);
|
||||
|
|
@ -1744,16 +1742,14 @@ insert_split_value(PyInterpreterState *interp, PyDictObject *mp, PyObject *key,
|
|||
MAINTAIN_TRACKING(mp, key, value);
|
||||
PyObject *old_value = mp->ma_values->values[ix];
|
||||
if (old_value == NULL) {
|
||||
uint64_t new_version = _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value));
|
||||
_PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
|
||||
STORE_USED(mp, mp->ma_used + 1);
|
||||
mp->ma_version_tag = new_version;
|
||||
}
|
||||
else {
|
||||
uint64_t new_version = _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value);
|
||||
STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value));
|
||||
mp->ma_version_tag = new_version;
|
||||
// old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,
|
||||
// when dict only holds the strong reference to value in ep->me_value.
|
||||
Py_DECREF(old_value);
|
||||
|
|
@ -1815,8 +1811,7 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
}
|
||||
|
||||
if (old_value != value) {
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_MODIFIED, mp, key, value);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value);
|
||||
assert(old_value != NULL);
|
||||
assert(!_PyDict_HasSplitTable(mp));
|
||||
if (DK_IS_UNICODE(mp->ma_keys)) {
|
||||
|
|
@ -1827,7 +1822,6 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
|
||||
STORE_VALUE(ep, value);
|
||||
}
|
||||
mp->ma_version_tag = new_version;
|
||||
}
|
||||
Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
|
||||
ASSERT_CONSISTENT(mp);
|
||||
|
|
@ -1857,8 +1851,7 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
Py_DECREF(value);
|
||||
return -1;
|
||||
}
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
|
||||
|
||||
/* We don't decref Py_EMPTY_KEYS here because it is immortal. */
|
||||
assert(mp->ma_values == NULL);
|
||||
|
|
@ -1879,7 +1872,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
|
|||
STORE_VALUE(ep, value);
|
||||
}
|
||||
STORE_USED(mp, mp->ma_used + 1);
|
||||
mp->ma_version_tag = new_version;
|
||||
newkeys->dk_usable--;
|
||||
newkeys->dk_nentries++;
|
||||
// We store the keys last so no one can see them in a partially inconsistent
|
||||
|
|
@ -2612,7 +2604,7 @@ delete_index_from_values(PyDictValues *values, Py_ssize_t ix)
|
|||
|
||||
static void
|
||||
delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
|
||||
PyObject *old_value, uint64_t new_version)
|
||||
PyObject *old_value)
|
||||
{
|
||||
PyObject *old_key;
|
||||
|
||||
|
|
@ -2622,7 +2614,6 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
|
|||
assert(hashpos >= 0);
|
||||
|
||||
STORE_USED(mp, mp->ma_used - 1);
|
||||
mp->ma_version_tag = new_version;
|
||||
if (_PyDict_HasSplitTable(mp)) {
|
||||
assert(old_value == mp->ma_values->values[ix]);
|
||||
STORE_SPLIT_VALUE(mp, ix, NULL);
|
||||
|
|
@ -2692,9 +2683,8 @@ delitem_knownhash_lock_held(PyObject *op, PyObject *key, Py_hash_t hash)
|
|||
}
|
||||
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, old_value, new_version);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, old_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2740,9 +2730,8 @@ delitemif_lock_held(PyObject *op, PyObject *key,
|
|||
|
||||
if (res > 0) {
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, old_value, new_version);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, old_value);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
@ -2786,11 +2775,9 @@ clear_lock_held(PyObject *op)
|
|||
}
|
||||
/* Empty the dict... */
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_CLEARED, mp, NULL, NULL);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_CLEARED, mp, NULL, NULL);
|
||||
// We don't inc ref empty keys because they're immortal
|
||||
ensure_shared_on_resize(mp);
|
||||
mp->ma_version_tag = new_version;
|
||||
STORE_USED(mp, 0);
|
||||
if (oldvalues == NULL) {
|
||||
set_keys(mp, Py_EMPTY_KEYS);
|
||||
|
|
@ -2950,9 +2937,8 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash,
|
|||
|
||||
assert(old_value != NULL);
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, Py_NewRef(old_value));
|
||||
|
||||
ASSERT_CONSISTENT(mp);
|
||||
if (result) {
|
||||
|
|
@ -3717,8 +3703,7 @@ dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *othe
|
|||
(DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
|
||||
USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)
|
||||
) {
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL);
|
||||
PyDictKeysObject *keys = clone_combined_dict_keys(other);
|
||||
if (keys == NULL)
|
||||
return -1;
|
||||
|
|
@ -3727,7 +3712,6 @@ dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *othe
|
|||
dictkeys_decref(interp, mp->ma_keys, IS_DICT_SHARED(mp));
|
||||
mp->ma_keys = keys;
|
||||
STORE_USED(mp, other->ma_used);
|
||||
mp->ma_version_tag = new_version;
|
||||
ASSERT_CONSISTENT(mp);
|
||||
|
||||
if (_PyObject_GC_IS_TRACKED(other) && !_PyObject_GC_IS_TRACKED(mp)) {
|
||||
|
|
@ -3982,7 +3966,7 @@ copy_lock_held(PyObject *o)
|
|||
split_copy->ma_values = newvalues;
|
||||
split_copy->ma_keys = mp->ma_keys;
|
||||
split_copy->ma_used = mp->ma_used;
|
||||
split_copy->ma_version_tag = DICT_NEXT_VERSION(interp);
|
||||
split_copy->_ma_watcher_tag = 0;
|
||||
dictkeys_incref(mp->ma_keys);
|
||||
if (_PyObject_GC_IS_TRACKED(mp))
|
||||
_PyObject_GC_TRACK(split_copy);
|
||||
|
|
@ -4430,7 +4414,6 @@ dict_popitem_impl(PyDictObject *self)
|
|||
{
|
||||
Py_ssize_t i, j;
|
||||
PyObject *res;
|
||||
uint64_t new_version;
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
|
||||
ASSERT_DICT_LOCKED(self);
|
||||
|
|
@ -4473,8 +4456,7 @@ dict_popitem_impl(PyDictObject *self)
|
|||
assert(i >= 0);
|
||||
|
||||
key = ep0[i].me_key;
|
||||
new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||
hash = unicode_get_hash(key);
|
||||
value = ep0[i].me_value;
|
||||
ep0[i].me_key = NULL;
|
||||
|
|
@ -4489,8 +4471,7 @@ dict_popitem_impl(PyDictObject *self)
|
|||
assert(i >= 0);
|
||||
|
||||
key = ep0[i].me_key;
|
||||
new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||
_PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL);
|
||||
hash = ep0[i].me_hash;
|
||||
value = ep0[i].me_value;
|
||||
ep0[i].me_key = NULL;
|
||||
|
|
@ -4508,7 +4489,6 @@ dict_popitem_impl(PyDictObject *self)
|
|||
/* We can't dk_usable++ since there is DKIX_DUMMY in indices */
|
||||
STORE_KEYS_NENTRIES(self->ma_keys, i);
|
||||
STORE_USED(self, self->ma_used - 1);
|
||||
self->ma_version_tag = new_version;
|
||||
ASSERT_CONSISTENT(self);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -4759,8 +4739,7 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
PyDictObject *d = (PyDictObject *)self;
|
||||
|
||||
d->ma_used = 0;
|
||||
d->ma_version_tag = DICT_NEXT_VERSION(
|
||||
_PyInterpreterState_GET());
|
||||
d->_ma_watcher_tag = 0;
|
||||
dictkeys_incref(Py_EMPTY_KEYS);
|
||||
d->ma_keys = Py_EMPTY_KEYS;
|
||||
d->ma_values = NULL;
|
||||
|
|
@ -7384,7 +7363,7 @@ PyDict_Watch(int watcher_id, PyObject* dict)
|
|||
if (validate_watcher_id(interp, watcher_id)) {
|
||||
return -1;
|
||||
}
|
||||
((PyDictObject*)dict)->ma_version_tag |= (1LL << watcher_id);
|
||||
((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -7399,7 +7378,7 @@ PyDict_Unwatch(int watcher_id, PyObject* dict)
|
|||
if (validate_watcher_id(interp, watcher_id)) {
|
||||
return -1;
|
||||
}
|
||||
((PyDictObject*)dict)->ma_version_tag &= ~(1LL << watcher_id);
|
||||
((PyDictObject*)dict)->_ma_watcher_tag &= ~(1LL << watcher_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue