@@ -56,6 +56,11 @@ static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
5656static unsigned int next_version_tag = 0 ;
5757#endif
5858
59+ typedef struct PySlot_Offset {
60+ short subslot_offset ;
61+ short slot_offset ;
62+ } PySlot_Offset ;
63+
5964#define MCACHE_STATS 0
6065
6166#if MCACHE_STATS
@@ -2870,8 +2875,18 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
28702875 return NULL ;
28712876}
28722877
2873- static const short slotoffsets [] = {
2874- -1 , /* invalid slot */
2878+ /* An array of type slot offsets corresponding to Py_tp_* constants,
2879+ * for use in e.g. PyType_Spec and PyType_GetSlot.
2880+ * Each entry has two offsets: "slot_offset" and "subslot_offset".
2881+ * If is subslot_offset is -1, slot_offset is an offset within the
2882+ * PyTypeObject struct.
2883+ * Otherwise slot_offset is an offset to a pointer to a sub-slots struct
2884+ * (such as "tp_as_number"), and subslot_offset is the offset within
2885+ * that struct.
2886+ * The actual table is generated by a script.
2887+ */
2888+ static const PySlot_Offset pyslot_offsets [] = {
2889+ {0 , 0 },
28752890#include "typeslots.inc"
28762891};
28772892
@@ -2892,6 +2907,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
28922907 const PyType_Slot * slot ;
28932908 Py_ssize_t nmembers , weaklistoffset , dictoffset , vectorcalloffset ;
28942909 char * res_start ;
2910+ short slot_offset , subslot_offset ;
28952911
28962912 nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0 ;
28972913 for (slot = spec -> slots ; slot -> slot ; slot ++ ) {
@@ -3001,7 +3017,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
30013017
30023018 for (slot = spec -> slots ; slot -> slot ; slot ++ ) {
30033019 if (slot -> slot < 0
3004- || (size_t )slot -> slot >= Py_ARRAY_LENGTH (slotoffsets )) {
3020+ || (size_t )slot -> slot >= Py_ARRAY_LENGTH (pyslot_offsets )) {
30053021 PyErr_SetString (PyExc_RuntimeError , "invalid slot offset" );
30063022 goto fail ;
30073023 }
@@ -3034,7 +3050,15 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
30343050 }
30353051 else {
30363052 /* Copy other slots directly */
3037- * (void * * )(res_start + slotoffsets [slot -> slot ]) = slot -> pfunc ;
3053+ PySlot_Offset slotoffsets = pyslot_offsets [slot -> slot ];
3054+ slot_offset = slotoffsets .slot_offset ;
3055+ if (slotoffsets .subslot_offset == -1 ) {
3056+ * (void * * )((char * )res_start + slot_offset ) = slot -> pfunc ;
3057+ } else {
3058+ void * parent_slot = * (void * * )((char * )res_start + slot_offset );
3059+ subslot_offset = slotoffsets .subslot_offset ;
3060+ * (void * * )((char * )parent_slot + subslot_offset ) = slot -> pfunc ;
3061+ }
30383062 }
30393063 }
30403064 if (type -> tp_dealloc == NULL ) {
@@ -3117,15 +3141,23 @@ PyType_FromSpec(PyType_Spec *spec)
31173141void *
31183142PyType_GetSlot (PyTypeObject * type , int slot )
31193143{
3120- if (!_PyType_HasFeature (type , Py_TPFLAGS_HEAPTYPE ) || slot < 0 ) {
3144+ void * parent_slot ;
3145+ int slots_len = Py_ARRAY_LENGTH (pyslot_offsets );
3146+
3147+ if (slot <= 0 || slot >= slots_len ) {
31213148 PyErr_BadInternalCall ();
31223149 return NULL ;
31233150 }
3124- if ((size_t )slot >= Py_ARRAY_LENGTH (slotoffsets )) {
3125- /* Extension module requesting slot from a future version */
3151+
3152+ parent_slot = * (void * * )((char * )type + pyslot_offsets [slot ].slot_offset );
3153+ if (parent_slot == NULL ) {
31263154 return NULL ;
31273155 }
3128- return * (void * * )(((char * )type ) + slotoffsets [slot ]);
3156+ /* Return slot directly if we have no sub slot. */
3157+ if (pyslot_offsets [slot ].subslot_offset == -1 ) {
3158+ return parent_slot ;
3159+ }
3160+ return * (void * * )((char * )parent_slot + pyslot_offsets [slot ].subslot_offset );
31293161}
31303162
31313163PyObject *
0 commit comments