@@ -1581,32 +1581,47 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyOb
15811581 return ix ;
15821582}
15831583
1584+ static Py_ssize_t
1585+ lookup_threadsafe_unicode (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1586+ {
1587+ assert (dk -> dk_kind == DICT_KEYS_UNICODE );
1588+ assert (PyUnicode_CheckExact (key ));
1589+
1590+ Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1591+ if (ix == DKIX_EMPTY ) {
1592+ * value_addr = PyStackRef_NULL ;
1593+ return ix ;
1594+ }
1595+ else if (ix >= 0 ) {
1596+ PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1597+ PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1598+ if (value == NULL ) {
1599+ * value_addr = PyStackRef_NULL ;
1600+ return DKIX_EMPTY ;
1601+ }
1602+ if (_PyObject_HasDeferredRefcount (value )) {
1603+ * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1604+ return ix ;
1605+ }
1606+ if (_Py_TryIncrefCompare (addr_of_value , value )) {
1607+ * value_addr = PyStackRef_FromPyObjectSteal (value );
1608+ return ix ;
1609+ }
1610+ return DKIX_KEY_CHANGED ;
1611+ }
1612+ assert (ix == DKIX_KEY_CHANGED );
1613+ return ix ;
1614+ }
1615+
15841616Py_ssize_t
15851617_Py_dict_lookup_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
15861618{
15871619 PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
15881620 if (dk -> dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact (key )) {
1589- Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1590- if (ix == DKIX_EMPTY ) {
1591- * value_addr = PyStackRef_NULL ;
1621+ Py_ssize_t ix = lookup_threadsafe_unicode (dk , key , hash , value_addr );
1622+ if (ix != DKIX_KEY_CHANGED ) {
15921623 return ix ;
15931624 }
1594- else if (ix >= 0 ) {
1595- PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1596- PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1597- if (value == NULL ) {
1598- * value_addr = PyStackRef_NULL ;
1599- return DKIX_EMPTY ;
1600- }
1601- if (_PyObject_HasDeferredRefcount (value )) {
1602- * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1603- return ix ;
1604- }
1605- if (_Py_TryIncrefCompare (addr_of_value , value )) {
1606- * value_addr = PyStackRef_FromPyObjectSteal (value );
1607- return ix ;
1608- }
1609- }
16101625 }
16111626
16121627 PyObject * obj ;
@@ -1646,6 +1661,46 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h
16461661
16471662#endif
16481663
1664+ // Looks up the unicode key `key` in the dictionary. Note that `*method` may
1665+ // already contain a valid value! See _PyObject_GetMethodStackRef().
1666+ int
1667+ _PyDict_GetMethodStackRef (PyDictObject * mp , PyObject * key , _PyStackRef * method )
1668+ {
1669+ assert (PyUnicode_CheckExact (key ));
1670+ Py_hash_t hash = hash_unicode_key (key );
1671+
1672+ #ifdef Py_GIL_DISABLED
1673+ PyDictKeysObject * dk = _Py_atomic_load_ptr_acquire (& mp -> ma_keys );
1674+ if (dk -> dk_kind == DICT_KEYS_UNICODE ) {
1675+ _PyStackRef ref ;
1676+ Py_ssize_t ix = lookup_threadsafe_unicode (dk , key , hash , & ref );
1677+ if (ix >= 0 ) {
1678+ assert (!PyStackRef_IsNull (ref ));
1679+ PyStackRef_XSETREF (* method , ref );
1680+ return 1 ;
1681+ }
1682+ else if (ix == DKIX_EMPTY ) {
1683+ return 0 ;
1684+ }
1685+ assert (ix == DKIX_KEY_CHANGED );
1686+ }
1687+ #endif
1688+
1689+ PyObject * obj ;
1690+ Py_INCREF (mp );
1691+ Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
1692+ Py_DECREF (mp );
1693+ if (ix == DKIX_ERROR ) {
1694+ PyStackRef_CLEAR (* method );
1695+ return -1 ;
1696+ }
1697+ else if (ix >= 0 && obj != NULL ) {
1698+ PyStackRef_XSETREF (* method , PyStackRef_FromPyObjectSteal (obj ));
1699+ return 1 ;
1700+ }
1701+ return 0 ; // not found
1702+ }
1703+
16491704int
16501705_PyDict_HasOnlyStringKeys (PyObject * dict )
16511706{
0 commit comments