bpo-1635741: Port _lsprof extension to multi-phase init (PEP 489) (GH… · python/cpython@83de110
@@ -55,12 +55,22 @@ module _lsprof
5555class _lsprof.Profiler "ProfilerObject *" "&ProfilerType"
5656[clinic start generated code]*/
5757/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e349ac952152f336]*/
58-static PyTypeObject PyProfiler_Type;
59586059#include "clinic/_lsprof.c.h"
616062-#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type)
63-#define PyProfiler_CheckExact(op) Py_IS_TYPE(op, &PyProfiler_Type)
61+typedef struct {
62+PyTypeObject *profiler_type;
63+PyTypeObject *stats_entry_type;
64+PyTypeObject *stats_subentry_type;
65+} _lsprof_state;
66+67+static inline _lsprof_state*
68+_lsprof_get_state(PyObject *module)
69+{
70+void *state = PyModule_GetState(module);
71+assert(state != NULL);
72+return (_lsprof_state *)state;
73+}
64746575/*** External Timers ***/
6676@@ -478,28 +488,24 @@ static PyStructSequence_Field profiler_subentry_fields[] = {
478488};
479489480490static PyStructSequence_Desc profiler_entry_desc = {
481-"_lsprof.profiler_entry", /* name */
482-NULL, /* doc */
483-profiler_entry_fields,
484-6
491+.name = "_lsprof.profiler_entry",
492+.doc = "",
493+.fields = profiler_entry_fields,
494+.n_in_sequence = 6
485495};
486496487497static PyStructSequence_Desc profiler_subentry_desc = {
488-"_lsprof.profiler_subentry", /* name */
489-NULL, /* doc */
490-profiler_subentry_fields,
491-5
498+.name = "_lsprof.profiler_subentry",
499+.doc = "",
500+.fields = profiler_subentry_fields,
501+.n_in_sequence = 5
492502};
493503494-static int initialized;
495-static PyTypeObject StatsEntryType;
496-static PyTypeObject StatsSubEntryType;
497-498-499504typedef struct {
500505PyObject *list;
501506PyObject *sublist;
502507double factor;
508+_lsprof_state *state;
503509} statscollector_t;
504510505511static int statsForSubEntry(rotating_node_t *node, void *arg)
@@ -509,7 +515,7 @@ static int statsForSubEntry(rotating_node_t *node, void *arg)
509515ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key;
510516int err;
511517PyObject *sinfo;
512-sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType,
518+sinfo = PyObject_CallFunction((PyObject*) collect->state->stats_subentry_type,
513519"((Olldd))",
514520entry->userObj,
515521sentry->callcount,
@@ -547,7 +553,7 @@ static int statsForEntry(rotating_node_t *node, void *arg)
547553collect->sublist = Py_None;
548554 }
549555550-info = PyObject_CallFunction((PyObject*) &StatsEntryType,
556+info = PyObject_CallFunction((PyObject*) collect->state->stats_entry_type,
551557"((OllddO))",
552558entry->userObj,
553559entry->callcount,
@@ -566,6 +572,8 @@ static int statsForEntry(rotating_node_t *node, void *arg)
566572/*[clinic input]
567573_lsprof.Profiler.getstats
568574575+ cls: defining_class
576+569577list of profiler_entry objects.
570578571579getstats() -> list of profiler_entry objects
@@ -592,10 +600,11 @@ profiler_subentry objects:
592600[clinic start generated code]*/
593601594602static PyObject *
595-_lsprof_Profiler_getstats_impl(ProfilerObject *self)
596-/*[clinic end generated code: output=9461b451e9ef0f24 input=ade04fa384ce450a]*/
603+_lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls)
604+/*[clinic end generated code: output=1806ef720019ee03 input=445e193ef4522902]*/
597605{
598606statscollector_t collect;
607+collect.state = PyType_GetModuleState(cls);
599608if (pending_exception(self)) {
600609return NULL;
601610 }
@@ -735,7 +744,9 @@ profiler_dealloc(ProfilerObject *op)
735744flush_unmatched(op);
736745clearEntries(op);
737746Py_XDECREF(op->externalTimer);
738-Py_TYPE(op)->tp_free(op);
747+PyTypeObject *tp = Py_TYPE(op);
748+tp->tp_free(op);
749+Py_DECREF(tp);
739750}
740751741752static int
@@ -782,91 +793,107 @@ Profiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\
782793 is, in seconds).\n\
783794");
784795785-static PyTypeObject PyProfiler_Type = {
786-PyVarObject_HEAD_INIT(NULL, 0)
787-"_lsprof.Profiler", /* tp_name */
788-sizeof(ProfilerObject), /* tp_basicsize */
789-0, /* tp_itemsize */
790- (destructor)profiler_dealloc, /* tp_dealloc */
791-0, /* tp_vectorcall_offset */
792-0, /* tp_getattr */
793-0, /* tp_setattr */
794-0, /* tp_as_async */
795-0, /* tp_repr */
796-0, /* tp_as_number */
797-0, /* tp_as_sequence */
798-0, /* tp_as_mapping */
799-0, /* tp_hash */
800-0, /* tp_call */
801-0, /* tp_str */
802-0, /* tp_getattro */
803-0, /* tp_setattro */
804-0, /* tp_as_buffer */
805-Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
806-profiler_doc, /* tp_doc */
807-0, /* tp_traverse */
808-0, /* tp_clear */
809-0, /* tp_richcompare */
810-0, /* tp_weaklistoffset */
811-0, /* tp_iter */
812-0, /* tp_iternext */
813-profiler_methods, /* tp_methods */
814-0, /* tp_members */
815-0, /* tp_getset */
816-0, /* tp_base */
817-0, /* tp_dict */
818-0, /* tp_descr_get */
819-0, /* tp_descr_set */
820-0, /* tp_dictoffset */
821- (initproc)profiler_init, /* tp_init */
822-PyType_GenericAlloc, /* tp_alloc */
823-PyType_GenericNew, /* tp_new */
824-PyObject_Del, /* tp_free */
796+static PyType_Slot _lsprof_profiler_type_spec_slots[] = {
797+ {Py_tp_doc, (void *)profiler_doc},
798+ {Py_tp_methods, profiler_methods},
799+ {Py_tp_dealloc, profiler_dealloc},
800+ {Py_tp_init, profiler_init},
801+ {Py_tp_alloc, PyType_GenericAlloc},
802+ {Py_tp_new, PyType_GenericNew},
803+ {Py_tp_free, PyObject_Del},
804+ {0, 0}
805+};
806+807+static PyType_Spec _lsprof_profiler_type_spec = {
808+ .name = "_lsprof.Profiler",
809+ .basicsize = sizeof(ProfilerObject),
810+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
811+ .slots = _lsprof_profiler_type_spec_slots,
825812};
826813827814static PyMethodDef moduleMethods[] = {
828815 {NULL, NULL}
829816};
830817818+static int
819+_lsprof_traverse(PyObject *module, visitproc visit, void *arg)
820+{
821+_lsprof_state *state = _lsprof_get_state(module);
822+Py_VISIT(state->profiler_type);
823+Py_VISIT(state->stats_entry_type);
824+Py_VISIT(state->stats_subentry_type);
825+return 0;
826+}
827+828+static int
829+_lsprof_clear(PyObject *module)
830+{
831+_lsprof_state *state = _lsprof_get_state(module);
832+Py_CLEAR(state->profiler_type);
833+Py_CLEAR(state->stats_entry_type);
834+Py_CLEAR(state->stats_subentry_type);
835+return 0;
836+}
837+838+static void
839+_lsprof_free(void *module)
840+{
841+_lsprof_clear((PyObject *)module);
842+}
843+844+static int
845+_lsprof_exec(PyObject *module)
846+{
847+_lsprof_state *state = PyModule_GetState(module);
848+849+state->profiler_type = (PyTypeObject *)PyType_FromModuleAndSpec(
850+module, &_lsprof_profiler_type_spec, NULL);
851+if (state->profiler_type == NULL) {
852+return -1;
853+ }
854+855+if (PyModule_AddType(module, state->profiler_type) < 0) {
856+return -1;
857+ }
858+859+state->stats_entry_type = PyStructSequence_NewType(&profiler_entry_desc);
860+if (state->stats_entry_type == NULL) {
861+return -1;
862+ }
863+if (PyModule_AddType(module, state->stats_entry_type) < 0) {
864+return -1;
865+ }
866+867+state->stats_subentry_type = PyStructSequence_NewType(&profiler_subentry_desc);
868+if (state->stats_subentry_type == NULL) {
869+return -1;
870+ }
871+if (PyModule_AddType(module, state->stats_subentry_type) < 0) {
872+return -1;
873+ }
874+875+return 0;
876+}
877+878+static PyModuleDef_Slot _lsprofslots[] = {
879+ {Py_mod_exec, _lsprof_exec},
880+ {0, NULL}
881+};
831882832883static struct PyModuleDef _lsprofmodule = {
833884PyModuleDef_HEAD_INIT,
834-"_lsprof",
835-"Fast profiler",
836--1,
837-moduleMethods,
838-NULL,
839-NULL,
840-NULL,
841-NULL
885+.m_name = "_lsprof",
886+.m_doc = "Fast profiler",
887+.m_size = sizeof(_lsprof_state),
888+.m_methods = moduleMethods,
889+.m_slots = _lsprofslots,
890+.m_traverse = _lsprof_traverse,
891+.m_clear = _lsprof_clear,
892+.m_free = _lsprof_free
842893};
843894844895PyMODINIT_FUNC
845896PyInit__lsprof(void)
846897{
847-PyObject *module, *d;
848-module = PyModule_Create(&_lsprofmodule);
849-if (module == NULL)
850-return NULL;
851-d = PyModule_GetDict(module);
852-if (PyType_Ready(&PyProfiler_Type) < 0)
853-return NULL;
854-PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type);
855-856-if (!initialized) {
857-if (PyStructSequence_InitType2(&StatsEntryType,
858-&profiler_entry_desc) < 0)
859-return NULL;
860-if (PyStructSequence_InitType2(&StatsSubEntryType,
861-&profiler_subentry_desc) < 0)
862-return NULL;
863- }
864-Py_INCREF((PyObject*) &StatsEntryType);
865-Py_INCREF((PyObject*) &StatsSubEntryType);
866-PyModule_AddObject(module, "profiler_entry",
867- (PyObject*) &StatsEntryType);
868-PyModule_AddObject(module, "profiler_subentry",
869- (PyObject*) &StatsSubEntryType);
870-initialized = 1;
871-return module;
898+return PyModuleDef_Init(&_lsprofmodule);
872899}