mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
bpo-41073: PyType_GetSlot() can now accept static types. (GH-21931)
PyType_GetSlot() can now accept static types. Co-Authored-By: Petr Viktorin <encukou@gmail.com> Automerge-Triggered-By: GH:encukou
This commit is contained in:
parent
ace3f9a0ce
commit
a13b26cac1
7 changed files with 205 additions and 101 deletions
|
@ -56,6 +56,11 @@ static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
|
|||
static unsigned int next_version_tag = 0;
|
||||
#endif
|
||||
|
||||
typedef struct PySlot_Offset {
|
||||
short subslot_offset;
|
||||
short slot_offset;
|
||||
} PySlot_Offset;
|
||||
|
||||
#define MCACHE_STATS 0
|
||||
|
||||
#if MCACHE_STATS
|
||||
|
@ -2870,8 +2875,18 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const short slotoffsets[] = {
|
||||
-1, /* invalid slot */
|
||||
/* An array of type slot offsets corresponding to Py_tp_* constants,
|
||||
* for use in e.g. PyType_Spec and PyType_GetSlot.
|
||||
* Each entry has two offsets: "slot_offset" and "subslot_offset".
|
||||
* If is subslot_offset is -1, slot_offset is an offset within the
|
||||
* PyTypeObject struct.
|
||||
* Otherwise slot_offset is an offset to a pointer to a sub-slots struct
|
||||
* (such as "tp_as_number"), and subslot_offset is the offset within
|
||||
* that struct.
|
||||
* The actual table is generated by a script.
|
||||
*/
|
||||
static const PySlot_Offset pyslot_offsets[] = {
|
||||
{0, 0},
|
||||
#include "typeslots.inc"
|
||||
};
|
||||
|
||||
|
@ -2892,6 +2907,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
|||
const PyType_Slot *slot;
|
||||
Py_ssize_t nmembers, weaklistoffset, dictoffset, vectorcalloffset;
|
||||
char *res_start;
|
||||
short slot_offset, subslot_offset;
|
||||
|
||||
nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0;
|
||||
for (slot = spec->slots; slot->slot; slot++) {
|
||||
|
@ -3001,7 +3017,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
|||
|
||||
for (slot = spec->slots; slot->slot; slot++) {
|
||||
if (slot->slot < 0
|
||||
|| (size_t)slot->slot >= Py_ARRAY_LENGTH(slotoffsets)) {
|
||||
|| (size_t)slot->slot >= Py_ARRAY_LENGTH(pyslot_offsets)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "invalid slot offset");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -3034,7 +3050,15 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
|||
}
|
||||
else {
|
||||
/* Copy other slots directly */
|
||||
*(void**)(res_start + slotoffsets[slot->slot]) = slot->pfunc;
|
||||
PySlot_Offset slotoffsets = pyslot_offsets[slot->slot];
|
||||
slot_offset = slotoffsets.slot_offset;
|
||||
if (slotoffsets.subslot_offset == -1) {
|
||||
*(void**)((char*)res_start + slot_offset) = slot->pfunc;
|
||||
} else {
|
||||
void *parent_slot = *(void**)((char*)res_start + slot_offset);
|
||||
subslot_offset = slotoffsets.subslot_offset;
|
||||
*(void**)((char*)parent_slot + subslot_offset) = slot->pfunc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type->tp_dealloc == NULL) {
|
||||
|
@ -3117,15 +3141,23 @@ PyType_FromSpec(PyType_Spec *spec)
|
|||
void *
|
||||
PyType_GetSlot(PyTypeObject *type, int slot)
|
||||
{
|
||||
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) {
|
||||
void *parent_slot;
|
||||
int slots_len = Py_ARRAY_LENGTH(pyslot_offsets);
|
||||
|
||||
if (slot <= 0 || slot >= slots_len) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) {
|
||||
/* Extension module requesting slot from a future version */
|
||||
|
||||
parent_slot = *(void**)((char*)type + pyslot_offsets[slot].slot_offset);
|
||||
if (parent_slot == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return *(void**)(((char*)type) + slotoffsets[slot]);
|
||||
/* Return slot directly if we have no sub slot. */
|
||||
if (pyslot_offsets[slot].subslot_offset == -1) {
|
||||
return parent_slot;
|
||||
}
|
||||
return *(void**)((char*)parent_slot + pyslot_offsets[slot].subslot_offset);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue