From 76641a34ace5759fa7f1725451677f19475e5d13 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:42:39 +0100 Subject: [PATCH 01/14] Prepare init function --- Modules/_elementtree.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 85fdfa7e5ed42c..caf535990a2f07 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4382,11 +4382,19 @@ static struct PyModuleDef elementtreemodule = { elementtree_free }; +#define CREATE_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (type == NULL) { \ + goto error; \ + } \ +} while (0) + PyMODINIT_FUNC PyInit__elementtree(void) { - PyObject *m, *temp; - elementtreestate *st; + PyObject *m = NULL, *temp; + elementtreestate *st = NULL; m = PyState_FindModule(&elementtreemodule); if (m) { @@ -4396,31 +4404,31 @@ PyInit__elementtree(void) /* Initialize object types */ if (PyType_Ready(&ElementIter_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&TreeBuilder_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&Element_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&XMLParser_Type) < 0) - return NULL; + goto error; m = PyModule_Create(&elementtreemodule); if (!m) - return NULL; + goto error; st = get_elementtree_state(m); if (!(temp = PyImport_ImportModule("copy"))) - return NULL; + goto error; st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); Py_XDECREF(temp); if (st->deepcopy_obj == NULL) { - return NULL; + goto error; } assert(!PyErr_Occurred()); if (!(st->elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) - return NULL; + goto error; /* link against pyexpat */ expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); @@ -4433,10 +4441,10 @@ PyInit__elementtree(void) expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { PyErr_SetString(PyExc_ImportError, "pyexpat version is incompatible"); - return NULL; + goto error; } } else { - return NULL; + goto error; } st->parseerror_obj = PyErr_NewException( @@ -4444,8 +4452,7 @@ PyInit__elementtree(void) ); Py_INCREF(st->parseerror_obj); if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) { - Py_DECREF(st->parseerror_obj); - return NULL; + goto error; } PyTypeObject *types[] = { @@ -4456,9 +4463,14 @@ PyInit__elementtree(void) for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { if (PyModule_AddType(m, types[i]) < 0) { - return NULL; + goto error; } } return m; + +error: + Py_XDECREF(st->parseerror_obj); + Py_XDECREF(m); + return NULL; } From 5cbbe163395ac0e0e95e7165831bd175df47c236 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:46:19 +0100 Subject: [PATCH 02/14] Convert element type to heap type --- Modules/_elementtree.c | 120 +++++++++++++------------------- Modules/clinic/_elementtree.c.h | 14 ++-- 2 files changed, 56 insertions(+), 78 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index caf535990a2f07..a6c263d4cdfec9 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -81,7 +81,7 @@ static void _clear_joined_ptr(PyObject **p) } /* Types defined by this extension */ -static PyTypeObject Element_Type; +static PyTypeObject *Element_Type; static PyTypeObject ElementIter_Type; static PyTypeObject TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -215,8 +215,8 @@ typedef struct { } ElementObject; -#define Element_CheckExact(op) Py_IS_TYPE(op, &Element_Type) -#define Element_Check(op) PyObject_TypeCheck(op, &Element_Type) +#define Element_CheckExact(op) Py_IS_TYPE(op, Element_Type) +#define Element_Check(op) PyObject_TypeCheck(op, Element_Type) /* -------------------------------------------------------------------- */ @@ -284,7 +284,7 @@ create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; - self = PyObject_GC_New(ElementObject, &Element_Type); + self = PyObject_GC_New(ElementObject, Element_Type); if (self == NULL) return NULL; self->extra = NULL; @@ -381,11 +381,11 @@ get_attrib_from_keywords(PyObject *kwds) /*[clinic input] module _elementtree -class _elementtree.Element "ElementObject *" "&Element_Type" +class _elementtree.Element "ElementObject *" "Element_Type" class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type" class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=159aa50a54061c22]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ static int element_init(PyObject *self, PyObject *args, PyObject *kwds) @@ -594,7 +594,7 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) PyObject* tag; PyObject* attrib = NULL; if (!PyArg_ParseTuple(args, "O!O|O!:SubElement", - &Element_Type, &parent, &tag, + Element_Type, &parent, &tag, &PyDict_Type, &attrib)) { return NULL; } @@ -676,7 +676,9 @@ element_dealloc(ElementObject* self) element_gc_clear(self); RELEASE(sizeof(ElementObject), "destroy element"); - Py_TYPE(self)->tp_free((PyObject *)self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); Py_TRASHCAN_END } @@ -685,14 +687,14 @@ element_dealloc(ElementObject* self) /*[clinic input] _elementtree.Element.append - subelement: object(subclass_of='&Element_Type') + subelement: object(subclass_of='Element_Type') / [clinic start generated code]*/ static PyObject * _elementtree_Element_append_impl(ElementObject *self, PyObject *subelement) -/*[clinic end generated code: output=54a884b7cf2295f4 input=3ed648beb5bfa22a]*/ +/*[clinic end generated code: output=54a884b7cf2295f4 input=59866b732e6e2891]*/ { if (element_add_subelement(self, subelement) < 0) return NULL; @@ -1475,7 +1477,7 @@ element_getitem(PyObject* self_, Py_ssize_t index) _elementtree.Element.insert index: Py_ssize_t - subelement: object(subclass_of='&Element_Type') + subelement: object(subclass_of='Element_Type') / [clinic start generated code]*/ @@ -1483,7 +1485,7 @@ _elementtree.Element.insert static PyObject * _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, PyObject *subelement) -/*[clinic end generated code: output=990adfef4d424c0b input=cd6fbfcdab52d7a8]*/ +/*[clinic end generated code: output=990adfef4d424c0b input=4382c42ab2659f9b]*/ { Py_ssize_t i; @@ -1583,14 +1585,14 @@ _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, /*[clinic input] _elementtree.Element.remove - subelement: object(subclass_of='&Element_Type') + subelement: object(subclass_of='Element_Type') / [clinic start generated code]*/ static PyObject * _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) -/*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/ +/*[clinic end generated code: output=38fe6c07d6d87d1f input=cbdf9f2ab34d93b0]*/ { Py_ssize_t i; int rc; @@ -2052,16 +2054,6 @@ element_attrib_setter(ElementObject *self, PyObject *value, void *closure) return 0; } -static PySequenceMethods element_as_sequence = { - (lenfunc) element_length, - 0, /* sq_concat */ - 0, /* sq_repeat */ - element_getitem, - 0, - element_setitem, - 0, -}; - /******************************* Element iterator ****************************/ /* ElementIterObject represents the iteration state over an XML element in @@ -4190,10 +4182,9 @@ static PyMethodDef element_methods[] = { {NULL, NULL} }; -static PyMappingMethods element_as_mapping = { - (lenfunc) element_length, - (binaryfunc) element_subscr, - (objobjargproc) element_ass_subscr, +static struct PyMemberDef element_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(ElementObject, weakreflist), READONLY}, + {NULL}, }; static PyGetSetDef element_getsetlist[] = { @@ -4216,48 +4207,36 @@ static PyGetSetDef element_getsetlist[] = { {NULL}, }; -static PyTypeObject Element_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.Element", sizeof(ElementObject), 0, - /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)element_repr, /* tp_repr */ - 0, /* tp_as_number */ - &element_as_sequence, /* tp_as_sequence */ - &element_as_mapping, /* 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_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)element_gc_traverse, /* tp_traverse */ - (inquiry)element_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - element_methods, /* tp_methods */ - 0, /* tp_members */ - element_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)element_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - element_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot element_slots[] = { + {Py_tp_dealloc, element_dealloc}, + {Py_tp_repr, element_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, element_gc_traverse}, + {Py_tp_clear, element_gc_clear}, + {Py_tp_methods, element_methods}, + {Py_tp_members, element_members}, + {Py_tp_getset, element_getsetlist}, + {Py_tp_init, element_init}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, element_new}, + {Py_sq_length, element_length}, + {Py_sq_item, element_getitem}, + {Py_sq_ass_item, element_setitem}, + {Py_mp_length, element_length}, + {Py_mp_subscript, element_subscr}, + {Py_mp_ass_subscript, element_ass_subscr}, + {0, NULL}, }; +static PyType_Spec element_spec = { + .name = "xml.etree.ElementTree.Element", + .basicsize = sizeof(ElementObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = element_slots, +}; + +static PyTypeObject *Element_Type = NULL; + static PyMethodDef treebuilder_methods[] = { _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF _ELEMENTTREE_TREEBUILDER_START_METHODDEF @@ -4407,8 +4386,7 @@ PyInit__elementtree(void) goto error; if (PyType_Ready(&TreeBuilder_Type) < 0) goto error; - if (PyType_Ready(&Element_Type) < 0) - goto error; + CREATE_TYPE(m, Element_Type, &element_spec); if (PyType_Ready(&XMLParser_Type) < 0) goto error; @@ -4456,7 +4434,7 @@ PyInit__elementtree(void) } PyTypeObject *types[] = { - &Element_Type, + Element_Type, &TreeBuilder_Type, &XMLParser_Type }; diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index 2c9ba47823bf43..28d53e33d3c0c7 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -19,8 +19,8 @@ _elementtree_Element_append(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("append", "argument", (&Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, Element_Type)) { + _PyArg_BadArgument("append", "argument", (Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -442,8 +442,8 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize } index = ival; } - if (!PyObject_TypeCheck(args[1], &Element_Type)) { - _PyArg_BadArgument("insert", "argument 2", (&Element_Type)->tp_name, args[1]); + if (!PyObject_TypeCheck(args[1], Element_Type)) { + _PyArg_BadArgument("insert", "argument 2", (Element_Type)->tp_name, args[1]); goto exit; } subelement = args[1]; @@ -538,8 +538,8 @@ _elementtree_Element_remove(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("remove", "argument", (&Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, Element_Type)) { + _PyArg_BadArgument("remove", "argument", (Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -915,4 +915,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=1385b5e5688f3614 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5ea065ac45181d56 input=a9049054013a1b77]*/ From 116fa39aa2b04cf142ae883045de9d33437956f7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:51:01 +0100 Subject: [PATCH 03/14] Convert element iter type to heap type --- Modules/_elementtree.c | 63 +++++++++++++----------------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index a6c263d4cdfec9..9b0d3aa0e64bb3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -82,7 +82,7 @@ static void _clear_joined_ptr(PyObject **p) /* Types defined by this extension */ static PyTypeObject *Element_Type; -static PyTypeObject ElementIter_Type; +static PyTypeObject *ElementIter_Type; static PyTypeObject TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -2095,6 +2095,8 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->root_element); PyObject_GC_Del(it); + PyTypeObject *tp = Py_TYPE(it); + Py_DECREF(tp); } static int @@ -2238,51 +2240,25 @@ elementiter_next(ElementIterObject *it) return NULL; } +static PyType_Slot elementiter_slots[] = { + {Py_tp_dealloc, elementiter_dealloc}, + {Py_tp_traverse, elementiter_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, elementiter_next}, + {0, NULL}, +}; -static PyTypeObject ElementIter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) +static PyType_Spec elementiter_spec = { /* Using the module's name since the pure-Python implementation does not have such a type. */ - "_elementtree._element_iterator", /* tp_name */ - sizeof(ElementIterObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)elementiter_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 */ - 0, /* tp_doc */ - (traverseproc)elementiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)elementiter_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 */ - 0, /* tp_alloc */ - 0, /* tp_new */ + .name = "_elementtree._element_iterator", + .basicsize = sizeof(ElementIterObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = elementiter_slots, }; +static PyTypeObject *ElementIter_Type = NULL; + #define INIT_PARENT_STACK_SIZE 8 static PyObject * @@ -2290,7 +2266,7 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext) { ElementIterObject *it; - it = PyObject_GC_New(ElementIterObject, &ElementIter_Type); + it = PyObject_GC_New(ElementIterObject, ElementIter_Type); if (!it) return NULL; @@ -4382,8 +4358,7 @@ PyInit__elementtree(void) } /* Initialize object types */ - if (PyType_Ready(&ElementIter_Type) < 0) - goto error; + CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); if (PyType_Ready(&TreeBuilder_Type) < 0) goto error; CREATE_TYPE(m, Element_Type, &element_spec); From a792fcf1db9a2db1efa5979094f21ab18a1cdada Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:55:34 +0100 Subject: [PATCH 04/14] Convert tree builder type to heap type --- Modules/_elementtree.c | 76 ++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 9b0d3aa0e64bb3..4ddea7a25cb011 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -83,7 +83,7 @@ static void _clear_joined_ptr(PyObject **p) /* Types defined by this extension */ static PyTypeObject *Element_Type; static PyTypeObject *ElementIter_Type; -static PyTypeObject TreeBuilder_Type; +static PyTypeObject *TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -382,7 +382,7 @@ get_attrib_from_keywords(PyObject *kwds) /*[clinic input] module _elementtree class _elementtree.Element "ElementObject *" "Element_Type" -class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type" +class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ @@ -2325,7 +2325,7 @@ typedef struct { char insert_pis; } TreeBuilderObject; -#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), &TreeBuilder_Type) +#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), TreeBuilder_Type) /* -------------------------------------------------------------------- */ /* constructor and destructor */ @@ -2469,7 +2469,10 @@ treebuilder_dealloc(TreeBuilderObject *self) { PyObject_GC_UnTrack(self); treebuilder_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } /* -------------------------------------------------------------------- */ @@ -3643,7 +3646,7 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, if (target) { Py_INCREF(target); } else { - target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); + target = treebuilder_new(TreeBuilder_Type, NULL, NULL); if (!target) { Py_CLEAR(self->entity); Py_CLEAR(self->names); @@ -4223,48 +4226,26 @@ static PyMethodDef treebuilder_methods[] = { {NULL, NULL} }; -static PyTypeObject TreeBuilder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.TreeBuilder", sizeof(TreeBuilderObject), 0, - /* methods */ - (destructor)treebuilder_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_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)treebuilder_gc_traverse, /* tp_traverse */ - (inquiry)treebuilder_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - treebuilder_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 */ - _elementtree_TreeBuilder___init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - treebuilder_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot treebuilder_slots[] = { + {Py_tp_dealloc, treebuilder_dealloc}, + {Py_tp_traverse, treebuilder_gc_traverse}, + {Py_tp_clear, treebuilder_gc_clear}, + {Py_tp_methods, treebuilder_methods}, + {Py_tp_init, _elementtree_TreeBuilder___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, treebuilder_new}, + {0, NULL}, }; +static PyType_Spec treebuilder_spec = { + .name = "xml.etree.ElementTree.TreeBuilder", + .basicsize = sizeof(TreeBuilderObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = treebuilder_slots, +}; + +static PyTypeObject *TreeBuilder_Type = NULL; + static PyMethodDef xmlparser_methods[] = { _ELEMENTTREE_XMLPARSER_FEED_METHODDEF _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF @@ -4359,8 +4340,7 @@ PyInit__elementtree(void) /* Initialize object types */ CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); - if (PyType_Ready(&TreeBuilder_Type) < 0) - goto error; + CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); if (PyType_Ready(&XMLParser_Type) < 0) goto error; @@ -4410,7 +4390,7 @@ PyInit__elementtree(void) PyTypeObject *types[] = { Element_Type, - &TreeBuilder_Type, + TreeBuilder_Type, &XMLParser_Type }; From 341a92ddaf8a065339d779a22374ce46db18ba75 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:02:18 +0100 Subject: [PATCH 05/14] Convert xml parser type to heap type --- Modules/_elementtree.c | 74 ++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 4ddea7a25cb011..8d427d884b35a3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -84,7 +84,7 @@ static void _clear_joined_ptr(PyObject **p) static PyTypeObject *Element_Type; static PyTypeObject *ElementIter_Type; static PyTypeObject *TreeBuilder_Type; -static PyTypeObject XMLParser_Type; +static PyTypeObject *XMLParser_Type; /* Per-module state; PEP 3121 */ @@ -383,7 +383,7 @@ get_attrib_from_keywords(PyObject *kwds) module _elementtree class _elementtree.Element "ElementObject *" "Element_Type" class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" -class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" +class _elementtree.XMLParser "XMLParserObject *" "XMLParser_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ @@ -3786,7 +3786,10 @@ xmlparser_dealloc(XMLParserObject* self) { PyObject_GC_UnTrack(self); xmlparser_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } Py_LOCAL_INLINE(int) @@ -4254,48 +4257,28 @@ static PyMethodDef xmlparser_methods[] = { {NULL, NULL} }; -static PyTypeObject XMLParser_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0, - /* methods */ - (destructor)xmlparser_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_BASETYPE | Py_TPFLAGS_HAVE_GC, - /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)xmlparser_gc_traverse, /* tp_traverse */ - (inquiry)xmlparser_gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - xmlparser_methods, /* tp_methods */ - xmlparser_members, /* tp_members */ - xmlparser_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _elementtree_XMLParser___init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - xmlparser_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot xmlparser_slots[] = { + {Py_tp_dealloc, xmlparser_dealloc}, + {Py_tp_traverse, xmlparser_gc_traverse}, + {Py_tp_clear, xmlparser_gc_clear}, + {Py_tp_methods, xmlparser_methods}, + {Py_tp_members, xmlparser_members}, + {Py_tp_getset, xmlparser_getsetlist}, + {Py_tp_init, _elementtree_XMLParser___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, xmlparser_new}, + {0, NULL}, }; +static PyType_Spec xmlparser_spec = { + .name = "xml.etree.ElementTree.XMLParser", + .basicsize = sizeof(XMLParserObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = xmlparser_slots, +}; + +static PyTypeObject *XMLParser_Type = NULL; + /* ==================================================================== */ /* python module interface */ @@ -4342,8 +4325,7 @@ PyInit__elementtree(void) CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); - if (PyType_Ready(&XMLParser_Type) < 0) - goto error; + CREATE_TYPE(m, XMLParser_Type, &xmlparser_spec); m = PyModule_Create(&elementtreemodule); if (!m) @@ -4391,7 +4373,7 @@ PyInit__elementtree(void) PyTypeObject *types[] = { Element_Type, TreeBuilder_Type, - &XMLParser_Type + XMLParser_Type }; for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { From f35c604d283a4cf70ec751651be1e57bcacb9be7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:05:13 +0100 Subject: [PATCH 06/14] Update clinic --- Modules/_elementtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 8d427d884b35a3..909809f01ad1a1 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -385,7 +385,7 @@ class _elementtree.Element "ElementObject *" "Element_Type" class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" class _elementtree.XMLParser "XMLParserObject *" "XMLParser_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1ecdb32b55d9d5de]*/ static int element_init(PyObject *self, PyObject *args, PyObject *kwds) From b6573b1bd038a10b73fdd2b45cb4e0da8120e7fe Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:06:53 +0100 Subject: [PATCH 07/14] Add NEWS --- .../NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst diff --git a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst new file mode 100644 index 00000000000000..567aed55ffcbff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst @@ -0,0 +1 @@ +Convert `_elementtree` type to heap types. Patch by Erlend E. Aasland From 404b398d69313a941b1dae753613f8066f00f4bd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:15:29 +0100 Subject: [PATCH 08/14] Use PyModule_AddObjectRef --- Modules/_elementtree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 909809f01ad1a1..f1268e2ac0e1cb 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4366,7 +4366,9 @@ PyInit__elementtree(void) "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL ); Py_INCREF(st->parseerror_obj); - if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) { + int res = PyModule_AddObjectRef(m, "ParseError", st->parseerror_obj); + Py_DECREF(st->parseerror_obj); + if (res < 0) { goto error; } @@ -4385,7 +4387,6 @@ PyInit__elementtree(void) return m; error: - Py_XDECREF(st->parseerror_obj); Py_XDECREF(m); return NULL; } From 6e53e92da1f98c0376a8d135c1594fc20748e1e2 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 22:44:22 +0100 Subject: [PATCH 09/14] Create module before creating types --- Modules/_elementtree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f1268e2ac0e1cb..327377b59e9a11 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4321,17 +4321,17 @@ PyInit__elementtree(void) return m; } + m = PyModule_Create(&elementtreemodule); + if (!m) + goto error; + st = get_elementtree_state(m); + /* Initialize object types */ CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); CREATE_TYPE(m, XMLParser_Type, &xmlparser_spec); - m = PyModule_Create(&elementtreemodule); - if (!m) - goto error; - st = get_elementtree_state(m); - if (!(temp = PyImport_ImportModule("copy"))) goto error; st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); From 525cfaff13289d39d0cd1a5fb051f1117ff5ca81 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Nov 2020 11:43:18 +0100 Subject: [PATCH 10/14] Fetch type before GC --- Modules/_elementtree.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 327377b59e9a11..9cf8942eb66577 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -664,6 +664,8 @@ element_gc_clear(ElementObject *self) static void element_dealloc(ElementObject* self) { + PyTypeObject *tp = Py_TYPE(self); + /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); Py_TRASHCAN_BEGIN(self, element_dealloc) @@ -676,7 +678,6 @@ element_dealloc(ElementObject* self) element_gc_clear(self); RELEASE(sizeof(ElementObject), "destroy element"); - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); Py_TRASHCAN_END @@ -2083,6 +2084,7 @@ typedef struct { static void elementiter_dealloc(ElementIterObject *it) { + PyTypeObject *tp = Py_TYPE(it); Py_ssize_t i = it->parent_stack_used; it->parent_stack_used = 0; /* bpo-31095: UnTrack is needed before calling any callbacks */ @@ -2095,7 +2097,6 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->root_element); PyObject_GC_Del(it); - PyTypeObject *tp = Py_TYPE(it); Py_DECREF(tp); } @@ -2467,10 +2468,9 @@ treebuilder_gc_clear(TreeBuilderObject *self) static void treebuilder_dealloc(TreeBuilderObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); treebuilder_gc_clear(self); - - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); } @@ -3784,10 +3784,9 @@ xmlparser_gc_clear(XMLParserObject *self) static void xmlparser_dealloc(XMLParserObject* self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); xmlparser_gc_clear(self); - - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); } From 2448e931616136441aa5bf1294ab426107b19396 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Nov 2020 21:51:10 +0100 Subject: [PATCH 11/14] Add initialisation guard --- Modules/_elementtree.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 9cf8942eb66577..188342309f93eb 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4302,6 +4302,9 @@ static struct PyModuleDef elementtreemodule = { #define CREATE_TYPE(module, type, spec) \ do { \ + if (type != NULL) { \ + break; \ + } \ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ if (type == NULL) { \ goto error; \ From 959a225aa64e6605a6cbc21df90fef60a76f3b16 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 23 Nov 2020 12:09:45 +0100 Subject: [PATCH 12/14] Address Heime's review: Don't define globals twice --- Modules/_elementtree.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 188342309f93eb..1ae14ec794e5b1 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2258,8 +2258,6 @@ static PyType_Spec elementiter_spec = { .slots = elementiter_slots, }; -static PyTypeObject *ElementIter_Type = NULL; - #define INIT_PARENT_STACK_SIZE 8 static PyObject * @@ -4216,8 +4214,6 @@ static PyType_Spec element_spec = { .slots = element_slots, }; -static PyTypeObject *Element_Type = NULL; - static PyMethodDef treebuilder_methods[] = { _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF _ELEMENTTREE_TREEBUILDER_START_METHODDEF @@ -4246,8 +4242,6 @@ static PyType_Spec treebuilder_spec = { .slots = treebuilder_slots, }; -static PyTypeObject *TreeBuilder_Type = NULL; - static PyMethodDef xmlparser_methods[] = { _ELEMENTTREE_XMLPARSER_FEED_METHODDEF _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF @@ -4276,8 +4270,6 @@ static PyType_Spec xmlparser_spec = { .slots = xmlparser_slots, }; -static PyTypeObject *XMLParser_Type = NULL; - /* ==================================================================== */ /* python module interface */ From 9210a36179fc289243819f9fcf8ad3979bb5055d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 11 Jan 2021 09:52:06 +0100 Subject: [PATCH 13/14] Visit type in type traverse functions --- Modules/_elementtree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 1ae14ec794e5b1..7e213368a45c5d 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -633,6 +633,7 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) static int element_gc_traverse(ElementObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->tag); Py_VISIT(JOIN_OBJ(self->text)); Py_VISIT(JOIN_OBJ(self->tail)); @@ -2096,7 +2097,7 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->sought_tag); Py_XDECREF(it->root_element); - PyObject_GC_Del(it); + tp->tp_free(it); Py_DECREF(tp); } @@ -2109,6 +2110,7 @@ elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg) Py_VISIT(it->root_element); Py_VISIT(it->sought_tag); + Py_VISIT(Py_TYPE(it)); return 0; } @@ -2422,6 +2424,7 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, static int treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->pi_event_obj); Py_VISIT(self->comment_event_obj); Py_VISIT(self->end_ns_event_obj); @@ -3736,6 +3739,7 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, static int xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->handle_close); Py_VISIT(self->handle_pi); Py_VISIT(self->handle_comment); From a6c6feab42185ace5751cebef9e82f72263cd4b6 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 11 Jan 2021 10:12:17 +0100 Subject: [PATCH 14/14] Fix NEWS formatting --- .../next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst index 567aed55ffcbff..8a74477a4b359d 100644 --- a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst +++ b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst @@ -1 +1 @@ -Convert `_elementtree` type to heap types. Patch by Erlend E. Aasland +Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland. pFad - Phonifier reborn

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

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy