@@ -1581,84 +1581,51 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyOb
15811581 return ix ;
15821582}
15831583
1584-
1585- Py_ssize_t
1586- _Py_dict_lookup_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1584+ static Py_ssize_t
1585+ lookup_threadsafe_unicode (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
15871586{
1588- PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
1589- if (dk -> dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact (key )) {
1590- Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1591- if (ix == DKIX_EMPTY ) {
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 ) {
15921599 * 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 };
15931604 return ix ;
15941605 }
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- }
1606+ if (_Py_TryIncrefCompare (addr_of_value , value )) {
1607+ * value_addr = PyStackRef_FromPyObjectSteal (value );
1608+ return ix ;
16101609 }
1610+ return DKIX_KEY_CHANGED ;
16111611 }
1612-
1613- PyObject * obj ;
1614- Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
1615- if (ix >= 0 && obj != NULL ) {
1616- * value_addr = PyStackRef_FromPyObjectSteal (obj );
1617- }
1618- else {
1619- * value_addr = PyStackRef_NULL ;
1620- }
1612+ assert (ix == DKIX_KEY_CHANGED );
16211613 return ix ;
16221614}
16231615
1624- // This is similar to _Py_dict_lookup_threadsafe_stackref() but
1625- // it is used when dict is borrowed reference and key is known to be unicode.
1626- // It avoids increfing the dict if dict only has unicode keys in which case
1627- // the lookup is safe, otherwise it increfs the dict and lookups the key.
1628-
16291616Py_ssize_t
1630- _Py_dict_lookup_unicode_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1617+ _Py_dict_lookup_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
16311618{
1632- assert (PyUnicode_CheckExact (key ));
16331619 PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
1634- if (dk -> dk_kind == DICT_KEYS_UNICODE ) {
1635- Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1636- if (ix == DKIX_EMPTY ) {
1637- * value_addr = PyStackRef_NULL ;
1620+ if (dk -> dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact (key )) {
1621+ Py_ssize_t ix = lookup_threadsafe_unicode (dk , key , hash , value_addr );
1622+ if (ix != DKIX_KEY_CHANGED ) {
16381623 return ix ;
16391624 }
1640- else if (ix >= 0 ) {
1641- PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1642- PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1643- if (value == NULL ) {
1644- * value_addr = PyStackRef_NULL ;
1645- return DKIX_EMPTY ;
1646- }
1647- if (_PyObject_HasDeferredRefcount (value )) {
1648- * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1649- return ix ;
1650- }
1651- if (_Py_TryIncrefCompare (addr_of_value , value )) {
1652- * value_addr = PyStackRef_FromPyObjectSteal (value );
1653- return ix ;
1654- }
1655- }
16561625 }
16571626
16581627 PyObject * obj ;
1659- Py_INCREF (mp );
16601628 Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
1661- Py_DECREF (mp );
16621629 if (ix >= 0 && obj != NULL ) {
16631630 * value_addr = PyStackRef_FromPyObjectSteal (obj );
16641631 }
@@ -1692,25 +1659,48 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h
16921659 return ix ;
16931660}
16941661
1695- Py_ssize_t
1696- _Py_dict_lookup_unicode_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1662+ #endif
1663+
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 )
16971668{
16981669 assert (PyUnicode_CheckExact (key ));
1699- PyObject * val ;
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 ;
17001690 Py_INCREF (mp );
1701- Py_ssize_t ix = _Py_dict_lookup (mp , key , hash , & val );
1691+ Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
17021692 Py_DECREF (mp );
1703- if (ix >= 0 && val != NULL ) {
1704- * value_addr = PyStackRef_FromPyObjectNew (val );
1693+ if (ix == DKIX_ERROR ) {
1694+ PyStackRef_CLEAR (* method );
1695+ return -1 ;
17051696 }
1706- else {
1707- * value_addr = PyStackRef_NULL ;
1697+ else if (ix >= 0 && obj != NULL ) {
1698+ PyStackRef_XSETREF (* method , PyStackRef_FromPyObjectSteal (obj ));
1699+ return 1 ;
17081700 }
1709- return ix ;
1701+ return 0 ; // not found
17101702}
17111703
1712- #endif
1713-
17141704int
17151705_PyDict_HasOnlyStringKeys (PyObject * dict )
17161706{
0 commit comments