@@ -131,6 +131,41 @@ bytes(cdata)
131131
132132#include "pycore_long.h" // _PyLong_GetZero()
133133
134+ #if 1 // GraalPy change
135+ // Assign a stgdict to type's tp_dict slot. In GraalPy we do not track our
136+ // builtin dicts, and type dicts for managed classes actually have no tp_dict
137+ // with an extra native ref, they are kept alive by the type only and their
138+ // handles are collected by the GC or on context shutdown. So when we assign a
139+ // fresh stgdict to the type's tp_dict, we make it also have only
140+ // MANAGED_REFCOUNT and let it be collected when the type is collected.
141+ #define set_graalpy_tp_dict (type , stgdict ) \
142+ { \
143+ PyObject *__stgdict = (PyObject *)(stgdict); \
144+ PyTypeObject *__type = (PyTypeObject *)(type); \
145+ PyObject_GC_UnTrack(__stgdict); \
146+ if (points_to_py_handle_space(__type)) { \
147+ _PyObject_ASSERT_FAILED_MSG((PyObject*) __type, \
148+ "type dict has increased refcnt, " \
149+ "something changed in how GraalPy " \
150+ "marries classes to native structs"); \
151+ } \
152+ if (Py_REFCNT(__type->tp_dict) != MANAGED_REFCNT) { \
153+ _PyObject_ASSERT_FAILED_MSG((PyObject*) __type, \
154+ "type dict has increased refcnt, " \
155+ "something changed in how GraalPy " \
156+ "marries classes to native structs"); \
157+ } \
158+ if (Py_REFCNT(__stgdict) != MANAGED_REFCNT + 1) { \
159+ _PyObject_ASSERT_FAILED_MSG(__stgdict, \
160+ "new stgdict has incorrect refcnt, " \
161+ "something changed in GraalPy"); \
162+ } \
163+ __type->tp_dict = (PyObject *)__stgdict; \
164+ PyType_Modified(__type); \
165+ Py_DecRef(__stgdict); \
166+ }
167+ #endif
168+
134169ctypes_state global_state ;
135170
136171PyObject * PyExc_ArgError = NULL ;
@@ -550,8 +585,7 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt
550585 Py_DECREF ((PyObject * )dict );
551586 return NULL ;
552587 }
553- result -> tp_dict = (PyObject * )dict ; // GraalPy change: do not use Py_SETREF
554- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
588+ set_graalpy_tp_dict (result , dict ); // GraalPy change: do not use Py_SETREF
555589 dict -> format = _ctypes_alloc_format_string (NULL , "B" );
556590 if (dict -> format == NULL ) {
557591 Py_DECREF (result );
@@ -1153,8 +1187,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11531187 Py_DECREF ((PyObject * )stgdict );
11541188 return NULL ;
11551189 }
1156- result -> tp_dict = (PyObject * )stgdict ; // GraalPy change: do not use Py_SETREF
1157- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
1190+ set_graalpy_tp_dict (result , stgdict ); // GraalPy change: do not use Py_SETREF
11581191
11591192 return (PyObject * )result ;
11601193}
@@ -1590,8 +1623,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
15901623 /* replace the class dict by our updated spam dict */
15911624 if (-1 == PyDict_Update ((PyObject * )stgdict , result -> tp_dict ))
15921625 goto error ;
1593- result -> tp_dict = (PyObject * )stgdict ; // GraalPy change: do not use Py_SETREF
1594- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
1626+ set_graalpy_tp_dict (result , stgdict ); // GraalPy change: do not use Py_SETREF
15951627 stgdict = NULL ;
15961628
15971629 /* Special case for character arrays.
@@ -2005,8 +2037,7 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
20052037 Py_DECREF ((PyObject * )stgdict );
20062038 return NULL ;
20072039 }
2008- result -> tp_dict = (PyObject * )stgdict ; // GraalPy change: do not use Py_SETREF
2009- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
2040+ set_graalpy_tp_dict (result , stgdict ); // GraalPy change: do not use Py_SETREF
20102041
20112042 return (PyObject * )result ;
20122043}
@@ -2135,8 +2166,7 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
21352166 Py_DECREF ((PyObject * )stgdict );
21362167 return NULL ;
21372168 }
2138- result -> tp_dict = (PyObject * )stgdict ; // GraalPy change: do not use Py_SETREF
2139- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
2169+ set_graalpy_tp_dict (result , stgdict ); // GraalPy change: do not use Py_SETREF
21402170
21412171 /* Install from_param class methods in ctypes base classes.
21422172 Overrides the PyCSimpleType_from_param generic method.
@@ -2578,8 +2608,7 @@ PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
25782608 Py_DECREF ((PyObject * )stgdict );
25792609 return NULL ;
25802610 }
2581- result -> tp_dict = (PyObject * )stgdict ; // GraalPy change: do not use Py_SETREF
2582- PyType_Modified (result ); // GraalPy change: sync tp_dict change to managed
2611+ set_graalpy_tp_dict (result , stgdict ); // GraalPy change: do not use Py_SETREF
25832612
25842613 if (-1 == make_funcptrtype_dict (stgdict )) {
25852614 Py_DECREF (result );
0 commit comments