@@ -1584,34 +1584,49 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyOb
15841584 return ix ;
15851585}
15861586
1587+ static Py_ssize_t
1588+ lookup_threadsafe_unicode (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1589+ {
1590+ assert (dk -> dk_kind == DICT_KEYS_UNICODE );
1591+ assert (PyUnicode_CheckExact (key ));
1592+
1593+ Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1594+ if (ix == DKIX_EMPTY ) {
1595+ * value_addr = PyStackRef_NULL ;
1596+ return ix ;
1597+ }
1598+ else if (ix >= 0 ) {
1599+ PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1600+ PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1601+ if (value == NULL ) {
1602+ * value_addr = PyStackRef_NULL ;
1603+ return DKIX_EMPTY ;
1604+ }
1605+ if (_PyObject_HasDeferredRefcount (value )) {
1606+ * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1607+ return ix ;
1608+ }
1609+ if (_Py_TryIncrefCompare (addr_of_value , value )) {
1610+ * value_addr = PyStackRef_FromPyObjectSteal (value );
1611+ return ix ;
1612+ }
1613+ return DKIX_KEY_CHANGED ;
1614+ }
1615+ assert (ix == DKIX_KEY_CHANGED );
1616+ return ix ;
1617+ }
1618+
15871619Py_ssize_t
15881620_Py_dict_lookup_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
15891621{
15901622 ensure_shared_on_read (mp );
15911623
15921624 PyDictKeysObject * dk = _Py_atomic_load_ptr_acquire (& mp -> ma_keys );
15931625 if (dk -> dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact (key )) {
1594- Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1595- if (ix == DKIX_EMPTY ) {
1596- * value_addr = PyStackRef_NULL ;
1626+ Py_ssize_t ix = lookup_threadsafe_unicode (dk , key , hash , value_addr );
1627+ if (ix != DKIX_KEY_CHANGED ) {
15971628 return ix ;
15981629 }
1599- else if (ix >= 0 ) {
1600- PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1601- PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1602- if (value == NULL ) {
1603- * value_addr = PyStackRef_NULL ;
1604- return DKIX_EMPTY ;
1605- }
1606- if (_PyObject_HasDeferredRefcount (value )) {
1607- * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1608- return ix ;
1609- }
1610- if (_Py_TryIncrefCompare (addr_of_value , value )) {
1611- * value_addr = PyStackRef_FromPyObjectSteal (value );
1612- return ix ;
1613- }
1614- }
16151630 }
16161631
16171632 PyObject * obj ;
@@ -1651,6 +1666,46 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h
16511666
16521667#endif
16531668
1669+ // Looks up the unicode key `key` in the dictionary. Note that `*method` may
1670+ // already contain a valid value! See _PyObject_GetMethodStackRef().
1671+ int
1672+ _PyDict_GetMethodStackRef (PyDictObject * mp , PyObject * key , _PyStackRef * method )
1673+ {
1674+ assert (PyUnicode_CheckExact (key ));
1675+ Py_hash_t hash = hash_unicode_key (key );
1676+
1677+ #ifdef Py_GIL_DISABLED
1678+ PyDictKeysObject * dk = _Py_atomic_load_ptr_acquire (& mp -> ma_keys );
1679+ if (dk -> dk_kind == DICT_KEYS_UNICODE ) {
1680+ _PyStackRef ref ;
1681+ Py_ssize_t ix = lookup_threadsafe_unicode (dk , key , hash , & ref );
1682+ if (ix >= 0 ) {
1683+ assert (!PyStackRef_IsNull (ref ));
1684+ PyStackRef_XSETREF (* method , ref );
1685+ return 1 ;
1686+ }
1687+ else if (ix == DKIX_EMPTY ) {
1688+ return 0 ;
1689+ }
1690+ assert (ix == DKIX_KEY_CHANGED );
1691+ }
1692+ #endif
1693+
1694+ PyObject * obj ;
1695+ Py_INCREF (mp );
1696+ Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
1697+ Py_DECREF (mp );
1698+ if (ix == DKIX_ERROR ) {
1699+ PyStackRef_CLEAR (* method );
1700+ return -1 ;
1701+ }
1702+ else if (ix >= 0 && obj != NULL ) {
1703+ PyStackRef_XSETREF (* method , PyStackRef_FromPyObjectSteal (obj ));
1704+ return 1 ;
1705+ }
1706+ return 0 ; // not found
1707+ }
1708+
16541709int
16551710_PyDict_HasOnlyStringKeys (PyObject * dict )
16561711{
0 commit comments