[Python-checkins] gh-100227: Move dict_state.global_version to PyInterpreterState (gh-102338)

ericsnowcurrently webhook-mailer at python.org
Thu Mar 9 10:25:57 EST 2023


https://github.com/python/cpython/commit/b45d14b88611fefc6f054226d3e1117082d322c8
commit: b45d14b88611fefc6f054226d3e1117082d322c8
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2023-03-09T08:16:30-07:00
summary:

gh-100227: Move dict_state.global_version to PyInterpreterState (gh-102338)

https://github.com/python/cpython/issues/100227

files:
M Include/internal/pycore_dict.h
M Include/internal/pycore_dict_state.h
M Include/internal/pycore_runtime.h
M Objects/dictobject.c
M Python/bytecodes.c
M Python/generated_cases.c.h

diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index 12c3c708e29b..6253e0841ad3 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -149,8 +149,8 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
 #define DICT_VERSION_INCREMENT (1 << DICT_MAX_WATCHERS)
 #define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)
 
-#define DICT_NEXT_VERSION() \
-    (_PyRuntime.dict_state.global_version += DICT_VERSION_INCREMENT)
+#define DICT_NEXT_VERSION(INTERP) \
+    ((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT)
 
 void
 _PyDict_SendEvent(int watcher_bits,
@@ -160,7 +160,8 @@ _PyDict_SendEvent(int watcher_bits,
                   PyObject *value);
 
 static inline uint64_t
-_PyDict_NotifyEvent(PyDict_WatchEvent event,
+_PyDict_NotifyEvent(PyInterpreterState *interp,
+                    PyDict_WatchEvent event,
                     PyDictObject *mp,
                     PyObject *key,
                     PyObject *value)
@@ -169,9 +170,9 @@ _PyDict_NotifyEvent(PyDict_WatchEvent event,
     int watcher_bits = mp->ma_version_tag & DICT_VERSION_MASK;
     if (watcher_bits) {
         _PyDict_SendEvent(watcher_bits, event, mp, key, value);
-        return DICT_NEXT_VERSION() | watcher_bits;
+        return DICT_NEXT_VERSION(interp) | watcher_bits;
     }
-    return DICT_NEXT_VERSION();
+    return DICT_NEXT_VERSION(interp);
 }
 
 extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values);
diff --git a/Include/internal/pycore_dict_state.h b/Include/internal/pycore_dict_state.h
index c5142ee6763a..d608088ed2d7 100644
--- a/Include/internal/pycore_dict_state.h
+++ b/Include/internal/pycore_dict_state.h
@@ -9,14 +9,6 @@ extern "C" {
 #endif
 
 
-struct _Py_dict_runtime_state {
-    /*Global counter used to set ma_version_tag field of dictionary.
-     * It is incremented each time that a dictionary is created and each
-     * time that a dictionary is modified. */
-    uint64_t global_version;
-};
-
-
 #ifndef WITH_FREELISTS
 // without freelists
 #  define PyDict_MAXFREELIST 0
@@ -29,6 +21,10 @@ struct _Py_dict_runtime_state {
 #define DICT_MAX_WATCHERS 8
 
 struct _Py_dict_state {
+    /*Global counter used to set ma_version_tag field of dictionary.
+     * 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;
 
 #if PyDict_MAXFREELIST > 0
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index e0e3d4ace0cf..520109ca4404 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -10,7 +10,6 @@ extern "C" {
 
 #include "pycore_atomic.h"          /* _Py_atomic_address */
 #include "pycore_ceval_state.h"     // struct _ceval_runtime_state
-#include "pycore_dict_state.h"      // struct _Py_dict_runtime_state
 #include "pycore_floatobject.h"     // struct _Py_float_runtime_state
 #include "pycore_faulthandler.h"    // struct _faulthandler_runtime_state
 #include "pycore_global_objects.h"  // struct _Py_global_objects
@@ -153,7 +152,6 @@ typedef struct pyruntimestate {
 
     struct _Py_float_runtime_state float_state;
     struct _Py_unicode_runtime_state unicode_state;
-    struct _Py_dict_runtime_state dict_state;
 
     struct {
         /* Used to set PyTypeObject.tp_version_tag */
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index b58e93f4320d..227e438a8dff 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -232,7 +232,8 @@ equally good collision statistics, needed less code & used less memory.
 
 */
 
-static int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
+static int dictresize(PyInterpreterState *interp, PyDictObject *mp,
+                      uint8_t log_newsize, int unicode);
 
 static PyObject* dict_iter(PyDictObject *dict);
 
@@ -241,9 +242,8 @@ static PyObject* dict_iter(PyDictObject *dict);
 
 #if PyDict_MAXFREELIST > 0
 static struct _Py_dict_state *
-get_dict_state(void)
+get_dict_state(PyInterpreterState *interp)
 {
-    PyInterpreterState *interp = _PyInterpreterState_GET();
     return &interp->dict_state;
 }
 #endif
@@ -289,7 +289,8 @@ void
 _PyDict_DebugMallocStats(FILE *out)
 {
 #if PyDict_MAXFREELIST > 0
-    struct _Py_dict_state *state = get_dict_state();
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    struct _Py_dict_state *state = get_dict_state(interp);
     _PyDebugAllocatorStats(out, "free PyDictObject",
                            state->numfree, sizeof(PyDictObject));
 #endif
@@ -297,7 +298,7 @@ _PyDict_DebugMallocStats(FILE *out)
 
 #define DK_MASK(dk) (DK_SIZE(dk)-1)
 
-static void free_keys_object(PyDictKeysObject *keys);
+static void free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys);
 
 static inline void
 dictkeys_incref(PyDictKeysObject *dk)
@@ -309,14 +310,14 @@ dictkeys_incref(PyDictKeysObject *dk)
 }
 
 static inline void
-dictkeys_decref(PyDictKeysObject *dk)
+dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk)
 {
     assert(dk->dk_refcnt > 0);
 #ifdef Py_REF_DEBUG
     _Py_DecRefTotal();
 #endif
     if (--dk->dk_refcnt == 0) {
-        free_keys_object(dk);
+        free_keys_object(interp, dk);
     }
 }
 
@@ -586,7 +587,7 @@ _PyDict_CheckConsistency(PyObject *op, int check_content)
 
 
 static PyDictKeysObject*
-new_keys_object(uint8_t log2_size, bool unicode)
+new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
 {
     PyDictKeysObject *dk;
     Py_ssize_t usable;
@@ -612,7 +613,7 @@ new_keys_object(uint8_t log2_size, bool unicode)
     }
 
 #if PyDict_MAXFREELIST > 0
-    struct _Py_dict_state *state = get_dict_state();
+    struct _Py_dict_state *state = get_dict_state(interp);
 #ifdef Py_DEBUG
     // new_keys_object() must not be called after _PyDict_Fini()
     assert(state->keys_numfree != -1);
@@ -648,7 +649,7 @@ new_keys_object(uint8_t log2_size, bool unicode)
 }
 
 static void
-free_keys_object(PyDictKeysObject *keys)
+free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys)
 {
     assert(keys != Py_EMPTY_KEYS);
     if (DK_IS_UNICODE(keys)) {
@@ -668,7 +669,7 @@ free_keys_object(PyDictKeysObject *keys)
         }
     }
 #if PyDict_MAXFREELIST > 0
-    struct _Py_dict_state *state = get_dict_state();
+    struct _Py_dict_state *state = get_dict_state(interp);
 #ifdef Py_DEBUG
     // free_keys_object() must not be called after _PyDict_Fini()
     assert(state->keys_numfree != -1);
@@ -709,12 +710,14 @@ free_values(PyDictValues *values)
 
 /* Consumes a reference to the keys object */
 static PyObject *
-new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free_values_on_failure)
+new_dict(PyInterpreterState *interp,
+         PyDictKeysObject *keys, PyDictValues *values,
+         Py_ssize_t used, int free_values_on_failure)
 {
     PyDictObject *mp;
     assert(keys != NULL);
 #if PyDict_MAXFREELIST > 0
-    struct _Py_dict_state *state = get_dict_state();
+    struct _Py_dict_state *state = get_dict_state(interp);
 #ifdef Py_DEBUG
     // new_dict() must not be called after _PyDict_Fini()
     assert(state->numfree != -1);
@@ -731,7 +734,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
     {
         mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
         if (mp == NULL) {
-            dictkeys_decref(keys);
+            dictkeys_decref(interp, keys);
             if (free_values_on_failure) {
                 free_values(values);
             }
@@ -741,7 +744,7 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free
     mp->ma_keys = keys;
     mp->ma_values = values;
     mp->ma_used = used;
-    mp->ma_version_tag = DICT_NEXT_VERSION();
+    mp->ma_version_tag = DICT_NEXT_VERSION(interp);
     ASSERT_CONSISTENT(mp);
     return (PyObject *)mp;
 }
@@ -754,19 +757,19 @@ shared_keys_usable_size(PyDictKeysObject *keys)
 
 /* Consumes a reference to the keys object */
 static PyObject *
-new_dict_with_shared_keys(PyDictKeysObject *keys)
+new_dict_with_shared_keys(PyInterpreterState *interp, PyDictKeysObject *keys)
 {
     size_t size = shared_keys_usable_size(keys);
     PyDictValues *values = new_values(size);
     if (values == NULL) {
-        dictkeys_decref(keys);
+        dictkeys_decref(interp, keys);
         return PyErr_NoMemory();
     }
     ((char *)values)[-2] = 0;
     for (size_t i = 0; i < size; i++) {
         values->values[i] = NULL;
     }
-    return new_dict(keys, values, 0, 1);
+    return new_dict(interp, keys, values, 0, 1);
 }
 
 
@@ -829,8 +832,9 @@ clone_combined_dict_keys(PyDictObject *orig)
 PyObject *
 PyDict_New(void)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     dictkeys_incref(Py_EMPTY_KEYS);
-    return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
+    return new_dict(interp, Py_EMPTY_KEYS, NULL, 0, 0);
 }
 
 /* Search index of hash table from offset of entry table */
@@ -1170,9 +1174,9 @@ find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
 }
 
 static int
-insertion_resize(PyDictObject *mp, int unicode)
+insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)
 {
-    return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
+    return dictresize(interp, mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
 }
 
 static Py_ssize_t
@@ -1214,12 +1218,13 @@ Returns -1 if an error occurred, or 0 on success.
 Consumes key and value references.
 */
 static int
-insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
+insertdict(PyInterpreterState *interp, PyDictObject *mp,
+           PyObject *key, Py_hash_t hash, PyObject *value)
 {
     PyObject *old_value;
 
     if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
-        if (insertion_resize(mp, 0) < 0)
+        if (insertion_resize(interp, mp, 0) < 0)
             goto Fail;
         assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
     }
@@ -1231,13 +1236,14 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
     MAINTAIN_TRACKING(mp, key, value);
 
     if (ix == DKIX_EMPTY) {
-        uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
+        uint64_t new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_ADDED, mp, key, value);
         /* Insert into new slot. */
         mp->ma_keys->dk_version = 0;
         assert(old_value == NULL);
         if (mp->ma_keys->dk_usable <= 0) {
             /* Need to resize. */
-            if (insertion_resize(mp, 1) < 0)
+            if (insertion_resize(interp, mp, 1) < 0)
                 goto Fail;
         }
 
@@ -1275,7 +1281,8 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
     }
 
     if (old_value != value) {
-        uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, mp, key, value);
+        uint64_t new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_MODIFIED, mp, key, value);
         if (_PyDict_HasSplitTable(mp)) {
             mp->ma_values->values[ix] = value;
             if (old_value == NULL) {
@@ -1308,21 +1315,23 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
 // Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
 // Consumes key and value references.
 static int
-insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash,
-                    PyObject *value)
+insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
+                    PyObject *key, Py_hash_t hash, PyObject *value)
 {
     assert(mp->ma_keys == Py_EMPTY_KEYS);
 
-    uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
+    uint64_t new_version = _PyDict_NotifyEvent(
+            interp, PyDict_EVENT_ADDED, mp, key, value);
 
     int unicode = PyUnicode_CheckExact(key);
-    PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
+    PyDictKeysObject *newkeys = new_keys_object(
+            interp, PyDict_LOG_MINSIZE, unicode);
     if (newkeys == NULL) {
         Py_DECREF(key);
         Py_DECREF(value);
         return -1;
     }
-    dictkeys_decref(Py_EMPTY_KEYS);
+    dictkeys_decref(interp, Py_EMPTY_KEYS);
     mp->ma_keys = newkeys;
     mp->ma_values = NULL;
 
@@ -1397,7 +1406,8 @@ This function supports:
  - Generic -> Generic
 */
 static int
-dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
+dictresize(PyInterpreterState *interp, PyDictObject *mp,
+           uint8_t log2_newsize, int unicode)
 {
     PyDictKeysObject *oldkeys;
     PyDictValues *oldvalues;
@@ -1421,7 +1431,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
      */
 
     /* Allocate a new table. */
-    mp->ma_keys = new_keys_object(log2_newsize, unicode);
+    mp->ma_keys = new_keys_object(interp, log2_newsize, unicode);
     if (mp->ma_keys == NULL) {
         mp->ma_keys = oldkeys;
         return -1;
@@ -1462,7 +1472,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
             }
             build_indices_unicode(mp->ma_keys, newentries, numentries);
         }
-        dictkeys_decref(oldkeys);
+        dictkeys_decref(interp, oldkeys);
         mp->ma_values = NULL;
         free_values(oldvalues);
     }
@@ -1530,7 +1540,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
             assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
             assert(oldkeys->dk_refcnt == 1);
 #if PyDict_MAXFREELIST > 0
-            struct _Py_dict_state *state = get_dict_state();
+            struct _Py_dict_state *state = get_dict_state(interp);
 #ifdef Py_DEBUG
             // dictresize() must not be called after _PyDict_Fini()
             assert(state->keys_numfree != -1);
@@ -1557,7 +1567,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
 }
 
 static PyObject *
-dict_new_presized(Py_ssize_t minused, bool unicode)
+dict_new_presized(PyInterpreterState *interp, Py_ssize_t minused, bool unicode)
 {
     const uint8_t log2_max_presize = 17;
     const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
@@ -1578,16 +1588,17 @@ dict_new_presized(Py_ssize_t minused, bool unicode)
         log2_newsize = estimate_log2_keysize(minused);
     }
 
-    new_keys = new_keys_object(log2_newsize, unicode);
+    new_keys = new_keys_object(interp, log2_newsize, unicode);
     if (new_keys == NULL)
         return NULL;
-    return new_dict(new_keys, NULL, 0, 0);
+    return new_dict(interp, new_keys, NULL, 0, 0);
 }
 
 PyObject *
 _PyDict_NewPresized(Py_ssize_t minused)
 {
-    return dict_new_presized(minused, false);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    return dict_new_presized(interp, minused, false);
 }
 
 PyObject *
@@ -1597,6 +1608,7 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
 {
     bool unicode = true;
     PyObject *const *ks = keys;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     for (Py_ssize_t i = 0; i < length; i++) {
         if (!PyUnicode_CheckExact(*ks)) {
@@ -1606,7 +1618,7 @@ _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
         ks += keys_offset;
     }
 
-    PyObject *dict = dict_new_presized(length, unicode);
+    PyObject *dict = dict_new_presized(interp, length, unicode);
     if (dict == NULL) {
         return NULL;
     }
@@ -1834,11 +1846,12 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
             return -1;
         }
     }
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     if (mp->ma_keys == Py_EMPTY_KEYS) {
-        return insert_to_emptydict(mp, key, hash, value);
+        return insert_to_emptydict(interp, mp, key, hash, value);
     }
     /* insertdict() handles any resizing that might be necessary */
-    return insertdict(mp, key, hash, value);
+    return insertdict(interp, mp, key, hash, value);
 }
 
 /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
@@ -1875,11 +1888,12 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
     assert(hash != -1);
     mp = (PyDictObject *)op;
 
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     if (mp->ma_keys == Py_EMPTY_KEYS) {
-        return insert_to_emptydict(mp, Py_NewRef(key), hash, Py_NewRef(value));
+        return insert_to_emptydict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
     }
     /* insertdict() handles any resizing that might be necessary */
-    return insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
+    return insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
 }
 
 static void
@@ -1977,7 +1991,9 @@ _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
         return -1;
     }
 
-    uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    uint64_t new_version = _PyDict_NotifyEvent(
+            interp, PyDict_EVENT_DELETED, mp, key, NULL);
     return delitem_common(mp, hash, ix, old_value, new_version);
 }
 
@@ -2020,7 +2036,9 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key,
     assert(hashpos >= 0);
 
     if (res > 0) {
-        uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
+        PyInterpreterState *interp = _PyInterpreterState_GET();
+        uint64_t new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_DELETED, mp, key, NULL);
         return delitem_common(mp, hashpos, ix, old_value, new_version);
     } else {
         return 0;
@@ -2045,7 +2063,9 @@ PyDict_Clear(PyObject *op)
         return;
     }
     /* Empty the dict... */
-    uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_CLEARED, mp, NULL, NULL);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    uint64_t new_version = _PyDict_NotifyEvent(
+            interp, PyDict_EVENT_CLEARED, mp, NULL, NULL);
     dictkeys_incref(Py_EMPTY_KEYS);
     mp->ma_keys = Py_EMPTY_KEYS;
     mp->ma_values = NULL;
@@ -2057,11 +2077,11 @@ PyDict_Clear(PyObject *op)
         for (i = 0; i < n; i++)
             Py_CLEAR(oldvalues->values[i]);
         free_values(oldvalues);
-        dictkeys_decref(oldkeys);
+        dictkeys_decref(interp, oldkeys);
     }
     else {
        assert(oldkeys->dk_refcnt == 1);
-       dictkeys_decref(oldkeys);
+       dictkeys_decref(interp, oldkeys);
     }
     ASSERT_CONSISTENT(mp);
 }
@@ -2165,6 +2185,7 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
     Py_ssize_t ix;
     PyObject *old_value;
     PyDictObject *mp;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     assert(PyDict_Check(dict));
     mp = (PyDictObject *)dict;
@@ -2187,7 +2208,8 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
         return NULL;
     }
     assert(old_value != NULL);
-    uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
+    uint64_t new_version = _PyDict_NotifyEvent(
+            interp, PyDict_EVENT_DELETED, mp, key, NULL);
     delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
 
     ASSERT_CONSISTENT(mp);
@@ -2222,6 +2244,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
     PyObject *key;
     PyObject *d;
     int status;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     d = _PyObject_CallNoArgs(cls);
     if (d == NULL)
@@ -2236,13 +2259,16 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
             Py_hash_t hash;
 
             int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
-            if (dictresize(mp, estimate_log2_keysize(PyDict_GET_SIZE(iterable)), unicode)) {
+            if (dictresize(interp, mp,
+                           estimate_log2_keysize(PyDict_GET_SIZE(iterable)),
+                           unicode)) {
                 Py_DECREF(d);
                 return NULL;
             }
 
             while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
-                if (insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value))) {
+                if (insertdict(interp, mp,
+                               Py_NewRef(key), hash, Py_NewRef(value))) {
                     Py_DECREF(d);
                     return NULL;
                 }
@@ -2255,13 +2281,14 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
             PyObject *key;
             Py_hash_t hash;
 
-            if (dictresize(mp, estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
+            if (dictresize(interp, mp,
+                           estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
                 Py_DECREF(d);
                 return NULL;
             }
 
             while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
-                if (insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value))) {
+                if (insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value))) {
                     Py_DECREF(d);
                     return NULL;
                 }
@@ -2308,9 +2335,10 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
 static void
 dict_dealloc(PyDictObject *mp)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     assert(Py_REFCNT(mp) == 0);
     Py_SET_REFCNT(mp, 1);
-    _PyDict_NotifyEvent(PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
+    _PyDict_NotifyEvent(interp, PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
     if (Py_REFCNT(mp) > 1) {
         Py_SET_REFCNT(mp, Py_REFCNT(mp) - 1);
         return;
@@ -2328,14 +2356,14 @@ dict_dealloc(PyDictObject *mp)
             Py_XDECREF(values->values[i]);
         }
         free_values(values);
-        dictkeys_decref(keys);
+        dictkeys_decref(interp, keys);
     }
     else if (keys != NULL) {
         assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
-        dictkeys_decref(keys);
+        dictkeys_decref(interp, keys);
     }
 #if PyDict_MAXFREELIST > 0
-    struct _Py_dict_state *state = get_dict_state();
+    struct _Py_dict_state *state = get_dict_state(interp);
 #ifdef Py_DEBUG
     // new_dict() must not be called after _PyDict_Fini()
     assert(state->numfree != -1);
@@ -2765,7 +2793,7 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
 }
 
 static int
-dict_merge(PyObject *a, PyObject *b, int override)
+dict_merge(PyInterpreterState *interp, PyObject *a, PyObject *b, int override)
 {
     PyDictObject *mp, *other;
 
@@ -2799,13 +2827,14 @@ dict_merge(PyObject *a, PyObject *b, int override)
                     other->ma_used == okeys->dk_nentries &&
                     (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
                      USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)) {
-                uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_CLONED, mp, b, NULL);
+                uint64_t new_version = _PyDict_NotifyEvent(
+                        interp, PyDict_EVENT_CLONED, mp, b, NULL);
                 PyDictKeysObject *keys = clone_combined_dict_keys(other);
                 if (keys == NULL) {
                     return -1;
                 }
 
-                dictkeys_decref(mp->ma_keys);
+                dictkeys_decref(interp, mp->ma_keys);
                 mp->ma_keys = keys;
                 if (mp->ma_values != NULL) {
                     free_values(mp->ma_values);
@@ -2830,7 +2859,9 @@ dict_merge(PyObject *a, PyObject *b, int override)
          */
         if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
             int unicode = DK_IS_UNICODE(other->ma_keys);
-            if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used), unicode)) {
+            if (dictresize(interp, mp,
+                           estimate_log2_keysize(mp->ma_used + other->ma_used),
+                           unicode)) {
                return -1;
             }
         }
@@ -2845,12 +2876,14 @@ dict_merge(PyObject *a, PyObject *b, int override)
             Py_INCREF(key);
             Py_INCREF(value);
             if (override == 1) {
-                err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
+                err = insertdict(interp, mp,
+                                 Py_NewRef(key), hash, Py_NewRef(value));
             }
             else {
                 err = _PyDict_Contains_KnownHash(a, key, hash);
                 if (err == 0) {
-                    err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
+                    err = insertdict(interp, mp,
+                                     Py_NewRef(key), hash, Py_NewRef(value));
                 }
                 else if (err > 0) {
                     if (override != 0) {
@@ -2936,20 +2969,23 @@ dict_merge(PyObject *a, PyObject *b, int override)
 int
 PyDict_Update(PyObject *a, PyObject *b)
 {
-    return dict_merge(a, b, 1);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    return dict_merge(interp, a, b, 1);
 }
 
 int
 PyDict_Merge(PyObject *a, PyObject *b, int override)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     /* XXX Deprecate override not in (0, 1). */
-    return dict_merge(a, b, override != 0);
+    return dict_merge(interp, a, b, override != 0);
 }
 
 int
 _PyDict_MergeEx(PyObject *a, PyObject *b, int override)
 {
-    return dict_merge(a, b, override);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    return dict_merge(interp, a, b, override);
 }
 
 static PyObject *
@@ -2963,6 +2999,7 @@ PyDict_Copy(PyObject *o)
 {
     PyObject *copy;
     PyDictObject *mp;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     if (o == NULL || !PyDict_Check(o)) {
         PyErr_BadInternalCall();
@@ -2991,7 +3028,7 @@ PyDict_Copy(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();
+        split_copy->ma_version_tag = DICT_NEXT_VERSION(interp);
         dictkeys_incref(mp->ma_keys);
         for (size_t i = 0; i < size; i++) {
             PyObject *value = mp->ma_values->values[i];
@@ -3024,7 +3061,7 @@ PyDict_Copy(PyObject *o)
         if (keys == NULL) {
             return NULL;
         }
-        PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
+        PyDictObject *new = (PyDictObject *)new_dict(interp, keys, NULL, 0, 0);
         if (new == NULL) {
             /* In case of an error, `new_dict()` takes care of
                cleaning up `keys`. */
@@ -3044,7 +3081,7 @@ PyDict_Copy(PyObject *o)
     copy = PyDict_New();
     if (copy == NULL)
         return NULL;
-    if (dict_merge(copy, o, 1) == 0)
+    if (dict_merge(interp, copy, o, 1) == 0)
         return copy;
     Py_DECREF(copy);
     return NULL;
@@ -3244,6 +3281,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
     PyDictObject *mp = (PyDictObject *)d;
     PyObject *value;
     Py_hash_t hash;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     if (!PyDict_Check(d)) {
         PyErr_BadInternalCall();
@@ -3257,7 +3295,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
     }
 
     if (mp->ma_keys == Py_EMPTY_KEYS) {
-        if (insert_to_emptydict(mp, Py_NewRef(key), hash,
+        if (insert_to_emptydict(interp, mp, Py_NewRef(key), hash,
                                 Py_NewRef(defaultobj)) < 0) {
             return NULL;
         }
@@ -3265,7 +3303,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
     }
 
     if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
-        if (insertion_resize(mp, 0) < 0) {
+        if (insertion_resize(interp, mp, 0) < 0) {
             return NULL;
         }
     }
@@ -3275,11 +3313,12 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
         return NULL;
 
     if (ix == DKIX_EMPTY) {
-        uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, defaultobj);
+        uint64_t new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
         mp->ma_keys->dk_version = 0;
         value = defaultobj;
         if (mp->ma_keys->dk_usable <= 0) {
-            if (insertion_resize(mp, 1) < 0) {
+            if (insertion_resize(interp, mp, 1) < 0) {
                 return NULL;
             }
         }
@@ -3314,7 +3353,8 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
         assert(mp->ma_keys->dk_usable >= 0);
     }
     else if (value == NULL) {
-        uint64_t new_version = _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, defaultobj);
+        uint64_t new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
         value = defaultobj;
         assert(_PyDict_HasSplitTable(mp));
         assert(mp->ma_values->values[ix] == NULL);
@@ -3395,6 +3435,7 @@ dict_popitem_impl(PyDictObject *self)
     Py_ssize_t i, j;
     PyObject *res;
     uint64_t new_version;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     /* Allocate the result tuple before checking the size.  Believe it
      * or not, this allocation could trigger a garbage collection which
@@ -3415,7 +3456,7 @@ dict_popitem_impl(PyDictObject *self)
     }
     /* Convert split table to combined table */
     if (self->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
-        if (dictresize(self, DK_LOG_SIZE(self->ma_keys), 1)) {
+        if (dictresize(interp, self, DK_LOG_SIZE(self->ma_keys), 1)) {
             Py_DECREF(res);
             return NULL;
         }
@@ -3434,7 +3475,8 @@ dict_popitem_impl(PyDictObject *self)
         assert(i >= 0);
 
         key = ep0[i].me_key;
-        new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, self, key, NULL);
+        new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_DELETED, self, key, NULL);
         hash = unicode_get_hash(key);
         value = ep0[i].me_value;
         ep0[i].me_key = NULL;
@@ -3449,7 +3491,8 @@ dict_popitem_impl(PyDictObject *self)
         assert(i >= 0);
 
         key = ep0[i].me_key;
-        new_version = _PyDict_NotifyEvent(PyDict_EVENT_DELETED, self, key, NULL);
+        new_version = _PyDict_NotifyEvent(
+                interp, PyDict_EVENT_DELETED, self, key, NULL);
         hash = ep0[i].me_hash;
         value = ep0[i].me_value;
         ep0[i].me_key = NULL;
@@ -3708,7 +3751,8 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyDictObject *d = (PyDictObject *)self;
 
     d->ma_used = 0;
-    d->ma_version_tag = DICT_NEXT_VERSION();
+    d->ma_version_tag = DICT_NEXT_VERSION(
+            _PyInterpreterState_GET());
     dictkeys_incref(Py_EMPTY_KEYS);
     d->ma_keys = Py_EMPTY_KEYS;
     d->ma_values = NULL;
@@ -5262,7 +5306,9 @@ dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
 PyDictKeysObject *
 _PyDict_NewKeysForClass(void)
 {
-    PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    PyDictKeysObject *keys = new_keys_object(
+            interp, NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
     if (keys == NULL) {
         PyErr_Clear();
     }
@@ -5306,6 +5352,7 @@ init_inline_values(PyObject *obj, PyTypeObject *tp)
 int
 _PyObject_InitializeDict(PyObject *obj)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     PyTypeObject *tp = Py_TYPE(obj);
     if (tp->tp_dictoffset == 0) {
         return 0;
@@ -5317,7 +5364,7 @@ _PyObject_InitializeDict(PyObject *obj)
     PyObject *dict;
     if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
         dictkeys_incref(CACHED_KEYS(tp));
-        dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
+        dict = new_dict_with_shared_keys(interp, CACHED_KEYS(tp));
     }
     else {
         dict = PyDict_New();
@@ -5331,7 +5378,8 @@ _PyObject_InitializeDict(PyObject *obj)
 }
 
 static PyObject *
-make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
+make_dict_from_instance_attributes(PyInterpreterState *interp,
+                                   PyDictKeysObject *keys, PyDictValues *values)
 {
     dictkeys_incref(keys);
     Py_ssize_t used = 0;
@@ -5344,7 +5392,7 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
             track += _PyObject_GC_MAY_BE_TRACKED(val);
         }
     }
-    PyObject *res = new_dict(keys, values, used, 0);
+    PyObject *res = new_dict(interp, keys, values, used, 0);
     if (track && res) {
         _PyObject_GC_TRACK(res);
     }
@@ -5354,15 +5402,17 @@ make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
 PyObject *
 _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
     OBJECT_STAT_INC(dict_materialized_on_request);
-    return make_dict_from_instance_attributes(keys, values);
+    return make_dict_from_instance_attributes(interp, keys, values);
 }
 
 int
 _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
                               PyObject *name, PyObject *value)
 {
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
     assert(keys != NULL);
     assert(values != NULL);
@@ -5385,7 +5435,8 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
             OBJECT_STAT_INC(dict_materialized_str_subclass);
         }
 #endif
-        PyObject *dict = make_dict_from_instance_attributes(keys, values);
+        PyObject *dict = make_dict_from_instance_attributes(
+                interp, keys, values);
         if (dict == NULL) {
             return -1;
         }
@@ -5564,13 +5615,15 @@ PyObject *
 PyObject_GenericGetDict(PyObject *obj, void *context)
 {
     PyObject *dict;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
     PyTypeObject *tp = Py_TYPE(obj);
     if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
         PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
         if (_PyDictOrValues_IsValues(*dorv_ptr)) {
             PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
             OBJECT_STAT_INC(dict_materialized_on_request);
-            dict = make_dict_from_instance_attributes(CACHED_KEYS(tp), values);
+            dict = make_dict_from_instance_attributes(
+                    interp, CACHED_KEYS(tp), values);
             if (dict != NULL) {
                 dorv_ptr->dict = dict;
             }
@@ -5579,7 +5632,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
             dict = _PyDictOrValues_GetDict(*dorv_ptr);
             if (dict == NULL) {
                 dictkeys_incref(CACHED_KEYS(tp));
-                dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
+                dict = new_dict_with_shared_keys(interp, CACHED_KEYS(tp));
                 dorv_ptr->dict = dict;
             }
         }
@@ -5596,7 +5649,8 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
             PyTypeObject *tp = Py_TYPE(obj);
             if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
                 dictkeys_incref(CACHED_KEYS(tp));
-                *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
+                *dictptr = dict = new_dict_with_shared_keys(
+                        interp, CACHED_KEYS(tp));
             }
             else {
                 *dictptr = dict = PyDict_New();
@@ -5613,6 +5667,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
     PyObject *dict;
     int res;
     PyDictKeysObject *cached;
+    PyInterpreterState *interp = _PyInterpreterState_GET();
 
     assert(dictptr != NULL);
     if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
@@ -5620,7 +5675,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
         dict = *dictptr;
         if (dict == NULL) {
             dictkeys_incref(cached);
-            dict = new_dict_with_shared_keys(cached);
+            dict = new_dict_with_shared_keys(interp, cached);
             if (dict == NULL)
                 return -1;
             *dictptr = dict;
@@ -5652,7 +5707,8 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
 void
 _PyDictKeys_DecRef(PyDictKeysObject *keys)
 {
-    dictkeys_decref(keys);
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    dictkeys_decref(interp, keys);
 }
 
 uint32_t _PyDictKeys_GetVersionForCurrentState(PyInterpreterState *interp,
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 63dbecad3b45..45d507266743 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1679,7 +1679,7 @@ dummy_func(
                 DEOPT_IF(ep->me_key != name, STORE_ATTR);
                 old_value = ep->me_value;
                 DEOPT_IF(old_value == NULL, STORE_ATTR);
-                new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
+                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
                 ep->me_value = value;
             }
             else {
@@ -1687,7 +1687,7 @@ dummy_func(
                 DEOPT_IF(ep->me_key != name, STORE_ATTR);
                 old_value = ep->me_value;
                 DEOPT_IF(old_value == NULL, STORE_ATTR);
-                new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
+                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
                 ep->me_value = value;
             }
             Py_DECREF(old_value);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 82e18505b0d4..51357cda4c89 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2114,7 +2114,7 @@
                 DEOPT_IF(ep->me_key != name, STORE_ATTR);
                 old_value = ep->me_value;
                 DEOPT_IF(old_value == NULL, STORE_ATTR);
-                new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
+                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
                 ep->me_value = value;
             }
             else {
@@ -2122,7 +2122,7 @@
                 DEOPT_IF(ep->me_key != name, STORE_ATTR);
                 old_value = ep->me_value;
                 DEOPT_IF(old_value == NULL, STORE_ATTR);
-                new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
+                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
                 ep->me_value = value;
             }
             Py_DECREF(old_value);



More information about the Python-checkins mailing list