#include "clinic/typeobject.c.h"
+/* bpo-40521: Type method cache is shared by all subinterpreters */
+#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
+# define MCACHE
+#endif
+
+#ifdef MCACHE
/* Support type attribute cache */
/* The cache can keep references to the names alive for longer than
static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
static unsigned int next_version_tag = 0;
+#endif
#define MCACHE_STATS 0
unsigned int
PyType_ClearCache(void)
{
+#ifdef MCACHE
Py_ssize_t i;
unsigned int cur_version_tag = next_version_tag - 1;
/* mark all version tags as invalid */
PyType_Modified(&PyBaseObject_Type);
return cur_version_tag;
+#else
+ return 0;
+#endif
}
void
Py_TPFLAGS_VALID_VERSION_TAG);
}
+#ifdef MCACHE
static int
assign_version_tag(PyTypeObject *type)
{
type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
return 1;
}
+#endif
static PyMemberDef type_members[] = {
{
PyObject *res;
int error;
- unsigned int h;
+#ifdef MCACHE
if (MCACHE_CACHEABLE_NAME(name) &&
_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
/* fast path */
- h = MCACHE_HASH_METHOD(type, name);
+ unsigned int h = MCACHE_HASH_METHOD(type, name);
if (method_cache[h].version == type->tp_version_tag &&
method_cache[h].name == name) {
#if MCACHE_STATS
return method_cache[h].value;
}
}
+#endif
/* We may end up clearing live exceptions below, so make sure it's ours. */
assert(!PyErr_Occurred());
return NULL;
}
+#ifdef MCACHE
if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) {
- h = MCACHE_HASH_METHOD(type, name);
+ unsigned int h = MCACHE_HASH_METHOD(type, name);
method_cache[h].version = type->tp_version_tag;
method_cache[h].value = res; /* borrowed */
Py_INCREF(name);
#endif
Py_SETREF(method_cache[h].name, name);
}
+#endif
return res;
}