ref->ref = PyStackRef_NULL;
}
+static inline void
+_PyThreadState_PushCStackRefNew(PyThreadState *tstate, _PyCStackRef *ref, PyObject *obj)
+{
+ _PyThreadState_PushCStackRef(tstate, ref);
+ ref->ref = PyStackRef_FromPyObjectNew(obj);
+}
+
static inline void
_PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
{
PyObject *mro, *res;
Py_ssize_t i, n;
- BEGIN_TYPE_LOCK();
mro = lookup_tp_mro(su_obj_type);
- /* keep a strong reference to mro because su_obj_type->tp_mro can be
- replaced during PyDict_GetItemRef(dict, name, &res) and because
- another thread can modify it after we end the critical section
- below */
- Py_XINCREF(mro);
- END_TYPE_LOCK();
-
if (mro == NULL)
return NULL;
+ /* Keep a strong reference to mro because su_obj_type->tp_mro can be
+ replaced during PyDict_GetItemRef(dict, name, &res). */
+ PyThreadState *tstate = _PyThreadState_GET();
+ _PyCStackRef mro_ref;
+ _PyThreadState_PushCStackRefNew(tstate, &mro_ref, mro);
+
assert(PyTuple_Check(mro));
n = PyTuple_GET_SIZE(mro);
}
i++; /* skip su->type (if any) */
if (i >= n) {
- Py_DECREF(mro);
+ _PyThreadState_PopCStackRef(tstate, &mro_ref);
return NULL;
}
if (PyDict_GetItemRef(dict, name, &res) != 0) {
// found or error
- Py_DECREF(mro);
+ _PyThreadState_PopCStackRef(tstate, &mro_ref);
return res;
}
i++;
} while (i < n);
- Py_DECREF(mro);
+ _PyThreadState_PopCStackRef(tstate, &mro_ref);
return NULL;
}
for _ in range(1000 * WORK_SCALE):
obj = MyTypingNamedTuple(x=1, y=2, z=3)
+@register_benchmark
+def super_call():
+ # TODO: super() on the same class from multiple threads still doesn't
+ # scale well, so use a class per-thread here for now.
+ class Base:
+ def method(self):
+ return 1
+
+ class Derived(Base):
+ def method(self):
+ return super().method()
+
+ obj = Derived()
+ for _ in range(1000 * WORK_SCALE):
+ obj.method()
+
@register_benchmark
def deepcopy():