From 25e6a1bcb4d2868c22b825469ad7300b43da446f Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 8 Jul 2020 20:13:10 +0800 Subject: [PATCH 01/23] PyType_GetSlot() could accept static types --- Doc/c-api/type.rst | 5 +++-- Include/typeslots.h | 21 +++++++++++++++++++ .../2020-07-08-21-01-49.bpo-41073.VqQZON.rst | 1 + Objects/typeobject.c | 2 +- Objects/typeslots.inc | 18 ++++++++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index f387279d143eec..b1666a8813ab6f 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -105,10 +105,11 @@ Type Objects See :c:member:`PyType_Slot.slot` for possible values of the *slot* argument. - An exception is raised if *type* is not a heap type. - .. versionadded:: 3.4 + .. versionchanged:: 3.10 + :c:func:`PyType_GetSlot` could accept static types. + .. c:function:: PyObject* PyType_GetModule(PyTypeObject *type) Return the module object associated with the given type when the type was diff --git a/Include/typeslots.h b/Include/typeslots.h index 64f6fff5144493..e50c66c7c5dcc3 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,3 +88,24 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x031000a1 +/* New in 3.10 */ +#define Py_tp_as_async 81 +#define Py_tp_as_buffer 82 +#define Py_tp_as_mapping 83 +#define Py_tp_as_number 84 +#define Py_tp_as_sequence 85 +#define Py_tp_basicsize 86 +#define Py_tp_cache 87 +#define Py_tp_dict 88 +#define Py_tp_dictoffset 89 +#define Py_tp_flags 90 +#define Py_tp_itemsize 91 +#define Py_tp_mro 92 +#define Py_tp_name 93 +#define Py_tp_subclasses 94 +#define Py_tp_vectorcall_offset 95 +#define Py_tp_version_tag 96 +#define Py_tp_weaklist 97 +#define Py_tp_weaklistoffset 98 +#endif diff --git a/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst b/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst new file mode 100644 index 00000000000000..668bfb2c2e2791 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst @@ -0,0 +1 @@ +:c:func:`PyType_GetSlot()` could accept static types. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c66f8fcec8ed51..dee8451eb54768 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3110,7 +3110,7 @@ PyType_FromSpec(PyType_Spec *spec) void * PyType_GetSlot(PyTypeObject *type, int slot) { - if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) { + if (slot < 0) { PyErr_BadInternalCall(); return NULL; } diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc index ffc9bb2e1c7710..58b11d678827a2 100644 --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -79,3 +79,21 @@ offsetof(PyHeapTypeObject, as_async.am_await), offsetof(PyHeapTypeObject, as_async.am_aiter), offsetof(PyHeapTypeObject, as_async.am_anext), offsetof(PyHeapTypeObject, ht_type.tp_finalize), +offsetof(PyHeapTypeObject, ht_type.tp_as_async), +offsetof(PyHeapTypeObject, ht_type.tp_as_buffer), +offsetof(PyHeapTypeObject, ht_type.tp_as_mapping), +offsetof(PyHeapTypeObject, ht_type.tp_as_number), +offsetof(PyHeapTypeObject, ht_type.tp_as_sequence), +offsetof(PyHeapTypeObject, ht_type.tp_basicsize), +offsetof(PyHeapTypeObject, ht_type.tp_cache), +offsetof(PyHeapTypeObject, ht_type.tp_dict), +offsetof(PyHeapTypeObject, ht_type.tp_dictoffset), +offsetof(PyHeapTypeObject, ht_type.tp_flags), +offsetof(PyHeapTypeObject, ht_type.tp_itemsize), +offsetof(PyHeapTypeObject, ht_type.tp_mro), +offsetof(PyHeapTypeObject, ht_type.tp_name), +offsetof(PyHeapTypeObject, ht_type.tp_subclasses), +offsetof(PyHeapTypeObject, ht_type.tp_vectorcall_offset), +offsetof(PyHeapTypeObject, ht_type.tp_version_tag), +offsetof(PyHeapTypeObject, ht_type.tp_weaklist), +offsetof(PyHeapTypeObject, ht_type.tp_weaklistoffset), From 7fcf9ebdf0a860ee142af44d394e2f9b3556fc42 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 8 Jul 2020 21:45:45 +0800 Subject: [PATCH 02/23] update docs' style --- Doc/c-api/type.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index b1666a8813ab6f..2694585660d286 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -108,7 +108,7 @@ Type Objects .. versionadded:: 3.4 .. versionchanged:: 3.10 - :c:func:`PyType_GetSlot` could accept static types. + :c:func:`PyType_GetSlot` could accept static types. .. c:function:: PyObject* PyType_GetModule(PyTypeObject *type) From 159fc09d0fdb88f0fbf5afde01fabe6a8d9b852e Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 10 Jul 2020 02:13:52 +0800 Subject: [PATCH 03/23] use typeslots not in limit apis --- Include/typeslots.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Include/typeslots.h b/Include/typeslots.h index e50c66c7c5dcc3..ffb0f64b62c240 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,7 +88,6 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x031000a1 /* New in 3.10 */ #define Py_tp_as_async 81 #define Py_tp_as_buffer 82 @@ -108,4 +107,3 @@ #define Py_tp_version_tag 96 #define Py_tp_weaklist 97 #define Py_tp_weaklistoffset 98 -#endif From 588a847ce5dd479a7a1ee3551ad11c1589dd2119 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 21 Aug 2020 00:55:04 +0800 Subject: [PATCH 04/23] add test cases to against PyType_GetSlot() --- Modules/_testcapimodule.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 593034ef65e2ca..07338b101e18ca 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1018,6 +1018,35 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) } +static PyObject * +test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + char *tp_name = PyType_GetSlot(&PyLong_Type, Py_tp_name); + assert(strcmp(tp_name, "int") == 0); + + newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); + PyObject *args = PyTuple_New(0); + PyObject *object = tp_new(&PyLong_Type, args, NULL); + assert(object); + + reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); + PyObject *decimal_str = tp_repr(object); + assert(decimal_str); + + PyNumberMethods *tp_as_number = PyType_GetSlot(&PyLong_Type, + Py_tp_as_number); + PyObject *object2 = tp_new(&PyLong_Type, args, NULL); + PyObject *res = tp_as_number->nb_add(object, object2); + assert(res); + + Py_DECREF(res); + Py_DECREF(decimal_str); + Py_DECREF(args); + Py_DECREF(object); + Py_RETURN_NONE; +} + + static PyObject * get_args(PyObject *self, PyObject *args) { @@ -5606,6 +5635,7 @@ static PyMethodDef TestMethods[] = { {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, {"get_args", get_args, METH_VARARGS}, + {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, {"getargs_keywords", (PyCFunction)(void(*)(void))getargs_keywords, From ec0348d768d070ac3e9ce2f768d6c602e80777e5 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 21 Aug 2020 01:04:15 +0800 Subject: [PATCH 05/23] update typeslots.h --- Include/typeslots.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Include/typeslots.h b/Include/typeslots.h index ffb0f64b62c240..8b571d37864819 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -89,6 +89,26 @@ #define Py_tp_finalize 80 #endif /* New in 3.10 */ +#if defined(Py_LIMITED_API) +#undef Py_tp_as_async +#undef Py_tp_as_buffer +#undef Py_tp_as_mapping +#undef Py_tp_as_number +#undef Py_tp_as_sequence +#undef Py_tp_basicsize +#undef Py_tp_cache +#undef Py_tp_dict +#undef Py_tp_dictoffset +#undef Py_tp_flags +#undef Py_tp_itemsize +#undef Py_tp_mro +#undef Py_tp_name +#undef Py_tp_subclasses +#undef Py_tp_vectorcall_offset +#undef Py_tp_version_tag +#undef Py_tp_weaklist +#undef Py_tp_weaklistoffset +#else #define Py_tp_as_async 81 #define Py_tp_as_buffer 82 #define Py_tp_as_mapping 83 @@ -107,3 +127,4 @@ #define Py_tp_version_tag 96 #define Py_tp_weaklist 97 #define Py_tp_weaklistoffset 98 +#endif From abda762e5ec2eeb7809c0f19c4186ddc36cb1eb4 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sat, 22 Aug 2020 22:27:32 +0800 Subject: [PATCH 06/23] Add generate statictypeslots feature --- Include/Python.h | 1 + Include/statictypeslots.h | 86 +++++++++++++++++++++++++++++++++++++ Include/typeslots.h | 40 ----------------- Modules/_testcapimodule.c | 15 +++---- Objects/statictypeslots.inc | 42 ++++++++++++++++++ Objects/statictypeslots.py | 37 ++++++++++++++++ Objects/typeobject.c | 20 +++++++-- 7 files changed, 188 insertions(+), 53 deletions(-) create mode 100644 Include/statictypeslots.h create mode 100644 Objects/statictypeslots.inc create mode 100755 Objects/statictypeslots.py diff --git a/Include/Python.h b/Include/Python.h index 57f71d41d8d477..b48e77d2ecea72 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -88,6 +88,7 @@ #include "object.h" #include "objimpl.h" #include "typeslots.h" +#include "statictypeslots.h" #include "pyhash.h" #include "pydebug.h" diff --git a/Include/statictypeslots.h b/Include/statictypeslots.h new file mode 100644 index 00000000000000..971e6f77388776 --- /dev/null +++ b/Include/statictypeslots.h @@ -0,0 +1,86 @@ +/* Do not renumber the file; these numbers are part of the stable ABI. */ +#if defined(Py_LIMITED_API) +#undef Py_type_name 1 +#undef Py_type_basicsize 2 +#undef Py_type_itemsize 3 +#undef Py_type_dealloc 4 +#undef Py_type_vectorcall_offset 5 +#undef Py_type_getattr 6 +#undef Py_type_setattr 7 +#undef Py_type_repr 8 +#undef Py_type_hash 9 +#undef Py_type_call 10 +#undef Py_type_str 11 +#undef Py_type_getattro 12 +#undef Py_type_setattro 13 +#undef Py_type_flags 14 +#undef Py_type_doc 15 +#undef Py_type_traverse 16 +#undef Py_type_clear 17 +#undef Py_type_richcompare 18 +#undef Py_type_weaklistoffset 19 +#undef Py_type_iter 20 +#undef Py_type_iternext 21 +#undef Py_type_methods 22 +#undef Py_type_members 23 +#undef Py_type_getset 24 +#undef Py_type_base 25 +#undef Py_type_dict 26 +#undef Py_type_descr_get 27 +#undef Py_type_descr_set 28 +#undef Py_type_dictoffset 29 +#undef Py_type_init 30 +#undef Py_type_alloc 31 +#undef Py_type_new 32 +#undef Py_type_free 33 +#undef Py_type_is_gc 34 +#undef Py_type_bases 35 +#undef Py_type_mro 36 +#undef Py_type_cache 37 +#undef Py_type_subclasses 38 +#undef Py_type_weaklist 39 +#undef Py_type_del 40 +#undef Py_type_finalize 41 +#else +#define Py_type_name 1 +#define Py_type_basicsize 2 +#define Py_type_itemsize 3 +#define Py_type_dealloc 4 +#define Py_type_vectorcall_offset 5 +#define Py_type_getattr 6 +#define Py_type_setattr 7 +#define Py_type_repr 8 +#define Py_type_hash 9 +#define Py_type_call 10 +#define Py_type_str 11 +#define Py_type_getattro 12 +#define Py_type_setattro 13 +#define Py_type_flags 14 +#define Py_type_doc 15 +#define Py_type_traverse 16 +#define Py_type_clear 17 +#define Py_type_richcompare 18 +#define Py_type_weaklistoffset 19 +#define Py_type_iter 20 +#define Py_type_iternext 21 +#define Py_type_methods 22 +#define Py_type_members 23 +#define Py_type_getset 24 +#define Py_type_base 25 +#define Py_type_dict 26 +#define Py_type_descr_get 27 +#define Py_type_descr_set 28 +#define Py_type_dictoffset 29 +#define Py_type_init 30 +#define Py_type_alloc 31 +#define Py_type_new 32 +#define Py_type_free 33 +#define Py_type_is_gc 34 +#define Py_type_bases 35 +#define Py_type_mro 36 +#define Py_type_cache 37 +#define Py_type_subclasses 38 +#define Py_type_weaklist 39 +#define Py_type_del 40 +#define Py_type_finalize 41 +#endif diff --git a/Include/typeslots.h b/Include/typeslots.h index 8b571d37864819..64f6fff5144493 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,43 +88,3 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif -/* New in 3.10 */ -#if defined(Py_LIMITED_API) -#undef Py_tp_as_async -#undef Py_tp_as_buffer -#undef Py_tp_as_mapping -#undef Py_tp_as_number -#undef Py_tp_as_sequence -#undef Py_tp_basicsize -#undef Py_tp_cache -#undef Py_tp_dict -#undef Py_tp_dictoffset -#undef Py_tp_flags -#undef Py_tp_itemsize -#undef Py_tp_mro -#undef Py_tp_name -#undef Py_tp_subclasses -#undef Py_tp_vectorcall_offset -#undef Py_tp_version_tag -#undef Py_tp_weaklist -#undef Py_tp_weaklistoffset -#else -#define Py_tp_as_async 81 -#define Py_tp_as_buffer 82 -#define Py_tp_as_mapping 83 -#define Py_tp_as_number 84 -#define Py_tp_as_sequence 85 -#define Py_tp_basicsize 86 -#define Py_tp_cache 87 -#define Py_tp_dict 88 -#define Py_tp_dictoffset 89 -#define Py_tp_flags 90 -#define Py_tp_itemsize 91 -#define Py_tp_mro 92 -#define Py_tp_name 93 -#define Py_tp_subclasses 94 -#define Py_tp_vectorcall_offset 95 -#define Py_tp_version_tag 96 -#define Py_tp_weaklist 97 -#define Py_tp_weaklistoffset 98 -#endif diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 07338b101e18ca..947ae607b260bd 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1021,25 +1021,22 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { - char *tp_name = PyType_GetSlot(&PyLong_Type, Py_tp_name); + char *tp_name = PyType_GetSlot(&PyLong_Type, Py_type_name); assert(strcmp(tp_name, "int") == 0); - newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); + newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_type_new); PyObject *args = PyTuple_New(0); PyObject *object = tp_new(&PyLong_Type, args, NULL); assert(object); - reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); + reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_type_repr); PyObject *decimal_str = tp_repr(object); assert(decimal_str); - PyNumberMethods *tp_as_number = PyType_GetSlot(&PyLong_Type, - Py_tp_as_number); - PyObject *object2 = tp_new(&PyLong_Type, args, NULL); - PyObject *res = tp_as_number->nb_add(object, object2); - assert(res); + ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, + Py_type_call); + assert(tp_call == 0); - Py_DECREF(res); Py_DECREF(decimal_str); Py_DECREF(args); Py_DECREF(object); diff --git a/Objects/statictypeslots.inc b/Objects/statictypeslots.inc new file mode 100644 index 00000000000000..e0564cb1995af9 --- /dev/null +++ b/Objects/statictypeslots.inc @@ -0,0 +1,42 @@ +/* Generated by statictypeslots.py */ +offsetof(PyTypeObject, tp_name), +offsetof(PyTypeObject, tp_basicsize), +offsetof(PyTypeObject, tp_itemsize), +offsetof(PyTypeObject, tp_dealloc), +offsetof(PyTypeObject, tp_vectorcall_offset), +offsetof(PyTypeObject, tp_getattr), +offsetof(PyTypeObject, tp_setattr), +offsetof(PyTypeObject, tp_repr), +offsetof(PyTypeObject, tp_hash), +offsetof(PyTypeObject, tp_call), +offsetof(PyTypeObject, tp_str), +offsetof(PyTypeObject, tp_getattro), +offsetof(PyTypeObject, tp_setattro), +offsetof(PyTypeObject, tp_flags), +offsetof(PyTypeObject, tp_doc), +offsetof(PyTypeObject, tp_traverse), +offsetof(PyTypeObject, tp_clear), +offsetof(PyTypeObject, tp_richcompare), +offsetof(PyTypeObject, tp_weaklistoffset), +offsetof(PyTypeObject, tp_iter), +offsetof(PyTypeObject, tp_iternext), +offsetof(PyTypeObject, tp_methods), +offsetof(PyTypeObject, tp_members), +offsetof(PyTypeObject, tp_getset), +offsetof(PyTypeObject, tp_base), +offsetof(PyTypeObject, tp_dict), +offsetof(PyTypeObject, tp_descr_get), +offsetof(PyTypeObject, tp_descr_set), +offsetof(PyTypeObject, tp_dictoffset), +offsetof(PyTypeObject, tp_init), +offsetof(PyTypeObject, tp_alloc), +offsetof(PyTypeObject, tp_new), +offsetof(PyTypeObject, tp_free), +offsetof(PyTypeObject, tp_is_gc), +offsetof(PyTypeObject, tp_bases), +offsetof(PyTypeObject, tp_mro), +offsetof(PyTypeObject, tp_cache), +offsetof(PyTypeObject, tp_subclasses), +offsetof(PyTypeObject, tp_weaklist), +offsetof(PyTypeObject, tp_del), +offsetof(PyTypeObject, tp_finalize), diff --git a/Objects/statictypeslots.py b/Objects/statictypeslots.py new file mode 100755 index 00000000000000..1c58d9ed520085 --- /dev/null +++ b/Objects/statictypeslots.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 +# Usage: statictypeslots.py < Include/statictypeslots.h statictypeslots.inc + +import sys, re + + +def generate_statictypeslots(out=sys.stdout): + out.write("/* Generated by statictypeslots.py */\n") + res = {} + for line in sys.stdin: + m = re.match("#define Py_([a-z_]+) ([0-9]+)", line) + if not m: + continue + member = m.group(1) + if member.startswith("tp_"): + member = member + res[int(m.group(2))] = member + + M = max(res.keys()) + 1 + for i in range(1, M): + if i in res: + out.write("offsetof(PyTypeObject, " + + f"{res[i].replace('type', 'tp')}),\n") + else: + out.write("0,\n") + + +def main(): + if len(sys.argv) == 2: + with open(sys.argv[1], "w") as f: + generate_statictypeslots(f) + else: + generate_statictypeslots() + + +if __name__ == "__main__": + main() diff --git a/Objects/typeobject.c b/Objects/typeobject.c index dee8451eb54768..f0088bd70324bb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2882,6 +2882,11 @@ static const short slotoffsets[] = { #include "typeslots.inc" }; +static const short static_slotoffsets[] = { + -1, /* invalid slot */ +#include "statictypeslots.inc" +}; + PyObject * PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) { @@ -3114,11 +3119,18 @@ PyType_GetSlot(PyTypeObject *type, int slot) PyErr_BadInternalCall(); return NULL; } - if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) { - /* Extension module requesting slot from a future version */ - return NULL; + + if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) && + (size_t)slot < Py_ARRAY_LENGTH(slotoffsets)) { + return *(void**)(((char*)type) + slotoffsets[slot]); + } + else if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) && + (size_t)slot < Py_ARRAY_LENGTH(static_slotoffsets)) { + return *(void**)(((char*)type) + static_slotoffsets[slot]); } - return *(void**)(((char*)type) + slotoffsets[slot]); + + /* Extension module requesting slot from a future version */ + return NULL; } PyObject * From 6d943814d733e9cf2b545b9ded605fe36e4e6f7c Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 23 Aug 2020 17:03:24 +0800 Subject: [PATCH 07/23] revert typeslots.inc to master base --- Objects/typeslots.inc | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc index 58b11d678827a2..ffc9bb2e1c7710 100644 --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -79,21 +79,3 @@ offsetof(PyHeapTypeObject, as_async.am_await), offsetof(PyHeapTypeObject, as_async.am_aiter), offsetof(PyHeapTypeObject, as_async.am_anext), offsetof(PyHeapTypeObject, ht_type.tp_finalize), -offsetof(PyHeapTypeObject, ht_type.tp_as_async), -offsetof(PyHeapTypeObject, ht_type.tp_as_buffer), -offsetof(PyHeapTypeObject, ht_type.tp_as_mapping), -offsetof(PyHeapTypeObject, ht_type.tp_as_number), -offsetof(PyHeapTypeObject, ht_type.tp_as_sequence), -offsetof(PyHeapTypeObject, ht_type.tp_basicsize), -offsetof(PyHeapTypeObject, ht_type.tp_cache), -offsetof(PyHeapTypeObject, ht_type.tp_dict), -offsetof(PyHeapTypeObject, ht_type.tp_dictoffset), -offsetof(PyHeapTypeObject, ht_type.tp_flags), -offsetof(PyHeapTypeObject, ht_type.tp_itemsize), -offsetof(PyHeapTypeObject, ht_type.tp_mro), -offsetof(PyHeapTypeObject, ht_type.tp_name), -offsetof(PyHeapTypeObject, ht_type.tp_subclasses), -offsetof(PyHeapTypeObject, ht_type.tp_vectorcall_offset), -offsetof(PyHeapTypeObject, ht_type.tp_version_tag), -offsetof(PyHeapTypeObject, ht_type.tp_weaklist), -offsetof(PyHeapTypeObject, ht_type.tp_weaklistoffset), From eb3907d06c37d19a10906ebff2cbd5edfda90e89 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Thu, 3 Sep 2020 00:09:13 +0800 Subject: [PATCH 08/23] update get static type slots --- Include/statictypeslots.h | 281 +++++++++++++++++++++++++----------- Modules/_testcapimodule.c | 15 +- Objects/statictypeslots.inc | 57 ++++++++ Objects/statictypeslots.py | 21 ++- Objects/typeobject.c | 55 ++++++- 5 files changed, 331 insertions(+), 98 deletions(-) diff --git a/Include/statictypeslots.h b/Include/statictypeslots.h index 971e6f77388776..8424fad4e29383 100644 --- a/Include/statictypeslots.h +++ b/Include/statictypeslots.h @@ -1,86 +1,203 @@ /* Do not renumber the file; these numbers are part of the stable ABI. */ #if defined(Py_LIMITED_API) -#undef Py_type_name 1 -#undef Py_type_basicsize 2 -#undef Py_type_itemsize 3 -#undef Py_type_dealloc 4 -#undef Py_type_vectorcall_offset 5 -#undef Py_type_getattr 6 -#undef Py_type_setattr 7 -#undef Py_type_repr 8 -#undef Py_type_hash 9 -#undef Py_type_call 10 -#undef Py_type_str 11 -#undef Py_type_getattro 12 -#undef Py_type_setattro 13 -#undef Py_type_flags 14 -#undef Py_type_doc 15 -#undef Py_type_traverse 16 -#undef Py_type_clear 17 -#undef Py_type_richcompare 18 -#undef Py_type_weaklistoffset 19 -#undef Py_type_iter 20 -#undef Py_type_iternext 21 -#undef Py_type_methods 22 -#undef Py_type_members 23 -#undef Py_type_getset 24 -#undef Py_type_base 25 -#undef Py_type_dict 26 -#undef Py_type_descr_get 27 -#undef Py_type_descr_set 28 -#undef Py_type_dictoffset 29 -#undef Py_type_init 30 -#undef Py_type_alloc 31 -#undef Py_type_new 32 -#undef Py_type_free 33 -#undef Py_type_is_gc 34 -#undef Py_type_bases 35 -#undef Py_type_mro 36 -#undef Py_type_cache 37 -#undef Py_type_subclasses 38 -#undef Py_type_weaklist 39 -#undef Py_type_del 40 -#undef Py_type_finalize 41 +#undef Py_type_name +#undef Py_type_basicsize +#undef Py_type_itemsize +#undef Py_type_dealloc +#undef Py_type_vectorcall_offset +#undef Py_type_getattr +#undef Py_type_setattr +#undef Py_type_repr +#undef Py_type_hash +#undef Py_type_call +#undef Py_type_str +#undef Py_type_getattro +#undef Py_type_setattro +#undef Py_type_flags +#undef Py_type_doc +#undef Py_type_traverse +#undef Py_type_clear +#undef Py_type_richcompare +#undef Py_type_weaklistoffset +#undef Py_type_iter +#undef Py_type_iternext +#undef Py_type_methods +#undef Py_type_members +#undef Py_type_getset +#undef Py_type_base +#undef Py_type_dict +#undef Py_type_descr_get +#undef Py_type_descr_set +#undef Py_type_dictoffset +#undef Py_type_init +#undef Py_type_alloc +#undef Py_type_new +#undef Py_type_free +#undef Py_type_is_gc +#undef Py_type_bases +#undef Py_type_mro +#undef Py_type_cache +#undef Py_type_subclasses +#undef Py_type_weaklist +#undef Py_type_del +#undef Py_type_finalize +#undef Py_type_as_async +#undef Py_type_am_await +#undef Py_type_am_aiter +#undef Py_type_am_anext +#undef Py_type_as_number +#undef Py_type_nb_add +#undef Py_type_nb_subtract +#undef Py_type_nb_multiply +#undef Py_type_nb_remainder +#undef Py_type_nb_divmod +#undef Py_type_nb_power +#undef Py_type_nb_negative +#undef Py_type_nb_positive +#undef Py_type_nb_absolute +#undef Py_type_nb_bool +#undef Py_type_nb_invert +#undef Py_type_nb_lshift +#undef Py_type_nb_rshift +#undef Py_type_nb_and +#undef Py_type_nb_xor +#undef Py_type_nb_or +#undef Py_type_nb_int +#undef Py_type_nb_reserved +#undef Py_type_nb_float +#undef Py_type_nb_inplace_add +#undef Py_type_nb_inplace_subtract +#undef Py_type_nb_inplace_multiply +#undef Py_type_nb_inplace_remainder +#undef Py_type_nb_inplace_power +#undef Py_type_nb_inplace_lshift +#undef Py_type_nb_inplace_rshift +#undef Py_type_nb_inplace_and +#undef Py_type_nb_inplace_xor +#undef Py_type_nb_inplace_or +#undef Py_type_nb_floor_divide +#undef Py_type_nb_true_divide +#undef Py_type_nb_inplace_floor_divide +#undef Py_type_nb_inplace_true_divide +#undef Py_type_nb_index +#undef Py_type_nb_matrix_multiply +#undef Py_type_nb_inplace_matrix_multiply +#undef Py_type_as_sequence +#undef Py_type_sq_length +#undef Py_type_sq_concat +#undef Py_type_sq_repeat +#undef Py_type_sq_item +#undef Py_type_sq_ass_item +#undef Py_type_sq_contains +#undef Py_type_sq_inplace_concat +#undef Py_type_sq_inplace_repeat +#undef Py_type_as_mapping +#undef Py_type_mp_length +#undef Py_type_mp_subscript +#undef Py_type_mp_ass_subscript +#undef Py_type_as_buffer +#undef Py_type_bf_getbuffer +#undef Py_type_bf_releasebuffer #else -#define Py_type_name 1 -#define Py_type_basicsize 2 -#define Py_type_itemsize 3 -#define Py_type_dealloc 4 -#define Py_type_vectorcall_offset 5 -#define Py_type_getattr 6 -#define Py_type_setattr 7 -#define Py_type_repr 8 -#define Py_type_hash 9 -#define Py_type_call 10 -#define Py_type_str 11 -#define Py_type_getattro 12 -#define Py_type_setattro 13 -#define Py_type_flags 14 -#define Py_type_doc 15 -#define Py_type_traverse 16 -#define Py_type_clear 17 -#define Py_type_richcompare 18 -#define Py_type_weaklistoffset 19 -#define Py_type_iter 20 -#define Py_type_iternext 21 -#define Py_type_methods 22 -#define Py_type_members 23 -#define Py_type_getset 24 -#define Py_type_base 25 -#define Py_type_dict 26 -#define Py_type_descr_get 27 -#define Py_type_descr_set 28 -#define Py_type_dictoffset 29 -#define Py_type_init 30 -#define Py_type_alloc 31 -#define Py_type_new 32 -#define Py_type_free 33 -#define Py_type_is_gc 34 -#define Py_type_bases 35 -#define Py_type_mro 36 -#define Py_type_cache 37 -#define Py_type_subclasses 38 -#define Py_type_weaklist 39 -#define Py_type_del 40 -#define Py_type_finalize 41 +/* Define STATIC_TYPE_OFFSET marco to avoid the duplicated number + * with typeslots.h. */ +#define STATIC_TYPE_OFFSET 500 +#define Py_type_name (1 + STATIC_TYPE_OFFSET) +#define Py_type_basicsize (2 + STATIC_TYPE_OFFSET) +#define Py_type_itemsize (3 + STATIC_TYPE_OFFSET) +#define Py_type_dealloc (4 + STATIC_TYPE_OFFSET) +#define Py_type_vectorcall_offset (5 + STATIC_TYPE_OFFSET) +#define Py_type_getattr (6 + STATIC_TYPE_OFFSET) +#define Py_type_setattr (7 + STATIC_TYPE_OFFSET) +#define Py_type_repr (8 + STATIC_TYPE_OFFSET) +#define Py_type_hash (9 + STATIC_TYPE_OFFSET) +#define Py_type_call (10 + STATIC_TYPE_OFFSET) +#define Py_type_str (11 + STATIC_TYPE_OFFSET) +#define Py_type_getattro (12 + STATIC_TYPE_OFFSET) +#define Py_type_setattro (13 + STATIC_TYPE_OFFSET) +#define Py_type_flags (14 + STATIC_TYPE_OFFSET) +#define Py_type_doc (15 + STATIC_TYPE_OFFSET) +#define Py_type_traverse (16 + STATIC_TYPE_OFFSET) +#define Py_type_clear (17 + STATIC_TYPE_OFFSET) +#define Py_type_richcompare (18 + STATIC_TYPE_OFFSET) +#define Py_type_weaklistoffset (19 + STATIC_TYPE_OFFSET) +#define Py_type_iter (20 + STATIC_TYPE_OFFSET) +#define Py_type_iternext (21 + STATIC_TYPE_OFFSET) +#define Py_type_methods (22 + STATIC_TYPE_OFFSET) +#define Py_type_members (23 + STATIC_TYPE_OFFSET) +#define Py_type_getset (24 + STATIC_TYPE_OFFSET) +#define Py_type_base (25 + STATIC_TYPE_OFFSET) +#define Py_type_dict (26 + STATIC_TYPE_OFFSET) +#define Py_type_descr_get (27 + STATIC_TYPE_OFFSET) +#define Py_type_descr_set (28 + STATIC_TYPE_OFFSET) +#define Py_type_dictoffset (29 + STATIC_TYPE_OFFSET) +#define Py_type_init (30 + STATIC_TYPE_OFFSET) +#define Py_type_alloc (31 + STATIC_TYPE_OFFSET) +#define Py_type_new (32 + STATIC_TYPE_OFFSET) +#define Py_type_free (33 + STATIC_TYPE_OFFSET) +#define Py_type_is_gc (34 + STATIC_TYPE_OFFSET) +#define Py_type_bases (35 + STATIC_TYPE_OFFSET) +#define Py_type_mro (36 + STATIC_TYPE_OFFSET) +#define Py_type_cache (37 + STATIC_TYPE_OFFSET) +#define Py_type_subclasses (38 + STATIC_TYPE_OFFSET) +#define Py_type_weaklist (39 + STATIC_TYPE_OFFSET) +#define Py_type_del (40 + STATIC_TYPE_OFFSET) +#define Py_type_finalize (41 + STATIC_TYPE_OFFSET) +#define Py_type_as_async (42 + STATIC_TYPE_OFFSET) +#define Py_type_am_await (43 + STATIC_TYPE_OFFSET) +#define Py_type_am_aiter (44 + STATIC_TYPE_OFFSET) +#define Py_type_am_anext (45 + STATIC_TYPE_OFFSET) +#define Py_type_as_number (46 + STATIC_TYPE_OFFSET) +#define Py_type_nb_add (47 + STATIC_TYPE_OFFSET) +#define Py_type_nb_subtract (48 + STATIC_TYPE_OFFSET) +#define Py_type_nb_multiply (49 + STATIC_TYPE_OFFSET) +#define Py_type_nb_remainder (50 + STATIC_TYPE_OFFSET) +#define Py_type_nb_divmod (51 + STATIC_TYPE_OFFSET) +#define Py_type_nb_power (52 + STATIC_TYPE_OFFSET) +#define Py_type_nb_negative (53 + STATIC_TYPE_OFFSET) +#define Py_type_nb_positive (54 + STATIC_TYPE_OFFSET) +#define Py_type_nb_absolute (55 + STATIC_TYPE_OFFSET) +#define Py_type_nb_bool (56 + STATIC_TYPE_OFFSET) +#define Py_type_nb_invert (57 + STATIC_TYPE_OFFSET) +#define Py_type_nb_lshift (58 + STATIC_TYPE_OFFSET) +#define Py_type_nb_rshift (59 + STATIC_TYPE_OFFSET) +#define Py_type_nb_and (60 + STATIC_TYPE_OFFSET) +#define Py_type_nb_xor (61 + STATIC_TYPE_OFFSET) +#define Py_type_nb_or (62 + STATIC_TYPE_OFFSET) +#define Py_type_nb_int (63 + STATIC_TYPE_OFFSET) +#define Py_type_nb_reserved (64 + STATIC_TYPE_OFFSET) +#define Py_type_nb_float (65 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_add (66 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_subtract (67 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_multiply (68 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_remainder (69 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_power (70 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_lshift (71 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_rshift (72 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_and (73 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_xor (74 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_or (75 + STATIC_TYPE_OFFSET) +#define Py_type_nb_floor_divide (76 + STATIC_TYPE_OFFSET) +#define Py_type_nb_true_divide (77 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_floor_divide (78 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_true_divide (79 + STATIC_TYPE_OFFSET) +#define Py_type_nb_index (80 + STATIC_TYPE_OFFSET) +#define Py_type_nb_matrix_multiply (81 + STATIC_TYPE_OFFSET) +#define Py_type_nb_inplace_matrix_multiply (82 + STATIC_TYPE_OFFSET) +#define Py_type_as_sequence (83 + STATIC_TYPE_OFFSET) +#define Py_type_sq_length (84 + STATIC_TYPE_OFFSET) +#define Py_type_sq_concat (85 + STATIC_TYPE_OFFSET) +#define Py_type_sq_repeat (86 + STATIC_TYPE_OFFSET) +#define Py_type_sq_item (87 + STATIC_TYPE_OFFSET) +#define Py_type_sq_ass_item (88 + STATIC_TYPE_OFFSET) +#define Py_type_sq_contains (89 + STATIC_TYPE_OFFSET) +#define Py_type_sq_inplace_concat (90 + STATIC_TYPE_OFFSET) +#define Py_type_sq_inplace_repeat (91 + STATIC_TYPE_OFFSET) +#define Py_type_as_mapping (92 + STATIC_TYPE_OFFSET) +#define Py_type_mp_length (93 + STATIC_TYPE_OFFSET) +#define Py_type_mp_subscript (94 + STATIC_TYPE_OFFSET) +#define Py_type_mp_ass_subscript (95 + STATIC_TYPE_OFFSET) +#define Py_type_as_buffer (96 + STATIC_TYPE_OFFSET) +#define Py_type_bf_getbuffer (97 + STATIC_TYPE_OFFSET) +#define Py_type_bf_releasebuffer (98 + STATIC_TYPE_OFFSET) #endif diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 947ae607b260bd..acb5d881e024e7 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1033,13 +1033,24 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) PyObject *decimal_str = tp_repr(object); assert(decimal_str); - ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, - Py_type_call); + ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_type_call); assert(tp_call == 0); + binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_type_nb_add); + PyObject *result = nb_add(object, object); + assert(result); + + lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_type_mp_length); + assert(mp_length == NULL); + + void *over_value = PyType_GetSlot(&PyLong_Type, + Py_type_bf_releasebuffer + 1); + assert(over_value == NULL); + Py_DECREF(decimal_str); Py_DECREF(args); Py_DECREF(object); + Py_DECREF(result); Py_RETURN_NONE; } diff --git a/Objects/statictypeslots.inc b/Objects/statictypeslots.inc index e0564cb1995af9..f749471b19734e 100644 --- a/Objects/statictypeslots.inc +++ b/Objects/statictypeslots.inc @@ -40,3 +40,60 @@ offsetof(PyTypeObject, tp_subclasses), offsetof(PyTypeObject, tp_weaklist), offsetof(PyTypeObject, tp_del), offsetof(PyTypeObject, tp_finalize), +offsetof(PyTypeObject, tp_as_async), +offsetof(PyAsyncMethods, am_await), +offsetof(PyAsyncMethods, am_aiter), +offsetof(PyAsyncMethods, am_anext), +offsetof(PyTypeObject, tp_as_number), +offsetof(PyNumberMethods, nb_add), +offsetof(PyNumberMethods, nb_subtract), +offsetof(PyNumberMethods, nb_multiply), +offsetof(PyNumberMethods, nb_remainder), +offsetof(PyNumberMethods, nb_divmod), +offsetof(PyNumberMethods, nb_power), +offsetof(PyNumberMethods, nb_negative), +offsetof(PyNumberMethods, nb_positive), +offsetof(PyNumberMethods, nb_absolute), +offsetof(PyNumberMethods, nb_bool), +offsetof(PyNumberMethods, nb_invert), +offsetof(PyNumberMethods, nb_lshift), +offsetof(PyNumberMethods, nb_rshift), +offsetof(PyNumberMethods, nb_and), +offsetof(PyNumberMethods, nb_xor), +offsetof(PyNumberMethods, nb_or), +offsetof(PyNumberMethods, nb_int), +offsetof(PyNumberMethods, nb_reserved), +offsetof(PyNumberMethods, nb_float), +offsetof(PyNumberMethods, nb_inplace_add), +offsetof(PyNumberMethods, nb_inplace_subtract), +offsetof(PyNumberMethods, nb_inplace_multiply), +offsetof(PyNumberMethods, nb_inplace_remainder), +offsetof(PyNumberMethods, nb_inplace_power), +offsetof(PyNumberMethods, nb_inplace_lshift), +offsetof(PyNumberMethods, nb_inplace_rshift), +offsetof(PyNumberMethods, nb_inplace_and), +offsetof(PyNumberMethods, nb_inplace_xor), +offsetof(PyNumberMethods, nb_inplace_or), +offsetof(PyNumberMethods, nb_floor_divide), +offsetof(PyNumberMethods, nb_true_divide), +offsetof(PyNumberMethods, nb_inplace_floor_divide), +offsetof(PyNumberMethods, nb_inplace_true_divide), +offsetof(PyNumberMethods, nb_index), +offsetof(PyNumberMethods, nb_matrix_multiply), +offsetof(PyNumberMethods, nb_inplace_matrix_multiply), +offsetof(PyTypeObject, tp_as_sequence), +offsetof(PySequenceMethods, sq_length), +offsetof(PySequenceMethods, sq_concat), +offsetof(PySequenceMethods, sq_repeat), +offsetof(PySequenceMethods, sq_item), +offsetof(PySequenceMethods, sq_ass_item), +offsetof(PySequenceMethods, sq_contains), +offsetof(PySequenceMethods, sq_inplace_concat), +offsetof(PySequenceMethods, sq_inplace_repeat), +offsetof(PyTypeObject, tp_as_mapping), +offsetof(PyMappingMethods, mp_length), +offsetof(PyMappingMethods, mp_subscript), +offsetof(PyMappingMethods, mp_ass_subscript), +offsetof(PyTypeObject, tp_as_buffer), +offsetof(PyBufferProcs, bf_getbuffer), +offsetof(PyBufferProcs, bf_releasebuffer), diff --git a/Objects/statictypeslots.py b/Objects/statictypeslots.py index 1c58d9ed520085..89d6f1f516ca52 100755 --- a/Objects/statictypeslots.py +++ b/Objects/statictypeslots.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # Usage: statictypeslots.py < Include/statictypeslots.h statictypeslots.inc import sys, re @@ -8,19 +8,28 @@ def generate_statictypeslots(out=sys.stdout): out.write("/* Generated by statictypeslots.py */\n") res = {} for line in sys.stdin: - m = re.match("#define Py_([a-z_]+) ([0-9]+)", line) + m = re.match("#define Py_type_([a-z_]+) \\(([0-9]+)", line) if not m: continue member = m.group(1) - if member.startswith("tp_"): - member = member + if member.startswith("am_"): + member = "PyAsyncMethods, " + member + elif member.startswith("nb_"): + member = "PyNumberMethods, " + member + elif member.startswith("sq_"): + member = "PySequenceMethods, " + member + elif member.startswith("mp_"): + member = "PyMappingMethods, " + member + elif member.startswith("bf_"): + member = "PyBufferProcs, " + member + else: + member = "PyTypeObject, tp_" + member res[int(m.group(2))] = member M = max(res.keys()) + 1 for i in range(1, M): if i in res: - out.write("offsetof(PyTypeObject, " - + f"{res[i].replace('type', 'tp')}),\n") + out.write(f"offsetof({res[i]}),\n") else: out.write("0,\n") diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f0088bd70324bb..6e550288dbb32f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3120,17 +3120,56 @@ PyType_GetSlot(PyTypeObject *type, int slot) return NULL; } - if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) && - (size_t)slot < Py_ARRAY_LENGTH(slotoffsets)) { + if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { + if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) { + /* Extension module requesting slot from a future version */ + return NULL; + } return *(void**)(((char*)type) + slotoffsets[slot]); } - else if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) && - (size_t)slot < Py_ARRAY_LENGTH(static_slotoffsets)) { - return *(void**)(((char*)type) + static_slotoffsets[slot]); - } - /* Extension module requesting slot from a future version */ - return NULL; + void *methods = NULL; + size_t base_slot = slot - STATIC_TYPE_OFFSET; + int methods_flag = 0; + if (base_slot >= Py_ARRAY_LENGTH(static_slotoffsets)) { + return NULL; + } else if (slot >= Py_type_am_await && + slot <= Py_type_am_anext) { + methods = *(void**)(((char*)type) + + static_slotoffsets[Py_type_as_async - STATIC_TYPE_OFFSET]); + methods_flag = 1; + } else if (slot >= Py_type_nb_add && + slot <= Py_type_nb_inplace_matrix_multiply) { + methods = *(void**)(((char*)type) + + static_slotoffsets[Py_type_as_number - STATIC_TYPE_OFFSET]); + methods_flag = 1; + } else if (slot >= Py_type_sq_length && + slot <= Py_type_sq_inplace_repeat) { + methods = *(void**)(((char*)type) + + static_slotoffsets[Py_type_as_sequence - STATIC_TYPE_OFFSET]); + methods_flag = 1; + } else if (slot >= Py_type_mp_length && + slot <= Py_type_mp_ass_subscript) { + methods = *(void**)(((char*)type) + + static_slotoffsets[Py_type_as_mapping - STATIC_TYPE_OFFSET]); + methods_flag = 1; + } else if (slot >= Py_type_bf_getbuffer && + slot <= Py_type_bf_releasebuffer) { + methods = *(void**)(((char*)type) + + static_slotoffsets[Py_type_as_buffer - STATIC_TYPE_OFFSET]); + methods_flag = 1; + } + if (methods != NULL) { + return *(void**)(methods + + static_slotoffsets[slot - STATIC_TYPE_OFFSET]); + } + else { + if (methods_flag) { + return NULL; + } + return *(void**)(((char*)type) + + static_slotoffsets[slot - STATIC_TYPE_OFFSET]); + } } PyObject * From fe9f858dcc0ac8e8aa9ac46339460e7b11003cf4 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sat, 5 Sep 2020 13:57:45 +0800 Subject: [PATCH 09/23] Fix compile error --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 930c6f80b6ae70..5452ece8c7275b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3169,7 +3169,7 @@ PyType_GetSlot(PyTypeObject *type, int slot) methods_flag = 1; } if (methods != NULL) { - return *(void**)(methods + + return *(void**)((char *)methods + static_slotoffsets[slot - STATIC_TYPE_OFFSET]); } else { From 93d849c00a006311406dd945519de05c0f24577d Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 21 Oct 2020 02:48:41 +0800 Subject: [PATCH 10/23] Use petr's idea --- Include/Python.h | 1 - Include/statictypeslots.h | 203 --------------------- Include/typeslots.h | 48 +++++ Modules/_testcapimodule.c | 15 +- Objects/statictypeslots.inc | 99 ----------- Objects/statictypeslots.py | 46 ----- Objects/typeobject.c | 344 ++++++++++++++++++++++++++++++------ 7 files changed, 348 insertions(+), 408 deletions(-) delete mode 100644 Include/statictypeslots.h delete mode 100644 Objects/statictypeslots.inc delete mode 100755 Objects/statictypeslots.py diff --git a/Include/Python.h b/Include/Python.h index b48e77d2ecea72..57f71d41d8d477 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -88,7 +88,6 @@ #include "object.h" #include "objimpl.h" #include "typeslots.h" -#include "statictypeslots.h" #include "pyhash.h" #include "pydebug.h" diff --git a/Include/statictypeslots.h b/Include/statictypeslots.h deleted file mode 100644 index 8424fad4e29383..00000000000000 --- a/Include/statictypeslots.h +++ /dev/null @@ -1,203 +0,0 @@ -/* Do not renumber the file; these numbers are part of the stable ABI. */ -#if defined(Py_LIMITED_API) -#undef Py_type_name -#undef Py_type_basicsize -#undef Py_type_itemsize -#undef Py_type_dealloc -#undef Py_type_vectorcall_offset -#undef Py_type_getattr -#undef Py_type_setattr -#undef Py_type_repr -#undef Py_type_hash -#undef Py_type_call -#undef Py_type_str -#undef Py_type_getattro -#undef Py_type_setattro -#undef Py_type_flags -#undef Py_type_doc -#undef Py_type_traverse -#undef Py_type_clear -#undef Py_type_richcompare -#undef Py_type_weaklistoffset -#undef Py_type_iter -#undef Py_type_iternext -#undef Py_type_methods -#undef Py_type_members -#undef Py_type_getset -#undef Py_type_base -#undef Py_type_dict -#undef Py_type_descr_get -#undef Py_type_descr_set -#undef Py_type_dictoffset -#undef Py_type_init -#undef Py_type_alloc -#undef Py_type_new -#undef Py_type_free -#undef Py_type_is_gc -#undef Py_type_bases -#undef Py_type_mro -#undef Py_type_cache -#undef Py_type_subclasses -#undef Py_type_weaklist -#undef Py_type_del -#undef Py_type_finalize -#undef Py_type_as_async -#undef Py_type_am_await -#undef Py_type_am_aiter -#undef Py_type_am_anext -#undef Py_type_as_number -#undef Py_type_nb_add -#undef Py_type_nb_subtract -#undef Py_type_nb_multiply -#undef Py_type_nb_remainder -#undef Py_type_nb_divmod -#undef Py_type_nb_power -#undef Py_type_nb_negative -#undef Py_type_nb_positive -#undef Py_type_nb_absolute -#undef Py_type_nb_bool -#undef Py_type_nb_invert -#undef Py_type_nb_lshift -#undef Py_type_nb_rshift -#undef Py_type_nb_and -#undef Py_type_nb_xor -#undef Py_type_nb_or -#undef Py_type_nb_int -#undef Py_type_nb_reserved -#undef Py_type_nb_float -#undef Py_type_nb_inplace_add -#undef Py_type_nb_inplace_subtract -#undef Py_type_nb_inplace_multiply -#undef Py_type_nb_inplace_remainder -#undef Py_type_nb_inplace_power -#undef Py_type_nb_inplace_lshift -#undef Py_type_nb_inplace_rshift -#undef Py_type_nb_inplace_and -#undef Py_type_nb_inplace_xor -#undef Py_type_nb_inplace_or -#undef Py_type_nb_floor_divide -#undef Py_type_nb_true_divide -#undef Py_type_nb_inplace_floor_divide -#undef Py_type_nb_inplace_true_divide -#undef Py_type_nb_index -#undef Py_type_nb_matrix_multiply -#undef Py_type_nb_inplace_matrix_multiply -#undef Py_type_as_sequence -#undef Py_type_sq_length -#undef Py_type_sq_concat -#undef Py_type_sq_repeat -#undef Py_type_sq_item -#undef Py_type_sq_ass_item -#undef Py_type_sq_contains -#undef Py_type_sq_inplace_concat -#undef Py_type_sq_inplace_repeat -#undef Py_type_as_mapping -#undef Py_type_mp_length -#undef Py_type_mp_subscript -#undef Py_type_mp_ass_subscript -#undef Py_type_as_buffer -#undef Py_type_bf_getbuffer -#undef Py_type_bf_releasebuffer -#else -/* Define STATIC_TYPE_OFFSET marco to avoid the duplicated number - * with typeslots.h. */ -#define STATIC_TYPE_OFFSET 500 -#define Py_type_name (1 + STATIC_TYPE_OFFSET) -#define Py_type_basicsize (2 + STATIC_TYPE_OFFSET) -#define Py_type_itemsize (3 + STATIC_TYPE_OFFSET) -#define Py_type_dealloc (4 + STATIC_TYPE_OFFSET) -#define Py_type_vectorcall_offset (5 + STATIC_TYPE_OFFSET) -#define Py_type_getattr (6 + STATIC_TYPE_OFFSET) -#define Py_type_setattr (7 + STATIC_TYPE_OFFSET) -#define Py_type_repr (8 + STATIC_TYPE_OFFSET) -#define Py_type_hash (9 + STATIC_TYPE_OFFSET) -#define Py_type_call (10 + STATIC_TYPE_OFFSET) -#define Py_type_str (11 + STATIC_TYPE_OFFSET) -#define Py_type_getattro (12 + STATIC_TYPE_OFFSET) -#define Py_type_setattro (13 + STATIC_TYPE_OFFSET) -#define Py_type_flags (14 + STATIC_TYPE_OFFSET) -#define Py_type_doc (15 + STATIC_TYPE_OFFSET) -#define Py_type_traverse (16 + STATIC_TYPE_OFFSET) -#define Py_type_clear (17 + STATIC_TYPE_OFFSET) -#define Py_type_richcompare (18 + STATIC_TYPE_OFFSET) -#define Py_type_weaklistoffset (19 + STATIC_TYPE_OFFSET) -#define Py_type_iter (20 + STATIC_TYPE_OFFSET) -#define Py_type_iternext (21 + STATIC_TYPE_OFFSET) -#define Py_type_methods (22 + STATIC_TYPE_OFFSET) -#define Py_type_members (23 + STATIC_TYPE_OFFSET) -#define Py_type_getset (24 + STATIC_TYPE_OFFSET) -#define Py_type_base (25 + STATIC_TYPE_OFFSET) -#define Py_type_dict (26 + STATIC_TYPE_OFFSET) -#define Py_type_descr_get (27 + STATIC_TYPE_OFFSET) -#define Py_type_descr_set (28 + STATIC_TYPE_OFFSET) -#define Py_type_dictoffset (29 + STATIC_TYPE_OFFSET) -#define Py_type_init (30 + STATIC_TYPE_OFFSET) -#define Py_type_alloc (31 + STATIC_TYPE_OFFSET) -#define Py_type_new (32 + STATIC_TYPE_OFFSET) -#define Py_type_free (33 + STATIC_TYPE_OFFSET) -#define Py_type_is_gc (34 + STATIC_TYPE_OFFSET) -#define Py_type_bases (35 + STATIC_TYPE_OFFSET) -#define Py_type_mro (36 + STATIC_TYPE_OFFSET) -#define Py_type_cache (37 + STATIC_TYPE_OFFSET) -#define Py_type_subclasses (38 + STATIC_TYPE_OFFSET) -#define Py_type_weaklist (39 + STATIC_TYPE_OFFSET) -#define Py_type_del (40 + STATIC_TYPE_OFFSET) -#define Py_type_finalize (41 + STATIC_TYPE_OFFSET) -#define Py_type_as_async (42 + STATIC_TYPE_OFFSET) -#define Py_type_am_await (43 + STATIC_TYPE_OFFSET) -#define Py_type_am_aiter (44 + STATIC_TYPE_OFFSET) -#define Py_type_am_anext (45 + STATIC_TYPE_OFFSET) -#define Py_type_as_number (46 + STATIC_TYPE_OFFSET) -#define Py_type_nb_add (47 + STATIC_TYPE_OFFSET) -#define Py_type_nb_subtract (48 + STATIC_TYPE_OFFSET) -#define Py_type_nb_multiply (49 + STATIC_TYPE_OFFSET) -#define Py_type_nb_remainder (50 + STATIC_TYPE_OFFSET) -#define Py_type_nb_divmod (51 + STATIC_TYPE_OFFSET) -#define Py_type_nb_power (52 + STATIC_TYPE_OFFSET) -#define Py_type_nb_negative (53 + STATIC_TYPE_OFFSET) -#define Py_type_nb_positive (54 + STATIC_TYPE_OFFSET) -#define Py_type_nb_absolute (55 + STATIC_TYPE_OFFSET) -#define Py_type_nb_bool (56 + STATIC_TYPE_OFFSET) -#define Py_type_nb_invert (57 + STATIC_TYPE_OFFSET) -#define Py_type_nb_lshift (58 + STATIC_TYPE_OFFSET) -#define Py_type_nb_rshift (59 + STATIC_TYPE_OFFSET) -#define Py_type_nb_and (60 + STATIC_TYPE_OFFSET) -#define Py_type_nb_xor (61 + STATIC_TYPE_OFFSET) -#define Py_type_nb_or (62 + STATIC_TYPE_OFFSET) -#define Py_type_nb_int (63 + STATIC_TYPE_OFFSET) -#define Py_type_nb_reserved (64 + STATIC_TYPE_OFFSET) -#define Py_type_nb_float (65 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_add (66 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_subtract (67 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_multiply (68 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_remainder (69 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_power (70 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_lshift (71 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_rshift (72 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_and (73 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_xor (74 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_or (75 + STATIC_TYPE_OFFSET) -#define Py_type_nb_floor_divide (76 + STATIC_TYPE_OFFSET) -#define Py_type_nb_true_divide (77 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_floor_divide (78 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_true_divide (79 + STATIC_TYPE_OFFSET) -#define Py_type_nb_index (80 + STATIC_TYPE_OFFSET) -#define Py_type_nb_matrix_multiply (81 + STATIC_TYPE_OFFSET) -#define Py_type_nb_inplace_matrix_multiply (82 + STATIC_TYPE_OFFSET) -#define Py_type_as_sequence (83 + STATIC_TYPE_OFFSET) -#define Py_type_sq_length (84 + STATIC_TYPE_OFFSET) -#define Py_type_sq_concat (85 + STATIC_TYPE_OFFSET) -#define Py_type_sq_repeat (86 + STATIC_TYPE_OFFSET) -#define Py_type_sq_item (87 + STATIC_TYPE_OFFSET) -#define Py_type_sq_ass_item (88 + STATIC_TYPE_OFFSET) -#define Py_type_sq_contains (89 + STATIC_TYPE_OFFSET) -#define Py_type_sq_inplace_concat (90 + STATIC_TYPE_OFFSET) -#define Py_type_sq_inplace_repeat (91 + STATIC_TYPE_OFFSET) -#define Py_type_as_mapping (92 + STATIC_TYPE_OFFSET) -#define Py_type_mp_length (93 + STATIC_TYPE_OFFSET) -#define Py_type_mp_subscript (94 + STATIC_TYPE_OFFSET) -#define Py_type_mp_ass_subscript (95 + STATIC_TYPE_OFFSET) -#define Py_type_as_buffer (96 + STATIC_TYPE_OFFSET) -#define Py_type_bf_getbuffer (97 + STATIC_TYPE_OFFSET) -#define Py_type_bf_releasebuffer (98 + STATIC_TYPE_OFFSET) -#endif diff --git a/Include/typeslots.h b/Include/typeslots.h index 64f6fff5144493..c3d46903425f59 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,3 +88,51 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif +#define Py_tp_name 81 +#define Py_tp_basicsize 82 +#define Py_tp_itemsize 83 +#define Py_tp_vectorcall_offset 84 +#define Py_tp_flags 85 +#define Py_tp_weaklistoffset 86 +#define Py_tp_dict 87 +#define Py_tp_dictoffset 88 +#define Py_tp_mro 89 +#define Py_tp_cache 90 +#define Py_tp_subclasses 91 +#define Py_tp_weaklist 92 +#define Py_tp_nb_add 93 +#define Py_tp_nb_subtract 94 +#define Py_tp_nb_multiply 95 +#define Py_tp_nb_remainder 96 +#define Py_tp_nb_divmod 97 +#define Py_tp_nb_power 98 +#define Py_tp_nb_negative 99 +#define Py_tp_nb_positive 100 +#define Py_tp_nb_absolute 101 +#define Py_tp_nb_bool 102 +#define Py_tp_nb_invert 103 +#define Py_tp_nb_lshift 104 +#define Py_tp_nb_rshift 105 +#define Py_tp_nb_and 106 +#define Py_tp_nb_xor 107 +#define Py_tp_nb_or 108 +#define Py_tp_nb_int 109 +#define Py_tp_nb_reserved 110 +#define Py_tp_nb_float 111 +#define Py_tp_nb_inplace_add 112 +#define Py_tp_nb_inplace_subtract 113 +#define Py_tp_nb_inplace_multiply 114 +#define Py_tp_nb_inplace_remainder 115 +#define Py_tp_nb_inplace_power 116 +#define Py_tp_nb_inplace_lshift 117 +#define Py_tp_nb_inplace_rshift 118 +#define Py_tp_nb_inplace_and 119 +#define Py_tp_nb_inplace_xor 120 +#define Py_tp_nb_inplace_or 121 +#define Py_tp_nb_floor_divide 122 +#define Py_tp_nb_true_divide 123 +#define Py_tp_nb_inplace_floor_divide 124 +#define Py_tp_nb_inplace_true_divide 125 +#define Py_tp_nb_index 126 +#define Py_tp_nb_matrix_multiply 127 +#define Py_tp_nb_inplace_matrix_multiply 128 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 614112a2108685..1269530f8d3c04 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1021,30 +1021,29 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { - char *tp_name = PyType_GetSlot(&PyLong_Type, Py_type_name); + char *tp_name = PyType_GetSlot(&PyLong_Type, Py_tp_name); assert(strcmp(tp_name, "int") == 0); - newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_type_new); + newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); PyObject *args = PyTuple_New(0); PyObject *object = tp_new(&PyLong_Type, args, NULL); assert(object); - reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_type_repr); + reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); PyObject *decimal_str = tp_repr(object); assert(decimal_str); - ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_type_call); + ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call); assert(tp_call == 0); - binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_type_nb_add); + binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_tp_nb_add); PyObject *result = nb_add(object, object); assert(result); - lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_type_mp_length); + lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length); assert(mp_length == NULL); - void *over_value = PyType_GetSlot(&PyLong_Type, - Py_type_bf_releasebuffer + 1); + void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); assert(over_value == NULL); Py_DECREF(decimal_str); diff --git a/Objects/statictypeslots.inc b/Objects/statictypeslots.inc deleted file mode 100644 index f749471b19734e..00000000000000 --- a/Objects/statictypeslots.inc +++ /dev/null @@ -1,99 +0,0 @@ -/* Generated by statictypeslots.py */ -offsetof(PyTypeObject, tp_name), -offsetof(PyTypeObject, tp_basicsize), -offsetof(PyTypeObject, tp_itemsize), -offsetof(PyTypeObject, tp_dealloc), -offsetof(PyTypeObject, tp_vectorcall_offset), -offsetof(PyTypeObject, tp_getattr), -offsetof(PyTypeObject, tp_setattr), -offsetof(PyTypeObject, tp_repr), -offsetof(PyTypeObject, tp_hash), -offsetof(PyTypeObject, tp_call), -offsetof(PyTypeObject, tp_str), -offsetof(PyTypeObject, tp_getattro), -offsetof(PyTypeObject, tp_setattro), -offsetof(PyTypeObject, tp_flags), -offsetof(PyTypeObject, tp_doc), -offsetof(PyTypeObject, tp_traverse), -offsetof(PyTypeObject, tp_clear), -offsetof(PyTypeObject, tp_richcompare), -offsetof(PyTypeObject, tp_weaklistoffset), -offsetof(PyTypeObject, tp_iter), -offsetof(PyTypeObject, tp_iternext), -offsetof(PyTypeObject, tp_methods), -offsetof(PyTypeObject, tp_members), -offsetof(PyTypeObject, tp_getset), -offsetof(PyTypeObject, tp_base), -offsetof(PyTypeObject, tp_dict), -offsetof(PyTypeObject, tp_descr_get), -offsetof(PyTypeObject, tp_descr_set), -offsetof(PyTypeObject, tp_dictoffset), -offsetof(PyTypeObject, tp_init), -offsetof(PyTypeObject, tp_alloc), -offsetof(PyTypeObject, tp_new), -offsetof(PyTypeObject, tp_free), -offsetof(PyTypeObject, tp_is_gc), -offsetof(PyTypeObject, tp_bases), -offsetof(PyTypeObject, tp_mro), -offsetof(PyTypeObject, tp_cache), -offsetof(PyTypeObject, tp_subclasses), -offsetof(PyTypeObject, tp_weaklist), -offsetof(PyTypeObject, tp_del), -offsetof(PyTypeObject, tp_finalize), -offsetof(PyTypeObject, tp_as_async), -offsetof(PyAsyncMethods, am_await), -offsetof(PyAsyncMethods, am_aiter), -offsetof(PyAsyncMethods, am_anext), -offsetof(PyTypeObject, tp_as_number), -offsetof(PyNumberMethods, nb_add), -offsetof(PyNumberMethods, nb_subtract), -offsetof(PyNumberMethods, nb_multiply), -offsetof(PyNumberMethods, nb_remainder), -offsetof(PyNumberMethods, nb_divmod), -offsetof(PyNumberMethods, nb_power), -offsetof(PyNumberMethods, nb_negative), -offsetof(PyNumberMethods, nb_positive), -offsetof(PyNumberMethods, nb_absolute), -offsetof(PyNumberMethods, nb_bool), -offsetof(PyNumberMethods, nb_invert), -offsetof(PyNumberMethods, nb_lshift), -offsetof(PyNumberMethods, nb_rshift), -offsetof(PyNumberMethods, nb_and), -offsetof(PyNumberMethods, nb_xor), -offsetof(PyNumberMethods, nb_or), -offsetof(PyNumberMethods, nb_int), -offsetof(PyNumberMethods, nb_reserved), -offsetof(PyNumberMethods, nb_float), -offsetof(PyNumberMethods, nb_inplace_add), -offsetof(PyNumberMethods, nb_inplace_subtract), -offsetof(PyNumberMethods, nb_inplace_multiply), -offsetof(PyNumberMethods, nb_inplace_remainder), -offsetof(PyNumberMethods, nb_inplace_power), -offsetof(PyNumberMethods, nb_inplace_lshift), -offsetof(PyNumberMethods, nb_inplace_rshift), -offsetof(PyNumberMethods, nb_inplace_and), -offsetof(PyNumberMethods, nb_inplace_xor), -offsetof(PyNumberMethods, nb_inplace_or), -offsetof(PyNumberMethods, nb_floor_divide), -offsetof(PyNumberMethods, nb_true_divide), -offsetof(PyNumberMethods, nb_inplace_floor_divide), -offsetof(PyNumberMethods, nb_inplace_true_divide), -offsetof(PyNumberMethods, nb_index), -offsetof(PyNumberMethods, nb_matrix_multiply), -offsetof(PyNumberMethods, nb_inplace_matrix_multiply), -offsetof(PyTypeObject, tp_as_sequence), -offsetof(PySequenceMethods, sq_length), -offsetof(PySequenceMethods, sq_concat), -offsetof(PySequenceMethods, sq_repeat), -offsetof(PySequenceMethods, sq_item), -offsetof(PySequenceMethods, sq_ass_item), -offsetof(PySequenceMethods, sq_contains), -offsetof(PySequenceMethods, sq_inplace_concat), -offsetof(PySequenceMethods, sq_inplace_repeat), -offsetof(PyTypeObject, tp_as_mapping), -offsetof(PyMappingMethods, mp_length), -offsetof(PyMappingMethods, mp_subscript), -offsetof(PyMappingMethods, mp_ass_subscript), -offsetof(PyTypeObject, tp_as_buffer), -offsetof(PyBufferProcs, bf_getbuffer), -offsetof(PyBufferProcs, bf_releasebuffer), diff --git a/Objects/statictypeslots.py b/Objects/statictypeslots.py deleted file mode 100755 index 89d6f1f516ca52..00000000000000 --- a/Objects/statictypeslots.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -# Usage: statictypeslots.py < Include/statictypeslots.h statictypeslots.inc - -import sys, re - - -def generate_statictypeslots(out=sys.stdout): - out.write("/* Generated by statictypeslots.py */\n") - res = {} - for line in sys.stdin: - m = re.match("#define Py_type_([a-z_]+) \\(([0-9]+)", line) - if not m: - continue - member = m.group(1) - if member.startswith("am_"): - member = "PyAsyncMethods, " + member - elif member.startswith("nb_"): - member = "PyNumberMethods, " + member - elif member.startswith("sq_"): - member = "PySequenceMethods, " + member - elif member.startswith("mp_"): - member = "PyMappingMethods, " + member - elif member.startswith("bf_"): - member = "PyBufferProcs, " + member - else: - member = "PyTypeObject, tp_" + member - res[int(m.group(2))] = member - - M = max(res.keys()) + 1 - for i in range(1, M): - if i in res: - out.write(f"offsetof({res[i]}),\n") - else: - out.write("0,\n") - - -def main(): - if len(sys.argv) == 2: - with open(sys.argv[1], "w") as f: - generate_statictypeslots(f) - else: - generate_statictypeslots() - - -if __name__ == "__main__": - main() diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5452ece8c7275b..2c5c592b38bdf0 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -55,6 +55,12 @@ static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP]; static unsigned int next_version_tag = 0; #endif +typedef struct PySlot_Offset { + int slot; + short offset; + short parent_offset; +} PySlot_Offset; + #define MCACHE_STATS 0 #if MCACHE_STATS @@ -2882,9 +2888,282 @@ static const short slotoffsets[] = { #include "typeslots.inc" }; -static const short static_slotoffsets[] = { - -1, /* invalid slot */ -#include "statictypeslots.inc" +static const PySlot_Offset pyslot_offsets[] = { + {Py_bf_getbuffer, offsetof(PyBufferProcs, bf_getbuffer), + offsetof(PyHeapTypeObject, as_buffer)}, + {Py_bf_releasebuffer, offsetof(PyBufferProcs, bf_releasebuffer), + offsetof(PyHeapTypeObject, as_buffer)}, + {Py_mp_ass_subscript, offsetof(PyMappingMethods, mp_ass_subscript), + offsetof(PyHeapTypeObject, as_mapping)}, + {Py_mp_length, offsetof(PyMappingMethods, mp_length), + offsetof(PyHeapTypeObject, as_mapping)}, + {Py_mp_subscript, offsetof(PyMappingMethods, mp_subscript), + offsetof(PyHeapTypeObject, as_mapping)}, + {Py_nb_absolute, offsetof(PyNumberMethods, nb_absolute), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_add, offsetof(PyNumberMethods, nb_add), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_and, offsetof(PyNumberMethods, nb_and), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_bool, offsetof(PyNumberMethods, nb_bool), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_divmod, offsetof(PyNumberMethods, nb_divmod), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_float, offsetof(PyNumberMethods, nb_float), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_floor_divide, offsetof(PyNumberMethods, nb_floor_divide), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_index, offsetof(PyNumberMethods, nb_index), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_and, offsetof(PyNumberMethods, nb_inplace_and), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_floor_divide, + offsetof(PyNumberMethods, nb_inplace_floor_divide), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_lshift, offsetof(PyNumberMethods, nb_inplace_lshift), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_multiply, offsetof(PyNumberMethods, nb_inplace_multiply), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_or, offsetof(PyNumberMethods, nb_inplace_or), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_power, offsetof(PyNumberMethods, nb_inplace_power), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_remainder, offsetof(PyNumberMethods, nb_inplace_remainder), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_rshift, offsetof(PyNumberMethods, nb_inplace_rshift), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_subtract, offsetof(PyNumberMethods, nb_inplace_subtract), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_true_divide, + offsetof(PyNumberMethods, nb_inplace_true_divide), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_xor, offsetof(PyNumberMethods, nb_inplace_xor), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_int, offsetof(PyNumberMethods, nb_int), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_invert, offsetof(PyNumberMethods, nb_invert), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_lshift, offsetof(PyNumberMethods, nb_lshift), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_multiply, offsetof(PyNumberMethods, nb_multiply), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_negative, offsetof(PyNumberMethods, nb_negative), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_or, offsetof(PyNumberMethods, nb_or), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_positive, offsetof(PyNumberMethods, nb_positive), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_power, offsetof(PyNumberMethods, nb_power), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_remainder, offsetof(PyNumberMethods, nb_remainder), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_rshift, offsetof(PyNumberMethods, nb_rshift), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_subtract, offsetof(PyNumberMethods, nb_subtract), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_true_divide, offsetof(PyNumberMethods, nb_true_divide), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_xor, offsetof(PyNumberMethods, nb_xor), + offsetof(PyHeapTypeObject, as_number)}, + {Py_sq_ass_item, offsetof(PySequenceMethods, sq_ass_item), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_concat, offsetof(PySequenceMethods, sq_concat), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_contains, offsetof(PySequenceMethods, sq_contains), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_inplace_concat, offsetof(PySequenceMethods, sq_inplace_concat), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_inplace_repeat, offsetof(PySequenceMethods, sq_inplace_repeat), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_item, offsetof(PySequenceMethods, sq_item), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_length, offsetof(PySequenceMethods, sq_length), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_sq_repeat, offsetof(PySequenceMethods, sq_repeat), + offsetof(PyHeapTypeObject, as_sequence)}, + {Py_tp_alloc, offsetof(PyTypeObject, tp_alloc), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_base, offsetof(PyTypeObject, tp_base), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_bases, offsetof(PyTypeObject, tp_bases), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_call, offsetof(PyTypeObject, tp_call), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_clear, offsetof(PyTypeObject, tp_clear), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_dealloc, offsetof(PyTypeObject, tp_dealloc), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_del, offsetof(PyTypeObject, tp_del), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_descr_get, offsetof(PyTypeObject, tp_descr_get), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_descr_set, offsetof(PyTypeObject, tp_descr_set), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_doc, offsetof(PyTypeObject, tp_doc), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_getattr, offsetof(PyTypeObject, tp_getattr), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_getattro, offsetof(PyTypeObject, tp_getattro), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_hash, offsetof(PyTypeObject, tp_hash), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_init, offsetof(PyTypeObject, tp_init), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_is_gc, offsetof(PyTypeObject, tp_is_gc), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_iter, offsetof(PyTypeObject, tp_iter), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_iternext, offsetof(PyTypeObject, tp_iternext), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_methods, offsetof(PyTypeObject, tp_methods), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_new, offsetof(PyTypeObject, tp_new), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_repr, offsetof(PyTypeObject, tp_repr), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_richcompare, offsetof(PyTypeObject, tp_richcompare), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_setattr, offsetof(PyTypeObject, tp_setattr), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_setattro, offsetof(PyTypeObject, tp_setattro), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_str, offsetof(PyTypeObject, tp_str), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_traverse, offsetof(PyTypeObject, tp_traverse), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_members, offsetof(PyTypeObject, tp_members), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_getset, offsetof(PyTypeObject, tp_getset), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_free, offsetof(PyTypeObject, tp_free), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_nb_matrix_multiply, offsetof(PyNumberMethods, nb_matrix_multiply), + offsetof(PyHeapTypeObject, as_number)}, + {Py_nb_inplace_matrix_multiply, + offsetof(PyNumberMethods, nb_inplace_matrix_multiply), + offsetof(PyHeapTypeObject, as_number)}, + {Py_am_await, offsetof(PyAsyncMethods, am_await), + offsetof(PyHeapTypeObject, as_async)}, + {Py_am_aiter, offsetof(PyAsyncMethods, am_aiter), + offsetof(PyHeapTypeObject, as_async)}, + {Py_am_anext, offsetof(PyAsyncMethods, am_anext), + offsetof(PyHeapTypeObject, as_async)}, + {Py_tp_finalize, offsetof(PyTypeObject, tp_finalize), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_name, offsetof(PyTypeObject, tp_name), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_basicsize, offsetof(PyTypeObject, tp_basicsize), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_itemsize, offsetof(PyTypeObject, tp_itemsize), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_vectorcall_offset, offsetof(PyTypeObject, tp_vectorcall_offset), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_flags, offsetof(PyTypeObject, tp_flags), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_weaklistoffset, offsetof(PyTypeObject, tp_weaklistoffset), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_dict, offsetof(PyTypeObject, tp_dict), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_dictoffset, offsetof(PyTypeObject, tp_dictoffset), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_mro, offsetof(PyTypeObject, tp_mro), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_cache, offsetof(PyTypeObject, tp_cache), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_subclasses, offsetof(PyTypeObject, tp_subclasses), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_weaklist, offsetof(PyTypeObject, tp_weaklist), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_add, offsetof(PyNumberMethods, nb_add), + offsetof(PyTypeObject, tp_as_number)}, + {Py_tp_nb_subtract, offsetof(PyNumberMethods, nb_subtract), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_multiply, offsetof(PyNumberMethods, nb_multiply), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_remainder, offsetof(PyNumberMethods, nb_remainder), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_divmod, offsetof(PyNumberMethods, nb_divmod), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_power, offsetof(PyNumberMethods, nb_power), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_negative, offsetof(PyNumberMethods, nb_negative), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_positive, offsetof(PyNumberMethods, nb_positive), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_absolute, offsetof(PyNumberMethods, nb_absolute), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_bool, offsetof(PyNumberMethods, nb_bool), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_invert, offsetof(PyNumberMethods, nb_invert), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_lshift, offsetof(PyNumberMethods, nb_lshift), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_rshift, offsetof(PyNumberMethods, nb_rshift), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_and, offsetof(PyNumberMethods, nb_and), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_xor, offsetof(PyNumberMethods, nb_xor), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_or, offsetof(PyNumberMethods, nb_or), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_int, offsetof(PyNumberMethods, nb_int), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_reserved, offsetof(PyNumberMethods, nb_reserved), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_float, offsetof(PyNumberMethods, nb_float), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_subtract, + offsetof(PyNumberMethods, nb_inplace_subtract), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_multiply, + offsetof(PyNumberMethods, nb_inplace_multiply), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_remainder, + offsetof(PyNumberMethods, nb_inplace_remainder), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_power, + offsetof(PyNumberMethods, nb_inplace_power), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_lshift, + offsetof(PyNumberMethods, nb_inplace_lshift), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_rshift, + offsetof(PyNumberMethods, nb_inplace_rshift), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_and, + offsetof(PyNumberMethods, nb_inplace_and), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_xor, + offsetof(PyNumberMethods, nb_inplace_xor), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_or, + offsetof(PyNumberMethods, nb_inplace_or), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_floor_divide, + offsetof(PyNumberMethods, nb_floor_divide), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_true_divide, + offsetof(PyNumberMethods, nb_true_divide), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_floor_divide, + offsetof(PyNumberMethods, nb_inplace_floor_divide), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_true_divide, + offsetof(PyNumberMethods, nb_inplace_true_divide), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_index, offsetof(PyNumberMethods, nb_index), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_matrix_multiply, + offsetof(PyNumberMethods, nb_matrix_multiply), + offsetof(PyHeapTypeObject, ht_type)}, + {Py_tp_nb_inplace_matrix_multiply, + offsetof(PyNumberMethods, nb_inplace_matrix_multiply), + offsetof(PyHeapTypeObject, ht_type)}, + {0, 0, 0} /* sentinel */ }; PyObject * @@ -3124,61 +3403,24 @@ PyType_FromSpec(PyType_Spec *spec) void * PyType_GetSlot(PyTypeObject *type, int slot) { + const PySlot_Offset *cur_offset; + void *parent_slot; + if (slot < 0) { PyErr_BadInternalCall(); return NULL; } - if (_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { - if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) { - /* Extension module requesting slot from a future version */ - return NULL; - } - return *(void**)(((char*)type) + slotoffsets[slot]); - } - - void *methods = NULL; - size_t base_slot = slot - STATIC_TYPE_OFFSET; - int methods_flag = 0; - if (base_slot >= Py_ARRAY_LENGTH(static_slotoffsets)) { - return NULL; - } else if (slot >= Py_type_am_await && - slot <= Py_type_am_anext) { - methods = *(void**)(((char*)type) + - static_slotoffsets[Py_type_as_async - STATIC_TYPE_OFFSET]); - methods_flag = 1; - } else if (slot >= Py_type_nb_add && - slot <= Py_type_nb_inplace_matrix_multiply) { - methods = *(void**)(((char*)type) + - static_slotoffsets[Py_type_as_number - STATIC_TYPE_OFFSET]); - methods_flag = 1; - } else if (slot >= Py_type_sq_length && - slot <= Py_type_sq_inplace_repeat) { - methods = *(void**)(((char*)type) + - static_slotoffsets[Py_type_as_sequence - STATIC_TYPE_OFFSET]); - methods_flag = 1; - } else if (slot >= Py_type_mp_length && - slot <= Py_type_mp_ass_subscript) { - methods = *(void**)(((char*)type) + - static_slotoffsets[Py_type_as_mapping - STATIC_TYPE_OFFSET]); - methods_flag = 1; - } else if (slot >= Py_type_bf_getbuffer && - slot <= Py_type_bf_releasebuffer) { - methods = *(void**)(((char*)type) + - static_slotoffsets[Py_type_as_buffer - STATIC_TYPE_OFFSET]); - methods_flag = 1; - } - if (methods != NULL) { - return *(void**)((char *)methods + - static_slotoffsets[slot - STATIC_TYPE_OFFSET]); - } - else { - if (methods_flag) { - return NULL; + for (cur_offset = pyslot_offsets; cur_offset->slot; cur_offset++) { + if (cur_offset->slot == slot) { + parent_slot = *(void**)((char*)type + cur_offset->parent_offset); + if (parent_slot == NULL) { + return NULL; + } + return *(void**)((char*)parent_slot + cur_offset->offset); } - return *(void**)(((char*)type) + - static_slotoffsets[slot - STATIC_TYPE_OFFSET]); } + return NULL; } PyObject * From 5171eb745d9e9255e6a64f999836aa7e989b0cbb Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 25 Oct 2020 14:54:58 +0800 Subject: [PATCH 11/23] apply petr's comment --- Include/typeslots.h | 51 +----- Modules/_testcapimodule.c | 19 +-- Objects/typeobject.c | 321 ++++---------------------------------- Objects/typeslots.inc | 163 +++++++++---------- Objects/typeslots.py | 25 +-- 5 files changed, 134 insertions(+), 445 deletions(-) diff --git a/Include/typeslots.h b/Include/typeslots.h index c3d46903425f59..a0449f648217e8 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,51 +88,6 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif -#define Py_tp_name 81 -#define Py_tp_basicsize 82 -#define Py_tp_itemsize 83 -#define Py_tp_vectorcall_offset 84 -#define Py_tp_flags 85 -#define Py_tp_weaklistoffset 86 -#define Py_tp_dict 87 -#define Py_tp_dictoffset 88 -#define Py_tp_mro 89 -#define Py_tp_cache 90 -#define Py_tp_subclasses 91 -#define Py_tp_weaklist 92 -#define Py_tp_nb_add 93 -#define Py_tp_nb_subtract 94 -#define Py_tp_nb_multiply 95 -#define Py_tp_nb_remainder 96 -#define Py_tp_nb_divmod 97 -#define Py_tp_nb_power 98 -#define Py_tp_nb_negative 99 -#define Py_tp_nb_positive 100 -#define Py_tp_nb_absolute 101 -#define Py_tp_nb_bool 102 -#define Py_tp_nb_invert 103 -#define Py_tp_nb_lshift 104 -#define Py_tp_nb_rshift 105 -#define Py_tp_nb_and 106 -#define Py_tp_nb_xor 107 -#define Py_tp_nb_or 108 -#define Py_tp_nb_int 109 -#define Py_tp_nb_reserved 110 -#define Py_tp_nb_float 111 -#define Py_tp_nb_inplace_add 112 -#define Py_tp_nb_inplace_subtract 113 -#define Py_tp_nb_inplace_multiply 114 -#define Py_tp_nb_inplace_remainder 115 -#define Py_tp_nb_inplace_power 116 -#define Py_tp_nb_inplace_lshift 117 -#define Py_tp_nb_inplace_rshift 118 -#define Py_tp_nb_inplace_and 119 -#define Py_tp_nb_inplace_xor 120 -#define Py_tp_nb_inplace_or 121 -#define Py_tp_nb_floor_divide 122 -#define Py_tp_nb_true_divide 123 -#define Py_tp_nb_inplace_floor_divide 124 -#define Py_tp_nb_inplace_true_divide 125 -#define Py_tp_nb_index 126 -#define Py_tp_nb_matrix_multiply 127 -#define Py_tp_nb_inplace_matrix_multiply 128 +#define Py_tp_dict 81 +#define Py_tp_mro 82 +#define Py_tp_subclasses 83 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1269530f8d3c04..e551cebadc24df 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1021,24 +1021,17 @@ test_buildvalue_N(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { - char *tp_name = PyType_GetSlot(&PyLong_Type, Py_tp_name); - assert(strcmp(tp_name, "int") == 0); - newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); - PyObject *args = PyTuple_New(0); - PyObject *object = tp_new(&PyLong_Type, args, NULL); - assert(object); + assert(PyLong_Type.tp_new == tp_new); reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); - PyObject *decimal_str = tp_repr(object); - assert(decimal_str); + assert(PyLong_Type.tp_repr == tp_repr); ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call); assert(tp_call == 0); - binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_tp_nb_add); - PyObject *result = nb_add(object, object); - assert(result); + binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add); + assert(PyLong_Type.tp_as_number->nb_add == nb_add); lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length); assert(mp_length == NULL); @@ -1046,10 +1039,6 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); assert(over_value == NULL); - Py_DECREF(decimal_str); - Py_DECREF(args); - Py_DECREF(object); - Py_DECREF(result); Py_RETURN_NONE; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2c5c592b38bdf0..f7ba7bdf6799b6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -57,8 +57,8 @@ static unsigned int next_version_tag = 0; typedef struct PySlot_Offset { int slot; - short offset; - short parent_offset; + short subslot_offset; + short slot_offset; } PySlot_Offset; #define MCACHE_STATS 0 @@ -2883,287 +2883,9 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) return NULL; } -static const short slotoffsets[] = { - -1, /* invalid slot */ -#include "typeslots.inc" -}; - static const PySlot_Offset pyslot_offsets[] = { - {Py_bf_getbuffer, offsetof(PyBufferProcs, bf_getbuffer), - offsetof(PyHeapTypeObject, as_buffer)}, - {Py_bf_releasebuffer, offsetof(PyBufferProcs, bf_releasebuffer), - offsetof(PyHeapTypeObject, as_buffer)}, - {Py_mp_ass_subscript, offsetof(PyMappingMethods, mp_ass_subscript), - offsetof(PyHeapTypeObject, as_mapping)}, - {Py_mp_length, offsetof(PyMappingMethods, mp_length), - offsetof(PyHeapTypeObject, as_mapping)}, - {Py_mp_subscript, offsetof(PyMappingMethods, mp_subscript), - offsetof(PyHeapTypeObject, as_mapping)}, - {Py_nb_absolute, offsetof(PyNumberMethods, nb_absolute), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_add, offsetof(PyNumberMethods, nb_add), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_and, offsetof(PyNumberMethods, nb_and), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_bool, offsetof(PyNumberMethods, nb_bool), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_divmod, offsetof(PyNumberMethods, nb_divmod), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_float, offsetof(PyNumberMethods, nb_float), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_floor_divide, offsetof(PyNumberMethods, nb_floor_divide), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_index, offsetof(PyNumberMethods, nb_index), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_and, offsetof(PyNumberMethods, nb_inplace_and), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_floor_divide, - offsetof(PyNumberMethods, nb_inplace_floor_divide), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_lshift, offsetof(PyNumberMethods, nb_inplace_lshift), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_multiply, offsetof(PyNumberMethods, nb_inplace_multiply), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_or, offsetof(PyNumberMethods, nb_inplace_or), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_power, offsetof(PyNumberMethods, nb_inplace_power), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_remainder, offsetof(PyNumberMethods, nb_inplace_remainder), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_rshift, offsetof(PyNumberMethods, nb_inplace_rshift), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_subtract, offsetof(PyNumberMethods, nb_inplace_subtract), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_true_divide, - offsetof(PyNumberMethods, nb_inplace_true_divide), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_xor, offsetof(PyNumberMethods, nb_inplace_xor), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_int, offsetof(PyNumberMethods, nb_int), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_invert, offsetof(PyNumberMethods, nb_invert), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_lshift, offsetof(PyNumberMethods, nb_lshift), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_multiply, offsetof(PyNumberMethods, nb_multiply), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_negative, offsetof(PyNumberMethods, nb_negative), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_or, offsetof(PyNumberMethods, nb_or), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_positive, offsetof(PyNumberMethods, nb_positive), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_power, offsetof(PyNumberMethods, nb_power), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_remainder, offsetof(PyNumberMethods, nb_remainder), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_rshift, offsetof(PyNumberMethods, nb_rshift), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_subtract, offsetof(PyNumberMethods, nb_subtract), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_true_divide, offsetof(PyNumberMethods, nb_true_divide), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_xor, offsetof(PyNumberMethods, nb_xor), - offsetof(PyHeapTypeObject, as_number)}, - {Py_sq_ass_item, offsetof(PySequenceMethods, sq_ass_item), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_concat, offsetof(PySequenceMethods, sq_concat), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_contains, offsetof(PySequenceMethods, sq_contains), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_inplace_concat, offsetof(PySequenceMethods, sq_inplace_concat), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_inplace_repeat, offsetof(PySequenceMethods, sq_inplace_repeat), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_item, offsetof(PySequenceMethods, sq_item), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_length, offsetof(PySequenceMethods, sq_length), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_sq_repeat, offsetof(PySequenceMethods, sq_repeat), - offsetof(PyHeapTypeObject, as_sequence)}, - {Py_tp_alloc, offsetof(PyTypeObject, tp_alloc), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_base, offsetof(PyTypeObject, tp_base), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_bases, offsetof(PyTypeObject, tp_bases), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_call, offsetof(PyTypeObject, tp_call), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_clear, offsetof(PyTypeObject, tp_clear), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_dealloc, offsetof(PyTypeObject, tp_dealloc), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_del, offsetof(PyTypeObject, tp_del), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_descr_get, offsetof(PyTypeObject, tp_descr_get), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_descr_set, offsetof(PyTypeObject, tp_descr_set), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_doc, offsetof(PyTypeObject, tp_doc), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_getattr, offsetof(PyTypeObject, tp_getattr), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_getattro, offsetof(PyTypeObject, tp_getattro), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_hash, offsetof(PyTypeObject, tp_hash), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_init, offsetof(PyTypeObject, tp_init), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_is_gc, offsetof(PyTypeObject, tp_is_gc), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_iter, offsetof(PyTypeObject, tp_iter), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_iternext, offsetof(PyTypeObject, tp_iternext), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_methods, offsetof(PyTypeObject, tp_methods), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_new, offsetof(PyTypeObject, tp_new), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_repr, offsetof(PyTypeObject, tp_repr), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_richcompare, offsetof(PyTypeObject, tp_richcompare), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_setattr, offsetof(PyTypeObject, tp_setattr), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_setattro, offsetof(PyTypeObject, tp_setattro), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_str, offsetof(PyTypeObject, tp_str), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_traverse, offsetof(PyTypeObject, tp_traverse), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_members, offsetof(PyTypeObject, tp_members), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_getset, offsetof(PyTypeObject, tp_getset), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_free, offsetof(PyTypeObject, tp_free), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_nb_matrix_multiply, offsetof(PyNumberMethods, nb_matrix_multiply), - offsetof(PyHeapTypeObject, as_number)}, - {Py_nb_inplace_matrix_multiply, - offsetof(PyNumberMethods, nb_inplace_matrix_multiply), - offsetof(PyHeapTypeObject, as_number)}, - {Py_am_await, offsetof(PyAsyncMethods, am_await), - offsetof(PyHeapTypeObject, as_async)}, - {Py_am_aiter, offsetof(PyAsyncMethods, am_aiter), - offsetof(PyHeapTypeObject, as_async)}, - {Py_am_anext, offsetof(PyAsyncMethods, am_anext), - offsetof(PyHeapTypeObject, as_async)}, - {Py_tp_finalize, offsetof(PyTypeObject, tp_finalize), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_name, offsetof(PyTypeObject, tp_name), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_basicsize, offsetof(PyTypeObject, tp_basicsize), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_itemsize, offsetof(PyTypeObject, tp_itemsize), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_vectorcall_offset, offsetof(PyTypeObject, tp_vectorcall_offset), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_flags, offsetof(PyTypeObject, tp_flags), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_weaklistoffset, offsetof(PyTypeObject, tp_weaklistoffset), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_dict, offsetof(PyTypeObject, tp_dict), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_dictoffset, offsetof(PyTypeObject, tp_dictoffset), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_mro, offsetof(PyTypeObject, tp_mro), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_cache, offsetof(PyTypeObject, tp_cache), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_subclasses, offsetof(PyTypeObject, tp_subclasses), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_weaklist, offsetof(PyTypeObject, tp_weaklist), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_add, offsetof(PyNumberMethods, nb_add), - offsetof(PyTypeObject, tp_as_number)}, - {Py_tp_nb_subtract, offsetof(PyNumberMethods, nb_subtract), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_multiply, offsetof(PyNumberMethods, nb_multiply), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_remainder, offsetof(PyNumberMethods, nb_remainder), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_divmod, offsetof(PyNumberMethods, nb_divmod), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_power, offsetof(PyNumberMethods, nb_power), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_negative, offsetof(PyNumberMethods, nb_negative), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_positive, offsetof(PyNumberMethods, nb_positive), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_absolute, offsetof(PyNumberMethods, nb_absolute), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_bool, offsetof(PyNumberMethods, nb_bool), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_invert, offsetof(PyNumberMethods, nb_invert), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_lshift, offsetof(PyNumberMethods, nb_lshift), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_rshift, offsetof(PyNumberMethods, nb_rshift), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_and, offsetof(PyNumberMethods, nb_and), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_xor, offsetof(PyNumberMethods, nb_xor), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_or, offsetof(PyNumberMethods, nb_or), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_int, offsetof(PyNumberMethods, nb_int), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_reserved, offsetof(PyNumberMethods, nb_reserved), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_float, offsetof(PyNumberMethods, nb_float), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_subtract, - offsetof(PyNumberMethods, nb_inplace_subtract), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_multiply, - offsetof(PyNumberMethods, nb_inplace_multiply), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_remainder, - offsetof(PyNumberMethods, nb_inplace_remainder), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_power, - offsetof(PyNumberMethods, nb_inplace_power), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_lshift, - offsetof(PyNumberMethods, nb_inplace_lshift), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_rshift, - offsetof(PyNumberMethods, nb_inplace_rshift), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_and, - offsetof(PyNumberMethods, nb_inplace_and), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_xor, - offsetof(PyNumberMethods, nb_inplace_xor), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_or, - offsetof(PyNumberMethods, nb_inplace_or), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_floor_divide, - offsetof(PyNumberMethods, nb_floor_divide), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_true_divide, - offsetof(PyNumberMethods, nb_true_divide), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_floor_divide, - offsetof(PyNumberMethods, nb_inplace_floor_divide), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_true_divide, - offsetof(PyNumberMethods, nb_inplace_true_divide), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_index, offsetof(PyNumberMethods, nb_index), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_matrix_multiply, - offsetof(PyNumberMethods, nb_matrix_multiply), - offsetof(PyHeapTypeObject, ht_type)}, - {Py_tp_nb_inplace_matrix_multiply, - offsetof(PyNumberMethods, nb_inplace_matrix_multiply), - offsetof(PyHeapTypeObject, ht_type)}, - {0, 0, 0} /* sentinel */ + {0, 0, 0}, +#include "typeslots.inc" }; PyObject * @@ -3182,6 +2904,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++) { @@ -3291,7 +3014,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; } @@ -3320,7 +3043,14 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) } else { /* Copy other slots directly */ - *(void**)(res_start + slotoffsets[slot->slot]) = slot->pfunc; + slot_offset = pyslot_offsets[slot->slot].slot_offset; + void *parent_slot = *(void**)((char*)res_start + slot_offset); + if (parent_slot == NULL) { + *(void**)((char*)res_start + slot_offset) = slot->pfunc; + } else { + subslot_offset = pyslot_offsets[slot->slot].subslot_offset; + *(void**)((char*)parent_slot + subslot_offset) = slot->pfunc; + } } } if (type->tp_dealloc == NULL) { @@ -3403,22 +3133,27 @@ PyType_FromSpec(PyType_Spec *spec) void * PyType_GetSlot(PyTypeObject *type, int slot) { - const PySlot_Offset *cur_offset; void *parent_slot; + int slots_len = Py_ARRAY_LENGTH(pyslot_offsets); - if (slot < 0) { + if (slot < 0 || slot >= slots_len) { PyErr_BadInternalCall(); return NULL; } - for (cur_offset = pyslot_offsets; cur_offset->slot; cur_offset++) { - if (cur_offset->slot == slot) { - parent_slot = *(void**)((char*)type + cur_offset->parent_offset); - if (parent_slot == NULL) { - return NULL; - } - return *(void**)((char*)parent_slot + cur_offset->offset); + for (int i = 1; i < slots_len; i++) { + if (pyslot_offsets[i].slot != slot) { + continue; + } + parent_slot = *(void**)((char*)type + pyslot_offsets[i].slot_offset); + if (parent_slot == NULL) { + return NULL; + } + /* Return slot directly if there have no sub slot. */ + if (pyslot_offsets[i].subslot_offset == -1) { + return parent_slot; } + return *(void**)((char*)parent_slot + pyslot_offsets[i].subslot_offset); } return NULL; } diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc index ffc9bb2e1c7710..37819af011c6c6 100644 --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -1,81 +1,84 @@ /* Generated by typeslots.py */ -offsetof(PyHeapTypeObject, as_buffer.bf_getbuffer), -offsetof(PyHeapTypeObject, as_buffer.bf_releasebuffer), -offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript), -offsetof(PyHeapTypeObject, as_mapping.mp_length), -offsetof(PyHeapTypeObject, as_mapping.mp_subscript), -offsetof(PyHeapTypeObject, as_number.nb_absolute), -offsetof(PyHeapTypeObject, as_number.nb_add), -offsetof(PyHeapTypeObject, as_number.nb_and), -offsetof(PyHeapTypeObject, as_number.nb_bool), -offsetof(PyHeapTypeObject, as_number.nb_divmod), -offsetof(PyHeapTypeObject, as_number.nb_float), -offsetof(PyHeapTypeObject, as_number.nb_floor_divide), -offsetof(PyHeapTypeObject, as_number.nb_index), -offsetof(PyHeapTypeObject, as_number.nb_inplace_add), -offsetof(PyHeapTypeObject, as_number.nb_inplace_and), -offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide), -offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift), -offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply), -offsetof(PyHeapTypeObject, as_number.nb_inplace_or), -offsetof(PyHeapTypeObject, as_number.nb_inplace_power), -offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder), -offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift), -offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract), -offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide), -offsetof(PyHeapTypeObject, as_number.nb_inplace_xor), -offsetof(PyHeapTypeObject, as_number.nb_int), -offsetof(PyHeapTypeObject, as_number.nb_invert), -offsetof(PyHeapTypeObject, as_number.nb_lshift), -offsetof(PyHeapTypeObject, as_number.nb_multiply), -offsetof(PyHeapTypeObject, as_number.nb_negative), -offsetof(PyHeapTypeObject, as_number.nb_or), -offsetof(PyHeapTypeObject, as_number.nb_positive), -offsetof(PyHeapTypeObject, as_number.nb_power), -offsetof(PyHeapTypeObject, as_number.nb_remainder), -offsetof(PyHeapTypeObject, as_number.nb_rshift), -offsetof(PyHeapTypeObject, as_number.nb_subtract), -offsetof(PyHeapTypeObject, as_number.nb_true_divide), -offsetof(PyHeapTypeObject, as_number.nb_xor), -offsetof(PyHeapTypeObject, as_sequence.sq_ass_item), -offsetof(PyHeapTypeObject, as_sequence.sq_concat), -offsetof(PyHeapTypeObject, as_sequence.sq_contains), -offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat), -offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat), -offsetof(PyHeapTypeObject, as_sequence.sq_item), -offsetof(PyHeapTypeObject, as_sequence.sq_length), -offsetof(PyHeapTypeObject, as_sequence.sq_repeat), -offsetof(PyHeapTypeObject, ht_type.tp_alloc), -offsetof(PyHeapTypeObject, ht_type.tp_base), -offsetof(PyHeapTypeObject, ht_type.tp_bases), -offsetof(PyHeapTypeObject, ht_type.tp_call), -offsetof(PyHeapTypeObject, ht_type.tp_clear), -offsetof(PyHeapTypeObject, ht_type.tp_dealloc), -offsetof(PyHeapTypeObject, ht_type.tp_del), -offsetof(PyHeapTypeObject, ht_type.tp_descr_get), -offsetof(PyHeapTypeObject, ht_type.tp_descr_set), -offsetof(PyHeapTypeObject, ht_type.tp_doc), -offsetof(PyHeapTypeObject, ht_type.tp_getattr), -offsetof(PyHeapTypeObject, ht_type.tp_getattro), -offsetof(PyHeapTypeObject, ht_type.tp_hash), -offsetof(PyHeapTypeObject, ht_type.tp_init), -offsetof(PyHeapTypeObject, ht_type.tp_is_gc), -offsetof(PyHeapTypeObject, ht_type.tp_iter), -offsetof(PyHeapTypeObject, ht_type.tp_iternext), -offsetof(PyHeapTypeObject, ht_type.tp_methods), -offsetof(PyHeapTypeObject, ht_type.tp_new), -offsetof(PyHeapTypeObject, ht_type.tp_repr), -offsetof(PyHeapTypeObject, ht_type.tp_richcompare), -offsetof(PyHeapTypeObject, ht_type.tp_setattr), -offsetof(PyHeapTypeObject, ht_type.tp_setattro), -offsetof(PyHeapTypeObject, ht_type.tp_str), -offsetof(PyHeapTypeObject, ht_type.tp_traverse), -offsetof(PyHeapTypeObject, ht_type.tp_members), -offsetof(PyHeapTypeObject, ht_type.tp_getset), -offsetof(PyHeapTypeObject, ht_type.tp_free), -offsetof(PyHeapTypeObject, as_number.nb_matrix_multiply), -offsetof(PyHeapTypeObject, as_number.nb_inplace_matrix_multiply), -offsetof(PyHeapTypeObject, as_async.am_await), -offsetof(PyHeapTypeObject, as_async.am_aiter), -offsetof(PyHeapTypeObject, as_async.am_anext), -offsetof(PyHeapTypeObject, ht_type.tp_finalize), +{Py_bf_getbuffer, offsetof(PyBufferProcs, bf_getbuffer), offsetof(PyTypeObject, tp_as_buffer)}, +{Py_bf_releasebuffer, offsetof(PyBufferProcs, bf_releasebuffer), offsetof(PyTypeObject, tp_as_buffer)}, +{Py_mp_ass_subscript, offsetof(PyMappingMethods, mp_ass_subscript), offsetof(PyTypeObject, tp_as_mapping)}, +{Py_mp_length, offsetof(PyMappingMethods, mp_length), offsetof(PyTypeObject, tp_as_mapping)}, +{Py_mp_subscript, offsetof(PyMappingMethods, mp_subscript), offsetof(PyTypeObject, tp_as_mapping)}, +{Py_nb_absolute, offsetof(PyNumberMethods, nb_absolute), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_add, offsetof(PyNumberMethods, nb_add), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_and, offsetof(PyNumberMethods, nb_and), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_bool, offsetof(PyNumberMethods, nb_bool), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_divmod, offsetof(PyNumberMethods, nb_divmod), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_float, offsetof(PyNumberMethods, nb_float), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_floor_divide, offsetof(PyNumberMethods, nb_floor_divide), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_index, offsetof(PyNumberMethods, nb_index), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_and, offsetof(PyNumberMethods, nb_inplace_and), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_floor_divide, offsetof(PyNumberMethods, nb_inplace_floor_divide), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_lshift, offsetof(PyNumberMethods, nb_inplace_lshift), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_multiply, offsetof(PyNumberMethods, nb_inplace_multiply), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_or, offsetof(PyNumberMethods, nb_inplace_or), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_power, offsetof(PyNumberMethods, nb_inplace_power), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_remainder, offsetof(PyNumberMethods, nb_inplace_remainder), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_rshift, offsetof(PyNumberMethods, nb_inplace_rshift), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_subtract, offsetof(PyNumberMethods, nb_inplace_subtract), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_true_divide, offsetof(PyNumberMethods, nb_inplace_true_divide), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_xor, offsetof(PyNumberMethods, nb_inplace_xor), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_int, offsetof(PyNumberMethods, nb_int), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_invert, offsetof(PyNumberMethods, nb_invert), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_lshift, offsetof(PyNumberMethods, nb_lshift), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_multiply, offsetof(PyNumberMethods, nb_multiply), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_negative, offsetof(PyNumberMethods, nb_negative), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_or, offsetof(PyNumberMethods, nb_or), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_positive, offsetof(PyNumberMethods, nb_positive), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_power, offsetof(PyNumberMethods, nb_power), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_remainder, offsetof(PyNumberMethods, nb_remainder), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_rshift, offsetof(PyNumberMethods, nb_rshift), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_subtract, offsetof(PyNumberMethods, nb_subtract), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_true_divide, offsetof(PyNumberMethods, nb_true_divide), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_xor, offsetof(PyNumberMethods, nb_xor), offsetof(PyTypeObject, tp_as_number)}, +{Py_sq_ass_item, offsetof(PySequenceMethods, sq_ass_item), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_concat, offsetof(PySequenceMethods, sq_concat), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_contains, offsetof(PySequenceMethods, sq_contains), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_inplace_concat, offsetof(PySequenceMethods, sq_inplace_concat), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_inplace_repeat, offsetof(PySequenceMethods, sq_inplace_repeat), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_item, offsetof(PySequenceMethods, sq_item), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_length, offsetof(PySequenceMethods, sq_length), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_sq_repeat, offsetof(PySequenceMethods, sq_repeat), offsetof(PyTypeObject, tp_as_sequence)}, +{Py_tp_alloc, -1, offsetof(PyTypeObject, tp_alloc)}, +{Py_tp_base, -1, offsetof(PyTypeObject, tp_base)}, +{Py_tp_bases, -1, offsetof(PyTypeObject, tp_bases)}, +{Py_tp_call, -1, offsetof(PyTypeObject, tp_call)}, +{Py_tp_clear, -1, offsetof(PyTypeObject, tp_clear)}, +{Py_tp_dealloc, -1, offsetof(PyTypeObject, tp_dealloc)}, +{Py_tp_del, -1, offsetof(PyTypeObject, tp_del)}, +{Py_tp_descr_get, -1, offsetof(PyTypeObject, tp_descr_get)}, +{Py_tp_descr_set, -1, offsetof(PyTypeObject, tp_descr_set)}, +{Py_tp_doc, -1, offsetof(PyTypeObject, tp_doc)}, +{Py_tp_getattr, -1, offsetof(PyTypeObject, tp_getattr)}, +{Py_tp_getattro, -1, offsetof(PyTypeObject, tp_getattro)}, +{Py_tp_hash, -1, offsetof(PyTypeObject, tp_hash)}, +{Py_tp_init, -1, offsetof(PyTypeObject, tp_init)}, +{Py_tp_is_gc, -1, offsetof(PyTypeObject, tp_is_gc)}, +{Py_tp_iter, -1, offsetof(PyTypeObject, tp_iter)}, +{Py_tp_iternext, -1, offsetof(PyTypeObject, tp_iternext)}, +{Py_tp_methods, -1, offsetof(PyTypeObject, tp_methods)}, +{Py_tp_new, -1, offsetof(PyTypeObject, tp_new)}, +{Py_tp_repr, -1, offsetof(PyTypeObject, tp_repr)}, +{Py_tp_richcompare, -1, offsetof(PyTypeObject, tp_richcompare)}, +{Py_tp_setattr, -1, offsetof(PyTypeObject, tp_setattr)}, +{Py_tp_setattro, -1, offsetof(PyTypeObject, tp_setattro)}, +{Py_tp_str, -1, offsetof(PyTypeObject, tp_str)}, +{Py_tp_traverse, -1, offsetof(PyTypeObject, tp_traverse)}, +{Py_tp_members, -1, offsetof(PyTypeObject, tp_members)}, +{Py_tp_getset, -1, offsetof(PyTypeObject, tp_getset)}, +{Py_tp_free, -1, offsetof(PyTypeObject, tp_free)}, +{Py_nb_matrix_multiply, offsetof(PyNumberMethods, nb_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, +{Py_nb_inplace_matrix_multiply, offsetof(PyNumberMethods, nb_inplace_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, +{Py_am_await, offsetof(PyAsyncMethods, am_await), offsetof(PyTypeObject, tp_as_async)}, +{Py_am_aiter, offsetof(PyAsyncMethods, am_aiter), offsetof(PyTypeObject, tp_as_async)}, +{Py_am_anext, offsetof(PyAsyncMethods, am_anext), offsetof(PyTypeObject, tp_as_async)}, +{Py_tp_finalize, -1, offsetof(PyTypeObject, tp_finalize)}, +{Py_tp_dict, -1, offsetof(PyTypeObject, tp_dict)}, +{Py_tp_mro, -1, offsetof(PyTypeObject, tp_mro)}, +{Py_tp_subclasses, -1, offsetof(PyTypeObject, tp_subclasses)}, diff --git a/Objects/typeslots.py b/Objects/typeslots.py index 9b6d4adbc7533b..67487d7ea5584b 100755 --- a/Objects/typeslots.py +++ b/Objects/typeslots.py @@ -3,6 +3,7 @@ import sys, re + def generate_typeslots(out=sys.stdout): out.write("/* Generated by typeslots.py */\n") res = {} @@ -10,27 +11,33 @@ def generate_typeslots(out=sys.stdout): m = re.match("#define Py_([a-z_]+) ([0-9]+)", line) if not m: continue + + slot_name = re.match("#define ([A-Za-z_]+) ([0-9]+)", line).group(1) member = m.group(1) if member.startswith("tp_"): - member = "ht_type."+member + member = f'{{{slot_name}, -1, offsetof(PyTypeObject, {member})}}' elif member.startswith("am_"): - member = "as_async."+member + member = (f'{{{slot_name}, offsetof(PyAsyncMethods, {member}),'+ + ' offsetof(PyTypeObject, tp_as_async)}') elif member.startswith("nb_"): - member = "as_number."+member + member = (f'{{{slot_name}, offsetof(PyNumberMethods, {member}),'+ + ' offsetof(PyTypeObject, tp_as_number)}') elif member.startswith("mp_"): - member = "as_mapping."+member + member = (f'{{{slot_name}, offsetof(PyMappingMethods, {member}),'+ + ' offsetof(PyTypeObject, tp_as_mapping)}') elif member.startswith("sq_"): - member = "as_sequence."+member + member = (f'{{{slot_name}, offsetof(PySequenceMethods, {member}),'+ + ' offsetof(PyTypeObject, tp_as_sequence)}') elif member.startswith("bf_"): - member = "as_buffer."+member + member = (f'{{{slot_name}, offsetof(PyBufferProcs, {member}),'+ + ' offsetof(PyTypeObject, tp_as_buffer)}') res[int(m.group(2))] = member M = max(res.keys())+1 for i in range(1,M): if i in res: - out.write("offsetof(PyHeapTypeObject, %s),\n" % res[i]) - else: - out.write("0,\n") + out.write("%s,\n" % res[i]) + def main(): if len(sys.argv) == 2: From 2a6e0f44fc0355d56edc3fa9c411956fbb22c9f5 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 30 Oct 2020 01:12:50 +0800 Subject: [PATCH 12/23] update release doc --- Doc/whatsnew/3.10.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 45258db4925718..6c9c83b50043d9 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -366,6 +366,8 @@ New Features * Added :c:func:`PyUnicode_AsUTF8AndSize` to the limited C API. (Contributed by Alex Gaynor in :issue:`41784`.) +* The :c:func:`PyType_GetSlot` function can accept static types. + (Contributed by Hai Shi in :issue:`41073`.) Porting to Python 3.10 ---------------------- From a9f66f333db3889b82de79fea47023de54d15b2c Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Fri, 30 Oct 2020 12:58:06 +0800 Subject: [PATCH 13/23] remove new adding slots --- Include/typeslots.h | 3 --- Objects/typeslots.inc | 3 --- 2 files changed, 6 deletions(-) diff --git a/Include/typeslots.h b/Include/typeslots.h index a0449f648217e8..64f6fff5144493 100644 --- a/Include/typeslots.h +++ b/Include/typeslots.h @@ -88,6 +88,3 @@ /* New in 3.5 */ #define Py_tp_finalize 80 #endif -#define Py_tp_dict 81 -#define Py_tp_mro 82 -#define Py_tp_subclasses 83 diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc index 37819af011c6c6..fa1046435d9f9c 100644 --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -79,6 +79,3 @@ {Py_am_aiter, offsetof(PyAsyncMethods, am_aiter), offsetof(PyTypeObject, tp_as_async)}, {Py_am_anext, offsetof(PyAsyncMethods, am_anext), offsetof(PyTypeObject, tp_as_async)}, {Py_tp_finalize, -1, offsetof(PyTypeObject, tp_finalize)}, -{Py_tp_dict, -1, offsetof(PyTypeObject, tp_dict)}, -{Py_tp_mro, -1, offsetof(PyTypeObject, tp_mro)}, -{Py_tp_subclasses, -1, offsetof(PyTypeObject, tp_subclasses)}, From c1844e3d1935daf1626519dd4031cfbe7ac27e66 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Mon, 2 Nov 2020 00:32:11 +0800 Subject: [PATCH 14/23] apply petr's comment --- Objects/typeobject.c | 5 +- Objects/typeslots.inc | 160 +++++++++++++++++++++--------------------- Objects/typeslots.py | 13 ++-- 3 files changed, 88 insertions(+), 90 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2d2f0739318cd0..e64eb1c857cf62 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -57,7 +57,6 @@ static unsigned int next_version_tag = 0; #endif typedef struct PySlot_Offset { - int slot; short subslot_offset; short slot_offset; } PySlot_Offset; @@ -2877,7 +2876,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) } static const PySlot_Offset pyslot_offsets[] = { - {0, 0, 0}, + {0, 0}, #include "typeslots.inc" }; @@ -3136,7 +3135,7 @@ PyType_GetSlot(PyTypeObject *type, int slot) } for (int i = 1; i < slots_len; i++) { - if (pyslot_offsets[i].slot != slot) { + if (i != slot) { continue; } parent_slot = *(void**)((char*)type + pyslot_offsets[i].slot_offset); diff --git a/Objects/typeslots.inc b/Objects/typeslots.inc index fa1046435d9f9c..38b3b6130436ee 100644 --- a/Objects/typeslots.inc +++ b/Objects/typeslots.inc @@ -1,81 +1,81 @@ /* Generated by typeslots.py */ -{Py_bf_getbuffer, offsetof(PyBufferProcs, bf_getbuffer), offsetof(PyTypeObject, tp_as_buffer)}, -{Py_bf_releasebuffer, offsetof(PyBufferProcs, bf_releasebuffer), offsetof(PyTypeObject, tp_as_buffer)}, -{Py_mp_ass_subscript, offsetof(PyMappingMethods, mp_ass_subscript), offsetof(PyTypeObject, tp_as_mapping)}, -{Py_mp_length, offsetof(PyMappingMethods, mp_length), offsetof(PyTypeObject, tp_as_mapping)}, -{Py_mp_subscript, offsetof(PyMappingMethods, mp_subscript), offsetof(PyTypeObject, tp_as_mapping)}, -{Py_nb_absolute, offsetof(PyNumberMethods, nb_absolute), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_add, offsetof(PyNumberMethods, nb_add), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_and, offsetof(PyNumberMethods, nb_and), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_bool, offsetof(PyNumberMethods, nb_bool), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_divmod, offsetof(PyNumberMethods, nb_divmod), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_float, offsetof(PyNumberMethods, nb_float), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_floor_divide, offsetof(PyNumberMethods, nb_floor_divide), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_index, offsetof(PyNumberMethods, nb_index), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_add, offsetof(PyNumberMethods, nb_inplace_add), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_and, offsetof(PyNumberMethods, nb_inplace_and), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_floor_divide, offsetof(PyNumberMethods, nb_inplace_floor_divide), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_lshift, offsetof(PyNumberMethods, nb_inplace_lshift), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_multiply, offsetof(PyNumberMethods, nb_inplace_multiply), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_or, offsetof(PyNumberMethods, nb_inplace_or), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_power, offsetof(PyNumberMethods, nb_inplace_power), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_remainder, offsetof(PyNumberMethods, nb_inplace_remainder), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_rshift, offsetof(PyNumberMethods, nb_inplace_rshift), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_subtract, offsetof(PyNumberMethods, nb_inplace_subtract), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_true_divide, offsetof(PyNumberMethods, nb_inplace_true_divide), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_xor, offsetof(PyNumberMethods, nb_inplace_xor), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_int, offsetof(PyNumberMethods, nb_int), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_invert, offsetof(PyNumberMethods, nb_invert), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_lshift, offsetof(PyNumberMethods, nb_lshift), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_multiply, offsetof(PyNumberMethods, nb_multiply), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_negative, offsetof(PyNumberMethods, nb_negative), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_or, offsetof(PyNumberMethods, nb_or), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_positive, offsetof(PyNumberMethods, nb_positive), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_power, offsetof(PyNumberMethods, nb_power), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_remainder, offsetof(PyNumberMethods, nb_remainder), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_rshift, offsetof(PyNumberMethods, nb_rshift), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_subtract, offsetof(PyNumberMethods, nb_subtract), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_true_divide, offsetof(PyNumberMethods, nb_true_divide), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_xor, offsetof(PyNumberMethods, nb_xor), offsetof(PyTypeObject, tp_as_number)}, -{Py_sq_ass_item, offsetof(PySequenceMethods, sq_ass_item), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_concat, offsetof(PySequenceMethods, sq_concat), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_contains, offsetof(PySequenceMethods, sq_contains), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_inplace_concat, offsetof(PySequenceMethods, sq_inplace_concat), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_inplace_repeat, offsetof(PySequenceMethods, sq_inplace_repeat), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_item, offsetof(PySequenceMethods, sq_item), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_length, offsetof(PySequenceMethods, sq_length), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_sq_repeat, offsetof(PySequenceMethods, sq_repeat), offsetof(PyTypeObject, tp_as_sequence)}, -{Py_tp_alloc, -1, offsetof(PyTypeObject, tp_alloc)}, -{Py_tp_base, -1, offsetof(PyTypeObject, tp_base)}, -{Py_tp_bases, -1, offsetof(PyTypeObject, tp_bases)}, -{Py_tp_call, -1, offsetof(PyTypeObject, tp_call)}, -{Py_tp_clear, -1, offsetof(PyTypeObject, tp_clear)}, -{Py_tp_dealloc, -1, offsetof(PyTypeObject, tp_dealloc)}, -{Py_tp_del, -1, offsetof(PyTypeObject, tp_del)}, -{Py_tp_descr_get, -1, offsetof(PyTypeObject, tp_descr_get)}, -{Py_tp_descr_set, -1, offsetof(PyTypeObject, tp_descr_set)}, -{Py_tp_doc, -1, offsetof(PyTypeObject, tp_doc)}, -{Py_tp_getattr, -1, offsetof(PyTypeObject, tp_getattr)}, -{Py_tp_getattro, -1, offsetof(PyTypeObject, tp_getattro)}, -{Py_tp_hash, -1, offsetof(PyTypeObject, tp_hash)}, -{Py_tp_init, -1, offsetof(PyTypeObject, tp_init)}, -{Py_tp_is_gc, -1, offsetof(PyTypeObject, tp_is_gc)}, -{Py_tp_iter, -1, offsetof(PyTypeObject, tp_iter)}, -{Py_tp_iternext, -1, offsetof(PyTypeObject, tp_iternext)}, -{Py_tp_methods, -1, offsetof(PyTypeObject, tp_methods)}, -{Py_tp_new, -1, offsetof(PyTypeObject, tp_new)}, -{Py_tp_repr, -1, offsetof(PyTypeObject, tp_repr)}, -{Py_tp_richcompare, -1, offsetof(PyTypeObject, tp_richcompare)}, -{Py_tp_setattr, -1, offsetof(PyTypeObject, tp_setattr)}, -{Py_tp_setattro, -1, offsetof(PyTypeObject, tp_setattro)}, -{Py_tp_str, -1, offsetof(PyTypeObject, tp_str)}, -{Py_tp_traverse, -1, offsetof(PyTypeObject, tp_traverse)}, -{Py_tp_members, -1, offsetof(PyTypeObject, tp_members)}, -{Py_tp_getset, -1, offsetof(PyTypeObject, tp_getset)}, -{Py_tp_free, -1, offsetof(PyTypeObject, tp_free)}, -{Py_nb_matrix_multiply, offsetof(PyNumberMethods, nb_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, -{Py_nb_inplace_matrix_multiply, offsetof(PyNumberMethods, nb_inplace_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, -{Py_am_await, offsetof(PyAsyncMethods, am_await), offsetof(PyTypeObject, tp_as_async)}, -{Py_am_aiter, offsetof(PyAsyncMethods, am_aiter), offsetof(PyTypeObject, tp_as_async)}, -{Py_am_anext, offsetof(PyAsyncMethods, am_anext), offsetof(PyTypeObject, tp_as_async)}, -{Py_tp_finalize, -1, offsetof(PyTypeObject, tp_finalize)}, +{offsetof(PyBufferProcs, bf_getbuffer), offsetof(PyTypeObject, tp_as_buffer)}, +{offsetof(PyBufferProcs, bf_releasebuffer), offsetof(PyTypeObject, tp_as_buffer)}, +{offsetof(PyMappingMethods, mp_ass_subscript), offsetof(PyTypeObject, tp_as_mapping)}, +{offsetof(PyMappingMethods, mp_length), offsetof(PyTypeObject, tp_as_mapping)}, +{offsetof(PyMappingMethods, mp_subscript), offsetof(PyTypeObject, tp_as_mapping)}, +{offsetof(PyNumberMethods, nb_absolute), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_add), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_and), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_bool), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_divmod), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_float), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_floor_divide), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_index), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_add), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_and), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_floor_divide), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_lshift), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_multiply), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_or), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_power), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_remainder), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_rshift), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_subtract), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_true_divide), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_xor), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_int), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_invert), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_lshift), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_multiply), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_negative), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_or), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_positive), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_power), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_remainder), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_rshift), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_subtract), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_true_divide), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_xor), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PySequenceMethods, sq_ass_item), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_concat), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_contains), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_inplace_concat), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_inplace_repeat), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_item), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_length), offsetof(PyTypeObject, tp_as_sequence)}, +{offsetof(PySequenceMethods, sq_repeat), offsetof(PyTypeObject, tp_as_sequence)}, +{-1, offsetof(PyTypeObject, tp_alloc)}, +{-1, offsetof(PyTypeObject, tp_base)}, +{-1, offsetof(PyTypeObject, tp_bases)}, +{-1, offsetof(PyTypeObject, tp_call)}, +{-1, offsetof(PyTypeObject, tp_clear)}, +{-1, offsetof(PyTypeObject, tp_dealloc)}, +{-1, offsetof(PyTypeObject, tp_del)}, +{-1, offsetof(PyTypeObject, tp_descr_get)}, +{-1, offsetof(PyTypeObject, tp_descr_set)}, +{-1, offsetof(PyTypeObject, tp_doc)}, +{-1, offsetof(PyTypeObject, tp_getattr)}, +{-1, offsetof(PyTypeObject, tp_getattro)}, +{-1, offsetof(PyTypeObject, tp_hash)}, +{-1, offsetof(PyTypeObject, tp_init)}, +{-1, offsetof(PyTypeObject, tp_is_gc)}, +{-1, offsetof(PyTypeObject, tp_iter)}, +{-1, offsetof(PyTypeObject, tp_iternext)}, +{-1, offsetof(PyTypeObject, tp_methods)}, +{-1, offsetof(PyTypeObject, tp_new)}, +{-1, offsetof(PyTypeObject, tp_repr)}, +{-1, offsetof(PyTypeObject, tp_richcompare)}, +{-1, offsetof(PyTypeObject, tp_setattr)}, +{-1, offsetof(PyTypeObject, tp_setattro)}, +{-1, offsetof(PyTypeObject, tp_str)}, +{-1, offsetof(PyTypeObject, tp_traverse)}, +{-1, offsetof(PyTypeObject, tp_members)}, +{-1, offsetof(PyTypeObject, tp_getset)}, +{-1, offsetof(PyTypeObject, tp_free)}, +{offsetof(PyNumberMethods, nb_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyNumberMethods, nb_inplace_matrix_multiply), offsetof(PyTypeObject, tp_as_number)}, +{offsetof(PyAsyncMethods, am_await), offsetof(PyTypeObject, tp_as_async)}, +{offsetof(PyAsyncMethods, am_aiter), offsetof(PyTypeObject, tp_as_async)}, +{offsetof(PyAsyncMethods, am_anext), offsetof(PyTypeObject, tp_as_async)}, +{-1, offsetof(PyTypeObject, tp_finalize)}, diff --git a/Objects/typeslots.py b/Objects/typeslots.py index 67487d7ea5584b..feb65bfc3b675d 100755 --- a/Objects/typeslots.py +++ b/Objects/typeslots.py @@ -12,24 +12,23 @@ def generate_typeslots(out=sys.stdout): if not m: continue - slot_name = re.match("#define ([A-Za-z_]+) ([0-9]+)", line).group(1) member = m.group(1) if member.startswith("tp_"): - member = f'{{{slot_name}, -1, offsetof(PyTypeObject, {member})}}' + member = f'{{-1, offsetof(PyTypeObject, {member})}}' elif member.startswith("am_"): - member = (f'{{{slot_name}, offsetof(PyAsyncMethods, {member}),'+ + member = (f'{{offsetof(PyAsyncMethods, {member}),'+ ' offsetof(PyTypeObject, tp_as_async)}') elif member.startswith("nb_"): - member = (f'{{{slot_name}, offsetof(PyNumberMethods, {member}),'+ + member = (f'{{offsetof(PyNumberMethods, {member}),'+ ' offsetof(PyTypeObject, tp_as_number)}') elif member.startswith("mp_"): - member = (f'{{{slot_name}, offsetof(PyMappingMethods, {member}),'+ + member = (f'{{offsetof(PyMappingMethods, {member}),'+ ' offsetof(PyTypeObject, tp_as_mapping)}') elif member.startswith("sq_"): - member = (f'{{{slot_name}, offsetof(PySequenceMethods, {member}),'+ + member = (f'{{offsetof(PySequenceMethods, {member}),'+ ' offsetof(PyTypeObject, tp_as_sequence)}') elif member.startswith("bf_"): - member = (f'{{{slot_name}, offsetof(PyBufferProcs, {member}),'+ + member = (f'{{offsetof(PyBufferProcs, {member}),'+ ' offsetof(PyTypeObject, tp_as_buffer)}') res[int(m.group(2))] = member From ccdd9b6615316bd76f190abba2cfec31e50b3d6e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 15:07:04 +0100 Subject: [PATCH 15/23] Call test_get_statictype_slots in the test suite --- Lib/test/test_capi.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index db62b47100ad3a..b3102b531529d3 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -544,6 +544,10 @@ def test_pynumber_tobase(self): self.assertRaises(TypeError, pynumber_tobase, '123', 10) self.assertRaises(SystemError, pynumber_tobase, 123, 0) + def test_get_statictype_slots(self): + from _testcapi import test_get_statictype_slots + test_get_statictype_slots() + class TestPendingCalls(unittest.TestCase): From 9194565c20282bb97f4707095f19817e47078c8d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 15:09:39 +0100 Subject: [PATCH 16/23] Raise exception on the invalid slot 0 --- Modules/_testcapimodule.c | 5 +++++ Objects/typeobject.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 8093eddfbd58f2..10c3bbf4ce8e23 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1039,6 +1039,11 @@ test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); assert(over_value == NULL); + tp_new = PyType_GetSlot(&PyLong_Type, 0); + assert(tp_new == NULL); + assert(PyErr_ExceptionMatches(PyExc_SystemError)); + PyErr_Clear(); + Py_RETURN_NONE; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e64eb1c857cf62..9e0b6326368c50 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3129,7 +3129,7 @@ PyType_GetSlot(PyTypeObject *type, int slot) void *parent_slot; int slots_len = Py_ARRAY_LENGTH(pyslot_offsets); - if (slot < 0 || slot >= slots_len) { + if (slot <= 0 || slot >= slots_len) { PyErr_BadInternalCall(); return NULL; } From 708cd824f42abad4e0c8d5f131450782be7087c1 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 15:16:48 +0100 Subject: [PATCH 17/23] Use if rather than assert in tests C asserts are removed in non-debug builds. --- Modules/_testcapimodule.c | 44 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 10c3bbf4ce8e23..c50d37eddc51f2 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1022,27 +1022,53 @@ static PyObject * test_get_statictype_slots(PyObject *self, PyObject *Py_UNUSED(ignored)) { newfunc tp_new = PyType_GetSlot(&PyLong_Type, Py_tp_new); - assert(PyLong_Type.tp_new == tp_new); + if (PyLong_Type.tp_new != tp_new) { + PyErr_SetString(PyExc_AssertionError, "mismatch: tp_new of long"); + return NULL; + } reprfunc tp_repr = PyType_GetSlot(&PyLong_Type, Py_tp_repr); - assert(PyLong_Type.tp_repr == tp_repr); + if (PyLong_Type.tp_repr != tp_repr) { + PyErr_SetString(PyExc_AssertionError, "mismatch: tp_repr of long"); + return NULL; + } ternaryfunc tp_call = PyType_GetSlot(&PyLong_Type, Py_tp_call); - assert(tp_call == 0); + if (tp_call != NULL) { + PyErr_SetString(PyExc_AssertionError, "mismatch: tp_call of long"); + return NULL; + } binaryfunc nb_add = PyType_GetSlot(&PyLong_Type, Py_nb_add); - assert(PyLong_Type.tp_as_number->nb_add == nb_add); + if (PyLong_Type.tp_as_number->nb_add != nb_add) { + PyErr_SetString(PyExc_AssertionError, "mismatch: nb_add of long"); + return NULL; + } lenfunc mp_length = PyType_GetSlot(&PyLong_Type, Py_mp_length); - assert(mp_length == NULL); + if (mp_length != NULL) { + PyErr_SetString(PyExc_AssertionError, "mismatch: mp_length of long"); + return NULL; + } void *over_value = PyType_GetSlot(&PyLong_Type, Py_bf_releasebuffer + 1); - assert(over_value == NULL); + if (over_value != NULL) { + PyErr_SetString(PyExc_AssertionError, "mismatch: max+1 of long"); + return NULL; + } tp_new = PyType_GetSlot(&PyLong_Type, 0); - assert(tp_new == NULL); - assert(PyErr_ExceptionMatches(PyExc_SystemError)); - PyErr_Clear(); + if (tp_new != NULL) { + PyErr_SetString(PyExc_AssertionError, "mismatch: slot 0 of long"); + return NULL; + } + if (PyErr_ExceptionMatches(PyExc_SystemError)) { + // This is the right exception + PyErr_Clear(); + } + else { + return NULL; + } Py_RETURN_NONE; } From b351b2cbd8212bc119b1619f27e6f06834b33fb1 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 15:20:41 +0100 Subject: [PATCH 18/23] Add/adjust comments & news entries --- Doc/c-api/type.rst | 3 ++- .../C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst | 2 +- Objects/typeobject.c | 10 ++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 48a1c39a9809a1..ea9ac655fd9ee0 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -108,7 +108,8 @@ Type Objects .. versionadded:: 3.4 .. versionchanged:: 3.10 - :c:func:`PyType_GetSlot` could accept static types. + :c:func:`PyType_GetSlot` can now accept all types. + Previously, it was limited to heap types. .. c:function:: PyObject* PyType_GetModule(PyTypeObject *type) diff --git a/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst b/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst index 668bfb2c2e2791..1bec2f1a197e1a 100644 --- a/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst +++ b/Misc/NEWS.d/next/C API/2020-07-08-21-01-49.bpo-41073.VqQZON.rst @@ -1 +1 @@ -:c:func:`PyType_GetSlot()` could accept static types. +:c:func:`PyType_GetSlot()` can now accept static types. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9e0b6326368c50..8e5c3145e76985 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2875,6 +2875,16 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) return NULL; } +/* 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" From 2df91806b9ccdb017ecc0ca96b6360dd19389965 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 15:21:29 +0100 Subject: [PATCH 19/23] Align method definitions in _testcapi This is how most of the table is formatted. Fix a few lines around the one added. --- Modules/_testcapimodule.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c50d37eddc51f2..bc899fc179e8b4 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5683,9 +5683,10 @@ static PyMethodDef TestMethods[] = { {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, - {"get_args", get_args, METH_VARARGS}, - {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, - {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, + {"get_args", get_args, METH_VARARGS}, + {"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS}, + {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, + METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, {"getargs_keywords", (PyCFunction)(void(*)(void))getargs_keywords, METH_VARARGS|METH_KEYWORDS}, From 2b077e3fca543e973400701e125ca45218e1cc0d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 17:05:38 +0100 Subject: [PATCH 20/23] Rewrite the slot-setting code a bit IMO, things are more easier to follow this way (combined with the comment added to pyslot_offsets). --- Objects/typeobject.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8e5c3145e76985..37d4f52e185218 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3046,12 +3046,13 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) } else { /* Copy other slots directly */ - slot_offset = pyslot_offsets[slot->slot].slot_offset; - void *parent_slot = *(void**)((char*)res_start + slot_offset); - if (parent_slot == NULL) { + 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 { - subslot_offset = pyslot_offsets[slot->slot].subslot_offset; + void *parent_slot = *(void**)((char*)res_start + slot_offset); + subslot_offset = slotoffsets.subslot_offset; *(void**)((char*)parent_slot + subslot_offset) = slot->pfunc; } } From 943174b46a546fcc7b0f7942c7061993a8d0fea3 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 17:08:41 +0100 Subject: [PATCH 21/23] Remove the loop in PyType_GetSlot; we already know the position --- Objects/typeobject.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 37d4f52e185218..bf318e4fc1209d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3145,21 +3145,15 @@ PyType_GetSlot(PyTypeObject *type, int slot) return NULL; } - for (int i = 1; i < slots_len; i++) { - if (i != slot) { - continue; - } - parent_slot = *(void**)((char*)type + pyslot_offsets[i].slot_offset); - if (parent_slot == NULL) { - return NULL; - } - /* Return slot directly if there have no sub slot. */ - if (pyslot_offsets[i].subslot_offset == -1) { - return parent_slot; - } - return *(void**)((char*)parent_slot + pyslot_offsets[i].subslot_offset); + parent_slot = *(void**)((char*)type + pyslot_offsets[slot].slot_offset); + if (parent_slot == NULL) { + return NULL; } - return NULL; + /* 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 * From 2d8b57f973cca85c4ff8c145abdc652baa8e2ca5 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Nov 2020 21:56:20 +0100 Subject: [PATCH 22/23] typeslots.py: Add back code writing null entries This way the table will be kept in sync if a slot is removed (which shouldn't happen). --- Objects/typeslots.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objects/typeslots.py b/Objects/typeslots.py index feb65bfc3b675d..8ab05f91be12b0 100755 --- a/Objects/typeslots.py +++ b/Objects/typeslots.py @@ -36,6 +36,8 @@ def generate_typeslots(out=sys.stdout): for i in range(1,M): if i in res: out.write("%s,\n" % res[i]) + else: + out.write("{0, 0},\n") def main(): From 6a688d991c759edc0b380ec62cf50110e8d1a419 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 10 Nov 2020 15:22:55 +0100 Subject: [PATCH 23/23] Remove redundant test function --- Lib/test/test_capi.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 3d981c0393de04..a4ebe4a0a1b5cb 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -547,10 +547,6 @@ def test_pynumber_tobase(self): self.assertRaises(TypeError, pynumber_tobase, '123', 10) self.assertRaises(SystemError, pynumber_tobase, 123, 0) - def test_get_statictype_slots(self): - from _testcapi import test_get_statictype_slots - test_get_statictype_slots() - class TestPendingCalls(unittest.TestCase):