@@ -1581,33 +1581,41 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyOb
1581
1581
return ix ;
1582
1582
}
1583
1583
1584
- Py_ssize_t
1585
- _Py_dict_lookup_threadsafe_stackref ( PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1584
+ static Py_ssize_t
1585
+ unicodekeys_lookup_unicode_threadsafe_stackref ( PyDictKeysObject * dk , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1586
1586
{
1587
- PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
1588
- 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 ) {
1587
+ assert (PyUnicode_CheckExact (key ));
1588
+ assert (dk -> dk_kind == DICT_KEYS_UNICODE );
1589
+ Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1590
+ if (ix == DKIX_EMPTY ) {
1591
+ * value_addr = PyStackRef_NULL ;
1592
+ return DKIX_EMPTY ;
1593
+ } else if (ix >= 0 ) {
1594
+ PyObject * * addr_of_value = & DK_UNICODE_ENTRIES (dk )[ix ].me_value ;
1595
+ PyObject * value = _Py_atomic_load_ptr (addr_of_value );
1596
+ if (value == NULL ) {
1591
1597
* value_addr = PyStackRef_NULL ;
1598
+ return DKIX_EMPTY ;
1599
+ }
1600
+ if (_PyObject_HasDeferredRefcount (value )) {
1601
+ * value_addr = (_PyStackRef ){ .bits = (uintptr_t )value | Py_TAG_DEFERRED };
1592
1602
return ix ;
1593
1603
}
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
- }
1604
+ if (_Py_TryIncrefCompare (addr_of_value , value )) {
1605
+ * value_addr = PyStackRef_FromPyObjectSteal (value );
1606
+ return ix ;
1609
1607
}
1610
1608
}
1609
+ }
1610
+
1611
+
1612
+ Py_ssize_t
1613
+ _Py_dict_lookup_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1614
+ {
1615
+ PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
1616
+ if (dk -> dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact (key )) {
1617
+ return unicodekeys_lookup_unicode_threadsafe_stackref (dk , key , hash , value_addr );
1618
+ }
1611
1619
1612
1620
PyObject * obj ;
1613
1621
Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
@@ -1620,6 +1628,33 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h
1620
1628
return ix ;
1621
1629
}
1622
1630
1631
+ // This is similar to _Py_dict_lookup_threadsafe_stackref() but
1632
+ // it is used when dict is borrowed reference and key is known to be unicode.
1633
+ // It avoids increfing the dict if dict only has unicode keys in which case
1634
+ // the lookup is safe, otherwise it increfs the dict and lookups the key.
1635
+
1636
+ Py_ssize_t
1637
+ _Py_dict_lookup_unicode_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1638
+ {
1639
+ assert (PyUnicode_CheckExact (key ));
1640
+ PyDictKeysObject * dk = _Py_atomic_load_ptr (& mp -> ma_keys );
1641
+ if (dk -> dk_kind == DICT_KEYS_UNICODE ) {
1642
+ return unicodekeys_lookup_unicode_threadsafe_stackref (dk , key , hash , value_addr );
1643
+ }
1644
+
1645
+ PyObject * obj ;
1646
+ Py_INCREF (mp );
1647
+ Py_ssize_t ix = _Py_dict_lookup_threadsafe (mp , key , hash , & obj );
1648
+ Py_DECREF (mp );
1649
+ if (ix >= 0 && obj != NULL ) {
1650
+ * value_addr = PyStackRef_FromPyObjectSteal (obj );
1651
+ }
1652
+ else {
1653
+ * value_addr = PyStackRef_NULL ;
1654
+ }
1655
+ return ix ;
1656
+ }
1657
+
1623
1658
#else // Py_GIL_DISABLED
1624
1659
1625
1660
Py_ssize_t
@@ -1644,6 +1679,23 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h
1644
1679
return ix ;
1645
1680
}
1646
1681
1682
+ Py_ssize_t
1683
+ _Py_dict_lookup_unicode_threadsafe_stackref (PyDictObject * mp , PyObject * key , Py_hash_t hash , _PyStackRef * value_addr )
1684
+ {
1685
+ assert (PyUnicode_CheckExact (key ));
1686
+ PyObject * val ;
1687
+ Py_INCREF (mp );
1688
+ Py_ssize_t ix = _Py_dict_lookup (mp , key , hash , & val );
1689
+ Py_DECREF (mp );
1690
+ if (ix >= 0 && val != NULL ) {
1691
+ * value_addr = PyStackRef_FromPyObjectNew (val );
1692
+ }
1693
+ else {
1694
+ * value_addr = PyStackRef_NULL ;
1695
+ }
1696
+ return ix ;
1697
+ }
1698
+
1647
1699
#endif
1648
1700
1649
1701
int
0 commit comments