@@ -10962,6 +10962,11 @@ static pytype_slotdef slotdefs[] = {
1096210962 {NULL }
1096310963};
1096410964
10965+ /* {name: [pytype_slotdef]}
10966+ */
10967+ static PyObject * slotdefs_cache = NULL ;
10968+
10969+
1096510970/* Given a type pointer and an offset gotten from a slotdef entry, return a
1096610971 pointer to the actual slot. This is not quite the same as simply adding
1096710972 the offset to the type pointer, since it takes care to indirect through the
@@ -11010,13 +11015,63 @@ static void **
1101011015resolve_slotdups (PyTypeObject * type , PyObject * name )
1101111016{
1101211017 /* XXX Maybe this could be optimized more -- but is it worth it? */
11018+ void * * res , * * ptr ;
11019+ res = NULL ;
11020+
11021+ if (slotdefs_cache ) {
11022+ int rc = 0 ;
11023+ // PyObject *cache = Py_NewRef(slotdefs_cache);
11024+ Py_BEGIN_CRITICAL_SECTION (slotdefs_cache );
11025+ PyObject * cache = slotdefs_cache ;
11026+ assert (Py_REFCNT (cache ) >= 1 );
11027+
11028+ Py_INCREF (cache );
11029+ assert (Py_REFCNT (cache ) > 1 );
11030+
11031+ PyObject * list = NULL ;
11032+ rc = PyDict_GetItemRef (cache , name , & list );
11033+ assert (Py_REFCNT (cache ) > 1 );
11034+ if (rc > 0 ) {
11035+
11036+ // assert(list);
11037+ // Py_ssize_t n = PyList_Size(list);
11038+ // assert(n >= 0);
11039+ // Py_ssize_t i;
11040+ // for(i = 0; i < n; i++) {
11041+ // PyObject *py_idx = PyList_GET_ITEM(list, i);
11042+ // assert(PyLong_Check(py_idx));
11043+ // Py_ssize_t idx = PyLong_AsSsize_t(py_idx);
11044+ // assert (idx < Py_ARRAY_LENGTH(slotdefs));
11045+ // pytype_slotdef *x = &slotdefs[idx];
11046+ // ptr = slotptr(type, x->offset);
11047+ // if (ptr == NULL || *ptr == NULL) {
11048+ // continue;
11049+ // }
11050+ // if (res != NULL) {
11051+ // res = NULL;
11052+ // break;
11053+ // }
11054+ // res = ptr;
11055+ // }
11056+ assert (Py_REFCNT (list ) > 1 );
11057+ Py_DECREF (list );
11058+ } else if (rc < 0 ) {
11059+ PyErr_Clear ();
11060+ }
11061+
11062+ assert (Py_REFCNT (cache ) > 1 );
11063+ Py_DECREF (cache );
11064+ Py_END_CRITICAL_SECTION ();
11065+ if (rc > 0 ) {
11066+ return res ;
11067+ }
11068+ }
1101311069
1101411070 /* pname and ptrs act as a little cache */
1101511071 PyInterpreterState * interp = _PyInterpreterState_GET ();
1101611072#define pname _Py_INTERP_CACHED_OBJECT(interp, type_slots_pname)
1101711073#define ptrs _Py_INTERP_CACHED_OBJECT(interp, type_slots_ptrs)
1101811074 pytype_slotdef * p , * * pp ;
11019- void * * res , * * ptr ;
1102011075
1102111076 if (pname != name ) {
1102211077 /* Collect all slotdefs that match name into ptrs. */
@@ -11032,7 +11087,6 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
1103211087 /* Look in all slots of the type matching the name. If exactly one of these
1103311088 has a filled-in slot, return a pointer to that slot.
1103411089 Otherwise, return NULL. */
11035- res = NULL ;
1103611090 for (pp = ptrs ; * pp ; pp ++ ) {
1103711091 ptr = slotptr (type , (* pp )-> offset );
1103811092 if (ptr == NULL || * ptr == NULL )
@@ -11306,6 +11360,72 @@ fixup_slot_dispatchers(PyTypeObject *type)
1130611360 }
1130711361 }
1130811362
11363+ if (!slotdefs_cache ) {
11364+ PyObject * cache = PyDict_New ();
11365+ if (cache ) {
11366+ pytype_slotdef * p ;
11367+ Py_ssize_t idx = 0 ;
11368+ for (p = slotdefs ; p -> name_strobj ; p ++ , idx ++ ) {
11369+ // Py_hash_t hash = _PyObject_HashFast(p->name_strobj);
11370+ // if (hash == -1) {
11371+ // Py_CLEAR(cache);
11372+ // break;
11373+ // }
11374+
11375+ // PyObject *list;
11376+ // if (_PyDict_GetItemRef_KnownHash_LockHeld((PyDictObject *)cache, p->name_strobj, hash, &list) < 0) {
11377+ // Py_CLEAR(cache);
11378+ // break;
11379+ // }
11380+
11381+ // if (!list) {
11382+ // list = PyList_New(0);
11383+ // if (!list) {
11384+ // Py_CLEAR(cache);
11385+ // break;
11386+ // }
11387+
11388+ // if (_PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)cache, p->name_strobj, list, hash) < 0) {
11389+ // Py_DECREF(list);
11390+ // Py_CLEAR(cache);
11391+ // break;
11392+ // }
11393+ // }
11394+
11395+ // PyObject *py_idx = PyLong_FromSsize_t(idx);
11396+ // if (!py_idx) {
11397+ // Py_DECREF(list);
11398+ // Py_CLEAR(cache);
11399+ // break;
11400+ // }
11401+
11402+ // if (PyList_Append(list, py_idx) < 0) {
11403+ // Py_DECREF(py_idx);
11404+ // Py_DECREF(list);
11405+ // Py_CLEAR(cache);
11406+ // break;
11407+ // }
11408+
11409+ // Py_DECREF(py_idx);
11410+ // Py_DECREF(list);
11411+ }
11412+ }
11413+
11414+ if (cache ) {
11415+ Py_ssize_t pos = 0 ;
11416+ PyObject * key = NULL ;
11417+ PyObject * value = NULL ;
11418+ while (PyDict_Next (cache , & pos , & key , & value )) {
11419+ assert (Py_REFCNT (key ) > 1 );
11420+ assert (Py_REFCNT (value ) == 1 );
11421+ }
11422+
11423+ Py_XSETREF (slotdefs_cache , cache );
11424+ } else {
11425+ PyErr_Clear ();
11426+ }
11427+ }
11428+
1130911429 assert (!PyErr_Occurred ());
1131011430 for (pytype_slotdef * p = slotdefs ; p -> name ; ) {
1131111431 p = update_one_slot (type , p , mro_dict );
0 commit comments