diff -r 0b1b9d39bea8 Modules/_lsprof.c --- a/Modules/_lsprof.c Wed Aug 15 11:05:38 2012 +0200 +++ b/Modules/_lsprof.c Wed Aug 15 15:03:29 2012 +0200 @@ -43,6 +43,49 @@ #include #endif +typedef struct { + PyObject *PyProfiler_Type; + PyObject *empty_tuple; + int initialized; + PyObject *StatsSubEntryType; + PyObject *StatsEntryType; +} _lsprofstate; + +#define _lsprof_state(o) ((_lsprofstate *)PyModule_GetState(o)) + +static int +_lsprof_clear(PyObject *m) +{ + _lsprofstate *s = _lsprof_state(m); + Py_CLEAR(s->PyProfiler_Type); + Py_CLEAR(s->empty_tuple); + Py_CLEAR(s->StatsEntryType); + Py_CLEAR(s->StatsSubEntryType); + return 0; +} + +static int +_lsprof_traverse(PyObject *m, visitproc visit, void *arg) +{ + _lsprofstate *s = _lsprof_state(m); + Py_VISIT(s->PyProfiler_Type); + Py_VISIT(s->empty_tuple); + Py_VISIT(s->StatsEntryType); + Py_VISIT(s->StatsSubEntryType); + return 0; +} + +static void +_lsprof_free(void *m) +{ + _lsprof_clear((PyObject *)m); +} + +static struct PyModuleDef _lsprofmodule; + +#define _lsprofstate_global ((_lsprofstate *) \ + PyModule_GetState(PyState_FindModule(&_lsprofmodule))) + static PY_LONG_LONG hpTimer(void) { @@ -115,20 +158,17 @@ #define POF_BUILTINS 0x004 #define POF_NOMEMORY 0x100 -static PyTypeObject PyProfiler_Type; - -#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type) -#define PyProfiler_CheckExact(op) (Py_TYPE(op) == &PyProfiler_Type) +#define PyProfiler_Check(op) PyObject_TypeCheck(op, _lsprofstate_global->PyProfiler_Type) +#define PyProfiler_CheckExact(op) (Py_TYPE(op) == _lsprofstate_global->PyProfiler_Type) /*** External Timers ***/ #define DOUBLE_TIMER_PRECISION 4294967296.0 -static PyObject *empty_tuple; static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj) { PY_LONG_LONG result; - PyObject *o = PyObject_Call(pObj->externalTimer, empty_tuple, NULL); + PyObject *o = PyObject_Call(pObj->externalTimer, _lsprofstate_global->empty_tuple, NULL); if (o == NULL) { PyErr_WriteUnraisable(pObj->externalTimer); return 0; @@ -532,10 +572,6 @@ 5 }; -static int initialized; -static PyTypeObject StatsEntryType; -static PyTypeObject StatsSubEntryType; - typedef struct { PyObject *list; @@ -550,7 +586,7 @@ ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key; int err; PyObject *sinfo; - sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType, + sinfo = PyObject_CallFunction(_lsprofstate_global->StatsSubEntryType, "((Olldd))", entry->userObj, sentry->callcount, @@ -588,7 +624,7 @@ collect->sublist = Py_None; } - info = PyObject_CallFunction((PyObject*) &StatsEntryType, + info = PyObject_CallFunction((PyObject*) _lsprofstate_global->StatsEntryType, "((OllddO))", entry->userObj, entry->callcount, @@ -756,12 +792,16 @@ static void profiler_dealloc(ProfilerObject *op) { + PyTypeObject *type = Py_TYPE(op); if (op->flags & POF_ENABLED) PyEval_SetProfile(NULL, NULL); flush_unmatched(op); clearEntries(op); Py_XDECREF(op->externalTimer); - Py_TYPE(op)->tp_free(op); + type->tp_free(op); + if((void *)type == (void *)profiler_dealloc) { + Py_DECREF(type); + } } static int @@ -816,48 +856,27 @@ is, in seconds).\n\ "); -static PyTypeObject PyProfiler_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lsprof.Profiler", /* tp_name */ - sizeof(ProfilerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)profiler_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - profiler_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - profiler_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 */ - (initproc)profiler_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - PyObject_Del, /* tp_free */ +static PyType_Slot PyProfiler_Type_slots[] = { + {Py_tp_dealloc, (destructor)profiler_dealloc}, + {Py_tp_doc, profiler_doc}, + {Py_tp_methods, profiler_methods}, + {Py_tp_init, (initproc)profiler_init}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, PyObject_Del}, + {Py_tp_is_gc, }, + {0, 0} }; +static PyType_Spec PyProfiler_Type_spec = { + "_lsprof.Profiler", + sizeof(ProfilerObject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + PyProfiler_Type_slots, +}; + + static PyMethodDef moduleMethods[] = { {NULL, NULL} }; @@ -867,39 +886,44 @@ PyModuleDef_HEAD_INIT, "_lsprof", "Fast profiler", - -1, + sizeof(_lsprofstate), moduleMethods, NULL, - NULL, - NULL, - NULL + _lsprof_traverse, + _lsprof_clear, + _lsprof_free }; PyMODINIT_FUNC PyInit__lsprof(void) { PyObject *module, *d; + module = PyModule_Create(&_lsprofmodule); if (module == NULL) return NULL; + d = PyModule_GetDict(module); - if (PyType_Ready(&PyProfiler_Type) < 0) + + _lsprof_state(module)->PyProfiler_Type = PyType_FromSpec(&PyProfiler_Type_spec); + if (_lsprof_state(module)->PyProfiler_Type == NULL) return NULL; - PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type); - if (!initialized) { - PyStructSequence_InitType(&StatsEntryType, - &profiler_entry_desc); - PyStructSequence_InitType(&StatsSubEntryType, - &profiler_subentry_desc); + PyDict_SetItemString(d, "Profiler", _lsprof_state(module)->PyProfiler_Type); + + if (!_lsprof_state(module)->initialized) { + _lsprof_state(module)->StatsEntryType = + (PyObject *)PyStructSequence_NewType(&profiler_entry_desc); + _lsprof_state(module)->StatsSubEntryType = + (PyObject *)PyStructSequence_NewType(&profiler_subentry_desc); } - Py_INCREF((PyObject*) &StatsEntryType); - Py_INCREF((PyObject*) &StatsSubEntryType); + Py_INCREF(_lsprof_state(module)->StatsEntryType); + Py_INCREF(_lsprof_state(module)->StatsSubEntryType); PyModule_AddObject(module, "profiler_entry", - (PyObject*) &StatsEntryType); + _lsprof_state(module)->StatsEntryType); PyModule_AddObject(module, "profiler_subentry", - (PyObject*) &StatsSubEntryType); - empty_tuple = PyTuple_New(0); - initialized = 1; + _lsprof_state(module)->StatsSubEntryType); + _lsprof_state(module)->empty_tuple = PyTuple_New(0); + _lsprof_state(module)->initialized = 1; return module; }