From 75e76229a67c5caf8b7147573537222abe6f1302 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:03:29 +0100 Subject: [PATCH 01/13] Convert array type to heap type --- Modules/arraymodule.c | 164 +++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 89 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 2ba2ff43aa8b8a..763373dddffe94 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -5,6 +5,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "structmember.h" // PyMemberDef #include // offsetof() #ifdef STDC_HEADERS @@ -46,7 +47,7 @@ typedef struct arrayobject { Py_ssize_t ob_exports; /* Number of exported buffers */ } arrayobject; -static PyTypeObject Arraytype; +static PyTypeObject *Arraytype = NULL; typedef struct { PyObject_HEAD @@ -105,8 +106,8 @@ enum machine_format_code { */ #include "clinic/arraymodule.c.h" -#define array_Check(op) PyObject_TypeCheck(op, &Arraytype) -#define array_CheckExact(op) Py_IS_TYPE(op, &Arraytype) +#define array_Check(op) PyObject_TypeCheck(op, Arraytype) +#define array_CheckExact(op) Py_IS_TYPE(op, Arraytype) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -562,7 +563,7 @@ static const struct arraydescr descriptors[] = { Implementations of array object methods. ****************************************************************************/ /*[clinic input] -class array.array "arrayobject *" "&Arraytype" +class array.array "arrayobject *" "Arraytype" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/ @@ -649,11 +650,14 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v) static void array_dealloc(arrayobject *op) { + PyTypeObject *tp = Py_TYPE(op); + if (op->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) op); if (op->ob_item != NULL) PyMem_DEL(op->ob_item); - Py_TYPE(op)->tp_free((PyObject *)op); + tp->tp_free(op); + Py_DECREF(tp); } static PyObject * @@ -798,7 +802,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject(Arraytype, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; if (ihigh > ilow) { @@ -858,7 +862,7 @@ array_concat(arrayobject *a, PyObject *bb) return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -885,7 +889,7 @@ array_repeat(arrayobject *a, Py_ssize_t n) return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr); if (np == NULL) return NULL; if (size == 0) @@ -1938,10 +1942,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, &Arraytype)) { + if (!PyType_IsSubtype(arraytype, Arraytype)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, Arraytype.tp_name); + arraytype->tp_name, Arraytype->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2310,10 +2314,10 @@ array_subscr(arrayobject* self, PyObject* item) step); if (slicelength <= 0) { - return newarrayobject(&Arraytype, 0, self->ob_descr); + return newarrayobject(Arraytype, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(&Arraytype, + PyObject *result = newarrayobject(Arraytype, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2323,7 +2327,7 @@ array_subscr(arrayobject* self, PyObject* item) return result; } else { - result = newarrayobject(&Arraytype, slicelength, self->ob_descr); + result = newarrayobject(Arraytype, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2502,12 +2506,6 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) } } -static PyMappingMethods array_as_mapping = { - (lenfunc)array_length, - (binaryfunc)array_subscr, - (objobjargproc)array_ass_subscr -}; - static const void *emptybuf = ""; @@ -2558,24 +2556,6 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view) self->ob_exports--; } -static PySequenceMethods array_as_sequence = { - (lenfunc)array_length, /*sq_length*/ - (binaryfunc)array_concat, /*sq_concat*/ - (ssizeargfunc)array_repeat, /*sq_repeat*/ - (ssizeargfunc)array_item, /*sq_item*/ - 0, /*sq_slice*/ - (ssizeobjargproc)array_ass_item, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - (objobjproc)array_contains, /*sq_contains*/ - (binaryfunc)array_inplace_concat, /*sq_inplace_concat*/ - (ssizeargfunc)array_inplace_repeat /*sq_inplace_repeat*/ -}; - -static PyBufferProcs array_as_buffer = { - (getbufferproc)array_buffer_getbuf, - (releasebufferproc)array_buffer_relbuf -}; - static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -2583,7 +2563,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; - if (type == &Arraytype && !_PyArg_NoKeywords("array.array", kwds)) + if (type == Arraytype && !_PyArg_NoKeywords("array.array", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2777,48 +2757,53 @@ itemsize -- the length in bytes of one array item\n\ static PyObject *array_iter(arrayobject *ao); -static PyTypeObject Arraytype = { - PyVarObject_HEAD_INIT(NULL, 0) - "array.array", - sizeof(arrayobject), - 0, - (destructor)array_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)array_repr, /* tp_repr */ - 0, /* tp_as_number*/ - &array_as_sequence, /* tp_as_sequence*/ - &array_as_mapping, /* tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - &array_as_buffer, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - arraytype_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - array_richcompare, /* tp_richcompare */ - offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)array_iter, /* tp_iter */ - 0, /* tp_iternext */ - array_methods, /* tp_methods */ - 0, /* tp_members */ - array_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - array_new, /* tp_new */ - PyObject_Del, /* tp_free */ +static struct PyMemberDef array_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(arrayobject, weakreflist), READONLY}, + {NULL}, }; +static PyType_Slot array_slots[] = { + {Py_tp_dealloc, array_dealloc}, + {Py_tp_repr, array_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)arraytype_doc}, + {Py_tp_richcompare, array_richcompare}, + {Py_tp_iter, array_iter}, + {Py_tp_methods, array_methods}, + {Py_tp_members, array_members}, + {Py_tp_getset, array_getsets}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, array_new}, + {Py_tp_free, PyObject_Del}, + + /* as sequence */ + {Py_sq_length, array_length}, + {Py_sq_concat, array_concat}, + {Py_sq_repeat, array_repeat}, + {Py_sq_item, array_item}, + {Py_sq_ass_item, array_ass_item}, + {Py_sq_contains, array_contains}, + {Py_sq_inplace_concat, array_inplace_concat}, + {Py_sq_inplace_repeat, array_inplace_repeat}, + + /* as mapping */ + {Py_mp_length, array_length}, + {Py_mp_subscript, array_subscr}, + {Py_mp_ass_subscript, array_ass_subscr}, + + /* as buffer */ + {Py_bf_getbuffer, array_buffer_getbuf}, + {Py_bf_releasebuffer, array_buffer_relbuf}, + + {0, NULL}, +}; + +static PyType_Spec array_spec = { + .name = "array.array", + .basicsize = sizeof(arrayobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = array_slots, +}; /*********************** Array Iterator **************************/ @@ -2980,38 +2965,39 @@ array_modexec(PyObject *m) PyObject *typecodes; const struct arraydescr *descr; - if (PyType_Ready(&Arraytype) < 0) + Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); + if (Arraytype == NULL) return -1; Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type); - Py_INCREF((PyObject *)&Arraytype); - if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) { - Py_DECREF((PyObject *)&Arraytype); + Py_INCREF((PyObject *)Arraytype); + if (PyModule_AddObject(m, "ArrayType", (PyObject *)Arraytype) < 0) { + Py_DECREF((PyObject *)Arraytype); return -1; } PyObject *abc_mod = PyImport_ImportModule("collections.abc"); if (!abc_mod) { - Py_DECREF((PyObject *)&Arraytype); + Py_DECREF((PyObject *)Arraytype); return -1; } PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence"); Py_DECREF(abc_mod); if (!mutablesequence) { - Py_DECREF((PyObject *)&Arraytype); + Py_DECREF((PyObject *)Arraytype); return -1; } - PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)&Arraytype); + PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)Arraytype); Py_DECREF(mutablesequence); if (!res) { - Py_DECREF((PyObject *)&Arraytype); + Py_DECREF((PyObject *)Arraytype); return -1; } Py_DECREF(res); - Py_INCREF((PyObject *)&Arraytype); - if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) { - Py_DECREF((PyObject *)&Arraytype); + Py_INCREF((PyObject *)Arraytype); + if (PyModule_AddObject(m, "array", (PyObject *)Arraytype) < 0) { + Py_DECREF((PyObject *)Arraytype); return -1; } From 7b8e273abde2c63a909732e51b3746ba408e193c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:12:29 +0100 Subject: [PATCH 02/13] Convert array iter type to heap type --- Modules/arraymodule.c | 63 +++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 763373dddffe94..56d4aa9f38e0b6 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -56,9 +56,9 @@ typedef struct { PyObject* (*getitem)(struct arrayobject *, Py_ssize_t); } arrayiterobject; -static PyTypeObject PyArrayIter_Type; +static PyTypeObject *PyArrayIter_Type = NULL; -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type) +#define PyArrayIter_Check(op) PyObject_TypeCheck(op, PyArrayIter_Type) enum machine_format_code { UNKNOWN_FORMAT = -1, @@ -2808,7 +2808,7 @@ static PyType_Spec array_spec = { /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "&PyArrayIter_Type" +class array.arrayiterator "arrayiterobject *" "PyArrayIter_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ @@ -2822,7 +2822,7 @@ array_iter(arrayobject *ao) return NULL; } - it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, PyArrayIter_Type); if (it == NULL) return NULL; @@ -2857,9 +2857,12 @@ arrayiter_next(arrayiterobject *it) static void arrayiter_dealloc(arrayiterobject *it) { + PyTypeObject *tp = Py_TYPE(it); + PyObject_GC_UnTrack(it); Py_XDECREF(it->ao); PyObject_GC_Del(it); + Py_DECREF(tp); } static int @@ -2917,36 +2920,21 @@ static PyMethodDef arrayiter_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject PyArrayIter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "arrayiterator", /* tp_name */ - sizeof(arrayiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)arrayiter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)arrayiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)arrayiter_next, /* tp_iternext */ - arrayiter_methods, /* tp_methods */ +static PyType_Slot arrayiter_slots[] = { + {Py_tp_dealloc, arrayiter_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, arrayiter_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, arrayiter_next}, + {Py_tp_methods, arrayiter_methods}, + {0, NULL}, +}; + +static PyType_Spec arrayiter_spec = { + .name = "array.arrayiterator", + .basicsize = sizeof(arrayiterobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = arrayiter_slots, }; @@ -2968,7 +2956,12 @@ array_modexec(PyObject *m) Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); if (Arraytype == NULL) return -1; - Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type); + PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, + &arrayiter_spec, + NULL); + if (PyArrayIter_Type == NULL) + return -1; + Py_SET_TYPE(PyArrayIter_Type, &PyType_Type); Py_INCREF((PyObject *)Arraytype); if (PyModule_AddObject(m, "ArrayType", (PyObject *)Arraytype) < 0) { From 3f7876667db0cb463d366b6517275c5590ac7964 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:28:40 +0100 Subject: [PATCH 03/13] Establish global state and add types to it --- Modules/arraymodule.c | 79 ++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 56d4aa9f38e0b6..06a88c6dfbcf2c 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -47,8 +47,6 @@ typedef struct arrayobject { Py_ssize_t ob_exports; /* Number of exported buffers */ } arrayobject; -static PyTypeObject *Arraytype = NULL; - typedef struct { PyObject_HEAD Py_ssize_t index; @@ -56,9 +54,20 @@ typedef struct { PyObject* (*getitem)(struct arrayobject *, Py_ssize_t); } arrayiterobject; -static PyTypeObject *PyArrayIter_Type = NULL; +typedef struct { + PyTypeObject *Arraytype; + PyTypeObject *PyArrayIter_Type; +} array_state; + +static array_state global_array_state; + +static array_state * +get_array_state() +{ + return &global_array_state; +} -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, PyArrayIter_Type) +#define PyArrayIter_Check(op) PyObject_TypeCheck(op, get_array_state()->PyArrayIter_Type) enum machine_format_code { UNKNOWN_FORMAT = -1, @@ -106,8 +115,8 @@ enum machine_format_code { */ #include "clinic/arraymodule.c.h" -#define array_Check(op) PyObject_TypeCheck(op, Arraytype) -#define array_CheckExact(op) Py_IS_TYPE(op, Arraytype) +#define array_Check(op) PyObject_TypeCheck(op, get_array_state()->Arraytype) +#define array_CheckExact(op) Py_IS_TYPE(op, get_array_state()->Arraytype) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -802,7 +811,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(Arraytype, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; if (ihigh > ilow) { @@ -862,7 +871,7 @@ array_concat(arrayobject *a, PyObject *bb) return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -889,7 +898,7 @@ array_repeat(arrayobject *a, Py_ssize_t n) return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr); if (np == NULL) return NULL; if (size == 0) @@ -1942,10 +1951,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, Arraytype)) { + if (!PyType_IsSubtype(arraytype, get_array_state()->Arraytype)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, Arraytype->tp_name); + arraytype->tp_name, get_array_state()->Arraytype->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2314,10 +2323,10 @@ array_subscr(arrayobject* self, PyObject* item) step); if (slicelength <= 0) { - return newarrayobject(Arraytype, 0, self->ob_descr); + return newarrayobject(get_array_state()->Arraytype, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(Arraytype, + PyObject *result = newarrayobject(get_array_state()->Arraytype, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2327,7 +2336,7 @@ array_subscr(arrayobject* self, PyObject* item) return result; } else { - result = newarrayobject(Arraytype, slicelength, self->ob_descr); + result = newarrayobject(get_array_state()->Arraytype, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2563,7 +2572,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; - if (type == Arraytype && !_PyArg_NoKeywords("array.array", kwds)) + if (type == get_array_state()->Arraytype && !_PyArg_NoKeywords("array.array", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2808,7 +2817,7 @@ static PyType_Spec array_spec = { /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "PyArrayIter_Type" +class array.arrayiterator "arrayiterobject *" "get_array_state()->PyArrayIter_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ @@ -2822,7 +2831,7 @@ array_iter(arrayobject *ao) return NULL; } - it = PyObject_GC_New(arrayiterobject, PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, get_array_state()->PyArrayIter_Type); if (it == NULL) return NULL; @@ -2949,48 +2958,50 @@ static PyMethodDef a_methods[] = { static int array_modexec(PyObject *m) { + array_state *state = get_array_state(); char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; const struct arraydescr *descr; - Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); - if (Arraytype == NULL) + state->Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); + if (state->Arraytype == NULL) return -1; - PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, - &arrayiter_spec, - NULL); - if (PyArrayIter_Type == NULL) + state->PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, + &arrayiter_spec, + NULL); + if (state->PyArrayIter_Type == NULL) return -1; - Py_SET_TYPE(PyArrayIter_Type, &PyType_Type); + Py_SET_TYPE(state->PyArrayIter_Type, &PyType_Type); - Py_INCREF((PyObject *)Arraytype); - if (PyModule_AddObject(m, "ArrayType", (PyObject *)Arraytype) < 0) { - Py_DECREF((PyObject *)Arraytype); + Py_INCREF((PyObject *)state->Arraytype); + if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->Arraytype) < 0) { + Py_DECREF((PyObject *)state->Arraytype); return -1; } PyObject *abc_mod = PyImport_ImportModule("collections.abc"); if (!abc_mod) { - Py_DECREF((PyObject *)Arraytype); + Py_DECREF((PyObject *)state->Arraytype); return -1; } PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence"); Py_DECREF(abc_mod); if (!mutablesequence) { - Py_DECREF((PyObject *)Arraytype); + Py_DECREF((PyObject *)state->Arraytype); return -1; } - PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)Arraytype); + PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", + (PyObject *)state->Arraytype); Py_DECREF(mutablesequence); if (!res) { - Py_DECREF((PyObject *)Arraytype); + Py_DECREF((PyObject *)state->Arraytype); return -1; } Py_DECREF(res); - Py_INCREF((PyObject *)Arraytype); - if (PyModule_AddObject(m, "array", (PyObject *)Arraytype) < 0) { - Py_DECREF((PyObject *)Arraytype); + Py_INCREF((PyObject *)state->Arraytype); + if (PyModule_AddObject(m, "array", (PyObject *)state->Arraytype) < 0) { + Py_DECREF((PyObject *)state->Arraytype); return -1; } From 23a582adcb972e3838ebd3b7ca3fd3eddba1701d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:31:07 +0100 Subject: [PATCH 04/13] Remove unused check macro --- Modules/arraymodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 06a88c6dfbcf2c..56c61bff472477 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -116,7 +116,6 @@ enum machine_format_code { #include "clinic/arraymodule.c.h" #define array_Check(op) PyObject_TypeCheck(op, get_array_state()->Arraytype) -#define array_CheckExact(op) Py_IS_TYPE(op, get_array_state()->Arraytype) static int array_resize(arrayobject *self, Py_ssize_t newsize) From 1869a3a93d6a64d5bee66db9429f8e09cf3d1ddb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:36:31 +0100 Subject: [PATCH 05/13] Use local state variables iso. calling get_array_state() all the time --- Modules/arraymodule.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 56c61bff472477..d6d7f11345f866 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -853,6 +853,7 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused) static PyObject * array_concat(arrayobject *a, PyObject *bb) { + array_state *state = get_array_state(); Py_ssize_t size; arrayobject *np; if (!array_Check(bb)) { @@ -870,7 +871,7 @@ array_concat(arrayobject *a, PyObject *bb) return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->Arraytype, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -888,6 +889,7 @@ array_concat(arrayobject *a, PyObject *bb) static PyObject * array_repeat(arrayobject *a, Py_ssize_t n) { + array_state *state = get_array_state(); Py_ssize_t size; arrayobject *np; Py_ssize_t oldbytes, newbytes; @@ -897,7 +899,7 @@ array_repeat(arrayobject *a, Py_ssize_t n) return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->Arraytype, size, a->ob_descr); if (np == NULL) return NULL; if (size == 0) @@ -1940,6 +1942,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, PyObject *items) /*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/ { + array_state *state = get_array_state(); PyObject *converted_items; PyObject *result; const struct arraydescr *descr; @@ -1950,10 +1953,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, get_array_state()->Arraytype)) { + if (!PyType_IsSubtype(arraytype, state->Arraytype)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, get_array_state()->Arraytype->tp_name); + arraytype->tp_name, state->Arraytype->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2299,6 +2302,8 @@ array_repr(arrayobject *a) static PyObject* array_subscr(arrayobject* self, PyObject* item) { + array_state *state = get_array_state(); + if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i==-1 && PyErr_Occurred()) { @@ -2322,10 +2327,10 @@ array_subscr(arrayobject* self, PyObject* item) step); if (slicelength <= 0) { - return newarrayobject(get_array_state()->Arraytype, 0, self->ob_descr); + return newarrayobject(state->Arraytype, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(get_array_state()->Arraytype, + PyObject *result = newarrayobject(state->Arraytype, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2335,7 +2340,7 @@ array_subscr(arrayobject* self, PyObject* item) return result; } else { - result = newarrayobject(get_array_state()->Arraytype, slicelength, self->ob_descr); + result = newarrayobject(state->Arraytype, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2567,11 +2572,12 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view) static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + array_state *state = get_array_state(); int c; PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; - if (type == get_array_state()->Arraytype && !_PyArg_NoKeywords("array.array", kwds)) + if (type == state->Arraytype && !_PyArg_NoKeywords("array.array", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2823,6 +2829,7 @@ class array.arrayiterator "arrayiterobject *" "get_array_state()->PyArrayIter_Ty static PyObject * array_iter(arrayobject *ao) { + array_state *state = get_array_state(); arrayiterobject *it; if (!array_Check(ao)) { @@ -2830,7 +2837,7 @@ array_iter(arrayobject *ao) return NULL; } - it = PyObject_GC_New(arrayiterobject, get_array_state()->PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, state->PyArrayIter_Type); if (it == NULL) return NULL; From 88d19283ae112b1e6a3e2335f0c6b2a79c0a66fd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:34:05 +0100 Subject: [PATCH 06/13] Normalize array type names --- Modules/arraymodule.c | 66 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index d6d7f11345f866..420e7b30eb0aeb 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -55,8 +55,8 @@ typedef struct { } arrayiterobject; typedef struct { - PyTypeObject *Arraytype; - PyTypeObject *PyArrayIter_Type; + PyTypeObject *ArrayType; + PyTypeObject *ArrayIterType; } array_state; static array_state global_array_state; @@ -67,7 +67,7 @@ get_array_state() return &global_array_state; } -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, get_array_state()->PyArrayIter_Type) +#define PyArrayIter_Check(op) PyObject_TypeCheck(op, get_array_state()->ArrayIterType) enum machine_format_code { UNKNOWN_FORMAT = -1, @@ -115,7 +115,7 @@ enum machine_format_code { */ #include "clinic/arraymodule.c.h" -#define array_Check(op) PyObject_TypeCheck(op, get_array_state()->Arraytype) +#define array_Check(op) PyObject_TypeCheck(op, get_array_state()->ArrayType) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -571,7 +571,7 @@ static const struct arraydescr descriptors[] = { Implementations of array object methods. ****************************************************************************/ /*[clinic input] -class array.array "arrayobject *" "Arraytype" +class array.array "arrayobject *" "ArrayType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/ @@ -810,7 +810,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(get_array_state()->Arraytype, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject(get_array_state()->ArrayType, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; if (ihigh > ilow) { @@ -871,7 +871,7 @@ array_concat(arrayobject *a, PyObject *bb) return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(state->Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -899,7 +899,7 @@ array_repeat(arrayobject *a, Py_ssize_t n) return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(state->Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr); if (np == NULL) return NULL; if (size == 0) @@ -1953,10 +1953,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, state->Arraytype)) { + if (!PyType_IsSubtype(arraytype, state->ArrayType)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, state->Arraytype->tp_name); + arraytype->tp_name, state->ArrayType->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2327,10 +2327,10 @@ array_subscr(arrayobject* self, PyObject* item) step); if (slicelength <= 0) { - return newarrayobject(state->Arraytype, 0, self->ob_descr); + return newarrayobject(state->ArrayType, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(state->Arraytype, + PyObject *result = newarrayobject(state->ArrayType, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2340,7 +2340,7 @@ array_subscr(arrayobject* self, PyObject* item) return result; } else { - result = newarrayobject(state->Arraytype, slicelength, self->ob_descr); + result = newarrayobject(state->ArrayType, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2577,7 +2577,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; - if (type == state->Arraytype && !_PyArg_NoKeywords("array.array", kwds)) + if (type == state->ArrayType && !_PyArg_NoKeywords("array.array", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2822,7 +2822,7 @@ static PyType_Spec array_spec = { /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "get_array_state()->PyArrayIter_Type" +class array.arrayiterator "arrayiterobject *" "get_array_state()->ArrayIterType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ @@ -2837,7 +2837,7 @@ array_iter(arrayobject *ao) return NULL; } - it = PyObject_GC_New(arrayiterobject, state->PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, state->ArrayIterType); if (it == NULL) return NULL; @@ -2969,45 +2969,45 @@ array_modexec(PyObject *m) PyObject *typecodes; const struct arraydescr *descr; - state->Arraytype = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); - if (state->Arraytype == NULL) + state->ArrayType = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); + if (state->ArrayType == NULL) return -1; - state->PyArrayIter_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, - &arrayiter_spec, - NULL); - if (state->PyArrayIter_Type == NULL) + state->ArrayIterType = (PyTypeObject *)PyType_FromModuleAndSpec(m, + &arrayiter_spec, + NULL); + if (state->ArrayIterType == NULL) return -1; - Py_SET_TYPE(state->PyArrayIter_Type, &PyType_Type); + Py_SET_TYPE(state->ArrayIterType, &PyType_Type); - Py_INCREF((PyObject *)state->Arraytype); - if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->Arraytype) < 0) { - Py_DECREF((PyObject *)state->Arraytype); + Py_INCREF((PyObject *)state->ArrayType); + if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) { + Py_DECREF((PyObject *)state->ArrayType); return -1; } PyObject *abc_mod = PyImport_ImportModule("collections.abc"); if (!abc_mod) { - Py_DECREF((PyObject *)state->Arraytype); + Py_DECREF((PyObject *)state->ArrayType); return -1; } PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence"); Py_DECREF(abc_mod); if (!mutablesequence) { - Py_DECREF((PyObject *)state->Arraytype); + Py_DECREF((PyObject *)state->ArrayType); return -1; } PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", - (PyObject *)state->Arraytype); + (PyObject *)state->ArrayType); Py_DECREF(mutablesequence); if (!res) { - Py_DECREF((PyObject *)state->Arraytype); + Py_DECREF((PyObject *)state->ArrayType); return -1; } Py_DECREF(res); - Py_INCREF((PyObject *)state->Arraytype); - if (PyModule_AddObject(m, "array", (PyObject *)state->Arraytype) < 0) { - Py_DECREF((PyObject *)state->Arraytype); + Py_INCREF((PyObject *)state->ArrayType); + if (PyModule_AddObject(m, "array", (PyObject *)state->ArrayType) < 0) { + Py_DECREF((PyObject *)state->ArrayType); return -1; } From d0ed2f7816b9ea591d36adae4cfa29a6530240ba Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:44:34 +0100 Subject: [PATCH 07/13] Update clinic --- Modules/arraymodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 420e7b30eb0aeb..a9eca6b7d48459 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -573,7 +573,7 @@ Implementations of array object methods. /*[clinic input] class array.array "arrayobject *" "ArrayType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5c29edf59f176a3]*/ static PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr) @@ -2824,7 +2824,7 @@ static PyType_Spec array_spec = { /*[clinic input] class array.arrayiterator "arrayiterobject *" "get_array_state()->ArrayIterType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=91c83ed82b09b941]*/ static PyObject * array_iter(arrayobject *ao) From a5798e2d9c1d779e9005b90408f5ef09ecf4cad0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 13:46:19 +0100 Subject: [PATCH 08/13] Add NEWS --- .../Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst b/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst new file mode 100644 index 00000000000000..fe687d6b05a175 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst @@ -0,0 +1,2 @@ +Convert :mod:`array` to use heap types, and establish a global state for +these. From c3dfade9c4558bcadcbc48e97dd0a7c7ab6f2d7a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 14:24:10 +0100 Subject: [PATCH 09/13] Use PyModule_AddType() --- Modules/arraymodule.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a9eca6b7d48459..cc03b107ad5d4e 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3005,9 +3005,7 @@ array_modexec(PyObject *m) } Py_DECREF(res); - Py_INCREF((PyObject *)state->ArrayType); - if (PyModule_AddObject(m, "array", (PyObject *)state->ArrayType) < 0) { - Py_DECREF((PyObject *)state->ArrayType); + if (PyModule_AddType(m, state->ArrayType) < 0) { return -1; } From aa3bd22bb83b2a40cae0f5b44ce552f0db4e5bfa Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 20:12:12 +0100 Subject: [PATCH 10/13] Migrate from global to module state --- Modules/arraymodule.c | 169 +++++++++++++++++++-------------- Modules/clinic/arraymodule.c.h | 123 +++++++++++++++++++----- 2 files changed, 193 insertions(+), 99 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index cc03b107ad5d4e..c3e5f7d420c2ae 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -22,6 +22,7 @@ module array /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/ struct arrayobject; /* Forward */ +static struct PyModuleDef arraymodule; /* All possible arraydescr values are defined in the vector "descriptors" * below. That's defined later because the appropriate get and set @@ -59,15 +60,16 @@ typedef struct { PyTypeObject *ArrayIterType; } array_state; -static array_state global_array_state; - static array_state * -get_array_state() +get_array_state(PyObject *module) { - return &global_array_state; + return (array_state *)PyModule_GetState(module); } -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, get_array_state()->ArrayIterType) +#define get_array_state_by_type(tp) \ + (get_array_state(_PyType_GetModuleByDef(tp, &arraymodule))) +#define get_array_state_by_class(cls) \ + (get_array_state(PyType_GetModule(cls))) enum machine_format_code { UNKNOWN_FORMAT = -1, @@ -115,7 +117,7 @@ enum machine_format_code { */ #include "clinic/arraymodule.c.h" -#define array_Check(op) PyObject_TypeCheck(op, get_array_state()->ArrayType) +#define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -614,10 +616,10 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des } static PyObject * -getarrayitem(PyObject *op, Py_ssize_t i) +getarrayitem(array_state *state, PyObject *op, Py_ssize_t i) { arrayobject *ap; - assert(array_Check(op)); + assert(array_Check(op, state)); ap = (arrayobject *)op; assert(i>=0 && iob_descr->getitem)(ap, i); @@ -671,13 +673,14 @@ array_dealloc(arrayobject *op) static PyObject * array_richcompare(PyObject *v, PyObject *w, int op) { + array_state *state = get_array_state_by_type(Py_TYPE(v)); arrayobject *va, *wa; PyObject *vi = NULL; PyObject *wi = NULL; Py_ssize_t i, k; PyObject *res; - if (!array_Check(v) || !array_Check(w)) + if (!array_Check(v, state) || !array_Check(w, state)) Py_RETURN_NOTIMPLEMENTED; va = (arrayobject *)v; @@ -721,8 +724,8 @@ array_richcompare(PyObject *v, PyObject *w, int op) /* Search for the first index where items are different */ k = 1; for (i = 0; i < Py_SIZE(va) && i < Py_SIZE(wa); i++) { - vi = getarrayitem(v, i); - wi = getarrayitem(w, i); + vi = getarrayitem(state, v, i); + wi = getarrayitem(state, w, i); if (vi == NULL || wi == NULL) { Py_XDECREF(vi); Py_XDECREF(wi); @@ -789,17 +792,21 @@ array_length(arrayobject *a) static PyObject * array_item(arrayobject *a, Py_ssize_t i) { + array_state *state = get_array_state_by_type(Py_TYPE(a)); + if (i < 0 || i >= Py_SIZE(a)) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return NULL; } - return getarrayitem((PyObject *)a, i); + return getarrayitem(state, (PyObject *)a, i); } static PyObject * array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { + array_state *state = get_array_state_by_type(Py_TYPE(a)); arrayobject *np; + if (ilow < 0) ilow = 0; else if (ilow > Py_SIZE(a)) @@ -810,7 +817,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(get_array_state()->ArrayType, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; if (ihigh > ilow) { @@ -853,10 +860,10 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused) static PyObject * array_concat(arrayobject *a, PyObject *bb) { - array_state *state = get_array_state(); + array_state *state = get_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; - if (!array_Check(bb)) { + if (!array_Check(bb, state)) { PyErr_Format(PyExc_TypeError, "can only append array (not \"%.200s\") to array", Py_TYPE(bb)->tp_name); @@ -889,7 +896,7 @@ array_concat(arrayobject *a, PyObject *bb) static PyObject * array_repeat(arrayobject *a, Py_ssize_t n) { - array_state *state = get_array_state(); + array_state *state = get_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; Py_ssize_t oldbytes, newbytes; @@ -970,9 +977,9 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v) } static int -setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v) +setarrayitem(array_state *state, PyObject *a, Py_ssize_t i, PyObject *v) { - assert(array_Check(a)); + assert(array_Check(a, state)); return array_ass_item((arrayobject *)a, i, v); } @@ -1000,11 +1007,11 @@ array_iter_extend(arrayobject *self, PyObject *bb) } static int -array_do_extend(arrayobject *self, PyObject *bb) +array_do_extend(array_state *state, arrayobject *self, PyObject *bb) { Py_ssize_t size, oldsize, bbsize; - if (!array_Check(bb)) + if (!array_Check(bb, state)) return array_iter_extend(self, bb); #define b ((arrayobject *)bb) if (self->ob_descr != b->ob_descr) { @@ -1035,13 +1042,15 @@ array_do_extend(arrayobject *self, PyObject *bb) static PyObject * array_inplace_concat(arrayobject *self, PyObject *bb) { - if (!array_Check(bb)) { + array_state *state = get_array_state_by_type(Py_TYPE(self)); + + if (!array_Check(bb, state)) { PyErr_Format(PyExc_TypeError, "can only extend array with array (not \"%.200s\")", Py_TYPE(bb)->tp_name); return NULL; } - if (array_do_extend(self, bb) == -1) + if (array_do_extend(state, self, bb) == -1) return NULL; Py_INCREF(self); return (PyObject *)self; @@ -1088,6 +1097,7 @@ ins(arrayobject *self, Py_ssize_t where, PyObject *v) /*[clinic input] array.array.count + cls: defining_class v: object / @@ -1095,9 +1105,10 @@ Return number of occurrences of v in the array. [clinic start generated code]*/ static PyObject * -array_array_count(arrayobject *self, PyObject *v) -/*[clinic end generated code: output=3dd3624bf7135a3a input=d9bce9d65e39d1f5]*/ +array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) +/*[clinic end generated code: output=241855185ec96660 input=dfe72cd1f59fb7e8]*/ { + array_state *state = get_array_state_by_class(cls); Py_ssize_t count = 0; Py_ssize_t i; @@ -1105,7 +1116,7 @@ array_array_count(arrayobject *self, PyObject *v) PyObject *selfi; int cmp; - selfi = getarrayitem((PyObject *)self, i); + selfi = getarrayitem(state, (PyObject *)self, i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1122,6 +1133,7 @@ array_array_count(arrayobject *self, PyObject *v) /*[clinic input] array.array.index + cls: defining_class v: object / @@ -1129,16 +1141,17 @@ Return index of first occurrence of v in the array. [clinic start generated code]*/ static PyObject * -array_array_index(arrayobject *self, PyObject *v) -/*[clinic end generated code: output=d48498d325602167 input=cf619898c6649d08]*/ +array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) +/*[clinic end generated code: output=1a14f9773acaa19b input=f5096176943e0366]*/ { + array_state *state = get_array_state_by_class(cls); Py_ssize_t i; for (i = 0; i < Py_SIZE(self); i++) { PyObject *selfi; int cmp; - selfi = getarrayitem((PyObject *)self, i); + selfi = getarrayitem(state, (PyObject *)self, i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1156,11 +1169,12 @@ array_array_index(arrayobject *self, PyObject *v) static int array_contains(arrayobject *self, PyObject *v) { + array_state *state = get_array_state_by_type(Py_TYPE(self)); Py_ssize_t i; int cmp; for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(self); i++) { - PyObject *selfi = getarrayitem((PyObject *)self, i); + PyObject *selfi = getarrayitem(state, (PyObject *)self, i); if (selfi == NULL) return -1; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1172,6 +1186,7 @@ array_contains(arrayobject *self, PyObject *v) /*[clinic input] array.array.remove + cls: defining_class v: object / @@ -1179,16 +1194,17 @@ Remove the first occurrence of v in the array. [clinic start generated code]*/ static PyObject * -array_array_remove(arrayobject *self, PyObject *v) -/*[clinic end generated code: output=bef06be9fdf9dceb input=0b1e5aed25590027]*/ +array_array_remove_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) +/*[clinic end generated code: output=ebaff78df1f62f4d input=c7d793c223b5b32f]*/ { + array_state *state = get_array_state_by_class(cls); Py_ssize_t i; for (i = 0; i < Py_SIZE(self); i++) { PyObject *selfi; int cmp; - selfi = getarrayitem((PyObject *)self,i); + selfi = getarrayitem(state, (PyObject *)self,i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1208,6 +1224,7 @@ array_array_remove(arrayobject *self, PyObject *v) /*[clinic input] array.array.pop + cls: defining_class i: Py_ssize_t = -1 / @@ -1217,9 +1234,10 @@ i defaults to -1. [clinic start generated code]*/ static PyObject * -array_array_pop_impl(arrayobject *self, Py_ssize_t i) -/*[clinic end generated code: output=bc1f0c54fe5308e4 input=8e5feb4c1a11cd44]*/ +array_array_pop_impl(arrayobject *self, PyTypeObject *cls, Py_ssize_t i) +/*[clinic end generated code: output=21f64a81d0509c1d input=412909f4b0eea987]*/ { + array_state *state = get_array_state_by_class(cls); PyObject *v; if (Py_SIZE(self) == 0) { @@ -1233,7 +1251,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i) PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } - v = getarrayitem((PyObject *)self, i); + v = getarrayitem(state, (PyObject *)self, i); if (v == NULL) return NULL; if (array_del_slice(self, i, i+1) != 0) { @@ -1246,6 +1264,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i) /*[clinic input] array.array.extend + cls: defining_class bb: object / @@ -1253,10 +1272,12 @@ Append items to the end of the array. [clinic start generated code]*/ static PyObject * -array_array_extend(arrayobject *self, PyObject *bb) -/*[clinic end generated code: output=bbddbc8e8bef871d input=43be86aba5c31e44]*/ +array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb) +/*[clinic end generated code: output=e65eb7588f0bc266 input=8eb6817ec4d2cb62]*/ { - if (array_do_extend(self, bb) == -1) + array_state *state = get_array_state_by_class(cls); + + if (array_do_extend(state, self, bb) == -1) return NULL; Py_RETURN_NONE; } @@ -1579,13 +1600,14 @@ static PyObject * array_array_tolist_impl(arrayobject *self) /*[clinic end generated code: output=00b60cc9eab8ef89 input=a8d7784a94f86b53]*/ { + array_state *state = get_array_state_by_type(Py_TYPE(self)); PyObject *list = PyList_New(Py_SIZE(self)); Py_ssize_t i; if (list == NULL) return NULL; for (i = 0; i < Py_SIZE(self); i++) { - PyObject *v = getarrayitem((PyObject *)self, i); + PyObject *v = getarrayitem(state, (PyObject *)self, i); if (v == NULL) goto error; PyList_SET_ITEM(list, i, v); @@ -1942,7 +1964,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, PyObject *items) /*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/ { - array_state *state = get_array_state(); + array_state *state = get_array_state(module); PyObject *converted_items; PyObject *result; const struct arraydescr *descr; @@ -2302,7 +2324,7 @@ array_repr(arrayobject *a) static PyObject* array_subscr(arrayobject* self, PyObject* item) { - array_state *state = get_array_state(); + array_state *state = get_array_state_by_type(Py_TYPE(self)); if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); @@ -2366,6 +2388,7 @@ static int array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) { Py_ssize_t start, stop, step, slicelength, needed; + array_state* state = get_array_state_by_type(Py_TYPE(self)); arrayobject* other; int itemsize; @@ -2407,7 +2430,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) other = NULL; needed = 0; } - else if (array_Check(value)) { + else if (array_Check(value, state)) { other = (arrayobject *)value; needed = Py_SIZE(other); if (self == other) { @@ -2572,7 +2595,7 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view) static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - array_state *state = get_array_state(); + array_state *state = get_array_state_by_type(type); int c; PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; @@ -2594,7 +2617,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) "an array with typecode '%c'", c); return NULL; } - else if (array_Check(initial) && + else if (array_Check(initial, state) && ((arrayobject*)initial)->ob_descr->typecode == 'u') { PyErr_Format(PyExc_TypeError, "cannot use a unicode array to " "initialize an array with typecode '%c'", c); @@ -2607,7 +2630,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) || PyBytes_Check(initial) || PyTuple_Check(initial) || ((c=='u') && PyUnicode_Check(initial)) - || (array_Check(initial) + || (array_Check(initial, state) && c == ((arrayobject*)initial)->ob_descr->typecode))) { it = PyObject_GetIter(initial); if (it == NULL) @@ -2628,7 +2651,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) len = 0; else if (PyList_Check(initial)) len = PyList_GET_SIZE(initial); - else if (PyTuple_Check(initial) || array_Check(initial)) + else if (PyTuple_Check(initial) || array_Check(initial, state)) len = Py_SIZE(initial); else len = 0; @@ -2637,7 +2660,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (a == NULL) return NULL; - if (len > 0 && !array_Check(initial)) { + if (len > 0 && !array_Check(initial, state)) { Py_ssize_t i; for (i = 0; i < len; i++) { PyObject *v = @@ -2646,7 +2669,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(a); return NULL; } - if (setarrayitem(a, i, v) != 0) { + if (setarrayitem(state, a, i, v) != 0) { Py_DECREF(v); Py_DECREF(a); return NULL; @@ -2682,7 +2705,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->allocated = n; } } - else if (initial != NULL && array_Check(initial) && len > 0) { + else if (initial != NULL && array_Check(initial, state) && len > 0) { arrayobject *self = (arrayobject *)a; arrayobject *other = (arrayobject *)initial; memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize); @@ -2822,17 +2845,17 @@ static PyType_Spec array_spec = { /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "get_array_state()->ArrayIterType" +class array.arrayiterator "arrayiterobject *" "get_array_state_by_type(type)->ArrayIterType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=91c83ed82b09b941]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c7271f8f61b69ef9]*/ static PyObject * array_iter(arrayobject *ao) { - array_state *state = get_array_state(); + array_state *state = get_array_state_by_type(Py_TYPE(ao)); arrayiterobject *it; - if (!array_Check(ao)) { + if (!array_Check(ao, state)) { PyErr_BadInternalCall(); return NULL; } @@ -2852,15 +2875,16 @@ array_iter(arrayobject *ao) static PyObject * arrayiter_next(arrayiterobject *it) { + array_state *state = get_array_state_by_type(Py_TYPE(it)); arrayobject *ao; assert(it != NULL); - assert(PyArrayIter_Check(it)); + assert(PyObject_TypeCheck(it, state->ArrayIterType)); ao = it->ao; if (ao == NULL) { return NULL; } - assert(array_Check(ao)); + assert(array_Check(ao, state)); if (it->index < Py_SIZE(ao)) { return (*it->getitem)(ao, it->index++); } @@ -2961,22 +2985,24 @@ static PyMethodDef a_methods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; +#define CREATE_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(m, spec, NULL); \ + if (type == NULL) { \ + return -1; \ + } \ +} while (0) + static int array_modexec(PyObject *m) { - array_state *state = get_array_state(); + array_state *state = get_array_state(m); char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; const struct arraydescr *descr; - state->ArrayType = (PyTypeObject *)PyType_FromModuleAndSpec(m, &array_spec, NULL); - if (state->ArrayType == NULL) - return -1; - state->ArrayIterType = (PyTypeObject *)PyType_FromModuleAndSpec(m, - &arrayiter_spec, - NULL); - if (state->ArrayIterType == NULL) - return -1; + CREATE_TYPE(m, state->ArrayType, &array_spec); + CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec); Py_SET_TYPE(state->ArrayIterType, &PyType_Type); Py_INCREF((PyObject *)state->ArrayType); @@ -3029,15 +3055,12 @@ static PyModuleDef_Slot arrayslots[] = { static struct PyModuleDef arraymodule = { - PyModuleDef_HEAD_INIT, - "array", - module_doc, - 0, - a_methods, - arrayslots, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "array", + .m_size = sizeof(array_state), + .m_doc = module_doc, + .m_methods = a_methods, + .m_slots = arrayslots, }; diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 300cd1397101e8..4c95fca31d47f7 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -36,7 +36,28 @@ PyDoc_STRVAR(array_array_count__doc__, "Return number of occurrences of v in the array."); #define ARRAY_ARRAY_COUNT_METHODDEF \ - {"count", (PyCFunction)array_array_count, METH_O, array_array_count__doc__}, + {"count", (PyCFunction)(void(*)(void))array_array_count, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_count__doc__}, + +static PyObject * +array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); + +static PyObject * +array_array_count(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:count", _keywords, 0}; + PyObject *v; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &v)) { + goto exit; + } + return_value = array_array_count_impl(self, cls, v); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_index__doc__, "index($self, v, /)\n" @@ -45,7 +66,28 @@ PyDoc_STRVAR(array_array_index__doc__, "Return index of first occurrence of v in the array."); #define ARRAY_ARRAY_INDEX_METHODDEF \ - {"index", (PyCFunction)array_array_index, METH_O, array_array_index__doc__}, + {"index", (PyCFunction)(void(*)(void))array_array_index, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_index__doc__}, + +static PyObject * +array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); + +static PyObject * +array_array_index(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:index", _keywords, 0}; + PyObject *v; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &v)) { + goto exit; + } + return_value = array_array_index_impl(self, cls, v); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_remove__doc__, "remove($self, v, /)\n" @@ -54,7 +96,28 @@ PyDoc_STRVAR(array_array_remove__doc__, "Remove the first occurrence of v in the array."); #define ARRAY_ARRAY_REMOVE_METHODDEF \ - {"remove", (PyCFunction)array_array_remove, METH_O, array_array_remove__doc__}, + {"remove", (PyCFunction)(void(*)(void))array_array_remove, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_remove__doc__}, + +static PyObject * +array_array_remove_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); + +static PyObject * +array_array_remove(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:remove", _keywords, 0}; + PyObject *v; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &v)) { + goto exit; + } + return_value = array_array_remove_impl(self, cls, v); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_pop__doc__, "pop($self, i=-1, /)\n" @@ -65,37 +128,24 @@ PyDoc_STRVAR(array_array_pop__doc__, "i defaults to -1."); #define ARRAY_ARRAY_POP_METHODDEF \ - {"pop", (PyCFunction)(void(*)(void))array_array_pop, METH_FASTCALL, array_array_pop__doc__}, + {"pop", (PyCFunction)(void(*)(void))array_array_pop, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_pop__doc__}, static PyObject * -array_array_pop_impl(arrayobject *self, Py_ssize_t i); +array_array_pop_impl(arrayobject *self, PyTypeObject *cls, Py_ssize_t i); static PyObject * -array_array_pop(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) +array_array_pop(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"|n:pop", _keywords, 0}; Py_ssize_t i = -1; - if (!_PyArg_CheckPositional("pop", nargs, 0, 1)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &i)) { goto exit; } - if (nargs < 1) { - goto skip_optional; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[0]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - i = ival; - } -skip_optional: - return_value = array_array_pop_impl(self, i); + return_value = array_array_pop_impl(self, cls, i); exit: return return_value; @@ -108,7 +158,28 @@ PyDoc_STRVAR(array_array_extend__doc__, "Append items to the end of the array."); #define ARRAY_ARRAY_EXTEND_METHODDEF \ - {"extend", (PyCFunction)array_array_extend, METH_O, array_array_extend__doc__}, + {"extend", (PyCFunction)(void(*)(void))array_array_extend, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_extend__doc__}, + +static PyObject * +array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb); + +static PyObject * +array_array_extend(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:extend", _keywords, 0}; + PyObject *bb; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &bb)) { + goto exit; + } + return_value = array_array_extend_impl(self, cls, bb); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_insert__doc__, "insert($self, i, v, /)\n" @@ -514,4 +585,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=91c1cded65a1285f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f98c6e141a9a5dcf input=a9049054013a1b77]*/ From 656c5d070f52937933d1dc8eb93993d4030ad290 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 23:35:31 +0100 Subject: [PATCH 11/13] Fix NEWS --- .../Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst b/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst index fe687d6b05a175..40c5511e321334 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2020-11-03-13-46-10.bpo-40077.NfAIdj.rst @@ -1,2 +1 @@ -Convert :mod:`array` to use heap types, and establish a global state for -these. +Convert :mod:`array` to use heap types, and establish module state for these. From 72434ad4651695948a08d71034f5696f3556883c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 4 Nov 2020 22:42:28 +0100 Subject: [PATCH 12/13] Address review comment: adjust naming to reflect time complexity --- Modules/arraymodule.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index c3e5f7d420c2ae..c7fc61d0309a29 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -66,7 +66,7 @@ get_array_state(PyObject *module) return (array_state *)PyModule_GetState(module); } -#define get_array_state_by_type(tp) \ +#define find_array_state_by_type(tp) \ (get_array_state(_PyType_GetModuleByDef(tp, &arraymodule))) #define get_array_state_by_class(cls) \ (get_array_state(PyType_GetModule(cls))) @@ -673,7 +673,7 @@ array_dealloc(arrayobject *op) static PyObject * array_richcompare(PyObject *v, PyObject *w, int op) { - array_state *state = get_array_state_by_type(Py_TYPE(v)); + array_state *state = find_array_state_by_type(Py_TYPE(v)); arrayobject *va, *wa; PyObject *vi = NULL; PyObject *wi = NULL; @@ -792,7 +792,7 @@ array_length(arrayobject *a) static PyObject * array_item(arrayobject *a, Py_ssize_t i) { - array_state *state = get_array_state_by_type(Py_TYPE(a)); + array_state *state = find_array_state_by_type(Py_TYPE(a)); if (i < 0 || i >= Py_SIZE(a)) { PyErr_SetString(PyExc_IndexError, "array index out of range"); @@ -804,7 +804,7 @@ array_item(arrayobject *a, Py_ssize_t i) static PyObject * array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { - array_state *state = get_array_state_by_type(Py_TYPE(a)); + array_state *state = find_array_state_by_type(Py_TYPE(a)); arrayobject *np; if (ilow < 0) @@ -860,7 +860,7 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused) static PyObject * array_concat(arrayobject *a, PyObject *bb) { - array_state *state = get_array_state_by_type(Py_TYPE(a)); + array_state *state = find_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; if (!array_Check(bb, state)) { @@ -896,7 +896,7 @@ array_concat(arrayobject *a, PyObject *bb) static PyObject * array_repeat(arrayobject *a, Py_ssize_t n) { - array_state *state = get_array_state_by_type(Py_TYPE(a)); + array_state *state = find_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; Py_ssize_t oldbytes, newbytes; @@ -1042,7 +1042,7 @@ array_do_extend(array_state *state, arrayobject *self, PyObject *bb) static PyObject * array_inplace_concat(arrayobject *self, PyObject *bb) { - array_state *state = get_array_state_by_type(Py_TYPE(self)); + array_state *state = find_array_state_by_type(Py_TYPE(self)); if (!array_Check(bb, state)) { PyErr_Format(PyExc_TypeError, @@ -1169,7 +1169,7 @@ array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) static int array_contains(arrayobject *self, PyObject *v) { - array_state *state = get_array_state_by_type(Py_TYPE(self)); + array_state *state = find_array_state_by_type(Py_TYPE(self)); Py_ssize_t i; int cmp; @@ -1600,7 +1600,7 @@ static PyObject * array_array_tolist_impl(arrayobject *self) /*[clinic end generated code: output=00b60cc9eab8ef89 input=a8d7784a94f86b53]*/ { - array_state *state = get_array_state_by_type(Py_TYPE(self)); + array_state *state = find_array_state_by_type(Py_TYPE(self)); PyObject *list = PyList_New(Py_SIZE(self)); Py_ssize_t i; @@ -2324,7 +2324,7 @@ array_repr(arrayobject *a) static PyObject* array_subscr(arrayobject* self, PyObject* item) { - array_state *state = get_array_state_by_type(Py_TYPE(self)); + array_state *state = find_array_state_by_type(Py_TYPE(self)); if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); @@ -2388,7 +2388,7 @@ static int array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) { Py_ssize_t start, stop, step, slicelength, needed; - array_state* state = get_array_state_by_type(Py_TYPE(self)); + array_state* state = find_array_state_by_type(Py_TYPE(self)); arrayobject* other; int itemsize; @@ -2595,7 +2595,7 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view) static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - array_state *state = get_array_state_by_type(type); + array_state *state = find_array_state_by_type(type); int c; PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; @@ -2845,14 +2845,14 @@ static PyType_Spec array_spec = { /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "get_array_state_by_type(type)->ArrayIterType" +class array.arrayiterator "arrayiterobject *" "find_array_state_by_type(type)->ArrayIterType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c7271f8f61b69ef9]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fb46d5ef98dd95ff]*/ static PyObject * array_iter(arrayobject *ao) { - array_state *state = get_array_state_by_type(Py_TYPE(ao)); + array_state *state = find_array_state_by_type(Py_TYPE(ao)); arrayiterobject *it; if (!array_Check(ao, state)) { @@ -2875,7 +2875,7 @@ array_iter(arrayobject *ao) static PyObject * arrayiter_next(arrayiterobject *it) { - array_state *state = get_array_state_by_type(Py_TYPE(it)); + array_state *state = find_array_state_by_type(Py_TYPE(it)); arrayobject *ao; assert(it != NULL); From f8649699eac6673497be01c4a986f2fc1d144f20 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 30 Dec 2020 12:30:55 +0100 Subject: [PATCH 13/13] Address review: Wrap state exclusively used in asserts in #ifndef NDEBUG --- Modules/arraymodule.c | 66 +++++++++++----------- Modules/clinic/arraymodule.c.h | 100 +++++++++------------------------ 2 files changed, 57 insertions(+), 109 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 8c0a01695311bf..12bd51705579bd 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -616,10 +616,13 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des } static PyObject * -getarrayitem(array_state *state, PyObject *op, Py_ssize_t i) +getarrayitem(PyObject *op, Py_ssize_t i) { - arrayobject *ap; +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(op)); assert(array_Check(op, state)); +#endif + arrayobject *ap; ap = (arrayobject *)op; assert(i>=0 && iob_descr->getitem)(ap, i); @@ -724,8 +727,8 @@ array_richcompare(PyObject *v, PyObject *w, int op) /* Search for the first index where items are different */ k = 1; for (i = 0; i < Py_SIZE(va) && i < Py_SIZE(wa); i++) { - vi = getarrayitem(state, v, i); - wi = getarrayitem(state, w, i); + vi = getarrayitem(v, i); + wi = getarrayitem(w, i); if (vi == NULL || wi == NULL) { Py_XDECREF(vi); Py_XDECREF(wi); @@ -792,13 +795,11 @@ array_length(arrayobject *a) static PyObject * array_item(arrayobject *a, Py_ssize_t i) { - array_state *state = find_array_state_by_type(Py_TYPE(a)); - if (i < 0 || i >= Py_SIZE(a)) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return NULL; } - return getarrayitem(state, (PyObject *)a, i); + return getarrayitem((PyObject *)a, i); } static PyObject * @@ -977,9 +978,12 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v) } static int -setarrayitem(array_state *state, PyObject *a, Py_ssize_t i, PyObject *v) +setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v) { +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(a)); assert(array_Check(a, state)); +#endif return array_ass_item((arrayobject *)a, i, v); } @@ -1097,7 +1101,6 @@ ins(arrayobject *self, Py_ssize_t where, PyObject *v) /*[clinic input] array.array.count - cls: defining_class v: object / @@ -1105,10 +1108,9 @@ Return number of occurrences of v in the array. [clinic start generated code]*/ static PyObject * -array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) -/*[clinic end generated code: output=241855185ec96660 input=dfe72cd1f59fb7e8]*/ +array_array_count(arrayobject *self, PyObject *v) +/*[clinic end generated code: output=3dd3624bf7135a3a input=d9bce9d65e39d1f5]*/ { - array_state *state = get_array_state_by_class(cls); Py_ssize_t count = 0; Py_ssize_t i; @@ -1116,7 +1118,7 @@ array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) PyObject *selfi; int cmp; - selfi = getarrayitem(state, (PyObject *)self, i); + selfi = getarrayitem((PyObject *)self, i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1133,7 +1135,6 @@ array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) /*[clinic input] array.array.index - cls: defining_class v: object / @@ -1141,17 +1142,16 @@ Return index of first occurrence of v in the array. [clinic start generated code]*/ static PyObject * -array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) -/*[clinic end generated code: output=1a14f9773acaa19b input=f5096176943e0366]*/ +array_array_index(arrayobject *self, PyObject *v) +/*[clinic end generated code: output=d48498d325602167 input=cf619898c6649d08]*/ { - array_state *state = get_array_state_by_class(cls); Py_ssize_t i; for (i = 0; i < Py_SIZE(self); i++) { PyObject *selfi; int cmp; - selfi = getarrayitem(state, (PyObject *)self, i); + selfi = getarrayitem((PyObject *)self, i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1169,12 +1169,11 @@ array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) static int array_contains(arrayobject *self, PyObject *v) { - array_state *state = find_array_state_by_type(Py_TYPE(self)); Py_ssize_t i; int cmp; for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(self); i++) { - PyObject *selfi = getarrayitem(state, (PyObject *)self, i); + PyObject *selfi = getarrayitem((PyObject *)self, i); if (selfi == NULL) return -1; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1186,7 +1185,6 @@ array_contains(arrayobject *self, PyObject *v) /*[clinic input] array.array.remove - cls: defining_class v: object / @@ -1194,17 +1192,16 @@ Remove the first occurrence of v in the array. [clinic start generated code]*/ static PyObject * -array_array_remove_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) -/*[clinic end generated code: output=ebaff78df1f62f4d input=c7d793c223b5b32f]*/ +array_array_remove(arrayobject *self, PyObject *v) +/*[clinic end generated code: output=bef06be9fdf9dceb input=0b1e5aed25590027]*/ { - array_state *state = get_array_state_by_class(cls); Py_ssize_t i; for (i = 0; i < Py_SIZE(self); i++) { PyObject *selfi; int cmp; - selfi = getarrayitem(state, (PyObject *)self,i); + selfi = getarrayitem((PyObject *)self,i); if (selfi == NULL) return NULL; cmp = PyObject_RichCompareBool(selfi, v, Py_EQ); @@ -1224,7 +1221,6 @@ array_array_remove_impl(arrayobject *self, PyTypeObject *cls, PyObject *v) /*[clinic input] array.array.pop - cls: defining_class i: Py_ssize_t = -1 / @@ -1234,10 +1230,9 @@ i defaults to -1. [clinic start generated code]*/ static PyObject * -array_array_pop_impl(arrayobject *self, PyTypeObject *cls, Py_ssize_t i) -/*[clinic end generated code: output=21f64a81d0509c1d input=412909f4b0eea987]*/ +array_array_pop_impl(arrayobject *self, Py_ssize_t i) +/*[clinic end generated code: output=bc1f0c54fe5308e4 input=8e5feb4c1a11cd44]*/ { - array_state *state = get_array_state_by_class(cls); PyObject *v; if (Py_SIZE(self) == 0) { @@ -1251,7 +1246,7 @@ array_array_pop_impl(arrayobject *self, PyTypeObject *cls, Py_ssize_t i) PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } - v = getarrayitem(state, (PyObject *)self, i); + v = getarrayitem((PyObject *)self, i); if (v == NULL) return NULL; if (array_del_slice(self, i, i+1) != 0) { @@ -1600,14 +1595,13 @@ static PyObject * array_array_tolist_impl(arrayobject *self) /*[clinic end generated code: output=00b60cc9eab8ef89 input=a8d7784a94f86b53]*/ { - array_state *state = find_array_state_by_type(Py_TYPE(self)); PyObject *list = PyList_New(Py_SIZE(self)); Py_ssize_t i; if (list == NULL) return NULL; for (i = 0; i < Py_SIZE(self); i++) { - PyObject *v = getarrayitem(state, (PyObject *)self, i); + PyObject *v = getarrayitem((PyObject *)self, i); if (v == NULL) goto error; PyList_SET_ITEM(list, i, v); @@ -2669,7 +2663,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(a); return NULL; } - if (setarrayitem(state, a, i, v) != 0) { + if (setarrayitem(a, i, v) != 0) { Py_DECREF(v); Py_DECREF(a); return NULL; @@ -2875,16 +2869,20 @@ array_iter(arrayobject *ao) static PyObject * arrayiter_next(arrayiterobject *it) { - array_state *state = find_array_state_by_type(Py_TYPE(it)); arrayobject *ao; assert(it != NULL); +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(it)); assert(PyObject_TypeCheck(it, state->ArrayIterType)); +#endif ao = it->ao; if (ao == NULL) { return NULL; } +#ifndef NDEBUG assert(array_Check(ao, state)); +#endif if (it->index < Py_SIZE(ao)) { return (*it->getitem)(ao, it->index++); } diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 4c95fca31d47f7..d0b70c46ff5707 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -36,28 +36,7 @@ PyDoc_STRVAR(array_array_count__doc__, "Return number of occurrences of v in the array."); #define ARRAY_ARRAY_COUNT_METHODDEF \ - {"count", (PyCFunction)(void(*)(void))array_array_count, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_count__doc__}, - -static PyObject * -array_array_count_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); - -static PyObject * -array_array_count(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"", NULL}; - static _PyArg_Parser _parser = {"O:count", _keywords, 0}; - PyObject *v; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &v)) { - goto exit; - } - return_value = array_array_count_impl(self, cls, v); - -exit: - return return_value; -} + {"count", (PyCFunction)array_array_count, METH_O, array_array_count__doc__}, PyDoc_STRVAR(array_array_index__doc__, "index($self, v, /)\n" @@ -66,28 +45,7 @@ PyDoc_STRVAR(array_array_index__doc__, "Return index of first occurrence of v in the array."); #define ARRAY_ARRAY_INDEX_METHODDEF \ - {"index", (PyCFunction)(void(*)(void))array_array_index, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_index__doc__}, - -static PyObject * -array_array_index_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); - -static PyObject * -array_array_index(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"", NULL}; - static _PyArg_Parser _parser = {"O:index", _keywords, 0}; - PyObject *v; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &v)) { - goto exit; - } - return_value = array_array_index_impl(self, cls, v); - -exit: - return return_value; -} + {"index", (PyCFunction)array_array_index, METH_O, array_array_index__doc__}, PyDoc_STRVAR(array_array_remove__doc__, "remove($self, v, /)\n" @@ -96,28 +54,7 @@ PyDoc_STRVAR(array_array_remove__doc__, "Remove the first occurrence of v in the array."); #define ARRAY_ARRAY_REMOVE_METHODDEF \ - {"remove", (PyCFunction)(void(*)(void))array_array_remove, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_remove__doc__}, - -static PyObject * -array_array_remove_impl(arrayobject *self, PyTypeObject *cls, PyObject *v); - -static PyObject * -array_array_remove(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"", NULL}; - static _PyArg_Parser _parser = {"O:remove", _keywords, 0}; - PyObject *v; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &v)) { - goto exit; - } - return_value = array_array_remove_impl(self, cls, v); - -exit: - return return_value; -} + {"remove", (PyCFunction)array_array_remove, METH_O, array_array_remove__doc__}, PyDoc_STRVAR(array_array_pop__doc__, "pop($self, i=-1, /)\n" @@ -128,24 +65,37 @@ PyDoc_STRVAR(array_array_pop__doc__, "i defaults to -1."); #define ARRAY_ARRAY_POP_METHODDEF \ - {"pop", (PyCFunction)(void(*)(void))array_array_pop, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_pop__doc__}, + {"pop", (PyCFunction)(void(*)(void))array_array_pop, METH_FASTCALL, array_array_pop__doc__}, static PyObject * -array_array_pop_impl(arrayobject *self, PyTypeObject *cls, Py_ssize_t i); +array_array_pop_impl(arrayobject *self, Py_ssize_t i); static PyObject * -array_array_pop(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +array_array_pop(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"", NULL}; - static _PyArg_Parser _parser = {"|n:pop", _keywords, 0}; Py_ssize_t i = -1; - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &i)) { + if (!_PyArg_CheckPositional("pop", nargs, 0, 1)) { goto exit; } - return_value = array_array_pop_impl(self, cls, i); + if (nargs < 1) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + i = ival; + } +skip_optional: + return_value = array_array_pop_impl(self, i); exit: return return_value; @@ -585,4 +535,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=f98c6e141a9a5dcf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a7f71a18b994c88f input=a9049054013a1b77]*/