From 1c93d366b767166fbe9e9734a217e61a56373e60 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 21:13:50 +0100 Subject: [PATCH 01/24] Convert groupby and _grouper to heap types --- Modules/clinic/itertoolsmodule.c.h | 8 +- Modules/itertoolsmodule.c | 219 +++++++++++++++-------------- 2 files changed, 120 insertions(+), 107 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 82729eeb56bce9..c78c1dd00a41e0 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -89,15 +89,15 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *parent; PyObject *tgtkey; - if ((type == &_grouper_type) && + if ((type == clinic_find_state()->_grouper_type) && !_PyArg_NoKeywords("_grouper", kwargs)) { goto exit; } if (!_PyArg_CheckPositional("_grouper", PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } - if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), &groupby_type)) { - _PyArg_BadArgument("_grouper", "argument 1", (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); + if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_find_state()->groupby_type)) { + _PyArg_BadArgument("_grouper", "argument 1", (clinic_find_state()->groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); goto exit; } parent = PyTuple_GET_ITEM(args, 0); @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=889c4afc3b13574f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b59160678baa177a input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 293735a886428b..d3d48d6254268d 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -11,10 +11,33 @@ by Raymond D. Hettinger */ +typedef struct { + PyTypeObject *groupby_type; + PyTypeObject *_grouper_type; +} itertoolsmodule_state; + +static itertoolsmodule_state * +itertoolsmodule_get_state(PyObject *m) +{ + itertoolsmodule_state *state = PyModule_GetState(m); + assert(state != NULL); + return state; +} + +static struct PyModuleDef itertoolsmodule; +static itertoolsmodule_state * +itertoolsmodule_find_state_by_type(PyTypeObject *tp) +{ + PyObject *m = _PyType_GetModuleByDef(tp, &itertoolsmodule); + assert(m != NULL); + return itertoolsmodule_get_state(m); +} +#define clinic_find_state() itertoolsmodule_find_state_by_type(type) + /*[clinic input] module itertools -class itertools.groupby "groupbyobject *" "&groupby_type" -class itertools._grouper "_grouperobject *" "&_grouper_type" +class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" +class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" class itertools.cycle "cycleobject *" "&cycle_type" @@ -31,10 +54,8 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6498ed21fbe1bf94]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfcda45ca759edca]*/ -static PyTypeObject groupby_type; -static PyTypeObject _grouper_type; static PyTypeObject teedataobject_type; static PyTypeObject tee_type; static PyTypeObject cycle_type; @@ -236,13 +257,15 @@ itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc) static void groupby_dealloc(groupbyobject *gbo) { + PyTypeObject *tp = Py_TYPE(gbo); PyObject_GC_UnTrack(gbo); Py_XDECREF(gbo->it); Py_XDECREF(gbo->keyfunc); Py_XDECREF(gbo->tgtkey); Py_XDECREF(gbo->currkey); Py_XDECREF(gbo->currvalue); - Py_TYPE(gbo)->tp_free(gbo); + tp->tp_free(gbo); + Py_DECREF(tp); } static int @@ -369,50 +392,25 @@ static PyMethodDef groupby_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject groupby_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.groupby", /* tp_name */ - sizeof(groupbyobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)groupby_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_groupby__doc__, /* tp_doc */ - (traverseproc)groupby_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)groupby_next, /* tp_iternext */ - groupby_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_groupby, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot groupby_slots[] = { + {Py_tp_dealloc, groupby_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_groupby__doc__}, + {Py_tp_traverse, groupby_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, groupby_next}, + {Py_tp_methods, groupby_methods}, + {Py_tp_new, itertools_groupby}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, }; +static PyType_Spec groupby_spec = { + .name = "itertools.groupby", + .basicsize= sizeof(groupbyobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = groupby_slots, +}; /* _grouper object (internal) ************************************************/ @@ -426,7 +424,7 @@ typedef struct { @classmethod itertools._grouper.__new__ - parent: object(subclass_of='&groupby_type') + parent: object(subclass_of='clinic_find_state()->groupby_type') tgtkey: object / [clinic start generated code]*/ @@ -434,7 +432,7 @@ itertools._grouper.__new__ static PyObject * itertools__grouper_impl(PyTypeObject *type, PyObject *parent, PyObject *tgtkey) -/*[clinic end generated code: output=462efb1cdebb5914 input=dc180d7771fc8c59]*/ +/*[clinic end generated code: output=462efb1cdebb5914 input=0a93f28286c8e913]*/ { return _grouper_create((groupbyobject*) parent, tgtkey); } @@ -443,8 +441,9 @@ static PyObject * _grouper_create(groupbyobject *parent, PyObject *tgtkey) { _grouperobject *igo; + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(parent)); - igo = PyObject_GC_New(_grouperobject, &_grouper_type); + igo = PyObject_GC_New(_grouperobject, state->_grouper_type); if (igo == NULL) return NULL; igo->parent = (PyObject *)parent; @@ -460,10 +459,12 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey) static void _grouper_dealloc(_grouperobject *igo) { + PyTypeObject *tp = Py_TYPE(igo); PyObject_GC_UnTrack(igo); Py_DECREF(igo->parent); Py_DECREF(igo->tgtkey); PyObject_GC_Del(igo); + Py_DECREF(tp); } static int @@ -517,48 +518,23 @@ static PyMethodDef _grouper_methods[] = { {NULL, NULL} /* sentinel */ }; +static PyType_Slot _grouper_slots[] = { + {Py_tp_dealloc, _grouper_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, _grouper_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, _grouper_next}, + {Py_tp_methods, _grouper_methods}, + {Py_tp_new, itertools__grouper}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; -static PyTypeObject _grouper_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools._grouper", /* tp_name */ - sizeof(_grouperobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)_grouper_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)_grouper_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)_grouper_next, /* tp_iternext */ - _grouper_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools__grouper, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Spec _grouper_spec = { + .name = "itertools._grouper", + .basicsize = sizeof(_grouperobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = _grouper_slots, }; @@ -4838,9 +4814,48 @@ combinations(p, r)\n\ combinations_with_replacement(p, r)\n\ "); +static int +itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) +{ + itertoolsmodule_state *state = itertoolsmodule_get_state(m); + Py_VISIT(state->groupby_type); + Py_VISIT(state->_grouper_type); + return 0; +} + +static int +itertoolsmodule_clear(PyObject *m) +{ + itertoolsmodule_state *state = itertoolsmodule_get_state(m); + Py_CLEAR(state->groupby_type); + Py_CLEAR(state->_grouper_type); + return 0; +} + +static void +itertoolsmodule_free(void *m) +{ + itertoolsmodule_clear((PyObject *)m); +} + +#define ADD_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (!type) { \ + return -1; \ + } \ + if (PyModule_AddType(module, type) < 0) { \ + return -1; \ + } \ +} while (0) + static int itertoolsmodule_exec(PyObject *m) { + itertoolsmodule_state *state = itertoolsmodule_get_state(m); + ADD_TYPE(m, state->groupby_type, &groupby_spec); + ADD_TYPE(m, state->_grouper_type, &_grouper_spec); + PyTypeObject *typelist[] = { &accumulate_type, &combinations_type, @@ -4859,8 +4874,6 @@ itertoolsmodule_exec(PyObject *m) &permutations_type, &product_type, &repeat_type, - &groupby_type, - &_grouper_type, &tee_type, &teedataobject_type }; @@ -4888,15 +4901,15 @@ static PyMethodDef module_methods[] = { static struct PyModuleDef itertoolsmodule = { - PyModuleDef_HEAD_INIT, - "itertools", - module_doc, - 0, - module_methods, - itertoolsmodule_slots, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "itertools", + .m_doc = module_doc, + .m_size = sizeof(itertoolsmodule_state), + .m_methods = module_methods, + .m_slots = itertoolsmodule_slots, + .m_traverse = itertoolsmodule_traverse, + .m_clear = itertoolsmodule_clear, + .m_free = itertoolsmodule_free, }; PyMODINIT_FUNC From f1d27e945fb3edab3a846a92c025575cbfecfa20 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 21:59:12 +0100 Subject: [PATCH 02/24] Convert cycle type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index c78c1dd00a41e0..2510d24d1326da 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -235,7 +235,7 @@ itertools_cycle(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *iterable; - if ((type == &cycle_type) && + if ((type == clinic_find_state()->cycle_type) && !_PyArg_NoKeywords("cycle", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b59160678baa177a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dbdd07daaf144abb input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index d3d48d6254268d..5b0ce092a426ae 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -14,6 +14,7 @@ typedef struct { PyTypeObject *groupby_type; PyTypeObject *_grouper_type; + PyTypeObject *cycle_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -40,7 +41,7 @@ class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" -class itertools.cycle "cycleobject *" "&cycle_type" +class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "&dropwhile_type" class itertools.takewhile "takewhileobject *" "&takewhile_type" class itertools.starmap "starmapobject *" "&starmap_type" @@ -54,11 +55,10 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfcda45ca759edca]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4168ebeae080ed0c]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject cycle_type; static PyTypeObject dropwhile_type; static PyTypeObject takewhile_type; static PyTypeObject starmap_type; @@ -1101,10 +1101,12 @@ itertools_cycle_impl(PyTypeObject *type, PyObject *iterable) static void cycle_dealloc(cycleobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->it); Py_XDECREF(lz->saved); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -1197,48 +1199,24 @@ static PyMethodDef cycle_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject cycle_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.cycle", /* tp_name */ - sizeof(cycleobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)cycle_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_cycle__doc__, /* tp_doc */ - (traverseproc)cycle_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cycle_next, /* tp_iternext */ - cycle_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_cycle, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot cycle_slots[] = { + {Py_tp_dealloc, cycle_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_cycle__doc__}, + {Py_tp_traverse, cycle_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, cycle_next}, + {Py_tp_methods, cycle_methods}, + {Py_tp_new, itertools_cycle}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec cycle_spec = { + .name = "itertools.cycle", + .basicsize = sizeof(cycleobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = cycle_slots, }; @@ -4820,6 +4798,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) itertoolsmodule_state *state = itertoolsmodule_get_state(m); Py_VISIT(state->groupby_type); Py_VISIT(state->_grouper_type); + Py_VISIT(state->cycle_type); return 0; } @@ -4829,6 +4808,7 @@ itertoolsmodule_clear(PyObject *m) itertoolsmodule_state *state = itertoolsmodule_get_state(m); Py_CLEAR(state->groupby_type); Py_CLEAR(state->_grouper_type); + Py_CLEAR(state->cycle_type); return 0; } @@ -4855,12 +4835,12 @@ itertoolsmodule_exec(PyObject *m) itertoolsmodule_state *state = itertoolsmodule_get_state(m); ADD_TYPE(m, state->groupby_type, &groupby_spec); ADD_TYPE(m, state->_grouper_type, &_grouper_spec); + ADD_TYPE(m, state->cycle_type, &cycle_spec); PyTypeObject *typelist[] = { &accumulate_type, &combinations_type, &cwr_type, - &cycle_type, &dropwhile_type, &takewhile_type, &islice_type, From c654ad38ea9612c6447a8da27f5cf0cf1b41d292 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:06:20 +0100 Subject: [PATCH 03/24] Convert dropwhile type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 2510d24d1326da..ddd5003bb7dcf5 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -267,7 +267,7 @@ itertools_dropwhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *func; PyObject *seq; - if ((type == &dropwhile_type) && + if ((type == clinic_find_state()->dropwhile_type) && !_PyArg_NoKeywords("dropwhile", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=dbdd07daaf144abb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1e5302266479d8b0 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 5b0ce092a426ae..965cc91d101967 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -15,6 +15,7 @@ typedef struct { PyTypeObject *groupby_type; PyTypeObject *_grouper_type; PyTypeObject *cycle_type; + PyTypeObject *dropwhile_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -42,7 +43,7 @@ class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" -class itertools.dropwhile "dropwhileobject *" "&dropwhile_type" +class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" class itertools.takewhile "takewhileobject *" "&takewhile_type" class itertools.starmap "starmapobject *" "&starmap_type" class itertools.chain "chainobject *" "&chain_type" @@ -55,11 +56,10 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4168ebeae080ed0c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8e072dc5246cec5d]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject dropwhile_type; static PyTypeObject takewhile_type; static PyTypeObject starmap_type; static PyTypeObject combinations_type; @@ -1269,10 +1269,12 @@ itertools_dropwhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void dropwhile_dealloc(dropwhileobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -1340,48 +1342,24 @@ static PyMethodDef dropwhile_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject dropwhile_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.dropwhile", /* tp_name */ - sizeof(dropwhileobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dropwhile_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_dropwhile__doc__, /* tp_doc */ - (traverseproc)dropwhile_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dropwhile_next, /* tp_iternext */ - dropwhile_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_dropwhile, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot dropwhile_slots[] = { + {Py_tp_dealloc, dropwhile_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_dropwhile__doc__}, + {Py_tp_traverse, dropwhile_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, dropwhile_next}, + {Py_tp_methods, dropwhile_methods}, + {Py_tp_new, itertools_dropwhile}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec dropwhile_spec = { + .name = "itertools.dropwhile", + .basicsize = sizeof(dropwhileobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = dropwhile_slots, }; @@ -4799,6 +4777,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->groupby_type); Py_VISIT(state->_grouper_type); Py_VISIT(state->cycle_type); + Py_VISIT(state->dropwhile_type); return 0; } @@ -4809,6 +4788,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->groupby_type); Py_CLEAR(state->_grouper_type); Py_CLEAR(state->cycle_type); + Py_CLEAR(state->dropwhile_type); return 0; } @@ -4836,12 +4816,12 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->groupby_type, &groupby_spec); ADD_TYPE(m, state->_grouper_type, &_grouper_spec); ADD_TYPE(m, state->cycle_type, &cycle_spec); + ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); PyTypeObject *typelist[] = { &accumulate_type, &combinations_type, &cwr_type, - &dropwhile_type, &takewhile_type, &islice_type, &starmap_type, From 09206f9662c01591de4654a88e81d19432a06b7b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:14:22 +0100 Subject: [PATCH 04/24] Convert takewhile type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index ddd5003bb7dcf5..02ce2683be60cb 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -298,7 +298,7 @@ itertools_takewhile(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *func; PyObject *seq; - if ((type == &takewhile_type) && + if ((type == clinic_find_state()->takewhile_type) && !_PyArg_NoKeywords("takewhile", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=1e5302266479d8b0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9d06bbc3a16f0bed input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 965cc91d101967..d033b535200a6b 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -16,6 +16,7 @@ typedef struct { PyTypeObject *_grouper_type; PyTypeObject *cycle_type; PyTypeObject *dropwhile_type; + PyTypeObject *takewhile_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -44,7 +45,7 @@ class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools._tee "teeobject *" "&tee_type" class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" -class itertools.takewhile "takewhileobject *" "&takewhile_type" +class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" class itertools.starmap "starmapobject *" "&starmap_type" class itertools.chain "chainobject *" "&chain_type" class itertools.combinations "combinationsobject *" "&combinations_type" @@ -56,11 +57,10 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8e072dc5246cec5d]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=355860e69ec3091a]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject takewhile_type; static PyTypeObject starmap_type; static PyTypeObject combinations_type; static PyTypeObject cwr_type; @@ -1410,10 +1410,12 @@ itertools_takewhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void takewhile_dealloc(takewhileobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -1478,48 +1480,24 @@ static PyMethodDef takewhile_reduce_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject takewhile_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.takewhile", /* tp_name */ - sizeof(takewhileobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)takewhile_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_takewhile__doc__, /* tp_doc */ - (traverseproc)takewhile_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)takewhile_next, /* tp_iternext */ - takewhile_reduce_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_takewhile, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot takewhile_slots[] = { + {Py_tp_dealloc, takewhile_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_takewhile__doc__}, + {Py_tp_traverse, takewhile_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, takewhile_next}, + {Py_tp_methods, takewhile_reduce_methods}, + {Py_tp_new, itertools_takewhile}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec takewhile_spec = { + .name = "itertools.takewhile", + .basicsize = sizeof(takewhileobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = takewhile_slots, }; @@ -4778,6 +4756,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->_grouper_type); Py_VISIT(state->cycle_type); Py_VISIT(state->dropwhile_type); + Py_VISIT(state->takewhile_type); return 0; } @@ -4789,6 +4768,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->_grouper_type); Py_CLEAR(state->cycle_type); Py_CLEAR(state->dropwhile_type); + Py_CLEAR(state->takewhile_type); return 0; } @@ -4817,12 +4797,12 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->_grouper_type, &_grouper_spec); ADD_TYPE(m, state->cycle_type, &cycle_spec); ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); + ADD_TYPE(m, state->takewhile_type, &takewhile_spec); PyTypeObject *typelist[] = { &accumulate_type, &combinations_type, &cwr_type, - &takewhile_type, &islice_type, &starmap_type, &chain_type, From 676d4ef816ea5d9efe47fb40008e5dd4d6ffe1bd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:21:50 +0100 Subject: [PATCH 05/24] Convert starmap type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 02ce2683be60cb..43a326a9bddb7f 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -329,7 +329,7 @@ itertools_starmap(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *func; PyObject *seq; - if ((type == &starmap_type) && + if ((type == clinic_find_state()->starmap_type) && !_PyArg_NoKeywords("starmap", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=9d06bbc3a16f0bed input=a9049054013a1b77]*/ +/*[clinic end generated code: output=41d6bc523590b967 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index d033b535200a6b..61e1e7be69a7ed 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -17,6 +17,7 @@ typedef struct { PyTypeObject *cycle_type; PyTypeObject *dropwhile_type; PyTypeObject *takewhile_type; + PyTypeObject *starmap_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -46,7 +47,7 @@ class itertools._tee "teeobject *" "&tee_type" class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" -class itertools.starmap "starmapobject *" "&starmap_type" +class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" class itertools.chain "chainobject *" "&chain_type" class itertools.combinations "combinationsobject *" "&combinations_type" class itertools.combinations_with_replacement "cwr_object *" "&cwr_type" @@ -57,11 +58,10 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=355860e69ec3091a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2378e41d4bd2ac8d]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject starmap_type; static PyTypeObject combinations_type; static PyTypeObject cwr_type; static PyTypeObject permutations_type; @@ -1805,10 +1805,12 @@ itertools_starmap_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void starmap_dealloc(starmapobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -1854,48 +1856,24 @@ static PyMethodDef starmap_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject starmap_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.starmap", /* tp_name */ - sizeof(starmapobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)starmap_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_starmap__doc__, /* tp_doc */ - (traverseproc)starmap_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)starmap_next, /* tp_iternext */ - starmap_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_starmap, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot starmap_slots[] = { + {Py_tp_dealloc, starmap_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_starmap__doc__}, + {Py_tp_traverse, starmap_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, starmap_next}, + {Py_tp_methods, starmap_methods}, + {Py_tp_new, itertools_starmap}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec starmap_spec = { + .name = "itertools.starmap", + .basicsize = sizeof(starmapobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = starmap_slots, }; @@ -4757,6 +4735,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->cycle_type); Py_VISIT(state->dropwhile_type); Py_VISIT(state->takewhile_type); + Py_VISIT(state->starmap_type); return 0; } @@ -4769,6 +4748,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->cycle_type); Py_CLEAR(state->dropwhile_type); Py_CLEAR(state->takewhile_type); + Py_CLEAR(state->starmap_type); return 0; } @@ -4798,13 +4778,13 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->cycle_type, &cycle_spec); ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); ADD_TYPE(m, state->takewhile_type, &takewhile_spec); + ADD_TYPE(m, state->starmap_type, &starmap_spec); PyTypeObject *typelist[] = { &accumulate_type, &combinations_type, &cwr_type, &islice_type, - &starmap_type, &chain_type, &compress_type, &filterfalse_type, From 68a64c6f1d928337c31182ae255ce09637a2214c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:31:58 +0100 Subject: [PATCH 06/24] Convert combinations & cwr types to heap types --- Modules/itertoolsmodule.c | 146 ++++++++++++++------------------------ 1 file changed, 53 insertions(+), 93 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 61e1e7be69a7ed..c4b09eb1cff3f1 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -18,6 +18,8 @@ typedef struct { PyTypeObject *dropwhile_type; PyTypeObject *takewhile_type; PyTypeObject *starmap_type; + PyTypeObject *combinations_type; + PyTypeObject *cwr_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -49,8 +51,8 @@ class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_ty class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" class itertools.chain "chainobject *" "&chain_type" -class itertools.combinations "combinationsobject *" "&combinations_type" -class itertools.combinations_with_replacement "cwr_object *" "&cwr_type" +class itertools.combinations "combinationsobject *" "clinic_find_state()->combinations_type" +class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" class itertools.permutations "permutationsobject *" "&permutations_type" class itertools.accumulate "accumulateobject *" "&accumulate_type" class itertools.compress "compressobject *" "&compress_type" @@ -58,12 +60,10 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2378e41d4bd2ac8d]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=84842f360226c940]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject combinations_type; -static PyTypeObject cwr_type; static PyTypeObject permutations_type; static PyTypeObject accumulate_type; static PyTypeObject compress_type; @@ -2532,12 +2532,14 @@ itertools_combinations_impl(PyTypeObject *type, PyObject *iterable, static void combinations_dealloc(combinationsobject *co) { + PyTypeObject *tp = Py_TYPE(co); PyObject_GC_UnTrack(co); Py_XDECREF(co->pool); Py_XDECREF(co->result); if (co->indices != NULL) PyMem_Free(co->indices); - Py_TYPE(co)->tp_free(co); + tp->tp_free(co); + Py_DECREF(tp); } static PyObject * @@ -2724,48 +2726,24 @@ static PyMethodDef combinations_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject combinations_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations", /* tp_name */ - sizeof(combinationsobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)combinations_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_combinations__doc__, /* tp_doc */ - (traverseproc)combinations_traverse,/* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)combinations_next, /* tp_iternext */ - combinations_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_combinations, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot combinations_slots[] = { + {Py_tp_dealloc, combinations_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_combinations__doc__}, + {Py_tp_traverse, combinations_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, combinations_next}, + {Py_tp_methods, combinations_methods}, + {Py_tp_new, itertools_combinations}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec combinations_spec = { + .name = "itertools.combinations", + .basicsize = sizeof(combinationsobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = combinations_slots, }; @@ -2869,12 +2847,14 @@ itertools_combinations_with_replacement_impl(PyTypeObject *type, static void cwr_dealloc(cwrobject *co) { + PyTypeObject *tp = Py_TYPE(co); PyObject_GC_UnTrack(co); Py_XDECREF(co->pool); Py_XDECREF(co->result); if (co->indices != NULL) PyMem_Free(co->indices); - Py_TYPE(co)->tp_free(co); + tp->tp_free(co); + Py_DECREF(tp); } static PyObject * @@ -3051,48 +3031,24 @@ static PyMethodDef cwr_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject cwr_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.combinations_with_replacement", /* tp_name */ - sizeof(cwrobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)cwr_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_combinations_with_replacement__doc__, /* tp_doc */ - (traverseproc)cwr_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)cwr_next, /* tp_iternext */ - cwr_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_combinations_with_replacement, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot cwr_slots[] = { + {Py_tp_dealloc, cwr_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_combinations_with_replacement__doc__}, + {Py_tp_traverse, cwr_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, cwr_next}, + {Py_tp_methods, cwr_methods}, + {Py_tp_new, itertools_combinations_with_replacement}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec cwr_spec = { + .name = "itertools.combinations_with_replacement", + .basicsize = sizeof(cwrobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = cwr_slots, }; @@ -4736,6 +4692,8 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->dropwhile_type); Py_VISIT(state->takewhile_type); Py_VISIT(state->starmap_type); + Py_VISIT(state->combinations_type); + Py_VISIT(state->cwr_type); return 0; } @@ -4749,6 +4707,8 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->dropwhile_type); Py_CLEAR(state->takewhile_type); Py_CLEAR(state->starmap_type); + Py_CLEAR(state->combinations_type); + Py_CLEAR(state->cwr_type); return 0; } @@ -4779,11 +4739,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); ADD_TYPE(m, state->takewhile_type, &takewhile_spec); ADD_TYPE(m, state->starmap_type, &starmap_spec); + ADD_TYPE(m, state->combinations_type, &combinations_spec); + ADD_TYPE(m, state->cwr_type, &cwr_spec); PyTypeObject *typelist[] = { &accumulate_type, - &combinations_type, - &cwr_type, &islice_type, &chain_type, &compress_type, From f46b80c8621ad553abd31f3604f94121cbeb78cb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:36:14 +0100 Subject: [PATCH 07/24] Convert permutations type to heap type --- Modules/itertoolsmodule.c | 74 ++++++++++++++------------------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index c4b09eb1cff3f1..f24618edcf07f7 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -20,6 +20,7 @@ typedef struct { PyTypeObject *starmap_type; PyTypeObject *combinations_type; PyTypeObject *cwr_type; + PyTypeObject *permutations_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -53,18 +54,17 @@ class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" class itertools.chain "chainobject *" "&chain_type" class itertools.combinations "combinationsobject *" "clinic_find_state()->combinations_type" class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" -class itertools.permutations "permutationsobject *" "&permutations_type" +class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" class itertools.accumulate "accumulateobject *" "&accumulate_type" class itertools.compress "compressobject *" "&compress_type" class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=84842f360226c940]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d98a1d4078c9635d]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject permutations_type; static PyTypeObject accumulate_type; static PyTypeObject compress_type; static PyTypeObject filterfalse_type; @@ -3171,12 +3171,14 @@ itertools_permutations_impl(PyTypeObject *type, PyObject *iterable, static void permutations_dealloc(permutationsobject *po) { + PyTypeObject *tp = Py_TYPE(po); PyObject_GC_UnTrack(po); Py_XDECREF(po->pool); Py_XDECREF(po->result); PyMem_Free(po->indices); PyMem_Free(po->cycles); - Py_TYPE(po)->tp_free(po); + tp->tp_free(po); + Py_DECREF(tp); } static PyObject * @@ -3399,48 +3401,24 @@ static PyMethodDef permuations_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject permutations_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.permutations", /* tp_name */ - sizeof(permutationsobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)permutations_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_permutations__doc__, /* tp_doc */ - (traverseproc)permutations_traverse,/* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)permutations_next, /* tp_iternext */ - permuations_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_permutations, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot permutations_slots[] = { + {Py_tp_dealloc, permutations_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_permutations__doc__}, + {Py_tp_traverse, permutations_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, permutations_next}, + {Py_tp_methods, permuations_methods}, + {Py_tp_new, itertools_permutations}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec permutations_spec = { + .name = "itertools.permutations", + .basicsize = sizeof(permutationsobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = permutations_slots, }; @@ -4694,6 +4672,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->starmap_type); Py_VISIT(state->combinations_type); Py_VISIT(state->cwr_type); + Py_VISIT(state->permutations_type); return 0; } @@ -4709,6 +4688,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->starmap_type); Py_CLEAR(state->combinations_type); Py_CLEAR(state->cwr_type); + Py_CLEAR(state->permutations_type); return 0; } @@ -4741,6 +4721,7 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->starmap_type, &starmap_spec); ADD_TYPE(m, state->combinations_type, &combinations_spec); ADD_TYPE(m, state->cwr_type, &cwr_spec); + ADD_TYPE(m, state->permutations_type, &permutations_spec); PyTypeObject *typelist[] = { &accumulate_type, @@ -4751,7 +4732,6 @@ itertoolsmodule_exec(PyObject *m) &count_type, &ziplongest_type, &pairwise_type, - &permutations_type, &product_type, &repeat_type, &tee_type, From 520b00924fccca138a89e2f818132ef6efaf66d5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:41:07 +0100 Subject: [PATCH 08/24] Convert accumulate type to heap type --- Modules/itertoolsmodule.c | 74 ++++++++++++++------------------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index f24618edcf07f7..104cbc9d67be27 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -21,6 +21,7 @@ typedef struct { PyTypeObject *combinations_type; PyTypeObject *cwr_type; PyTypeObject *permutations_type; + PyTypeObject *accumulate_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -55,17 +56,16 @@ class itertools.chain "chainobject *" "&chain_type" class itertools.combinations "combinationsobject *" "clinic_find_state()->combinations_type" class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" -class itertools.accumulate "accumulateobject *" "&accumulate_type" +class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" class itertools.compress "compressobject *" "&compress_type" class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d98a1d4078c9635d]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2d745b73d7b6fa4c]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject accumulate_type; static PyTypeObject compress_type; static PyTypeObject filterfalse_type; static PyTypeObject count_type; @@ -3476,12 +3476,14 @@ itertools_accumulate_impl(PyTypeObject *type, PyObject *iterable, static void accumulate_dealloc(accumulateobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->binop); Py_XDECREF(lz->total); Py_XDECREF(lz->it); Py_XDECREF(lz->initial); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -3583,48 +3585,24 @@ static PyMethodDef accumulate_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject accumulate_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.accumulate", /* tp_name */ - sizeof(accumulateobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)accumulate_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_accumulate__doc__, /* tp_doc */ - (traverseproc)accumulate_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)accumulate_next, /* tp_iternext */ - accumulate_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_accumulate, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot accumulate_slots[] = { + {Py_tp_dealloc, accumulate_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_accumulate__doc__}, + {Py_tp_traverse, accumulate_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, accumulate_next}, + {Py_tp_methods, accumulate_methods}, + {Py_tp_new, itertools_accumulate}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec accumulate_spec = { + .name = "itertools.accumulate", + .basicsize = sizeof(accumulateobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = accumulate_slots, }; @@ -4673,6 +4651,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->combinations_type); Py_VISIT(state->cwr_type); Py_VISIT(state->permutations_type); + Py_VISIT(state->accumulate_type); return 0; } @@ -4689,6 +4668,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->combinations_type); Py_CLEAR(state->cwr_type); Py_CLEAR(state->permutations_type); + Py_CLEAR(state->accumulate_type); return 0; } @@ -4722,9 +4702,9 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->combinations_type, &combinations_spec); ADD_TYPE(m, state->cwr_type, &cwr_spec); ADD_TYPE(m, state->permutations_type, &permutations_spec); + ADD_TYPE(m, state->accumulate_type, &accumulate_spec); PyTypeObject *typelist[] = { - &accumulate_type, &islice_type, &chain_type, &compress_type, From 970c8bbd446caefbc492e9f509344cd7d0a3b994 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:45:05 +0100 Subject: [PATCH 09/24] Convert compress type to heap type --- Modules/itertoolsmodule.c | 74 ++++++++++++++------------------------- 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 104cbc9d67be27..b3bd50244ed228 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -22,6 +22,7 @@ typedef struct { PyTypeObject *cwr_type; PyTypeObject *permutations_type; PyTypeObject *accumulate_type; + PyTypeObject *compress_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -57,16 +58,15 @@ class itertools.combinations "combinationsobject *" "clinic_find_state()->combin class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" -class itertools.compress "compressobject *" "&compress_type" +class itertools.compress "compressobject *" "clinic_find_state()->compress_type" class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2d745b73d7b6fa4c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdc7eab4ea99a6af]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject compress_type; static PyTypeObject filterfalse_type; static PyTypeObject count_type; static PyTypeObject pairwise_type; @@ -3663,10 +3663,12 @@ itertools_compress_impl(PyTypeObject *type, PyObject *seq1, PyObject *seq2) static void compress_dealloc(compressobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->data); Py_XDECREF(lz->selectors); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -3726,48 +3728,24 @@ static PyMethodDef compress_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject compress_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.compress", /* tp_name */ - sizeof(compressobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)compress_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_compress__doc__, /* tp_doc */ - (traverseproc)compress_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)compress_next, /* tp_iternext */ - compress_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_compress, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot compress_slots[] = { + {Py_tp_dealloc, compress_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_compress__doc__}, + {Py_tp_traverse, compress_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, compress_next}, + {Py_tp_methods, compress_methods}, + {Py_tp_new, itertools_compress}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec compress_spec = { + .name = "itertools.compress", + .basicsize = sizeof(compressobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = compress_slots, }; @@ -4652,6 +4630,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->cwr_type); Py_VISIT(state->permutations_type); Py_VISIT(state->accumulate_type); + Py_VISIT(state->compress_type); return 0; } @@ -4669,6 +4648,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->cwr_type); Py_CLEAR(state->permutations_type); Py_CLEAR(state->accumulate_type); + Py_CLEAR(state->compress_type); return 0; } @@ -4703,11 +4683,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->cwr_type, &cwr_spec); ADD_TYPE(m, state->permutations_type, &permutations_spec); ADD_TYPE(m, state->accumulate_type, &accumulate_spec); + ADD_TYPE(m, state->compress_type, &compress_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &compress_type, &filterfalse_type, &count_type, &ziplongest_type, From 8f24fb565d31bc967f812ca3f38c9d33070ddc47 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:48:31 +0100 Subject: [PATCH 10/24] Convert filterfalse type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 43a326a9bddb7f..432821ba3ee4c3 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -593,7 +593,7 @@ itertools_filterfalse(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *func; PyObject *seq; - if ((type == &filterfalse_type) && + if ((type == clinic_find_state()->filterfalse_type) && !_PyArg_NoKeywords("filterfalse", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=41d6bc523590b967 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c0f8df85f3e8ebf2 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index b3bd50244ed228..e5c07050c1f5a7 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -23,6 +23,7 @@ typedef struct { PyTypeObject *permutations_type; PyTypeObject *accumulate_type; PyTypeObject *compress_type; + PyTypeObject *filterfalse_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -59,15 +60,14 @@ class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state( class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" class itertools.compress "compressobject *" "clinic_find_state()->compress_type" -class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" +class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfalse_type" class itertools.count "countobject *" "&count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdc7eab4ea99a6af]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fe1234706efeb497]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject filterfalse_type; static PyTypeObject count_type; static PyTypeObject pairwise_type; @@ -3796,10 +3796,12 @@ itertools_filterfalse_impl(PyTypeObject *type, PyObject *func, PyObject *seq) static void filterfalse_dealloc(filterfalseobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + lz->tp_free(lz); + Py_DECREF(tp); } static int @@ -3856,48 +3858,24 @@ static PyMethodDef filterfalse_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject filterfalse_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.filterfalse", /* tp_name */ - sizeof(filterfalseobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)filterfalse_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_filterfalse__doc__, /* tp_doc */ - (traverseproc)filterfalse_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)filterfalse_next, /* tp_iternext */ - filterfalse_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_filterfalse, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot filterfalse_slots[] = { + {Py_tp_dealloc, filterfalse_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_filterfalse__doc__}, + {Py_tp_traverse, filterfalse_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, filterfalse_next}, + {Py_tp_methods, filterfalse_methods}, + {Py_tp_new, itertools_filterfalse}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec filterfalse_spec = { + .name = "itertools.filterfalse", + .basicsize = sizeof(filterfalseobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = filterfalse_slots, }; @@ -4631,6 +4609,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->permutations_type); Py_VISIT(state->accumulate_type); Py_VISIT(state->compress_type); + Py_VISIT(state->filterfalse_type); return 0; } @@ -4649,6 +4628,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->permutations_type); Py_CLEAR(state->accumulate_type); Py_CLEAR(state->compress_type); + Py_CLEAR(state->filterfalse_type); return 0; } @@ -4684,11 +4664,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->permutations_type, &permutations_spec); ADD_TYPE(m, state->accumulate_type, &accumulate_spec); ADD_TYPE(m, state->compress_type, &compress_spec); + ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &filterfalse_type, &count_type, &ziplongest_type, &pairwise_type, From 1e8d1ccfdd1c860156f4d2e6c52d62142ba868b8 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:52:07 +0100 Subject: [PATCH 11/24] Convert count type to heap type --- Modules/itertoolsmodule.c | 77 +++++++++++++++------------------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index e5c07050c1f5a7..d12b75504e94d0 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -24,6 +24,7 @@ typedef struct { PyTypeObject *accumulate_type; PyTypeObject *compress_type; PyTypeObject *filterfalse_type; + PyTypeObject *count_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -61,14 +62,13 @@ class itertools.permutations "permutationsobject *" "clinic_find_state()->permut class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" class itertools.compress "compressobject *" "clinic_find_state()->compress_type" class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfalse_type" -class itertools.count "countobject *" "&count_type" +class itertools.count "countobject *" "clinic_find_state()->count_type" class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fe1234706efeb497]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=df92deef14c14cfe]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject count_type; static PyTypeObject pairwise_type; #include "clinic/itertoolsmodule.c.h" @@ -3800,7 +3800,7 @@ filterfalse_dealloc(filterfalseobject *lz) PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); - lz->tp_free(lz); + tp->tp_free(lz); Py_DECREF(tp); } @@ -4001,10 +4001,12 @@ itertools_count_impl(PyTypeObject *type, PyObject *long_cnt, static void count_dealloc(countobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->long_cnt); Py_XDECREF(lz->long_step); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -4083,48 +4085,25 @@ static PyMethodDef count_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject count_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.count", /* tp_name */ - sizeof(countobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)count_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)count_repr, /* 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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_count__doc__, /* tp_doc */ - (traverseproc)count_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)count_next, /* tp_iternext */ - count_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_count, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot count_slots[] = { + {Py_tp_dealloc, count_dealloc}, + {Py_tp_repr, count_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_count__doc__}, + {Py_tp_traverse, count_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, count_next}, + {Py_tp_methods, count_methods}, + {Py_tp_new, itertools_count}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec count_spec = { + .name = "itertools.count", + .basicsize = sizeof(countobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = count_slots, }; @@ -4610,6 +4589,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->accumulate_type); Py_VISIT(state->compress_type); Py_VISIT(state->filterfalse_type); + Py_VISIT(state->count_type); return 0; } @@ -4629,6 +4609,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->accumulate_type); Py_CLEAR(state->compress_type); Py_CLEAR(state->filterfalse_type); + Py_CLEAR(state->count_type); return 0; } @@ -4665,11 +4646,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->accumulate_type, &accumulate_spec); ADD_TYPE(m, state->compress_type, &compress_spec); ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); + ADD_TYPE(m, state->count_type, &count_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &count_type, &ziplongest_type, &pairwise_type, &product_type, From a6df90d76d8a977b35a84f6639c8c58106a357cb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 22:56:20 +0100 Subject: [PATCH 12/24] Convert pairwise type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 74 +++++++++++------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 432821ba3ee4c3..c83c2ab714ccae 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -19,7 +19,7 @@ pairwise_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *iterable; - if ((type == &pairwise_type) && + if ((type == clinic_find_state()->pairwise_type) && !_PyArg_NoKeywords("pairwise", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=c0f8df85f3e8ebf2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6779256f3e84094b input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index d12b75504e94d0..304f34e533c282 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -25,6 +25,7 @@ typedef struct { PyTypeObject *compress_type; PyTypeObject *filterfalse_type; PyTypeObject *count_type; + PyTypeObject *pairwise_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -63,13 +64,12 @@ class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate class itertools.compress "compressobject *" "clinic_find_state()->compress_type" class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfalse_type" class itertools.count "countobject *" "clinic_find_state()->count_type" -class itertools.pairwise "pairwiseobject *" "&pairwise_type" +class itertools.pairwise "pairwiseobject *" "clinic_find_state()->pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=df92deef14c14cfe]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=87b5761911a9e0b6]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; -static PyTypeObject pairwise_type; #include "clinic/itertoolsmodule.c.h" @@ -116,10 +116,12 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable) static void pairwise_dealloc(pairwiseobject *po) { + PyTypeObject *tp = Py_TYPE(po); PyObject_GC_UnTrack(po); Py_XDECREF(po->it); Py_XDECREF(po->old); - Py_TYPE(po)->tp_free(po); + tp->tp_free(po); + Py_DECREF(tp); } static int @@ -159,48 +161,24 @@ pairwise_next(pairwiseobject *po) return result; } -static PyTypeObject pairwise_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "itertools.pairwise", /* tp_name */ - sizeof(pairwiseobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pairwise_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - pairwise_new__doc__, /* tp_doc */ - (traverseproc)pairwise_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)pairwise_next, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* 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 */ - pairwise_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot pairwise_slots[] = { + {Py_tp_dealloc, pairwise_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)pairwise_new__doc__}, + {Py_tp_traverse, pairwise_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, pairwise_next}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, pairwise_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec pairwise_spec = { + .name = "itertools.pairwise", + .basicsize = sizeof(pairwiseobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = pairwise_slots, }; @@ -4590,6 +4568,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->compress_type); Py_VISIT(state->filterfalse_type); Py_VISIT(state->count_type); + Py_VISIT(state->pairwise_type); return 0; } @@ -4610,6 +4589,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->compress_type); Py_CLEAR(state->filterfalse_type); Py_CLEAR(state->count_type); + Py_CLEAR(state->pairwise_type); return 0; } @@ -4647,12 +4627,12 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->compress_type, &compress_spec); ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); ADD_TYPE(m, state->count_type, &count_spec); + ADD_TYPE(m, state->pairwise_type, &pairwise_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, &ziplongest_type, - &pairwise_type, &product_type, &repeat_type, &tee_type, From ea4ac6460f2e3fb63424718676937a9184d5deed Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:00:11 +0100 Subject: [PATCH 13/24] Convert ziplongest type to heap type --- Modules/itertoolsmodule.c | 71 ++++++++++++++------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 304f34e533c282..17ee5780c8a66e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -26,6 +26,7 @@ typedef struct { PyTypeObject *filterfalse_type; PyTypeObject *count_type; PyTypeObject *pairwise_type; + PyTypeObject *ziplongest_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -4251,8 +4252,6 @@ typedef struct { PyObject *fillvalue; } ziplongestobject; -static PyTypeObject ziplongest_type; - static PyObject * zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -4326,11 +4325,13 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void zip_longest_dealloc(ziplongestobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->ittuple); Py_XDECREF(lz->result); Py_XDECREF(lz->fillvalue); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -4473,48 +4474,24 @@ are exhausted, the fillvalue is substituted in their place. The fillvalue\n\ defaults to None or can be specified by a keyword argument.\n\ "); -static PyTypeObject ziplongest_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.zip_longest", /* tp_name */ - sizeof(ziplongestobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)zip_longest_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - zip_longest_doc, /* tp_doc */ - (traverseproc)zip_longest_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)zip_longest_next, /* tp_iternext */ - zip_longest_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - zip_longest_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot ziplongest_slots[] = { + {Py_tp_dealloc, zip_longest_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)zip_longest_doc}, + {Py_tp_traverse, zip_longest_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, zip_longest_next}, + {Py_tp_methods, zip_longest_methods}, + {Py_tp_new, zip_longest_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec ziplongest_spec = { + .name = "itertools.zip_longest", + .basicsize = sizeof(ziplongestobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = ziplongest_slots, }; @@ -4569,6 +4546,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->filterfalse_type); Py_VISIT(state->count_type); Py_VISIT(state->pairwise_type); + Py_VISIT(state->ziplongest_type); return 0; } @@ -4590,6 +4568,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->filterfalse_type); Py_CLEAR(state->count_type); Py_CLEAR(state->pairwise_type); + Py_CLEAR(state->ziplongest_type); return 0; } @@ -4628,11 +4607,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); ADD_TYPE(m, state->count_type, &count_spec); ADD_TYPE(m, state->pairwise_type, &pairwise_spec); + ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &ziplongest_type, &product_type, &repeat_type, &tee_type, From 55fc0886e5ff9189b8787c922036a0aaa52f35bf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:04:03 +0100 Subject: [PATCH 14/24] Convert product type to heap type --- Modules/itertoolsmodule.c | 71 ++++++++++++++------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 17ee5780c8a66e..c2b7d44915d34e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -27,6 +27,7 @@ typedef struct { PyTypeObject *count_type; PyTypeObject *pairwise_type; PyTypeObject *ziplongest_type; + PyTypeObject *product_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -2089,8 +2090,6 @@ typedef struct { int stopped; /* set to 1 when the iterator is exhausted */ } productobject; -static PyTypeObject product_type; - static PyObject * product_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -2177,12 +2176,14 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void product_dealloc(productobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->pools); Py_XDECREF(lz->result); if (lz->indices != NULL) PyMem_Free(lz->indices); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static PyObject * @@ -2392,48 +2393,24 @@ product(A, repeat=4) means the same as product(A, A, A, A).\n\n\ product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n\ product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ..."); -static PyTypeObject product_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.product", /* tp_name */ - sizeof(productobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)product_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - product_doc, /* tp_doc */ - (traverseproc)product_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)product_next, /* tp_iternext */ - product_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - product_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot product_slots[] = { + {Py_tp_dealloc, product_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)product_doc}, + {Py_tp_traverse, product_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, product_next}, + {Py_tp_methods, product_methods}, + {Py_tp_new, product_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec product_spec = { + .name = "itertools.product", + .basicsize = sizeof(productobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = product_slots, }; @@ -4547,6 +4524,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->count_type); Py_VISIT(state->pairwise_type); Py_VISIT(state->ziplongest_type); + Py_VISIT(state->product_type); return 0; } @@ -4569,6 +4547,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->count_type); Py_CLEAR(state->pairwise_type); Py_CLEAR(state->ziplongest_type); + Py_CLEAR(state->product_type); return 0; } @@ -4608,11 +4587,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->count_type, &count_spec); ADD_TYPE(m, state->pairwise_type, &pairwise_spec); ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); + ADD_TYPE(m, state->product_type, &product_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &product_type, &repeat_type, &tee_type, &teedataobject_type From 7c32c2feb1e49bb5837fd96d184307a0ed8bba88 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:08:05 +0100 Subject: [PATCH 15/24] Convert repeat type to heap type --- Modules/itertoolsmodule.c | 72 ++++++++++++++------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index c2b7d44915d34e..32ed4c4eb82ed1 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -28,6 +28,7 @@ typedef struct { PyTypeObject *pairwise_type; PyTypeObject *ziplongest_type; PyTypeObject *product_type; + PyTypeObject *repeat_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -4071,8 +4072,6 @@ typedef struct { Py_ssize_t cnt; } repeatobject; -static PyTypeObject repeat_type; - static PyObject * repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -4103,9 +4102,11 @@ repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void repeat_dealloc(repeatobject *ro) { + PyTypeObject *tp = Py_TYPE(ro); PyObject_GC_UnTrack(ro); Py_XDECREF(ro->element); - Py_TYPE(ro)->tp_free(ro); + tp->tp_free(ro); + Py_DECREF(tp); } static int @@ -4173,48 +4174,25 @@ PyDoc_STRVAR(repeat_doc, for the specified number of times. If not specified, returns the object\n\ endlessly."); -static PyTypeObject repeat_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.repeat", /* tp_name */ - sizeof(repeatobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)repeat_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)repeat_repr, /* 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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - repeat_doc, /* tp_doc */ - (traverseproc)repeat_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)repeat_next, /* tp_iternext */ - repeat_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - repeat_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot repeat_slots[] = { + {Py_tp_dealloc, repeat_dealloc}, + {Py_tp_repr, repeat_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)repeat_doc}, + {Py_tp_traverse, repeat_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, repeat_next}, + {Py_tp_methods, repeat_methods}, + {Py_tp_new, repeat_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec repeat_spec = { + .name = "itertools.repeat", + .basicsize = sizeof(repeatobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = repeat_slots, }; @@ -4525,6 +4503,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->pairwise_type); Py_VISIT(state->ziplongest_type); Py_VISIT(state->product_type); + Py_VISIT(state->repeat_type); return 0; } @@ -4548,6 +4527,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->pairwise_type); Py_CLEAR(state->ziplongest_type); Py_CLEAR(state->product_type); + Py_CLEAR(state->repeat_type); return 0; } @@ -4588,11 +4568,11 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->pairwise_type, &pairwise_spec); ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); ADD_TYPE(m, state->product_type, &product_spec); + ADD_TYPE(m, state->repeat_type, &repeat_spec); PyTypeObject *typelist[] = { &islice_type, &chain_type, - &repeat_type, &tee_type, &teedataobject_type }; From 3bde6b403f749b6384c447d3b6a9681a19d8aa7a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:14:23 +0100 Subject: [PATCH 16/24] Convert islice type to heap type --- Modules/itertoolsmodule.c | 79 +++++++++++++++------------------------ 1 file changed, 30 insertions(+), 49 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 32ed4c4eb82ed1..d8387c1a298c01 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -29,6 +29,7 @@ typedef struct { PyTypeObject *ziplongest_type; PyTypeObject *product_type; PyTypeObject *repeat_type; + PyTypeObject *islice_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -1493,8 +1494,6 @@ typedef struct { Py_ssize_t cnt; } isliceobject; -static PyTypeObject islice_type; - static PyObject * islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -1504,7 +1503,8 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_ssize_t numargs; isliceobject *lz; - if (type == &islice_type && !_PyArg_NoKeywords("islice", kwds)) + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(type); + if (type == state->islice_type && !_PyArg_NoKeywords("islice", kwds)) return NULL; if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3)) @@ -1582,9 +1582,11 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void islice_dealloc(isliceobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -1696,48 +1698,24 @@ specified as another value, step determines how many values are\n\ skipped between successive calls. Works like a slice() on a list\n\ but returns an iterator."); -static PyTypeObject islice_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.islice", /* tp_name */ - sizeof(isliceobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)islice_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - islice_doc, /* tp_doc */ - (traverseproc)islice_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)islice_next, /* tp_iternext */ - islice_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - islice_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot islice_slots[] = { + {Py_tp_dealloc, islice_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)islice_doc}, + {Py_tp_traverse, islice_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, islice_next}, + {Py_tp_methods, islice_methods}, + {Py_tp_new, islice_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec islice_spec = { + .name = "itertools.islice", + .basicsize = sizeof(isliceobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = islice_slots, }; @@ -3509,7 +3487,8 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) if (PyType_Ready(&chain_type) < 0) return NULL; - if (PyType_Ready(&islice_type) < 0) + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(lz)); + if (PyType_Ready(state->islice_type) < 0) return NULL; it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O", lz->total, lz->it); @@ -3519,7 +3498,7 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) it, lz->binop ? lz->binop : Py_None); if (it == NULL) return NULL; - return Py_BuildValue("O(NiO)", &islice_type, it, 1, Py_None); + return Py_BuildValue("O(NiO)", state->islice_type, it, 1, Py_None); } return Py_BuildValue("O(OO)O", Py_TYPE(lz), lz->it, lz->binop?lz->binop:Py_None, @@ -4504,6 +4483,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->ziplongest_type); Py_VISIT(state->product_type); Py_VISIT(state->repeat_type); + Py_VISIT(state->islice_type); return 0; } @@ -4528,6 +4508,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->ziplongest_type); Py_CLEAR(state->product_type); Py_CLEAR(state->repeat_type); + Py_CLEAR(state->islice_type); return 0; } @@ -4569,9 +4550,9 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); ADD_TYPE(m, state->product_type, &product_spec); ADD_TYPE(m, state->repeat_type, &repeat_spec); + ADD_TYPE(m, state->islice_type, &islice_spec); PyTypeObject *typelist[] = { - &islice_type, &chain_type, &tee_type, &teedataobject_type From 88b09264a7e34899db5a9b758c23802c77148a1f Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:22:45 +0100 Subject: [PATCH 17/24] Convert chain type to heap type --- Modules/itertoolsmodule.c | 89 +++++++++++++++------------------------ 1 file changed, 35 insertions(+), 54 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index d8387c1a298c01..5c68000c0482ee 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -30,6 +30,7 @@ typedef struct { PyTypeObject *product_type; PyTypeObject *repeat_type; PyTypeObject *islice_type; + PyTypeObject *chain_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -60,7 +61,7 @@ class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" -class itertools.chain "chainobject *" "&chain_type" +class itertools.chain "chainobject *" "clinic_find_state->chain_type" class itertools.combinations "combinationsobject *" "clinic_find_state()->combinations_type" class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" @@ -70,7 +71,7 @@ class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfa class itertools.count "countobject *" "clinic_find_state()->count_type" class itertools.pairwise "pairwiseobject *" "clinic_find_state()->pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=87b5761911a9e0b6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e3b76dfd5ef27d0a]*/ static PyTypeObject teedataobject_type; static PyTypeObject tee_type; @@ -1844,8 +1845,6 @@ typedef struct { PyObject *active; /* Currently running input iterator */ } chainobject; -static PyTypeObject chain_type; - static PyObject * chain_new_internal(PyTypeObject *type, PyObject *source) { @@ -1867,7 +1866,8 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *source; - if (type == &chain_type && !_PyArg_NoKeywords("chain", kwds)) + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(type); + if (type == state->chain_type && !_PyArg_NoKeywords("chain", kwds)) return NULL; source = PyObject_GetIter(args); @@ -1901,10 +1901,12 @@ itertools_chain_from_iterable(PyTypeObject *type, PyObject *arg) static void chain_dealloc(chainobject *lz) { + PyTypeObject *tp = Py_TYPE(lz); PyObject_GC_UnTrack(lz); Py_XDECREF(lz->active); Py_XDECREF(lz->source); - Py_TYPE(lz)->tp_free(lz); + tp->tp_free(lz); + Py_DECREF(tp); } static int @@ -2014,48 +2016,24 @@ static PyMethodDef chain_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject chain_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.chain", /* tp_name */ - sizeof(chainobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)chain_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 | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - chain_doc, /* tp_doc */ - (traverseproc)chain_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)chain_next, /* tp_iternext */ - chain_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - chain_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot chain_slots[] = { + {Py_tp_dealloc, chain_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)chain_doc}, + {Py_tp_traverse, chain_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, chain_next}, + {Py_tp_methods, chain_methods}, + {Py_tp_new, chain_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec chain_spec = { + .name = "itertools.chain", + .basicsize = sizeof(chainobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .slots = chain_slots, }; @@ -3469,13 +3447,15 @@ accumulate_next(accumulateobject *lz) static PyObject * accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) { + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(lz)); + if (lz->initial != Py_None) { PyObject *it; assert(lz->total == NULL); - if (PyType_Ready(&chain_type) < 0) + if (PyType_Ready(state->chain_type) < 0) return NULL; - it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O", + it = PyObject_CallFunction((PyObject *)state->chain_type, "(O)O", lz->initial, lz->it); if (it == NULL) return NULL; @@ -3485,12 +3465,11 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) if (lz->total == Py_None) { PyObject *it; - if (PyType_Ready(&chain_type) < 0) + if (PyType_Ready(state->chain_type) < 0) return NULL; - itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(lz)); if (PyType_Ready(state->islice_type) < 0) return NULL; - it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O", + it = PyObject_CallFunction((PyObject *)state->chain_type, "(O)O", lz->total, lz->it); if (it == NULL) return NULL; @@ -4484,6 +4463,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->product_type); Py_VISIT(state->repeat_type); Py_VISIT(state->islice_type); + Py_VISIT(state->chain_type); return 0; } @@ -4509,6 +4489,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->product_type); Py_CLEAR(state->repeat_type); Py_CLEAR(state->islice_type); + Py_CLEAR(state->chain_type); return 0; } @@ -4551,9 +4532,9 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->product_type, &product_spec); ADD_TYPE(m, state->repeat_type, &repeat_spec); ADD_TYPE(m, state->islice_type, &islice_spec); + ADD_TYPE(m, state->chain_type, &chain_spec); PyTypeObject *typelist[] = { - &chain_type, &tee_type, &teedataobject_type }; From de95b43a7e3a9f0b464da2c9794bb5fadef25a90 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:41:21 +0100 Subject: [PATCH 18/24] Convert tee type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 93 ++++++++++++++---------------- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index c83c2ab714ccae..c485db3180f0c0 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -161,7 +161,7 @@ itertools__tee(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; PyObject *iterable; - if ((type == &tee_type) && + if ((type == clinic_find_state()->tee_type) && !_PyArg_NoKeywords("_tee", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=6779256f3e84094b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=20efa4310a6252fa input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 5c68000c0482ee..e7065a496e0248 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -5,6 +5,7 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_tuple.h" // _PyTuple_ITEMS() +#include "structmember.h" // PyMemberDef #include // offsetof() /* Itertools module written and maintained @@ -31,6 +32,7 @@ typedef struct { PyTypeObject *repeat_type; PyTypeObject *islice_type; PyTypeObject *chain_type; + PyTypeObject *tee_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -56,7 +58,7 @@ module itertools class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" class itertools.teedataobject "teedataobject *" "&teedataobject_type" -class itertools._tee "teeobject *" "&tee_type" +class itertools._tee "teeobject *" "clinic_find_state()->tee_type" class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" @@ -71,10 +73,9 @@ class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfa class itertools.count "countobject *" "clinic_find_state()->count_type" class itertools.pairwise "pairwiseobject *" "clinic_find_state()->pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e3b76dfd5ef27d0a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7da21a588c1fd9e3]*/ static PyTypeObject teedataobject_type; -static PyTypeObject tee_type; #include "clinic/itertoolsmodule.c.h" @@ -805,7 +806,8 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored)) { teeobject *newto; - newto = PyObject_GC_New(teeobject, &tee_type); + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(to)); + newto = PyObject_GC_New(teeobject, state->tee_type); if (newto == NULL) return NULL; Py_INCREF(to->dataobj); @@ -819,7 +821,7 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored)) PyDoc_STRVAR(teecopy_doc, "Returns an independent iterator."); static PyObject * -tee_fromiterable(PyObject *iterable) +tee_fromiterable(PyObject *iterable, itertoolsmodule_state *state) { teeobject *to; PyObject *it = NULL; @@ -827,12 +829,12 @@ tee_fromiterable(PyObject *iterable) it = PyObject_GetIter(iterable); if (it == NULL) return NULL; - if (PyObject_TypeCheck(it, &tee_type)) { + if (PyObject_TypeCheck(it, state->tee_type)) { to = (teeobject *)tee_copy((teeobject *)it, NULL); goto done; } - to = PyObject_GC_New(teeobject, &tee_type); + to = PyObject_GC_New(teeobject, state->tee_type); if (to == NULL) goto done; to->dataobj = (teedataobject *)teedataobject_newinternal(it); @@ -862,7 +864,8 @@ static PyObject * itertools__tee_impl(PyTypeObject *type, PyObject *iterable) /*[clinic end generated code: output=b02d3fd26c810c3f input=adc0779d2afe37a2]*/ { - return tee_fromiterable(iterable); + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(type); + return tee_fromiterable(iterable, state); } static int @@ -877,9 +880,11 @@ tee_clear(teeobject *to) static void tee_dealloc(teeobject *to) { + PyTypeObject *tp = Py_TYPE(to); PyObject_GC_UnTrack(to); tee_clear(to); PyObject_GC_Del(to); + Py_DECREF(tp); } static PyObject * @@ -917,47 +922,30 @@ static PyMethodDef tee_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject tee_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools._tee", /* tp_name */ - sizeof(teeobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)tee_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 */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - itertools__tee__doc__, /* tp_doc */ - (traverseproc)tee_traverse, /* tp_traverse */ - (inquiry)tee_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(teeobject, weakreflist), /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)tee_next, /* tp_iternext */ - tee_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools__tee, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyMemberDef tee_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(teeobject, weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot tee_slots[] = { + {Py_tp_dealloc, tee_dealloc}, + {Py_tp_doc, (void *)itertools__tee__doc__}, + {Py_tp_traverse, tee_traverse}, + {Py_tp_clear, tee_clear}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, tee_next}, + {Py_tp_methods, tee_methods}, + {Py_tp_members, tee_members}, + {Py_tp_new, itertools__tee}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec tee_spec = { + .name = "itertools._tee", + .basicsize = sizeof(teeobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = tee_slots, }; /*[clinic input] @@ -1000,7 +988,8 @@ itertools_tee_impl(PyObject *module, PyObject *iterable, Py_ssize_t n) copyable = it; } else { - copyable = tee_fromiterable(it); + itertoolsmodule_state *state = itertoolsmodule_get_state(module); + copyable = tee_fromiterable(it, state); Py_DECREF(it); if (copyable == NULL) { Py_DECREF(result); @@ -4464,6 +4453,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->repeat_type); Py_VISIT(state->islice_type); Py_VISIT(state->chain_type); + Py_VISIT(state->tee_type); return 0; } @@ -4490,6 +4480,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->repeat_type); Py_CLEAR(state->islice_type); Py_CLEAR(state->chain_type); + Py_CLEAR(state->tee_type); return 0; } @@ -4533,9 +4524,9 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->repeat_type, &repeat_spec); ADD_TYPE(m, state->islice_type, &islice_spec); ADD_TYPE(m, state->chain_type, &chain_spec); + ADD_TYPE(m, state->tee_type, &tee_spec); PyTypeObject *typelist[] = { - &tee_type, &teedataobject_type }; From 3df69b620eafd3e1e42f805461be4c99adc5551c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:54:27 +0100 Subject: [PATCH 19/24] Convert teedataobject type to heap type --- Modules/clinic/itertoolsmodule.c.h | 4 +- Modules/itertoolsmodule.c | 113 +++++++++++------------------ 2 files changed, 46 insertions(+), 71 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index c485db3180f0c0..14fac1657292f4 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -126,7 +126,7 @@ itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *values; PyObject *next; - if ((type == &teedataobject_type) && + if ((type == clinic_find_state()->teedataobject_type) && !_PyArg_NoKeywords("teedataobject", kwargs)) { goto exit; } @@ -658,4 +658,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=20efa4310a6252fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5964987035397973 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index e7065a496e0248..a75dd4b602493a 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -33,6 +33,7 @@ typedef struct { PyTypeObject *islice_type; PyTypeObject *chain_type; PyTypeObject *tee_type; + PyTypeObject *teedataobject_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -57,7 +58,7 @@ itertoolsmodule_find_state_by_type(PyTypeObject *tp) module itertools class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" -class itertools.teedataobject "teedataobject *" "&teedataobject_type" +class itertools.teedataobject "teedataobject *" "clinic_find_state()->teedataobject_type" class itertools._tee "teeobject *" "clinic_find_state()->tee_type" class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" @@ -73,9 +74,7 @@ class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfa class itertools.count "countobject *" "clinic_find_state()->count_type" class itertools.pairwise "pairwiseobject *" "clinic_find_state()->pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7da21a588c1fd9e3]*/ - -static PyTypeObject teedataobject_type; +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=453c9bd09dcd8039]*/ #include "clinic/itertoolsmodule.c.h" @@ -551,11 +550,11 @@ typedef struct { } teeobject; static PyObject * -teedataobject_newinternal(PyObject *it) +teedataobject_newinternal(PyObject *it, itertoolsmodule_state *state) { teedataobject *tdo; - tdo = PyObject_GC_New(teedataobject, &teedataobject_type); + tdo = PyObject_GC_New(teedataobject, state->teedataobject_type); if (tdo == NULL) return NULL; @@ -571,8 +570,10 @@ teedataobject_newinternal(PyObject *it) static PyObject * teedataobject_jumplink(teedataobject *tdo) { - if (tdo->nextlink == NULL) - tdo->nextlink = teedataobject_newinternal(tdo->it); + if (tdo->nextlink == NULL) { + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(tdo)); + tdo->nextlink = teedataobject_newinternal(tdo->it, state); + } Py_XINCREF(tdo->nextlink); return tdo->nextlink; } @@ -618,9 +619,9 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg) } static void -teedataobject_safe_decref(PyObject *obj) +teedataobject_safe_decref(PyObject *obj, PyTypeObject *tdo_type) { - while (obj && Py_IS_TYPE(obj, &teedataobject_type) && + while (obj && Py_IS_TYPE(obj, tdo_type) && Py_REFCNT(obj) == 1) { PyObject *nextlink = ((teedataobject *)obj)->nextlink; ((teedataobject *)obj)->nextlink = NULL; @@ -641,16 +642,19 @@ teedataobject_clear(teedataobject *tdo) Py_CLEAR(tdo->values[i]); tmp = tdo->nextlink; tdo->nextlink = NULL; - teedataobject_safe_decref(tmp); + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(tdo)); + teedataobject_safe_decref(tmp, state->teedataobject_type); return 0; } static void teedataobject_dealloc(teedataobject *tdo) { + PyTypeObject *tp = Py_TYPE(tdo); PyObject_GC_UnTrack(tdo); teedataobject_clear(tdo); PyObject_GC_Del(tdo); + Py_DECREF(tp); } static PyObject * @@ -689,9 +693,10 @@ itertools_teedataobject_impl(PyTypeObject *type, PyObject *it, teedataobject *tdo; Py_ssize_t i, len; - assert(type == &teedataobject_type); + itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(type); + assert(type == state->teedataobject_type); - tdo = (teedataobject *)teedataobject_newinternal(it); + tdo = (teedataobject *)teedataobject_newinternal(it, state); if (!tdo) return NULL; @@ -707,7 +712,7 @@ itertools_teedataobject_impl(PyTypeObject *type, PyObject *it, if (len == LINKCELLS) { if (next != Py_None) { - if (!Py_IS_TYPE(next, &teedataobject_type)) + if (!Py_IS_TYPE(next, state->teedataobject_type)) goto err; assert(tdo->nextlink == NULL); Py_INCREF(next); @@ -731,47 +736,23 @@ static PyMethodDef teedataobject_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject teedataobject_type = { - PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */ - "itertools._tee_dataobject", /* tp_name */ - sizeof(teedataobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)teedataobject_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 */ - itertools_teedataobject__doc__, /* tp_doc */ - (traverseproc)teedataobject_traverse, /* tp_traverse */ - (inquiry)teedataobject_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - teedataobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_teedataobject, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot teedataobject_slots[] = { + {Py_tp_dealloc, teedataobject_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)itertools_teedataobject__doc__}, + {Py_tp_traverse, teedataobject_traverse}, + {Py_tp_clear, teedataobject_clear}, + {Py_tp_methods, teedataobject_methods}, + {Py_tp_new, itertools_teedataobject}, + {Py_tp_free, PyObject_GC_Del}, + {0, NULL}, +}; + +static PyType_Spec teedataobject_spec = { + .name = "itertools._tee_dataobject", + .basicsize = sizeof(teedataobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = teedataobject_slots, }; @@ -837,7 +818,7 @@ tee_fromiterable(PyObject *iterable, itertoolsmodule_state *state) to = PyObject_GC_New(teeobject, state->tee_type); if (to == NULL) goto done; - to->dataobj = (teedataobject *)teedataobject_newinternal(it); + to->dataobj = (teedataobject *)teedataobject_newinternal(it, state); if (!to->dataobj) { PyObject_GC_Del(to); to = NULL; @@ -902,7 +883,8 @@ tee_setstate(teeobject *to, PyObject *state) PyErr_SetString(PyExc_TypeError, "state is not a tuple"); return NULL; } - if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index)) { + itertoolsmodule_state *m_state = itertoolsmodule_find_state_by_type(Py_TYPE(to)); + if (!PyArg_ParseTuple(state, "O!i", m_state->teedataobject_type, &tdo, &index)) { return NULL; } if (index < 0 || index > LINKCELLS) { @@ -4454,6 +4436,7 @@ itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(state->islice_type); Py_VISIT(state->chain_type); Py_VISIT(state->tee_type); + Py_VISIT(state->teedataobject_type); return 0; } @@ -4481,6 +4464,7 @@ itertoolsmodule_clear(PyObject *m) Py_CLEAR(state->islice_type); Py_CLEAR(state->chain_type); Py_CLEAR(state->tee_type); + Py_CLEAR(state->teedataobject_type); return 0; } @@ -4505,6 +4489,7 @@ static int itertoolsmodule_exec(PyObject *m) { itertoolsmodule_state *state = itertoolsmodule_get_state(m); + ADD_TYPE(m, state->groupby_type, &groupby_spec); ADD_TYPE(m, state->_grouper_type, &_grouper_spec); ADD_TYPE(m, state->cycle_type, &cycle_spec); @@ -4525,18 +4510,8 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->islice_type, &islice_spec); ADD_TYPE(m, state->chain_type, &chain_spec); ADD_TYPE(m, state->tee_type, &tee_spec); - - PyTypeObject *typelist[] = { - &teedataobject_type - }; - - Py_SET_TYPE(&teedataobject_type, &PyType_Type); - - for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { - if (PyModule_AddType(m, typelist[i]) < 0) { - return -1; - } - } + ADD_TYPE(m, state->teedataobject_type, &teedataobject_spec); + Py_SET_TYPE(state->teedataobject_type, &PyType_Type); return 0; } From adbde61c3deb2bcd4d325361f6158f101767c4eb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 3 Jan 2021 00:01:30 +0100 Subject: [PATCH 20/24] Remove unneeded PyType_Ready() calls --- Modules/itertoolsmodule.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index a75dd4b602493a..3e92668864ef48 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -3424,8 +3424,6 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) PyObject *it; assert(lz->total == NULL); - if (PyType_Ready(state->chain_type) < 0) - return NULL; it = PyObject_CallFunction((PyObject *)state->chain_type, "(O)O", lz->initial, lz->it); if (it == NULL) @@ -3436,10 +3434,6 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) if (lz->total == Py_None) { PyObject *it; - if (PyType_Ready(state->chain_type) < 0) - return NULL; - if (PyType_Ready(state->islice_type) < 0) - return NULL; it = PyObject_CallFunction((PyObject *)state->chain_type, "(O)O", lz->total, lz->it); if (it == NULL) From cb8c7fe0f86dfe3e0d8b21cc80813608f331a19e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:55:17 +0100 Subject: [PATCH 21/24] Sort types --- Modules/itertoolsmodule.c | 114 +++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 3e92668864ef48..8882684a9d0831 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -13,27 +13,27 @@ */ typedef struct { - PyTypeObject *groupby_type; PyTypeObject *_grouper_type; - PyTypeObject *cycle_type; - PyTypeObject *dropwhile_type; - PyTypeObject *takewhile_type; - PyTypeObject *starmap_type; - PyTypeObject *combinations_type; - PyTypeObject *cwr_type; - PyTypeObject *permutations_type; PyTypeObject *accumulate_type; + PyTypeObject *chain_type; + PyTypeObject *combinations_type; PyTypeObject *compress_type; - PyTypeObject *filterfalse_type; PyTypeObject *count_type; + PyTypeObject *cwr_type; + PyTypeObject *cycle_type; + PyTypeObject *dropwhile_type; + PyTypeObject *filterfalse_type; + PyTypeObject *groupby_type; + PyTypeObject *islice_type; PyTypeObject *pairwise_type; - PyTypeObject *ziplongest_type; + PyTypeObject *permutations_type; PyTypeObject *product_type; PyTypeObject *repeat_type; - PyTypeObject *islice_type; - PyTypeObject *chain_type; + PyTypeObject *starmap_type; + PyTypeObject *takewhile_type; PyTypeObject *tee_type; PyTypeObject *teedataobject_type; + PyTypeObject *ziplongest_type; } itertoolsmodule_state; static itertoolsmodule_state * @@ -56,23 +56,23 @@ itertoolsmodule_find_state_by_type(PyTypeObject *tp) /*[clinic input] module itertools -class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" class itertools._grouper "_grouperobject *" "clinic_find_state()->_grouper_type" -class itertools.teedataobject "teedataobject *" "clinic_find_state()->teedataobject_type" class itertools._tee "teeobject *" "clinic_find_state()->tee_type" -class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" -class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" -class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" -class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" +class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" class itertools.chain "chainobject *" "clinic_find_state->chain_type" class itertools.combinations "combinationsobject *" "clinic_find_state()->combinations_type" class itertools.combinations_with_replacement "cwr_object *" "clinic_find_state()->cwr_type" -class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" -class itertools.accumulate "accumulateobject *" "clinic_find_state()->accumulate_type" class itertools.compress "compressobject *" "clinic_find_state()->compress_type" -class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfalse_type" class itertools.count "countobject *" "clinic_find_state()->count_type" +class itertools.cycle "cycleobject *" "clinic_find_state()->cycle_type" +class itertools.dropwhile "dropwhileobject *" "clinic_find_state()->dropwhile_type" +class itertools.filterfalse "filterfalseobject *" "clinic_find_state()->filterfalse_type" +class itertools.groupby "groupbyobject *" "clinic_find_state()->groupby_type" class itertools.pairwise "pairwiseobject *" "clinic_find_state()->pairwise_type" +class itertools.permutations "permutationsobject *" "clinic_find_state()->permutations_type" +class itertools.starmap "starmapobject *" "clinic_find_state()->starmap_type" +class itertools.takewhile "takewhileobject *" "clinic_find_state()->takewhile_type" +class itertools.teedataobject "teedataobject *" "clinic_find_state()->teedataobject_type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=453c9bd09dcd8039]*/ @@ -4410,27 +4410,27 @@ static int itertoolsmodule_traverse(PyObject *m, visitproc visit, void *arg) { itertoolsmodule_state *state = itertoolsmodule_get_state(m); - Py_VISIT(state->groupby_type); Py_VISIT(state->_grouper_type); - Py_VISIT(state->cycle_type); - Py_VISIT(state->dropwhile_type); - Py_VISIT(state->takewhile_type); - Py_VISIT(state->starmap_type); - Py_VISIT(state->combinations_type); - Py_VISIT(state->cwr_type); - Py_VISIT(state->permutations_type); Py_VISIT(state->accumulate_type); + Py_VISIT(state->chain_type); + Py_VISIT(state->combinations_type); Py_VISIT(state->compress_type); - Py_VISIT(state->filterfalse_type); Py_VISIT(state->count_type); + Py_VISIT(state->cwr_type); + Py_VISIT(state->cycle_type); + Py_VISIT(state->dropwhile_type); + Py_VISIT(state->filterfalse_type); + Py_VISIT(state->groupby_type); + Py_VISIT(state->islice_type); Py_VISIT(state->pairwise_type); - Py_VISIT(state->ziplongest_type); + Py_VISIT(state->permutations_type); Py_VISIT(state->product_type); Py_VISIT(state->repeat_type); - Py_VISIT(state->islice_type); - Py_VISIT(state->chain_type); + Py_VISIT(state->starmap_type); + Py_VISIT(state->takewhile_type); Py_VISIT(state->tee_type); Py_VISIT(state->teedataobject_type); + Py_VISIT(state->ziplongest_type); return 0; } @@ -4438,27 +4438,27 @@ static int itertoolsmodule_clear(PyObject *m) { itertoolsmodule_state *state = itertoolsmodule_get_state(m); - Py_CLEAR(state->groupby_type); Py_CLEAR(state->_grouper_type); - Py_CLEAR(state->cycle_type); - Py_CLEAR(state->dropwhile_type); - Py_CLEAR(state->takewhile_type); - Py_CLEAR(state->starmap_type); - Py_CLEAR(state->combinations_type); - Py_CLEAR(state->cwr_type); - Py_CLEAR(state->permutations_type); Py_CLEAR(state->accumulate_type); + Py_CLEAR(state->chain_type); + Py_CLEAR(state->combinations_type); Py_CLEAR(state->compress_type); - Py_CLEAR(state->filterfalse_type); Py_CLEAR(state->count_type); + Py_CLEAR(state->cwr_type); + Py_CLEAR(state->cycle_type); + Py_CLEAR(state->dropwhile_type); + Py_CLEAR(state->filterfalse_type); + Py_CLEAR(state->groupby_type); + Py_CLEAR(state->islice_type); Py_CLEAR(state->pairwise_type); - Py_CLEAR(state->ziplongest_type); + Py_CLEAR(state->permutations_type); Py_CLEAR(state->product_type); Py_CLEAR(state->repeat_type); - Py_CLEAR(state->islice_type); - Py_CLEAR(state->chain_type); + Py_CLEAR(state->starmap_type); + Py_CLEAR(state->takewhile_type); Py_CLEAR(state->tee_type); Py_CLEAR(state->teedataobject_type); + Py_CLEAR(state->ziplongest_type); return 0; } @@ -4484,27 +4484,27 @@ itertoolsmodule_exec(PyObject *m) { itertoolsmodule_state *state = itertoolsmodule_get_state(m); - ADD_TYPE(m, state->groupby_type, &groupby_spec); ADD_TYPE(m, state->_grouper_type, &_grouper_spec); - ADD_TYPE(m, state->cycle_type, &cycle_spec); - ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); - ADD_TYPE(m, state->takewhile_type, &takewhile_spec); - ADD_TYPE(m, state->starmap_type, &starmap_spec); - ADD_TYPE(m, state->combinations_type, &combinations_spec); - ADD_TYPE(m, state->cwr_type, &cwr_spec); - ADD_TYPE(m, state->permutations_type, &permutations_spec); ADD_TYPE(m, state->accumulate_type, &accumulate_spec); + ADD_TYPE(m, state->chain_type, &chain_spec); + ADD_TYPE(m, state->combinations_type, &combinations_spec); ADD_TYPE(m, state->compress_type, &compress_spec); - ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); ADD_TYPE(m, state->count_type, &count_spec); + ADD_TYPE(m, state->cwr_type, &cwr_spec); + ADD_TYPE(m, state->cycle_type, &cycle_spec); + ADD_TYPE(m, state->dropwhile_type, &dropwhile_spec); + ADD_TYPE(m, state->filterfalse_type, &filterfalse_spec); + ADD_TYPE(m, state->groupby_type, &groupby_spec); + ADD_TYPE(m, state->islice_type, &islice_spec); ADD_TYPE(m, state->pairwise_type, &pairwise_spec); - ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); + ADD_TYPE(m, state->permutations_type, &permutations_spec); ADD_TYPE(m, state->product_type, &product_spec); ADD_TYPE(m, state->repeat_type, &repeat_spec); - ADD_TYPE(m, state->islice_type, &islice_spec); - ADD_TYPE(m, state->chain_type, &chain_spec); + ADD_TYPE(m, state->starmap_type, &starmap_spec); + ADD_TYPE(m, state->takewhile_type, &takewhile_spec); ADD_TYPE(m, state->tee_type, &tee_spec); ADD_TYPE(m, state->teedataobject_type, &teedataobject_spec); + ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); Py_SET_TYPE(state->teedataobject_type, &PyType_Type); return 0; From a2c93496138fe315fda1e0992b80f2097eb29e30 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 2 Jan 2021 23:58:56 +0100 Subject: [PATCH 22/24] Remove unneeded Py_SET_TYPE on teedataobject type --- Modules/itertoolsmodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 8882684a9d0831..f9fcd550a90ac6 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4505,7 +4505,6 @@ itertoolsmodule_exec(PyObject *m) ADD_TYPE(m, state->tee_type, &tee_spec); ADD_TYPE(m, state->teedataobject_type, &teedataobject_spec); ADD_TYPE(m, state->ziplongest_type, &ziplongest_spec); - Py_SET_TYPE(state->teedataobject_type, &PyType_Type); return 0; } From 8d8cd61df0bf41d7bc9974d5c51ba11243459f65 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 3 Jan 2021 00:03:44 +0100 Subject: [PATCH 23/24] Add NEWS --- .../NEWS.d/next/Library/2021-01-03-00-03-27.bpo-40077.JbhJl2.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-01-03-00-03-27.bpo-40077.JbhJl2.rst diff --git a/Misc/NEWS.d/next/Library/2021-01-03-00-03-27.bpo-40077.JbhJl2.rst b/Misc/NEWS.d/next/Library/2021-01-03-00-03-27.bpo-40077.JbhJl2.rst new file mode 100644 index 00000000000000..61dd9cdbf943cc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-01-03-00-03-27.bpo-40077.JbhJl2.rst @@ -0,0 +1 @@ +Convert :mod:`itertools` to heap types. Patch by Erlend E. Aasland. From 55cee70766f48b6dd54932000e652dddd8c8c732 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 3 Jan 2021 10:38:00 +0100 Subject: [PATCH 24/24] Address review: fix performance issue in tee_copy() --- Modules/itertoolsmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index f9fcd550a90ac6..05b2f039e38ff4 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -787,8 +787,7 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored)) { teeobject *newto; - itertoolsmodule_state *state = itertoolsmodule_find_state_by_type(Py_TYPE(to)); - newto = PyObject_GC_New(teeobject, state->tee_type); + newto = PyObject_GC_New(teeobject, Py_TYPE(to)); if (newto == NULL) return NULL; Py_INCREF(to->dataobj);