bpo-1635741: Port _lsprof extension to multi-phase init (PEP 489) (GH… · python/cpython@83de110

@@ -55,12 +55,22 @@ module _lsprof

5555

class _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

};

479489480490

static 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

};

486496487497

static 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-499504

typedef struct {

500505

PyObject *list;

501506

PyObject *sublist;

502507

double factor;

508+

_lsprof_state *state;

503509

} statscollector_t;

504510505511

static int statsForSubEntry(rotating_node_t *node, void *arg)

@@ -509,7 +515,7 @@ static int statsForSubEntry(rotating_node_t *node, void *arg)

509515

ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key;

510516

int err;

511517

PyObject *sinfo;

512-

sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType,

518+

sinfo = PyObject_CallFunction((PyObject*) collect->state->stats_subentry_type,

513519

"((Olldd))",

514520

entry->userObj,

515521

sentry->callcount,

@@ -547,7 +553,7 @@ static int statsForEntry(rotating_node_t *node, void *arg)

547553

collect->sublist = Py_None;

548554

}

549555550-

info = PyObject_CallFunction((PyObject*) &StatsEntryType,

556+

info = PyObject_CallFunction((PyObject*) collect->state->stats_entry_type,

551557

"((OllddO))",

552558

entry->userObj,

553559

entry->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+569577

list of profiler_entry objects.

570578571579

getstats() -> list of profiler_entry objects

@@ -592,10 +600,11 @@ profiler_subentry objects:

592600

[clinic start generated code]*/

593601594602

static 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

{

598606

statscollector_t collect;

607+

collect.state = PyType_GetModuleState(cls);

599608

if (pending_exception(self)) {

600609

return NULL;

601610

}

@@ -735,7 +744,9 @@ profiler_dealloc(ProfilerObject *op)

735744

flush_unmatched(op);

736745

clearEntries(op);

737746

Py_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

}

740751741752

static 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

};

826813827814

static 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+

};

831882832883

static struct PyModuleDef _lsprofmodule = {

833884

PyModuleDef_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

};

843894844895

PyMODINIT_FUNC

845896

PyInit__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

}