getattr = _PyType_LookupRef(tp, &_Py_ID(__getattr__));
if (getattr == NULL) {
/* No __getattr__ hook: use a simpler dispatcher */
+#ifndef Py_GIL_DISABLED
+ // Replacing the slot is only thread-safe if there is a GIL.
tp->tp_getattro = _Py_slot_tp_getattro;
+#endif
return _Py_slot_tp_getattro(self, name);
}
/* speed hack: we could use lookup_maybe, but that would resolve the
PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
has_getattr = getattr != NULL;
if (has_custom_getattribute) {
- if (getattro_slot == _Py_slot_tp_getattro &&
- !has_getattr &&
+ if (!has_getattr &&
Py_IS_TYPE(getattribute, &PyFunction_Type)) {
*descr = getattribute;
*tp_version = ga_version;
return -1;
case GETATTRIBUTE_IS_PYTHON_FUNCTION:
{
- #ifndef Py_GIL_DISABLED
- // In free-threaded builds it's possible for tp_getattro to change
- // after the call to analyze_descriptor. That is fine: the version
- // guard will fail.
- assert(type->tp_getattro == _Py_slot_tp_getattro);
- #endif
assert(Py_IS_TYPE(descr, &PyFunction_Type));
_PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
if (!function_check_args(descr, 2, LOAD_ATTR)) {