bpo-40077: Convert arraymodule to use heap types and establish module state (GH-23124)

This commit is contained in:
Erlend Egeberg Aasland 2021-01-02 17:38:47 +01:00 committed by GitHub
parent 49cd68fb1e
commit 75bf107c62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 196 additions and 159 deletions

View File

@ -0,0 +1 @@
Convert :mod:`array` to use heap types, and establish module state for these.

View File

@ -5,6 +5,7 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "Python.h" #include "Python.h"
#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof() #include <stddef.h> // offsetof()
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
@ -21,6 +22,7 @@ module array
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/
struct arrayobject; /* Forward */ struct arrayobject; /* Forward */
static struct PyModuleDef arraymodule;
/* All possible arraydescr values are defined in the vector "descriptors" /* All possible arraydescr values are defined in the vector "descriptors"
* below. That's defined later because the appropriate get and set * below. That's defined later because the appropriate get and set
@ -46,8 +48,6 @@ typedef struct arrayobject {
Py_ssize_t ob_exports; /* Number of exported buffers */ Py_ssize_t ob_exports; /* Number of exported buffers */
} arrayobject; } arrayobject;
static PyTypeObject Arraytype;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
Py_ssize_t index; Py_ssize_t index;
@ -55,9 +55,21 @@ typedef struct {
PyObject* (*getitem)(struct arrayobject *, Py_ssize_t); PyObject* (*getitem)(struct arrayobject *, Py_ssize_t);
} arrayiterobject; } arrayiterobject;
static PyTypeObject PyArrayIter_Type; typedef struct {
PyTypeObject *ArrayType;
PyTypeObject *ArrayIterType;
} array_state;
#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type) static array_state *
get_array_state(PyObject *module)
{
return (array_state *)PyModule_GetState(module);
}
#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)))
enum machine_format_code { enum machine_format_code {
UNKNOWN_FORMAT = -1, UNKNOWN_FORMAT = -1,
@ -105,8 +117,7 @@ enum machine_format_code {
*/ */
#include "clinic/arraymodule.c.h" #include "clinic/arraymodule.c.h"
#define array_Check(op) PyObject_TypeCheck(op, &Arraytype) #define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType)
#define array_CheckExact(op) Py_IS_TYPE(op, &Arraytype)
static int static int
array_resize(arrayobject *self, Py_ssize_t newsize) array_resize(arrayobject *self, Py_ssize_t newsize)
@ -562,9 +573,9 @@ static const struct arraydescr descriptors[] = {
Implementations of array object methods. Implementations of array object methods.
****************************************************************************/ ****************************************************************************/
/*[clinic input] /*[clinic input]
class array.array "arrayobject *" "&Arraytype" class array.array "arrayobject *" "ArrayType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5c29edf59f176a3]*/
static PyObject * static PyObject *
newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr) newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr)
@ -607,8 +618,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des
static PyObject * static PyObject *
getarrayitem(PyObject *op, Py_ssize_t i) getarrayitem(PyObject *op, Py_ssize_t i)
{ {
#ifndef NDEBUG
array_state *state = find_array_state_by_type(Py_TYPE(op));
assert(array_Check(op, state));
#endif
arrayobject *ap; arrayobject *ap;
assert(array_Check(op));
ap = (arrayobject *)op; ap = (arrayobject *)op;
assert(i>=0 && i<Py_SIZE(ap)); assert(i>=0 && i<Py_SIZE(ap));
return (*ap->ob_descr->getitem)(ap, i); return (*ap->ob_descr->getitem)(ap, i);
@ -649,23 +663,27 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v)
static void static void
array_dealloc(arrayobject *op) array_dealloc(arrayobject *op)
{ {
PyTypeObject *tp = Py_TYPE(op);
if (op->weakreflist != NULL) if (op->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) op); PyObject_ClearWeakRefs((PyObject *) op);
if (op->ob_item != NULL) if (op->ob_item != NULL)
PyMem_Free(op->ob_item); PyMem_Free(op->ob_item);
Py_TYPE(op)->tp_free((PyObject *)op); tp->tp_free(op);
Py_DECREF(tp);
} }
static PyObject * static PyObject *
array_richcompare(PyObject *v, PyObject *w, int op) array_richcompare(PyObject *v, PyObject *w, int op)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(v));
arrayobject *va, *wa; arrayobject *va, *wa;
PyObject *vi = NULL; PyObject *vi = NULL;
PyObject *wi = NULL; PyObject *wi = NULL;
Py_ssize_t i, k; Py_ssize_t i, k;
PyObject *res; PyObject *res;
if (!array_Check(v) || !array_Check(w)) if (!array_Check(v, state) || !array_Check(w, state))
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
va = (arrayobject *)v; va = (arrayobject *)v;
@ -787,7 +805,9 @@ array_item(arrayobject *a, Py_ssize_t i)
static PyObject * static PyObject *
array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(a));
arrayobject *np; arrayobject *np;
if (ilow < 0) if (ilow < 0)
ilow = 0; ilow = 0;
else if (ilow > Py_SIZE(a)) else if (ilow > Py_SIZE(a))
@ -798,7 +818,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
ihigh = ilow; ihigh = ilow;
else if (ihigh > Py_SIZE(a)) else if (ihigh > Py_SIZE(a))
ihigh = Py_SIZE(a); ihigh = Py_SIZE(a);
np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr); np = (arrayobject *) newarrayobject(state->ArrayType, ihigh - ilow, a->ob_descr);
if (np == NULL) if (np == NULL)
return NULL; return NULL;
if (ihigh > ilow) { if (ihigh > ilow) {
@ -841,9 +861,10 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused)
static PyObject * static PyObject *
array_concat(arrayobject *a, PyObject *bb) array_concat(arrayobject *a, PyObject *bb)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(a));
Py_ssize_t size; Py_ssize_t size;
arrayobject *np; arrayobject *np;
if (!array_Check(bb)) { if (!array_Check(bb, state)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can only append array (not \"%.200s\") to array", "can only append array (not \"%.200s\") to array",
Py_TYPE(bb)->tp_name); Py_TYPE(bb)->tp_name);
@ -858,7 +879,7 @@ array_concat(arrayobject *a, PyObject *bb)
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
size = Py_SIZE(a) + Py_SIZE(b); size = Py_SIZE(a) + Py_SIZE(b);
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
if (np == NULL) { if (np == NULL) {
return NULL; return NULL;
} }
@ -876,6 +897,7 @@ array_concat(arrayobject *a, PyObject *bb)
static PyObject * static PyObject *
array_repeat(arrayobject *a, Py_ssize_t n) array_repeat(arrayobject *a, Py_ssize_t n)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(a));
Py_ssize_t size; Py_ssize_t size;
arrayobject *np; arrayobject *np;
Py_ssize_t oldbytes, newbytes; Py_ssize_t oldbytes, newbytes;
@ -885,7 +907,7 @@ array_repeat(arrayobject *a, Py_ssize_t n)
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
size = Py_SIZE(a) * n; size = Py_SIZE(a) * n;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
if (np == NULL) if (np == NULL)
return NULL; return NULL;
if (size == 0) if (size == 0)
@ -958,7 +980,10 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v)
static int static int
setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v) setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v)
{ {
assert(array_Check(a)); #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); return array_ass_item((arrayobject *)a, i, v);
} }
@ -986,11 +1011,11 @@ array_iter_extend(arrayobject *self, PyObject *bb)
} }
static int 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; Py_ssize_t size, oldsize, bbsize;
if (!array_Check(bb)) if (!array_Check(bb, state))
return array_iter_extend(self, bb); return array_iter_extend(self, bb);
#define b ((arrayobject *)bb) #define b ((arrayobject *)bb)
if (self->ob_descr != b->ob_descr) { if (self->ob_descr != b->ob_descr) {
@ -1021,13 +1046,15 @@ array_do_extend(arrayobject *self, PyObject *bb)
static PyObject * static PyObject *
array_inplace_concat(arrayobject *self, PyObject *bb) array_inplace_concat(arrayobject *self, PyObject *bb)
{ {
if (!array_Check(bb)) { array_state *state = find_array_state_by_type(Py_TYPE(self));
if (!array_Check(bb, state)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can only extend array with array (not \"%.200s\")", "can only extend array with array (not \"%.200s\")",
Py_TYPE(bb)->tp_name); Py_TYPE(bb)->tp_name);
return NULL; return NULL;
} }
if (array_do_extend(self, bb) == -1) if (array_do_extend(state, self, bb) == -1)
return NULL; return NULL;
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
@ -1232,6 +1259,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i)
/*[clinic input] /*[clinic input]
array.array.extend array.array.extend
cls: defining_class
bb: object bb: object
/ /
@ -1239,10 +1267,12 @@ Append items to the end of the array.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
array_array_extend(arrayobject *self, PyObject *bb) array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb)
/*[clinic end generated code: output=bbddbc8e8bef871d input=43be86aba5c31e44]*/ /*[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; return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -1928,6 +1958,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
PyObject *items) PyObject *items)
/*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/ /*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/
{ {
array_state *state = get_array_state(module);
PyObject *converted_items; PyObject *converted_items;
PyObject *result; PyObject *result;
const struct arraydescr *descr; const struct arraydescr *descr;
@ -1938,10 +1969,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
Py_TYPE(arraytype)->tp_name); Py_TYPE(arraytype)->tp_name);
return NULL; return NULL;
} }
if (!PyType_IsSubtype(arraytype, &Arraytype)) { if (!PyType_IsSubtype(arraytype, state->ArrayType)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s is not a subtype of %.200s", "%.200s is not a subtype of %.200s",
arraytype->tp_name, Arraytype.tp_name); arraytype->tp_name, state->ArrayType->tp_name);
return NULL; return NULL;
} }
for (descr = descriptors; descr->typecode != '\0'; descr++) { for (descr = descriptors; descr->typecode != '\0'; descr++) {
@ -2287,6 +2318,8 @@ array_repr(arrayobject *a)
static PyObject* static PyObject*
array_subscr(arrayobject* self, PyObject* item) array_subscr(arrayobject* self, PyObject* item)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(self));
if (PyIndex_Check(item)) { if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i==-1 && PyErr_Occurred()) { if (i==-1 && PyErr_Occurred()) {
@ -2310,10 +2343,10 @@ array_subscr(arrayobject* self, PyObject* item)
step); step);
if (slicelength <= 0) { if (slicelength <= 0) {
return newarrayobject(&Arraytype, 0, self->ob_descr); return newarrayobject(state->ArrayType, 0, self->ob_descr);
} }
else if (step == 1) { else if (step == 1) {
PyObject *result = newarrayobject(&Arraytype, PyObject *result = newarrayobject(state->ArrayType,
slicelength, self->ob_descr); slicelength, self->ob_descr);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
@ -2323,7 +2356,7 @@ array_subscr(arrayobject* self, PyObject* item)
return result; return result;
} }
else { else {
result = newarrayobject(&Arraytype, slicelength, self->ob_descr); result = newarrayobject(state->ArrayType, slicelength, self->ob_descr);
if (!result) return NULL; if (!result) return NULL;
ar = (arrayobject*)result; ar = (arrayobject*)result;
@ -2349,6 +2382,7 @@ static int
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
{ {
Py_ssize_t start, stop, step, slicelength, needed; Py_ssize_t start, stop, step, slicelength, needed;
array_state* state = find_array_state_by_type(Py_TYPE(self));
arrayobject* other; arrayobject* other;
int itemsize; int itemsize;
@ -2390,7 +2424,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
other = NULL; other = NULL;
needed = 0; needed = 0;
} }
else if (array_Check(value)) { else if (array_Check(value, state)) {
other = (arrayobject *)value; other = (arrayobject *)value;
needed = Py_SIZE(other); needed = Py_SIZE(other);
if (self == other) { if (self == other) {
@ -2502,12 +2536,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 = ""; static const void *emptybuf = "";
@ -2558,32 +2586,15 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view)
self->ob_exports--; 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 * static PyObject *
array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
array_state *state = find_array_state_by_type(type);
int c; int c;
PyObject *initial = NULL, *it = NULL; PyObject *initial = NULL, *it = NULL;
const struct arraydescr *descr; const struct arraydescr *descr;
if (type == &Arraytype && !_PyArg_NoKeywords("array.array", kwds)) if (type == state->ArrayType && !_PyArg_NoKeywords("array.array", kwds))
return NULL; return NULL;
if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial))
@ -2600,7 +2611,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"an array with typecode '%c'", c); "an array with typecode '%c'", c);
return NULL; return NULL;
} }
else if (array_Check(initial) && else if (array_Check(initial, state) &&
((arrayobject*)initial)->ob_descr->typecode == 'u') { ((arrayobject*)initial)->ob_descr->typecode == 'u') {
PyErr_Format(PyExc_TypeError, "cannot use a unicode array to " PyErr_Format(PyExc_TypeError, "cannot use a unicode array to "
"initialize an array with typecode '%c'", c); "initialize an array with typecode '%c'", c);
@ -2613,7 +2624,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|| PyBytes_Check(initial) || PyBytes_Check(initial)
|| PyTuple_Check(initial) || PyTuple_Check(initial)
|| ((c=='u') && PyUnicode_Check(initial)) || ((c=='u') && PyUnicode_Check(initial))
|| (array_Check(initial) || (array_Check(initial, state)
&& c == ((arrayobject*)initial)->ob_descr->typecode))) { && c == ((arrayobject*)initial)->ob_descr->typecode))) {
it = PyObject_GetIter(initial); it = PyObject_GetIter(initial);
if (it == NULL) if (it == NULL)
@ -2634,7 +2645,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
len = 0; len = 0;
else if (PyList_Check(initial)) else if (PyList_Check(initial))
len = PyList_GET_SIZE(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); len = Py_SIZE(initial);
else else
len = 0; len = 0;
@ -2643,7 +2654,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (a == NULL) if (a == NULL)
return NULL; return NULL;
if (len > 0 && !array_Check(initial)) { if (len > 0 && !array_Check(initial, state)) {
Py_ssize_t i; Py_ssize_t i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
PyObject *v = PyObject *v =
@ -2688,7 +2699,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->allocated = n; 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 *self = (arrayobject *)a;
arrayobject *other = (arrayobject *)initial; arrayobject *other = (arrayobject *)initial;
memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize); memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize);
@ -2777,67 +2788,73 @@ itemsize -- the length in bytes of one array item\n\
static PyObject *array_iter(arrayobject *ao); static PyObject *array_iter(arrayobject *ao);
static PyTypeObject Arraytype = { static struct PyMemberDef array_members[] = {
PyVarObject_HEAD_INIT(NULL, 0) {"__weaklistoffset__", T_PYSSIZET, offsetof(arrayobject, weakreflist), READONLY},
"array.array", {NULL},
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 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 **************************/ /*********************** Array Iterator **************************/
/*[clinic input] /*[clinic input]
class array.arrayiterator "arrayiterobject *" "&PyArrayIter_Type" class array.arrayiterator "arrayiterobject *" "find_array_state_by_type(type)->ArrayIterType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=fb46d5ef98dd95ff]*/
static PyObject * static PyObject *
array_iter(arrayobject *ao) array_iter(arrayobject *ao)
{ {
array_state *state = find_array_state_by_type(Py_TYPE(ao));
arrayiterobject *it; arrayiterobject *it;
if (!array_Check(ao)) { if (!array_Check(ao, state)) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type); it = PyObject_GC_New(arrayiterobject, state->ArrayIterType);
if (it == NULL) if (it == NULL)
return NULL; return NULL;
@ -2855,12 +2872,17 @@ arrayiter_next(arrayiterobject *it)
arrayobject *ao; arrayobject *ao;
assert(it != NULL); assert(it != NULL);
assert(PyArrayIter_Check(it)); #ifndef NDEBUG
array_state *state = find_array_state_by_type(Py_TYPE(it));
assert(PyObject_TypeCheck(it, state->ArrayIterType));
#endif
ao = it->ao; ao = it->ao;
if (ao == NULL) { if (ao == NULL) {
return NULL; return NULL;
} }
assert(array_Check(ao)); #ifndef NDEBUG
assert(array_Check(ao, state));
#endif
if (it->index < Py_SIZE(ao)) { if (it->index < Py_SIZE(ao)) {
return (*it->getitem)(ao, it->index++); return (*it->getitem)(ao, it->index++);
} }
@ -2872,9 +2894,12 @@ arrayiter_next(arrayiterobject *it)
static void static void
arrayiter_dealloc(arrayiterobject *it) arrayiter_dealloc(arrayiterobject *it)
{ {
PyTypeObject *tp = Py_TYPE(it);
PyObject_GC_UnTrack(it); PyObject_GC_UnTrack(it);
Py_XDECREF(it->ao); Py_XDECREF(it->ao);
PyObject_GC_Del(it); PyObject_GC_Del(it);
Py_DECREF(tp);
} }
static int static int
@ -2932,36 +2957,21 @@ static PyMethodDef arrayiter_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyTypeObject PyArrayIter_Type = { static PyType_Slot arrayiter_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, arrayiter_dealloc},
"arrayiterator", /* tp_name */ {Py_tp_getattro, PyObject_GenericGetAttr},
sizeof(arrayiterobject), /* tp_basicsize */ {Py_tp_traverse, arrayiter_traverse},
0, /* tp_itemsize */ {Py_tp_iter, PyObject_SelfIter},
/* methods */ {Py_tp_iternext, arrayiter_next},
(destructor)arrayiter_dealloc, /* tp_dealloc */ {Py_tp_methods, arrayiter_methods},
0, /* tp_vectorcall_offset */ {0, NULL},
0, /* tp_getattr */ };
0, /* tp_setattr */
0, /* tp_as_async */ static PyType_Spec arrayiter_spec = {
0, /* tp_repr */ .name = "array.arrayiterator",
0, /* tp_as_number */ .basicsize = sizeof(arrayiterobject),
0, /* tp_as_sequence */ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
0, /* tp_as_mapping */ .slots = arrayiter_slots,
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 */
}; };
@ -2973,45 +2983,53 @@ static PyMethodDef a_methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */ {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 static int
array_modexec(PyObject *m) array_modexec(PyObject *m)
{ {
array_state *state = get_array_state(m);
char buffer[Py_ARRAY_LENGTH(descriptors)], *p; char buffer[Py_ARRAY_LENGTH(descriptors)], *p;
PyObject *typecodes; PyObject *typecodes;
const struct arraydescr *descr; const struct arraydescr *descr;
if (PyType_Ready(&Arraytype) < 0) CREATE_TYPE(m, state->ArrayType, &array_spec);
return -1; CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec);
Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type); Py_SET_TYPE(state->ArrayIterType, &PyType_Type);
Py_INCREF((PyObject *)&Arraytype); Py_INCREF((PyObject *)state->ArrayType);
if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) { if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) {
Py_DECREF((PyObject *)&Arraytype); Py_DECREF((PyObject *)state->ArrayType);
return -1; return -1;
} }
PyObject *abc_mod = PyImport_ImportModule("collections.abc"); PyObject *abc_mod = PyImport_ImportModule("collections.abc");
if (!abc_mod) { if (!abc_mod) {
Py_DECREF((PyObject *)&Arraytype); Py_DECREF((PyObject *)state->ArrayType);
return -1; return -1;
} }
PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence"); PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
Py_DECREF(abc_mod); Py_DECREF(abc_mod);
if (!mutablesequence) { if (!mutablesequence) {
Py_DECREF((PyObject *)&Arraytype); Py_DECREF((PyObject *)state->ArrayType);
return -1; return -1;
} }
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)&Arraytype); PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O",
(PyObject *)state->ArrayType);
Py_DECREF(mutablesequence); Py_DECREF(mutablesequence);
if (!res) { if (!res) {
Py_DECREF((PyObject *)&Arraytype); Py_DECREF((PyObject *)state->ArrayType);
return -1; return -1;
} }
Py_DECREF(res); Py_DECREF(res);
Py_INCREF((PyObject *)&Arraytype); if (PyModule_AddType(m, state->ArrayType) < 0) {
if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) {
Py_DECREF((PyObject *)&Arraytype);
return -1; return -1;
} }
@ -3035,15 +3053,12 @@ static PyModuleDef_Slot arrayslots[] = {
static struct PyModuleDef arraymodule = { static struct PyModuleDef arraymodule = {
PyModuleDef_HEAD_INIT, .m_base = PyModuleDef_HEAD_INIT,
"array", .m_name = "array",
module_doc, .m_size = sizeof(array_state),
0, .m_doc = module_doc,
a_methods, .m_methods = a_methods,
arrayslots, .m_slots = arrayslots,
NULL,
NULL,
NULL
}; };

View File

@ -108,7 +108,28 @@ PyDoc_STRVAR(array_array_extend__doc__,
"Append items to the end of the array."); "Append items to the end of the array.");
#define ARRAY_ARRAY_EXTEND_METHODDEF \ #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__, PyDoc_STRVAR(array_array_insert__doc__,
"insert($self, i, v, /)\n" "insert($self, i, v, /)\n"
@ -514,4 +535,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__,
#define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \
{"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__},
/*[clinic end generated code: output=91c1cded65a1285f input=a9049054013a1b77]*/ /*[clinic end generated code: output=a7f71a18b994c88f input=a9049054013a1b77]*/