Skip to content

Commit f04846e

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
Move genericinst_cache into ModuleState
Summary: Move the `genericinst_cache` file-scope global from `StaticPython/generic_type.c` into the `ModuleState` class as a `Ref<>` member with proper GC traversal. C accessor functions `Ci_GetGenericInstCache()`, `Ci_SetGenericInstCache()`, and `Ci_ClearGenericInstCache()` are provided in `module_c_state.h/cpp` for use from C code. Reviewed By: jbower-fb Differential Revision: D96617792 fbshipit-source-id: 5553217897e93c3ff92cd049cda31db4cd736693
1 parent 57b51d8 commit f04846e

5 files changed

Lines changed: 36 additions & 8 deletions

File tree

cinderx/StaticPython/generic_type.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
#include "cinderx/StaticPython/vtable.h"
77
#include "cinderx/StaticPython/vtable_builder.h"
88
#include "cinderx/UpstreamBorrow/borrowed.h"
9+
#include "cinderx/module_c_state.h"
910

1011
#if PY_VERSION_HEX < 0x030C0000
1112
#include "cinder/exports.h"
1213
#endif
1314

14-
static PyObject* genericinst_cache;
15-
1615
void _PyClassLoader_ClearGenericTypes() {
17-
Py_CLEAR(genericinst_cache);
16+
Ci_ClearGenericInstCache();
1817
}
1918

2019
static PyObject* get_optional_type(PyObject* type) {
@@ -398,19 +397,22 @@ PyObject* _PyClassLoader_GetGenericInst(
398397
PyObject* type,
399398
PyObject** args,
400399
Py_ssize_t nargs) {
401-
if (genericinst_cache == NULL) {
402-
genericinst_cache = PyDict_New();
403-
if (genericinst_cache == NULL) {
400+
PyObject* cache = Ci_GetGenericInstCache();
401+
if (cache == NULL) {
402+
cache = PyDict_New();
403+
if (cache == NULL) {
404404
return NULL;
405405
}
406+
Ci_SetGenericInstCache((PyDictObject*)cache);
407+
Py_DECREF(cache);
406408
}
407409

408410
PyObject* key = gtd_make_key(type, args, nargs);
409411
if (key == NULL) {
410412
return NULL;
411413
}
412414

413-
PyObject* inst = PyDict_GetItem(genericinst_cache, key);
415+
PyObject* inst = PyDict_GetItem(cache, key);
414416
if (inst != NULL) {
415417
Py_DECREF(key);
416418
Py_INCREF(inst);
@@ -442,7 +444,7 @@ PyObject* _PyClassLoader_GetGenericInst(
442444
}
443445
}
444446

445-
if (res == NULL || PyDict_SetItem(genericinst_cache, key, res)) {
447+
if (res == NULL || PyDict_SetItem(cache, key, res)) {
446448
Py_XDECREF(res);
447449
Py_DECREF(key);
448450
return NULL;

cinderx/module_c_state.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ PyObject* Ci_GetStaticTypeError(void) {
1616
return state != nullptr ? state->static_type_error.getObj() : nullptr;
1717
}
1818

19+
PyObject* Ci_GetGenericInstCache(void) {
20+
auto state = cinderx::getModuleState();
21+
return state != nullptr ? state->genericinst_cache.getObj() : nullptr;
22+
}
23+
24+
void Ci_SetGenericInstCache(PyDictObject* cache) {
25+
cinderx::getModuleState()->genericinst_cache =
26+
Ref<PyDictObject>::create(cache);
27+
}
28+
29+
void Ci_ClearGenericInstCache(void) {
30+
if (auto state = cinderx::getModuleState(); state != nullptr) {
31+
state->genericinst_cache.reset();
32+
}
33+
}
34+
1935
int Ci_Watchers_WatchDict(PyObject* dict) {
2036
return cinderx::getModuleState()->watcher_state.watchDict(dict);
2137
}

cinderx/module_c_state.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ extern vectorcallfunc Ci_PyFunction_Vectorcall;
2323
// Get the StaticTypeError exception type.
2424
PyObject* Ci_GetStaticTypeError(void);
2525

26+
// Generic type instantiation cache.
27+
PyObject* Ci_GetGenericInstCache(void);
28+
void Ci_SetGenericInstCache(PyDictObject* cache);
29+
void Ci_ClearGenericInstCache(void);
30+
2631
// WatcherState.
2732

2833
int Ci_Watchers_WatchDict(PyObject* dict);

cinderx/module_state.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ ModuleState* s_cinderx_state;
1414

1515
int ModuleState::traverse(visitproc visit, void* arg) {
1616
Py_VISIT(static_type_error);
17+
Py_VISIT(genericinst_cache);
1718
Py_VISIT(builtin_next);
1819
return 0;
1920
}
2021

2122
int ModuleState::clear() {
2223
static_type_error.reset();
24+
genericinst_cache.reset();
2325
sys_clear_caches.reset();
2426
builtin_next.reset();
2527
return 0;

cinderx/module_state.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ struct ModuleState {
5858
// The cinderx.StaticTypeError exception type.
5959
Ref<PyTypeObject> static_type_error;
6060

61+
// Cache for generic type instantiations (e.g. list[int]).
62+
Ref<PyDictObject> genericinst_cache;
63+
6164
// Snapshotted member dicts for standard builtin types (int, str, list, etc.)
6265
// so the JIT optimizer can look up methods during multithreaded compilation
6366
// without calling PyType_Lookup (which isn't safe off the main thread).

0 commit comments

Comments
 (0)