Skip to content

Commit 89fc4a3

Browse files
authored
bpo-40521: Disable method cache in subinterpreters (GH-19960)
When Python is built with experimental isolated interpreters, disable the type method cache. Temporary workaround until the cache is made per-interpreter.
1 parent 091951a commit 89fc4a3

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

Objects/typeobject.c

+19-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ class object "PyObject *" "&PyBaseObject_Type"
1919

2020
#include "clinic/typeobject.c.h"
2121

22+
/* bpo-40521: Type method cache is shared by all subinterpreters */
23+
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
24+
# define MCACHE
25+
#endif
26+
27+
#ifdef MCACHE
2228
/* Support type attribute cache */
2329

2430
/* The cache can keep references to the names alive for longer than
@@ -47,6 +53,7 @@ struct method_cache_entry {
4753

4854
static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
4955
static unsigned int next_version_tag = 0;
56+
#endif
5057

5158
#define MCACHE_STATS 0
5259

@@ -216,6 +223,7 @@ _PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_d
216223
unsigned int
217224
PyType_ClearCache(void)
218225
{
226+
#ifdef MCACHE
219227
Py_ssize_t i;
220228
unsigned int cur_version_tag = next_version_tag - 1;
221229

@@ -240,6 +248,9 @@ PyType_ClearCache(void)
240248
/* mark all version tags as invalid */
241249
PyType_Modified(&PyBaseObject_Type);
242250
return cur_version_tag;
251+
#else
252+
return 0;
253+
#endif
243254
}
244255

245256
void
@@ -350,6 +361,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
350361
Py_TPFLAGS_VALID_VERSION_TAG);
351362
}
352363

364+
#ifdef MCACHE
353365
static int
354366
assign_version_tag(PyTypeObject *type)
355367
{
@@ -396,6 +408,7 @@ assign_version_tag(PyTypeObject *type)
396408
type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
397409
return 1;
398410
}
411+
#endif
399412

400413

401414
static PyMemberDef type_members[] = {
@@ -3232,12 +3245,12 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
32323245
{
32333246
PyObject *res;
32343247
int error;
3235-
unsigned int h;
32363248

3249+
#ifdef MCACHE
32373250
if (MCACHE_CACHEABLE_NAME(name) &&
32383251
_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
32393252
/* fast path */
3240-
h = MCACHE_HASH_METHOD(type, name);
3253+
unsigned int h = MCACHE_HASH_METHOD(type, name);
32413254
if (method_cache[h].version == type->tp_version_tag &&
32423255
method_cache[h].name == name) {
32433256
#if MCACHE_STATS
@@ -3246,6 +3259,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
32463259
return method_cache[h].value;
32473260
}
32483261
}
3262+
#endif
32493263

32503264
/* We may end up clearing live exceptions below, so make sure it's ours. */
32513265
assert(!PyErr_Occurred());
@@ -3267,8 +3281,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
32673281
return NULL;
32683282
}
32693283

3284+
#ifdef MCACHE
32703285
if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) {
3271-
h = MCACHE_HASH_METHOD(type, name);
3286+
unsigned int h = MCACHE_HASH_METHOD(type, name);
32723287
method_cache[h].version = type->tp_version_tag;
32733288
method_cache[h].value = res; /* borrowed */
32743289
Py_INCREF(name);
@@ -3281,6 +3296,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
32813296
#endif
32823297
Py_SETREF(method_cache[h].name, name);
32833298
}
3299+
#endif
32843300
return res;
32853301
}
32863302

0 commit comments

Comments
 (0)