@@ -5636,6 +5636,26 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
56365636 return res ;
56375637}
56385638
5639+ static PyObject *
5640+ find_name_in_mro_new (PyObject * mro_dict , PyObject * name , int * error )
5641+ {
5642+ ASSERT_TYPE_LOCK_HELD ();
5643+
5644+ Py_hash_t hash = _PyObject_HashFast (name );
5645+ if (hash == -1 ) {
5646+ * error = -1 ;
5647+ return NULL ;
5648+ }
5649+
5650+ PyObject * res = NULL ;
5651+ if (_PyDict_GetItemRef_KnownHash ((PyDictObject * )mro_dict , name , hash , & res ) < 0 ) {
5652+ * error = -1 ;
5653+ } else {
5654+ * error = 0 ;
5655+ }
5656+ return res ;
5657+ }
5658+
56395659/* Check if the "readied" PyUnicode name
56405660 is a double-underscore special name. */
56415661static int
@@ -11086,7 +11106,7 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
1108611106 * because that's convenient for fixup_slot_dispatchers(). This function never
1108711107 * sets an exception: if an internal error happens (unlikely), it's ignored. */
1108811108static pytype_slotdef *
11089- update_one_slot (PyTypeObject * type , pytype_slotdef * p )
11109+ update_one_slot (PyTypeObject * type , pytype_slotdef * p , PyObject * mro_dict )
1109011110{
1109111111 ASSERT_TYPE_LOCK_HELD ();
1109211112
@@ -11117,7 +11137,11 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p)
1111711137 assert (!PyErr_Occurred ());
1111811138 do {
1111911139 /* Use faster uncached lookup as we won't get any cache hits during type setup. */
11120- descr = find_name_in_mro (type , p -> name_strobj , & error );
11140+ if (mro_dict == NULL ) {
11141+ descr = find_name_in_mro (type , p -> name_strobj , & error );
11142+ } else {
11143+ descr = find_name_in_mro_new (mro_dict , p -> name_strobj , & error );
11144+ }
1112111145 if (descr == NULL ) {
1112211146 if (error == -1 ) {
1112311147 /* It is unlikely but not impossible that there has been an exception
@@ -11208,7 +11232,7 @@ update_slots_callback(PyTypeObject *type, void *data)
1120811232
1120911233 pytype_slotdef * * pp = (pytype_slotdef * * )data ;
1121011234 for (; * pp ; pp ++ ) {
11211- update_one_slot (type , * pp );
11235+ update_one_slot (type , * pp , NULL );
1121211236 }
1121311237 return 0 ;
1121411238}
@@ -11261,11 +11285,38 @@ fixup_slot_dispatchers(PyTypeObject *type)
1126111285 // where we'd like to assert that the type is locked.
1126211286 BEGIN_TYPE_LOCK ();
1126311287
11288+ PyObject * mro = lookup_tp_mro (type );
11289+ assert (mro );
11290+
11291+ PyObject * mro_dict = NULL ;
11292+ Py_ssize_t n = PyTuple_GET_SIZE (mro );
11293+ for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
11294+ PyObject * base = PyTuple_GET_ITEM (mro , n - i - 1 );
11295+ PyObject * dict = lookup_tp_dict (_PyType_CAST (base ));
11296+ assert (dict && PyDict_Check (dict ));
11297+
11298+ if (i == 0 ) {
11299+ mro_dict = PyDict_Copy (dict );
11300+ if (!mro_dict ) {
11301+ PyErr_Clear ();
11302+ break ;
11303+ }
11304+ } else {
11305+ if (PyDict_Merge (mro_dict , dict , 1 ) < 0 ) {
11306+ Py_CLEAR (mro_dict );
11307+ PyErr_Clear ();
11308+ break ;
11309+ }
11310+ }
11311+ }
11312+
1126411313 assert (!PyErr_Occurred ());
1126511314 for (pytype_slotdef * p = slotdefs ; p -> name ; ) {
11266- p = update_one_slot (type , p );
11315+ p = update_one_slot (type , p , mro_dict );
1126711316 }
1126811317
11318+ Py_XDECREF (mro_dict );
11319+
1126911320 END_TYPE_LOCK ();
1127011321}
1127111322
0 commit comments