diff -r 35d0db3b5bb5 Modules/arraymodule.c --- a/Modules/arraymodule.c Wed Aug 15 17:06:47 2012 +0200 +++ b/Modules/arraymodule.c Wed Aug 15 17:11:05 2012 +0200 @@ -40,10 +40,46 @@ int ob_exports; /* Number of exported buffers */ } arrayobject; -static PyTypeObject Arraytype; +typedef struct { + PyObject *PyArrayIter_Type; + PyObject *Arraytype; + PyObject *array_reconstructor; +} arraystate; -#define array_Check(op) PyObject_TypeCheck(op, &Arraytype) -#define array_CheckExact(op) (Py_TYPE(op) == &Arraytype) +#define array_state(o) ((arraystate *)PyModule_GetState(o)) + +static int +array_clear(PyObject *m) +{ + arraystate *state = array_state(m); + Py_CLEAR(state->PyArrayIter_Type); + Py_CLEAR(state->Arraytype); + Py_CLEAR(state->array_reconstructor); + return 0; +} + +static int +array_traverse(PyObject *m, visitproc visit, void *arg) +{ + arraystate *state = array_state(m); + Py_VISIT(state->PyArrayIter_Type); + Py_VISIT(state->Arraytype); + Py_VISIT(state->array_reconstructor); + return 0; +} + +static void +array_free(void *m) +{ + array_clear((PyObject *)m); +} + +static PyModuleDef arraymodule; + +#define arraystate_global ((arraystate *)PyModule_GetState(PyState_FindModule(&arraymodule))) + +#define array_Check(op) PyObject_TypeCheck(op, (PyTypeObject *)arraystate_global->Arraytype) +#define array_CheckExact(op) (Py_TYPE(op) == (PyTypeObject *)arraystate_global->Arraytype) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -507,6 +543,7 @@ } } op->ob_exports = 0; + Py_INCREF(type); return (PyObject *) op; } @@ -555,11 +592,15 @@ static void array_dealloc(arrayobject *op) { + PyTypeObject *type = 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); + type->tp_free((PyObject *)op); + if((void *)type->tp_dealloc == (void *)array_dealloc) { + Py_DECREF(type); + } } static PyObject * @@ -676,7 +717,7 @@ ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject((PyTypeObject *)arraystate_global->Arraytype, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; memcpy(np->ob_item, a->ob_item + ilow * a->ob_descr->itemsize, @@ -715,7 +756,7 @@ return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject((PyTypeObject *)arraystate_global->Arraytype, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -738,7 +779,7 @@ return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject((PyTypeObject *)arraystate_global->Arraytype, size, a->ob_descr); if (np == NULL) return NULL; if (n == 0) @@ -1821,10 +1862,10 @@ Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, &Arraytype)) { + if (!PyType_IsSubtype(arraytype, (PyTypeObject *)arraystate_global->Arraytype)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, Arraytype.tp_name); + arraytype->tp_name, ((PyTypeObject *)arraystate_global->Arraytype)->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2011,20 +2052,20 @@ PyObject *array_str; int typecode = array->ob_descr->typecode; int mformat_code; - static PyObject *array_reconstructor = NULL; + long protocol; _Py_IDENTIFIER(_array_reconstructor); _Py_IDENTIFIER(__dict__); - if (array_reconstructor == NULL) { + if (arraystate_global->array_reconstructor == NULL) { PyObject *array_module = PyImport_ImportModule("array"); if (array_module == NULL) return NULL; - array_reconstructor = _PyObject_GetAttrId( + arraystate_global->array_reconstructor = _PyObject_GetAttrId( array_module, &PyId__array_reconstructor); Py_DECREF(array_module); - if (array_reconstructor == NULL) + if (arraystate_global->array_reconstructor == NULL) return NULL; } @@ -2078,7 +2119,7 @@ return NULL; } result = Py_BuildValue( - "O(OCiN)O", array_reconstructor, Py_TYPE(array), typecode, + "O(OCiN)O", arraystate_global->array_reconstructor, Py_TYPE(array), typecode, mformat_code, array_str, dict); Py_DECREF(dict); return result; @@ -2207,10 +2248,10 @@ } if (slicelength <= 0) { - return newarrayobject(&Arraytype, 0, self->ob_descr); + return newarrayobject((PyTypeObject *)arraystate_global->Arraytype, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(&Arraytype, + PyObject *result = newarrayobject((PyTypeObject *)arraystate_global->Arraytype, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2220,7 +2261,7 @@ return result; } else { - result = newarrayobject(&Arraytype, slicelength, self->ob_descr); + result = newarrayobject((PyTypeObject *)arraystate_global->Arraytype, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2398,11 +2439,7 @@ } } -static PyMappingMethods array_as_mapping = { - (lenfunc)array_length, - (binaryfunc)array_subscr, - (objobjargproc)array_ass_subscr -}; + static const void *emptybuf = ""; @@ -2451,24 +2488,6 @@ 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) { @@ -2476,7 +2495,7 @@ PyObject *initial = NULL, *it = NULL; struct arraydescr *descr; - if (type == &Arraytype && !_PyArg_NoKeywords("array.array()", kwds)) + if (type == (PyTypeObject *)arraystate_global->Arraytype && !_PyArg_NoKeywords("array.array()", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2676,61 +2695,58 @@ static PyObject *array_iter(arrayobject *ao); -static PyTypeObject Arraytype = { - PyVarObject_HEAD_INIT(NULL, 0) +static PyBufferProcs array_as_buffer = { + (getbufferproc)array_buffer_getbuf, + (releasebufferproc)array_buffer_relbuf +}; + +static PyType_Slot Arraytype_slots[] = { + {Py_tp_dealloc, (destructor)array_dealloc}, + {Py_tp_repr, (reprfunc)array_repr}, + {Py_sq_length, (lenfunc)array_length}, + {Py_sq_concat, (binaryfunc)array_concat}, + {Py_sq_repeat, (ssizeargfunc)array_repeat}, + {Py_sq_item, (ssizeargfunc)array_item}, + {Py_sq_ass_item, (ssizeobjargproc)array_ass_item}, + {Py_sq_contains, (objobjproc)array_contains}, + {Py_sq_inplace_concat, (binaryfunc)array_inplace_concat}, + {Py_sq_inplace_repeat, (ssizeargfunc)array_inplace_repeat}, + {Py_mp_length, (lenfunc)array_length}, + {Py_mp_subscript, (binaryfunc)array_subscr}, + {Py_mp_ass_subscript, (objobjargproc)array_ass_subscr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, arraytype_doc}, + {Py_tp_richcompare, array_richcompare}, + {Py_tp_iter, (getiterfunc)array_iter}, + {Py_tp_methods, array_methods}, + {Py_tp_getset, array_getsets}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, array_new}, + {Py_tp_free, PyObject_Del}, + {Py_tp_is_gc, }, + {0, 0} +}; + +static PyType_Spec Arraytype_spec = { "array.array", sizeof(arrayobject), 0, - (destructor)array_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (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 */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Arraytype_slots, }; + /*********************** Array Iterator **************************/ typedef struct { PyObject_HEAD - Py_ssize_t index; - arrayobject *ao; - PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); + Py_ssize_t index; + arrayobject *ao; + PyObject* (*getitem)(struct arrayobject *, Py_ssize_t); } arrayiterobject; -static PyTypeObject PyArrayIter_Type; - -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type) +#define PyArrayIter_Check(op) PyObject_TypeCheck(op, (PyTypeObject *)arraystate_global->PyArrayIter_Type) static PyObject * array_iter(arrayobject *ao) @@ -2742,10 +2758,11 @@ return NULL; } - it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, (PyTypeObject *)arraystate_global->PyArrayIter_Type); if (it == NULL) return NULL; + Py_INCREF(arraystate_global->PyArrayIter_Type); Py_INCREF(ao); it->ao = ao; it->index = 0; @@ -2766,8 +2783,12 @@ static void arrayiter_dealloc(arrayiterobject *it) { + PyTypeObject *type = Py_TYPE(it); PyObject_GC_UnTrack(it); Py_XDECREF(it->ao); + if((void *)type->tp_dealloc == (void *)arrayiter_dealloc) { + Py_DECREF(type); + } PyObject_GC_Del(it); } @@ -2806,38 +2827,26 @@ {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_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 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 PyArrayIter_Type_slots[] = { + {Py_tp_dealloc, (destructor)arrayiter_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, (traverseproc)arrayiter_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, (iternextfunc)arrayiter_next}, + {Py_tp_methods, arrayiter_methods}, + {Py_tp_members, }, + {0, 0} }; +static PyType_Spec PyArrayIter_Type_spec = { + "arrayiterator", + sizeof(arrayiterobject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + PyArrayIter_Type_slots, +}; + + /*********************** Install Module **************************/ @@ -2852,12 +2861,12 @@ PyModuleDef_HEAD_INIT, "array", module_doc, - -1, + sizeof(arraystate), a_methods, NULL, - NULL, - NULL, - NULL + array_traverse, + array_clear, + array_free }; @@ -2869,18 +2878,32 @@ PyObject *typecodes; Py_ssize_t size = 0; struct arraydescr *descr; + arraystate *state; - if (PyType_Ready(&Arraytype) < 0) - return NULL; - Py_TYPE(&PyArrayIter_Type) = &PyType_Type; m = PyModule_Create(&arraymodule); if (m == NULL) return NULL; - Py_INCREF((PyObject *)&Arraytype); - PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype); - Py_INCREF((PyObject *)&Arraytype); - PyModule_AddObject(m, "array", (PyObject *)&Arraytype); + state = array_state(m); + + state->array_reconstructor = NULL; + + state->PyArrayIter_Type = PyType_FromSpec(&PyArrayIter_Type_spec); + if(state->PyArrayIter_Type == NULL) + return NULL; + + state->Arraytype = PyType_FromSpec(&Arraytype_spec); + if (state->Arraytype == NULL) + return NULL; + ((PyTypeObject *)state->Arraytype)->tp_weaklistoffset = + offsetof(arrayobject, weakreflist); + ((PyTypeObject *)state->Arraytype)->tp_as_buffer = + &array_as_buffer; + + Py_INCREF(state->Arraytype); + PyModule_AddObject(m, "ArrayType", state->Arraytype); + Py_INCREF(state->Arraytype); + PyModule_AddObject(m, "array", state->Arraytype); for (descr=descriptors; descr->typecode != '\0'; descr++) { size++;