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]*/ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy