| 
									
										
										
										
											2021-10-22 16:36:28 +03:00
										 |  |  | #ifndef Py_BUILD_CORE_BUILTIN
 | 
					
						
							|  |  |  | #  define Py_BUILD_CORE_MODULE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2021-10-12 08:38:19 +02:00
										 |  |  | #include "pycore_call.h"          // _PyObject_CallNoArgs()
 | 
					
						
							| 
									
										
										
										
											2023-08-24 20:25:22 +02:00
										 |  |  | #include "pycore_ceval.h"         // _PyEval_SetProfile()
 | 
					
						
							| 
									
										
										
										
											2021-10-13 14:09:13 +02:00
										 |  |  | #include "pycore_pystate.h"       // _PyThreadState_GET()
 | 
					
						
							| 
									
										
										
										
											2024-02-21 11:46:00 +01:00
										 |  |  | #include "pycore_time.h"          // _PyTime_FromLong()
 | 
					
						
							| 
									
										
										
										
											2025-03-20 12:35:23 +01:00
										 |  |  | #include "pycore_typeobject.h"    // _PyType_GetModuleState()
 | 
					
						
							| 
									
										
										
										
											2025-03-19 23:01:32 +01:00
										 |  |  | #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
 | 
					
						
							| 
									
										
										
										
											2023-09-05 01:54:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | #include "rotatingtree.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************/ | 
					
						
							|  |  |  | /* Written by Brett Rosen and Ted Czotter */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _ProfilerEntry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* represents a function called from another function */ | 
					
						
							|  |  |  | typedef struct _ProfilerSubEntry { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     rotating_node_t header; | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |     PyTime_t tt; | 
					
						
							|  |  |  |     PyTime_t it; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     long callcount; | 
					
						
							|  |  |  |     long recursivecallcount; | 
					
						
							|  |  |  |     long recursionLevel; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } ProfilerSubEntry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* represents a function or user defined block */ | 
					
						
							|  |  |  | typedef struct _ProfilerEntry { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     rotating_node_t header; | 
					
						
							|  |  |  |     PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */ | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |     PyTime_t tt; /* total time in this entry */ | 
					
						
							|  |  |  |     PyTime_t it; /* inline time in this entry (not in subcalls) */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     long callcount; /* how many times this was called */ | 
					
						
							|  |  |  |     long recursivecallcount; /* how many times called recursively */ | 
					
						
							|  |  |  |     long recursionLevel; | 
					
						
							|  |  |  |     rotating_node_t *calls; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } ProfilerEntry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _ProfilerContext { | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |     PyTime_t t0; | 
					
						
							|  |  |  |     PyTime_t subt; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     struct _ProfilerContext *previous; | 
					
						
							|  |  |  |     ProfilerEntry *ctxEntry; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } ProfilerContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     rotating_node_t *profilerEntries; | 
					
						
							|  |  |  |     ProfilerContext *currentProfilerContext; | 
					
						
							|  |  |  |     ProfilerContext *freelistProfilerContext; | 
					
						
							|  |  |  |     int flags; | 
					
						
							|  |  |  |     PyObject *externalTimer; | 
					
						
							|  |  |  |     double externalTimerUnit; | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     int tool_id; | 
					
						
							|  |  |  |     PyObject* missing; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } ProfilerObject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  | #define ProfilerObject_CAST(op) ((ProfilerObject *)(op))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | #define POF_ENABLED     0x001
 | 
					
						
							|  |  |  | #define POF_SUBCALLS    0x002
 | 
					
						
							|  |  |  | #define POF_BUILTINS    0x004
 | 
					
						
							| 
									
										
										
										
											2024-07-18 12:47:22 -07:00
										 |  |  | #define POF_EXT_TIMER   0x008
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | #define POF_NOMEMORY    0x100
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | module _lsprof | 
					
						
							|  |  |  | class _lsprof.Profiler "ProfilerObject *" "&ProfilerType" | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e349ac952152f336]*/ | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  | #include "clinic/_lsprof.c.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     PyTypeObject *profiler_type; | 
					
						
							|  |  |  |     PyTypeObject *stats_entry_type; | 
					
						
							|  |  |  |     PyTypeObject *stats_subentry_type; | 
					
						
							|  |  |  | } _lsprof_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline _lsprof_state* | 
					
						
							|  |  |  | _lsprof_get_state(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     void *state = PyModule_GetState(module); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     return (_lsprof_state *)state; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*** External Timers ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  | static PyTime_t CallExternalTimer(ProfilerObject *pObj) | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-18 12:47:22 -07:00
										 |  |  |     PyObject *o = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // External timer can do arbitrary things so we need a flag to prevent
 | 
					
						
							|  |  |  |     // horrible things to happen
 | 
					
						
							|  |  |  |     pObj->flags |= POF_EXT_TIMER; | 
					
						
							|  |  |  |     o = _PyObject_CallNoArgs(pObj->externalTimer); | 
					
						
							|  |  |  |     pObj->flags &= ~POF_EXT_TIMER; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (o == NULL) { | 
					
						
							| 
									
										
										
										
											2025-01-31 13:16:08 +01:00
										 |  |  |         PyErr_FormatUnraisable("Exception ignored while calling " | 
					
						
							|  |  |  |                                "_lsprof timer %R", pObj->externalTimer); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |     PyTime_t result; | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |     int err; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (pObj->externalTimerUnit > 0.0) { | 
					
						
							|  |  |  |         /* interpret the result as an integer that will be scaled
 | 
					
						
							|  |  |  |            in profiler_getstats() */ | 
					
						
							| 
									
										
										
										
											2024-02-21 11:46:00 +01:00
										 |  |  |         err = _PyTime_FromLong(&result, o); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         /* interpret the result as a double measured in seconds.
 | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |            As the profiler works with PyTime_t internally | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |            we convert it to a large integer */ | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |         err = _PyTime_FromSecondsObject(&result, o, _PyTime_ROUND_FLOOR); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(o); | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |     if (err < 0) { | 
					
						
							| 
									
										
										
										
											2025-01-31 13:16:08 +01:00
										 |  |  |         PyErr_FormatUnraisable("Exception ignored while calling " | 
					
						
							|  |  |  |                                "_lsprof timer %R", pObj->externalTimer); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  | static inline PyTime_t | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  | call_timer(ProfilerObject *pObj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (pObj->externalTimer != NULL) { | 
					
						
							|  |  |  |         return CallExternalTimer(pObj); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2024-05-05 12:15:19 +02:00
										 |  |  |         PyTime_t t; | 
					
						
							|  |  |  |         (void)PyTime_PerfCounterRaw(&t); | 
					
						
							|  |  |  |         return t; | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*** ProfilerObject ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | normalizeUserObj(PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyCFunctionObject *fn; | 
					
						
							|  |  |  |     if (!PyCFunction_Check(obj)) { | 
					
						
							| 
									
										
										
										
											2022-11-14 13:08:43 +01:00
										 |  |  |         return Py_NewRef(obj); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     /* Replace built-in function objects with a descriptive string
 | 
					
						
							|  |  |  |        because of built-in methods -- keeping a reference to | 
					
						
							|  |  |  |        __self__ is probably not a good idea. */ | 
					
						
							|  |  |  |     fn = (PyCFunctionObject *)obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fn->m_self == NULL) { | 
					
						
							|  |  |  |         /* built-in function: look up the module name */ | 
					
						
							|  |  |  |         PyObject *mod = fn->m_module; | 
					
						
							| 
									
										
										
										
											2011-06-20 14:59:53 +02:00
										 |  |  |         PyObject *modname = NULL; | 
					
						
							|  |  |  |         if (mod != NULL) { | 
					
						
							|  |  |  |             if (PyUnicode_Check(mod)) { | 
					
						
							| 
									
										
										
										
											2022-11-14 13:08:43 +01:00
										 |  |  |                 modname = Py_NewRef(mod); | 
					
						
							| 
									
										
										
										
											2010-12-08 23:31:48 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-06-20 14:59:53 +02:00
										 |  |  |             else if (PyModule_Check(mod)) { | 
					
						
							|  |  |  |                 modname = PyModule_GetNameObject(mod); | 
					
						
							|  |  |  |                 if (modname == NULL) | 
					
						
							|  |  |  |                     PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-06-20 14:59:53 +02:00
										 |  |  |         if (modname != NULL) { | 
					
						
							| 
									
										
										
										
											2016-11-16 10:17:58 +02:00
										 |  |  |             if (!_PyUnicode_EqualToASCIIString(modname, "builtins")) { | 
					
						
							| 
									
										
										
										
											2011-06-20 14:59:53 +02:00
										 |  |  |                 PyObject *result; | 
					
						
							|  |  |  |                 result = PyUnicode_FromFormat("<%U.%s>", modname, | 
					
						
							|  |  |  |                                               fn->m_ml->ml_name); | 
					
						
							|  |  |  |                 Py_DECREF(modname); | 
					
						
							|  |  |  |                 return result; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(modname); | 
					
						
							| 
									
										
										
										
											2010-12-10 18:14:16 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-06-20 14:59:53 +02:00
										 |  |  |         return PyUnicode_FromFormat("<%s>", fn->m_ml->ml_name); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         /* built-in method: try to return
 | 
					
						
							|  |  |  |             repr(getattr(type(__self__), __name__)) | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         PyObject *self = fn->m_self; | 
					
						
							|  |  |  |         PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name); | 
					
						
							| 
									
										
										
										
											2014-06-27 23:49:29 -04:00
										 |  |  |         PyObject *modname = fn->m_module; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (name != NULL) { | 
					
						
							| 
									
										
										
										
											2024-05-06 10:50:35 -07:00
										 |  |  |             PyObject *mo = _PyType_LookupRef(Py_TYPE(self), name); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             Py_DECREF(name); | 
					
						
							|  |  |  |             if (mo != NULL) { | 
					
						
							|  |  |  |                 PyObject *res = PyObject_Repr(mo); | 
					
						
							|  |  |  |                 Py_DECREF(mo); | 
					
						
							|  |  |  |                 if (res != NULL) | 
					
						
							|  |  |  |                     return res; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-06-27 23:49:29 -04:00
										 |  |  |         /* Otherwise, use __module__ */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2014-06-27 23:49:29 -04:00
										 |  |  |         if (modname != NULL && PyUnicode_Check(modname)) | 
					
						
							|  |  |  |             return PyUnicode_FromFormat("<built-in method %S.%s>", | 
					
						
							|  |  |  |                                         modname,  fn->m_ml->ml_name); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return PyUnicode_FromFormat("<built-in method %s>", | 
					
						
							|  |  |  |                                         fn->m_ml->ml_name); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ProfilerEntry* | 
					
						
							|  |  |  | newProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerEntry *self; | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |     self = (ProfilerEntry*) PyMem_Malloc(sizeof(ProfilerEntry)); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (self == NULL) { | 
					
						
							|  |  |  |         pObj->flags |= POF_NOMEMORY; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     userObj = normalizeUserObj(userObj); | 
					
						
							|  |  |  |     if (userObj == NULL) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |         PyMem_Free(self); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         pObj->flags |= POF_NOMEMORY; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->header.key = key; | 
					
						
							|  |  |  |     self->userObj = userObj; | 
					
						
							|  |  |  |     self->tt = 0; | 
					
						
							|  |  |  |     self->it = 0; | 
					
						
							|  |  |  |     self->callcount = 0; | 
					
						
							|  |  |  |     self->recursivecallcount = 0; | 
					
						
							|  |  |  |     self->recursionLevel = 0; | 
					
						
							|  |  |  |     self->calls = EMPTY_ROTATING_TREE; | 
					
						
							|  |  |  |     RotatingTree_Add(&pObj->profilerEntries, &self->header); | 
					
						
							|  |  |  |     return self; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ProfilerEntry* | 
					
						
							|  |  |  | getEntry(ProfilerObject *pObj, void *key) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | static ProfilerSubEntry * | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | getSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls, | 
					
						
							|  |  |  |                                                 (void *)entry); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ProfilerSubEntry * | 
					
						
							|  |  |  | newSubEntry(ProfilerObject *pObj,  ProfilerEntry *caller, ProfilerEntry* entry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerSubEntry *self; | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |     self = (ProfilerSubEntry*) PyMem_Malloc(sizeof(ProfilerSubEntry)); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (self == NULL) { | 
					
						
							|  |  |  |         pObj->flags |= POF_NOMEMORY; | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->header.key = (void *)entry; | 
					
						
							|  |  |  |     self->tt = 0; | 
					
						
							|  |  |  |     self->it = 0; | 
					
						
							|  |  |  |     self->callcount = 0; | 
					
						
							|  |  |  |     self->recursivecallcount = 0; | 
					
						
							|  |  |  |     self->recursionLevel = 0; | 
					
						
							|  |  |  |     RotatingTree_Add(&caller->calls, &self->header); | 
					
						
							|  |  |  |     return self; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int freeSubEntry(rotating_node_t *header, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerSubEntry *subentry = (ProfilerSubEntry*) header; | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |     PyMem_Free(subentry); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int freeEntry(rotating_node_t *header, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerEntry *entry = (ProfilerEntry*) header; | 
					
						
							|  |  |  |     RotatingTree_Enum(entry->calls, freeSubEntry, NULL); | 
					
						
							|  |  |  |     Py_DECREF(entry->userObj); | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |     PyMem_Free(entry); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void clearEntries(ProfilerObject *pObj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL); | 
					
						
							|  |  |  |     pObj->profilerEntries = EMPTY_ROTATING_TREE; | 
					
						
							|  |  |  |     /* release the memory hold by the ProfilerContexts */ | 
					
						
							|  |  |  |     if (pObj->currentProfilerContext) { | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |         PyMem_Free(pObj->currentProfilerContext); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         pObj->currentProfilerContext = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while (pObj->freelistProfilerContext) { | 
					
						
							|  |  |  |         ProfilerContext *c = pObj->freelistProfilerContext; | 
					
						
							|  |  |  |         pObj->freelistProfilerContext = c->previous; | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |         PyMem_Free(c); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     pObj->freelistProfilerContext = NULL; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     self->ctxEntry = entry; | 
					
						
							|  |  |  |     self->subt = 0; | 
					
						
							|  |  |  |     self->previous = pObj->currentProfilerContext; | 
					
						
							|  |  |  |     pObj->currentProfilerContext = self; | 
					
						
							|  |  |  |     ++entry->recursionLevel; | 
					
						
							|  |  |  |     if ((pObj->flags & POF_SUBCALLS) && self->previous) { | 
					
						
							|  |  |  |         /* find or create an entry for me in my caller's entry */ | 
					
						
							|  |  |  |         ProfilerEntry *caller = self->previous->ctxEntry; | 
					
						
							|  |  |  |         ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); | 
					
						
							|  |  |  |         if (subentry == NULL) | 
					
						
							|  |  |  |             subentry = newSubEntry(pObj, caller, entry); | 
					
						
							|  |  |  |         if (subentry) | 
					
						
							|  |  |  |             ++subentry->recursionLevel; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |     self->t0 = call_timer(pObj); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | Stop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |     PyTime_t tt = call_timer(pObj) - self->t0; | 
					
						
							|  |  |  |     PyTime_t it = tt - self->subt; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (self->previous) | 
					
						
							|  |  |  |         self->previous->subt += tt; | 
					
						
							|  |  |  |     pObj->currentProfilerContext = self->previous; | 
					
						
							|  |  |  |     if (--entry->recursionLevel == 0) | 
					
						
							|  |  |  |         entry->tt += tt; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ++entry->recursivecallcount; | 
					
						
							|  |  |  |     entry->it += it; | 
					
						
							|  |  |  |     entry->callcount++; | 
					
						
							|  |  |  |     if ((pObj->flags & POF_SUBCALLS) && self->previous) { | 
					
						
							|  |  |  |         /* find or create an entry for me in my caller's entry */ | 
					
						
							|  |  |  |         ProfilerEntry *caller = self->previous->ctxEntry; | 
					
						
							|  |  |  |         ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); | 
					
						
							|  |  |  |         if (subentry) { | 
					
						
							|  |  |  |             if (--subentry->recursionLevel == 0) | 
					
						
							|  |  |  |                 subentry->tt += tt; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 ++subentry->recursivecallcount; | 
					
						
							|  |  |  |             subentry->it += it; | 
					
						
							|  |  |  |             ++subentry->callcount; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | ptrace_enter_call(PyObject *self, void *key, PyObject *userObj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* entering a call to the function identified by 'key'
 | 
					
						
							|  |  |  |        (which can be a PyCodeObject or a PyMethodDef pointer) */ | 
					
						
							|  |  |  |     ProfilerObject *pObj = (ProfilerObject*)self; | 
					
						
							|  |  |  |     ProfilerEntry *profEntry; | 
					
						
							|  |  |  |     ProfilerContext *pContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* In the case of entering a generator expression frame via a
 | 
					
						
							|  |  |  |      * throw (gen_send_ex(.., 1)), we may already have an | 
					
						
							|  |  |  |      * Exception set here. We must not mess around with this | 
					
						
							|  |  |  |      * exception, and some of the code under here assumes that | 
					
						
							|  |  |  |      * PyErr_* is its own to mess around with, so we have to | 
					
						
							|  |  |  |      * save and restore any current exception. */ | 
					
						
							| 
									
										
										
										
											2023-02-24 21:43:03 +00:00
										 |  |  |     PyObject *exc = PyErr_GetRaisedException(); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     profEntry = getEntry(pObj, key); | 
					
						
							|  |  |  |     if (profEntry == NULL) { | 
					
						
							|  |  |  |         profEntry = newProfilerEntry(pObj, key, userObj); | 
					
						
							|  |  |  |         if (profEntry == NULL) | 
					
						
							|  |  |  |             goto restorePyerr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* grab a ProfilerContext out of the free list */ | 
					
						
							|  |  |  |     pContext = pObj->freelistProfilerContext; | 
					
						
							|  |  |  |     if (pContext) { | 
					
						
							|  |  |  |         pObj->freelistProfilerContext = pContext->previous; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         /* free list exhausted, allocate a new one */ | 
					
						
							|  |  |  |         pContext = (ProfilerContext*) | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |             PyMem_Malloc(sizeof(ProfilerContext)); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (pContext == NULL) { | 
					
						
							|  |  |  |             pObj->flags |= POF_NOMEMORY; | 
					
						
							|  |  |  |             goto restorePyerr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     initContext(pObj, pContext, profEntry); | 
					
						
							| 
									
										
											  
											
												Merged revisions 57778-58052 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r57820 | georg.brandl | 2007-08-31 08:59:27 +0200 (Fri, 31 Aug 2007) | 2 lines
  Document new shorthand notation for index entries.
........
  r57827 | georg.brandl | 2007-08-31 10:47:51 +0200 (Fri, 31 Aug 2007) | 2 lines
  Fix subitem markup.
........
  r57833 | martin.v.loewis | 2007-08-31 12:01:07 +0200 (Fri, 31 Aug 2007) | 1 line
  Mark registry components as 64-bit on Win64.
........
  r57854 | bill.janssen | 2007-08-31 21:02:23 +0200 (Fri, 31 Aug 2007) | 1 line
  deprecate use of FakeSocket
........
  r57855 | bill.janssen | 2007-08-31 21:02:46 +0200 (Fri, 31 Aug 2007) | 1 line
  remove mentions of socket.ssl in comments
........
  r57856 | bill.janssen | 2007-08-31 21:03:31 +0200 (Fri, 31 Aug 2007) | 1 line
  remove use of non-existent SSLFakeSocket in apparently untested code
........
  r57859 | martin.v.loewis | 2007-09-01 08:36:03 +0200 (Sat, 01 Sep 2007) | 3 lines
  Bug #1737210: Change Manufacturer of Windows installer to PSF.
  Will backport to 2.5.
........
  r57865 | georg.brandl | 2007-09-01 09:51:24 +0200 (Sat, 01 Sep 2007) | 2 lines
  Fix RST link (backport from Py3k).
........
  r57876 | georg.brandl | 2007-09-01 17:49:49 +0200 (Sat, 01 Sep 2007) | 2 lines
  Document sets' ">" and "<" operations (backport from py3k).
........
  r57878 | skip.montanaro | 2007-09-01 19:40:03 +0200 (Sat, 01 Sep 2007) | 4 lines
  Added a note and examples to explain that re.split does not split on an
  empty pattern match. (issue 852532).
........
  r57879 | walter.doerwald | 2007-09-01 20:18:09 +0200 (Sat, 01 Sep 2007) | 2 lines
  Fix wrong function names.
........
  r57880 | walter.doerwald | 2007-09-01 20:34:05 +0200 (Sat, 01 Sep 2007) | 2 lines
  Fix typo.
........
  r57889 | andrew.kuchling | 2007-09-01 22:31:59 +0200 (Sat, 01 Sep 2007) | 1 line
  Markup fix
........
  r57892 | andrew.kuchling | 2007-09-01 22:43:36 +0200 (Sat, 01 Sep 2007) | 1 line
  Add various items
........
  r57895 | andrew.kuchling | 2007-09-01 23:17:58 +0200 (Sat, 01 Sep 2007) | 1 line
  Wording change
........
  r57896 | andrew.kuchling | 2007-09-01 23:18:31 +0200 (Sat, 01 Sep 2007) | 1 line
  Add more items
........
  r57904 | ronald.oussoren | 2007-09-02 11:46:07 +0200 (Sun, 02 Sep 2007) | 3 lines
  Macosx: this patch ensures that the value of MACOSX_DEPLOYMENT_TARGET used
  by the Makefile is also used at configure-time.
........
  r57925 | georg.brandl | 2007-09-03 09:16:46 +0200 (Mon, 03 Sep 2007) | 2 lines
  Fix #883466: don't allow Unicode as arguments to quopri and uu codecs.
........
  r57936 | matthias.klose | 2007-09-04 01:33:04 +0200 (Tue, 04 Sep 2007) | 2 lines
  - Added support for linking the bsddb module against BerkeleyDB 4.6.x.
........
  r57954 | mark.summerfield | 2007-09-04 10:16:15 +0200 (Tue, 04 Sep 2007) | 3 lines
  Added cross-references plus a note about dict & list shallow copying.
........
  r57958 | martin.v.loewis | 2007-09-04 11:51:57 +0200 (Tue, 04 Sep 2007) | 3 lines
  Document that we rely on the OS to release the crypto
  context. Fixes #1626801.
........
  r57960 | martin.v.loewis | 2007-09-04 15:13:14 +0200 (Tue, 04 Sep 2007) | 3 lines
  Patch #1388440: Add set_completion_display_matches_hook and
  get_completion_type to readline.
........
  r57961 | martin.v.loewis | 2007-09-04 16:19:28 +0200 (Tue, 04 Sep 2007) | 3 lines
  Patch #1031213: Decode source line in SyntaxErrors back to its original
  source encoding. Will backport to 2.5.
........
  r57972 | matthias.klose | 2007-09-04 20:17:36 +0200 (Tue, 04 Sep 2007) | 3 lines
  - Makefile.pre.in(buildbottest): Run an optional script pybuildbot.identify
    to include some information about the build environment.
........
  r57973 | matthias.klose | 2007-09-04 21:05:38 +0200 (Tue, 04 Sep 2007) | 2 lines
  - Makefile.pre.in(buildbottest): Remove whitespace at eol.
........
  r57975 | matthias.klose | 2007-09-04 22:46:02 +0200 (Tue, 04 Sep 2007) | 2 lines
  - Fix libffi configure for hppa*-*-linux* | parisc*-*-linux*.
........
  r57980 | bill.janssen | 2007-09-05 02:46:27 +0200 (Wed, 05 Sep 2007) | 1 line
  SSL certificate distinguished names should be represented by tuples
........
  r57985 | martin.v.loewis | 2007-09-05 08:39:17 +0200 (Wed, 05 Sep 2007) | 3 lines
  Patch #1105: Explain that one needs to build the solution
  to get dependencies right.
........
  r57987 | armin.rigo | 2007-09-05 09:51:21 +0200 (Wed, 05 Sep 2007) | 4 lines
  PyDict_GetItem() returns a borrowed reference.
  There are probably a number of places that are open to attacks
  such as the following one, in bltinmodule.c:min_max().
........
  r57991 | martin.v.loewis | 2007-09-05 13:47:34 +0200 (Wed, 05 Sep 2007) | 3 lines
  Patch #786737: Allow building in a tree of symlinks pointing to
  a readonly source.
........
  r57993 | georg.brandl | 2007-09-05 15:36:44 +0200 (Wed, 05 Sep 2007) | 2 lines
  Backport from Py3k: Bug #1684991: explain lookup semantics for __special__ methods (new-style classes only).
........
  r58004 | armin.rigo | 2007-09-06 10:30:51 +0200 (Thu, 06 Sep 2007) | 4 lines
  Patch #1733973 by peaker:
  ptrace_enter_call() assumes no exception is currently set.
  This assumption is broken when throwing into a generator.
........
  r58006 | armin.rigo | 2007-09-06 11:30:38 +0200 (Thu, 06 Sep 2007) | 4 lines
  PyDict_GetItem() returns a borrowed reference.
  This attack is against ceval.c:IMPORT_NAME, which calls an
  object (__builtin__.__import__) without holding a reference to it.
........
  r58013 | georg.brandl | 2007-09-06 16:49:56 +0200 (Thu, 06 Sep 2007) | 2 lines
  Backport from 3k: #1116: fix reference to old filename.
........
  r58021 | thomas.heller | 2007-09-06 22:26:20 +0200 (Thu, 06 Sep 2007) | 1 line
  Fix typo:  c_float represents to C float type.
........
  r58022 | skip.montanaro | 2007-09-07 00:29:06 +0200 (Fri, 07 Sep 2007) | 3 lines
  If this is correct for py3k branch and it's already in the release25-maint
  branch, seems like it ought to be on the trunk as well.
........
  r58023 | gregory.p.smith | 2007-09-07 00:59:59 +0200 (Fri, 07 Sep 2007) | 4 lines
  Apply the fix from Issue1112 to make this test more robust and keep
  windows happy.
........
  r58031 | brett.cannon | 2007-09-07 05:17:50 +0200 (Fri, 07 Sep 2007) | 4 lines
  Make uuid1 and uuid4 tests conditional on whether ctypes can be imported;
  implementation of either function depends on ctypes but uuid as a whole does
  not.
........
  r58032 | brett.cannon | 2007-09-07 06:18:30 +0200 (Fri, 07 Sep 2007) | 6 lines
  Fix a crasher where Python code managed to infinitely recurse in C code without
  ever going back out to Python code in PyObject_Call().  Required introducing a
  static RuntimeError instance so that normalizing an exception there is no
  reliance on a recursive call that would put the exception system over the
  recursion check itself.
........
  r58034 | thomas.heller | 2007-09-07 08:32:17 +0200 (Fri, 07 Sep 2007) | 1 line
  Add a 'c_longdouble' type to the ctypes module.
........
  r58035 | thomas.heller | 2007-09-07 11:30:40 +0200 (Fri, 07 Sep 2007) | 1 line
  Remove unneeded #include.
........
  r58036 | thomas.heller | 2007-09-07 11:33:24 +0200 (Fri, 07 Sep 2007) | 6 lines
  Backport from py3k branch:
  Add a workaround for a strange bug on win64, when _ctypes is compiled
  with the SDK compiler.  This should fix the failing
  Lib\ctypes\test\test_as_parameter.py test.
........
  r58037 | georg.brandl | 2007-09-07 16:14:40 +0200 (Fri, 07 Sep 2007) | 2 lines
  Fix a wrong indentation for sublists.
........
  r58043 | georg.brandl | 2007-09-07 22:10:49 +0200 (Fri, 07 Sep 2007) | 2 lines
  #1095: ln -f doesn't work portably, fix in Makefile.
........
  r58049 | skip.montanaro | 2007-09-08 02:34:17 +0200 (Sat, 08 Sep 2007) | 1 line
  be explicit about the actual location of the missing file
........
											
										 
											2007-09-08 17:39:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | restorePyerr: | 
					
						
							| 
									
										
										
										
											2023-02-24 21:43:03 +00:00
										 |  |  |     PyErr_SetRaisedException(exc); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | ptrace_leave_call(PyObject *self, void *key) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* leaving a call to the function identified by 'key' */ | 
					
						
							|  |  |  |     ProfilerObject *pObj = (ProfilerObject*)self; | 
					
						
							|  |  |  |     ProfilerEntry *profEntry; | 
					
						
							|  |  |  |     ProfilerContext *pContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pContext = pObj->currentProfilerContext; | 
					
						
							|  |  |  |     if (pContext == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     profEntry = getEntry(pObj, key); | 
					
						
							|  |  |  |     if (profEntry) { | 
					
						
							|  |  |  |         Stop(pObj, pContext, profEntry); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         pObj->currentProfilerContext = pContext->previous; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* put pContext into the free list */ | 
					
						
							|  |  |  |     pContext->previous = pObj->freelistProfilerContext; | 
					
						
							|  |  |  |     pObj->freelistProfilerContext = pContext; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | pending_exception(ProfilerObject *pObj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (pObj->flags & POF_NOMEMORY) { | 
					
						
							|  |  |  |         pObj->flags -= POF_NOMEMORY; | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_MemoryError, | 
					
						
							|  |  |  |                         "memory was exhausted while profiling"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyStructSequence_Field profiler_entry_fields[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {"code",         "code object or built-in function name"}, | 
					
						
							|  |  |  |     {"callcount",    "how many times this was called"}, | 
					
						
							|  |  |  |     {"reccallcount", "how many times called recursively"}, | 
					
						
							|  |  |  |     {"totaltime",    "total time in this entry"}, | 
					
						
							|  |  |  |     {"inlinetime",   "inline time in this entry (not in subcalls)"}, | 
					
						
							|  |  |  |     {"calls",        "details of the calls"}, | 
					
						
							|  |  |  |     {0} | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyStructSequence_Field profiler_subentry_fields[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {"code",         "called code object or built-in function name"}, | 
					
						
							|  |  |  |     {"callcount",    "how many times this is called"}, | 
					
						
							|  |  |  |     {"reccallcount", "how many times this is called recursively"}, | 
					
						
							|  |  |  |     {"totaltime",    "total time spent in this call"}, | 
					
						
							|  |  |  |     {"inlinetime",   "inline time (not in further subcalls)"}, | 
					
						
							|  |  |  |     {0} | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyStructSequence_Desc profiler_entry_desc = { | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .name = "_lsprof.profiler_entry", | 
					
						
							|  |  |  |     .fields = profiler_entry_fields, | 
					
						
							| 
									
										
										
										
											2020-11-07 00:04:47 +08:00
										 |  |  |     .doc = NULL, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .n_in_sequence = 6 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyStructSequence_Desc profiler_subentry_desc = { | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .name = "_lsprof.profiler_subentry", | 
					
						
							|  |  |  |     .fields = profiler_subentry_fields, | 
					
						
							| 
									
										
										
										
											2020-11-07 00:04:47 +08:00
										 |  |  |     .doc = NULL, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .n_in_sequence = 5 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *list; | 
					
						
							|  |  |  |     PyObject *sublist; | 
					
						
							|  |  |  |     double factor; | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     _lsprof_state *state; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } statscollector_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int statsForSubEntry(rotating_node_t *node, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerSubEntry *sentry = (ProfilerSubEntry*) node; | 
					
						
							|  |  |  |     statscollector_t *collect = (statscollector_t*) arg; | 
					
						
							|  |  |  |     ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  |     PyObject *sinfo; | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     sinfo = PyObject_CallFunction((PyObject*) collect->state->stats_subentry_type, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                                   "((Olldd))", | 
					
						
							|  |  |  |                                   entry->userObj, | 
					
						
							|  |  |  |                                   sentry->callcount, | 
					
						
							|  |  |  |                                   sentry->recursivecallcount, | 
					
						
							|  |  |  |                                   collect->factor * sentry->tt, | 
					
						
							|  |  |  |                                   collect->factor * sentry->it); | 
					
						
							|  |  |  |     if (sinfo == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     err = PyList_Append(collect->sublist, sinfo); | 
					
						
							|  |  |  |     Py_DECREF(sinfo); | 
					
						
							|  |  |  |     return err; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int statsForEntry(rotating_node_t *node, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ProfilerEntry *entry = (ProfilerEntry*) node; | 
					
						
							|  |  |  |     statscollector_t *collect = (statscollector_t*) arg; | 
					
						
							|  |  |  |     PyObject *info; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  |     if (entry->callcount == 0) | 
					
						
							|  |  |  |         return 0;   /* skip */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (entry->calls != EMPTY_ROTATING_TREE) { | 
					
						
							|  |  |  |         collect->sublist = PyList_New(0); | 
					
						
							|  |  |  |         if (collect->sublist == NULL) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         if (RotatingTree_Enum(entry->calls, | 
					
						
							|  |  |  |                               statsForSubEntry, collect) != 0) { | 
					
						
							|  |  |  |             Py_DECREF(collect->sublist); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2022-11-14 13:08:43 +01:00
										 |  |  |         collect->sublist = Py_NewRef(Py_None); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     info = PyObject_CallFunction((PyObject*) collect->state->stats_entry_type, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                                  "((OllddO))", | 
					
						
							|  |  |  |                                  entry->userObj, | 
					
						
							|  |  |  |                                  entry->callcount, | 
					
						
							|  |  |  |                                  entry->recursivecallcount, | 
					
						
							|  |  |  |                                  collect->factor * entry->tt, | 
					
						
							|  |  |  |                                  collect->factor * entry->it, | 
					
						
							|  |  |  |                                  collect->sublist); | 
					
						
							|  |  |  |     Py_DECREF(collect->sublist); | 
					
						
							|  |  |  |     if (info == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     err = PyList_Append(collect->list, info); | 
					
						
							|  |  |  |     Py_DECREF(info); | 
					
						
							|  |  |  |     return err; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler.getstats | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     cls: defining_class | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  | list of profiler_entry objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | getstats() -> list of profiler_entry objects | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return all information collected by the profiler. | 
					
						
							|  |  |  | Each profiler_entry is a tuple-like object with the | 
					
						
							|  |  |  | following attributes: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code          code object | 
					
						
							|  |  |  |     callcount     how many times this was called | 
					
						
							|  |  |  |     reccallcount  how many times called recursively | 
					
						
							|  |  |  |     totaltime     total time in this entry | 
					
						
							|  |  |  |     inlinetime    inline time in this entry (not in subcalls) | 
					
						
							|  |  |  |     calls         details of the calls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The calls attribute is either None or a list of | 
					
						
							|  |  |  | profiler_subentry objects: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code          called code object | 
					
						
							|  |  |  |     callcount     how many times this is called | 
					
						
							|  |  |  |     reccallcount  how many times this is called recursively | 
					
						
							|  |  |  |     totaltime     total time spent in this call | 
					
						
							|  |  |  |     inlinetime    inline time (not in further subcalls) | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  | _lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls) | 
					
						
							|  |  |  | /*[clinic end generated code: output=1806ef720019ee03 input=445e193ef4522902]*/ | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     statscollector_t collect; | 
					
						
							| 
									
										
										
										
											2023-02-24 21:16:29 +01:00
										 |  |  |     collect.state = _PyType_GetModuleState(cls); | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  |     if (pending_exception(self)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  |     if (!self->externalTimer || self->externalTimerUnit == 0.0) { | 
					
						
							| 
									
										
										
										
											2024-02-20 16:02:27 +01:00
										 |  |  |         PyTime_t onesec = _PyTime_FromSeconds(1); | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |         collect.factor = (double)1 / onesec; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  |         collect.factor = self->externalTimerUnit; | 
					
						
							| 
									
										
										
										
											2019-04-11 19:11:46 +09:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     collect.list = PyList_New(0); | 
					
						
							|  |  |  |     if (collect.list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  |     if (RotatingTree_Enum(self->profilerEntries, statsForEntry, &collect) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         != 0) { | 
					
						
							|  |  |  |         Py_DECREF(collect.list); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return collect.list; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | setSubcalls(ProfilerObject *pObj, int nvalue) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (nvalue == 0) | 
					
						
							|  |  |  |         pObj->flags &= ~POF_SUBCALLS; | 
					
						
							|  |  |  |     else if (nvalue > 0) | 
					
						
							|  |  |  |         pObj->flags |=  POF_SUBCALLS; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | setBuiltins(ProfilerObject *pObj, int nvalue) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (nvalue == 0) | 
					
						
							|  |  |  |         pObj->flags &= ~POF_BUILTINS; | 
					
						
							|  |  |  |     else if (nvalue > 0) { | 
					
						
							|  |  |  |         pObj->flags |=  POF_BUILTINS; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler._pystart_callback | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code: object | 
					
						
							|  |  |  |     instruction_offset: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, | 
					
						
							|  |  |  |                                         PyObject *instruction_offset) | 
					
						
							|  |  |  | /*[clinic end generated code: output=5fec8b7ad5ed25e8 input=b166e6953c579cda]*/ | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     ptrace_enter_call((PyObject*)self, (void *)code, code); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler._pyreturn_callback | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code: object | 
					
						
							|  |  |  |     instruction_offset: object | 
					
						
							|  |  |  |     retval: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, | 
					
						
							|  |  |  |                                          PyObject *code, | 
					
						
							|  |  |  |                                          PyObject *instruction_offset, | 
					
						
							|  |  |  |                                          PyObject *retval) | 
					
						
							|  |  |  | /*[clinic end generated code: output=9e2f6fc1b882c51e input=667ffaeb2fa6fd1f]*/ | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     ptrace_leave_call((PyObject*)self, (void *)code); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObject* missing) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // return a new reference
 | 
					
						
							|  |  |  |     if (PyCFunction_Check(callable)) { | 
					
						
							|  |  |  |         Py_INCREF(callable); | 
					
						
							|  |  |  |         return (PyObject*)((PyCFunctionObject *)callable); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (Py_TYPE(callable) == &PyMethodDescr_Type) { | 
					
						
							|  |  |  |         /* For backwards compatibility need to
 | 
					
						
							|  |  |  |          * convert to builtin method */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* If no arg, skip */ | 
					
						
							|  |  |  |         if (self_arg == missing) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyObject *meth = Py_TYPE(callable)->tp_descr_get( | 
					
						
							|  |  |  |             callable, self_arg, (PyObject*)Py_TYPE(self_arg)); | 
					
						
							|  |  |  |         if (meth == NULL) { | 
					
						
							| 
									
										
										
										
											2025-04-08 10:36:47 -07:00
										 |  |  |             PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (PyCFunction_Check(meth)) { | 
					
						
							|  |  |  |             return (PyObject*)((PyCFunctionObject *)meth); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler._ccall_callback | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code: object | 
					
						
							|  |  |  |     instruction_offset: object | 
					
						
							|  |  |  |     callable: object | 
					
						
							|  |  |  |     self_arg: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, | 
					
						
							|  |  |  |                                       PyObject *instruction_offset, | 
					
						
							|  |  |  |                                       PyObject *callable, PyObject *self_arg) | 
					
						
							|  |  |  | /*[clinic end generated code: output=152db83cabd18cad input=0e66687cfb95c001]*/ | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     if (self->flags & POF_BUILTINS) { | 
					
						
							|  |  |  |         PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (cfunc) { | 
					
						
							|  |  |  |             ptrace_enter_call((PyObject*)self, | 
					
						
							|  |  |  |                               ((PyCFunctionObject *)cfunc)->m_ml, | 
					
						
							|  |  |  |                               cfunc); | 
					
						
							|  |  |  |             Py_DECREF(cfunc); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler._creturn_callback | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     code: object | 
					
						
							|  |  |  |     instruction_offset: object | 
					
						
							|  |  |  |     callable: object | 
					
						
							|  |  |  |     self_arg: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, | 
					
						
							|  |  |  |                                         PyObject *instruction_offset, | 
					
						
							|  |  |  |                                         PyObject *callable, | 
					
						
							|  |  |  |                                         PyObject *self_arg) | 
					
						
							|  |  |  | /*[clinic end generated code: output=1e886dde8fed8fb0 input=b18afe023746923a]*/ | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     if (self->flags & POF_BUILTINS) { | 
					
						
							|  |  |  |         PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (cfunc) { | 
					
						
							|  |  |  |             ptrace_leave_call((PyObject*)self, | 
					
						
							|  |  |  |                               ((PyCFunctionObject *)cfunc)->m_ml); | 
					
						
							|  |  |  |             Py_DECREF(cfunc); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct { | 
					
						
							|  |  |  |     int event; | 
					
						
							|  |  |  |     const char* callback_method; | 
					
						
							|  |  |  | } callback_table[] = { | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_PY_START, "_pystart_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_PY_RESUME, "_pystart_callback"}, | 
					
						
							| 
									
										
										
										
											2023-06-29 16:14:09 -07:00
										 |  |  |     {PY_MONITORING_EVENT_PY_THROW, "_pystart_callback"}, | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     {PY_MONITORING_EVENT_PY_RETURN, "_pyreturn_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_PY_YIELD, "_pyreturn_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_PY_UNWIND, "_pyreturn_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_CALL, "_ccall_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_C_RETURN, "_creturn_callback"}, | 
					
						
							|  |  |  |     {PY_MONITORING_EVENT_C_RAISE, "_creturn_callback"}, | 
					
						
							|  |  |  |     {0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler.enable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     subcalls: bool = True | 
					
						
							|  |  |  |         If True, also records for each function | 
					
						
							|  |  |  |         statistics separated according to its current caller. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     builtins: bool = True | 
					
						
							|  |  |  |         If True, records the time spent in | 
					
						
							|  |  |  |         built-in functions separately from their caller. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Start collecting profiling information. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, | 
					
						
							|  |  |  |                              int builtins) | 
					
						
							|  |  |  | /*[clinic end generated code: output=1e747f9dc1edd571 input=9ab81405107ab7f1]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int all_events = 0; | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |     if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-30 12:17:29 +01:00
										 |  |  |     PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring"); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     if (!monitoring) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |     PyObject *check = PyObject_CallMethod(monitoring, | 
					
						
							|  |  |  |                                           "use_tool_id", "is", | 
					
						
							|  |  |  |                                           self->tool_id, "cProfile"); | 
					
						
							|  |  |  |     if (check == NULL) { | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |         PyErr_Format(PyExc_ValueError, "Another profiling tool is already active"); | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |         goto error; | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |     Py_DECREF(check); | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     for (int i = 0; callback_table[i].callback_method; i++) { | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |         int event = (1 << callback_table[i].event); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |         PyObject* callback = PyObject_GetAttrString((PyObject*)self, callback_table[i].callback_method); | 
					
						
							|  |  |  |         if (!callback) { | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |             goto error; | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |         PyObject *register_result = PyObject_CallMethod(monitoring, "register_callback", | 
					
						
							|  |  |  |                                                         "iiO", self->tool_id, | 
					
						
							|  |  |  |                                                         event, callback); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |         Py_DECREF(callback); | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |         if (register_result == NULL) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(register_result); | 
					
						
							|  |  |  |         all_events |= event; | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |     PyObject *event_result = PyObject_CallMethod(monitoring, "set_events", "ii", | 
					
						
							|  |  |  |                                                  self->tool_id, all_events); | 
					
						
							|  |  |  |     if (event_result == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  |     Py_DECREF(event_result); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     Py_DECREF(monitoring); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     self->flags |= POF_ENABLED; | 
					
						
							| 
									
										
										
										
											2017-01-23 09:47:21 +02:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2024-11-05 15:23:24 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     Py_DECREF(monitoring); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | flush_unmatched(ProfilerObject *pObj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     while (pObj->currentProfilerContext) { | 
					
						
							|  |  |  |         ProfilerContext *pContext = pObj->currentProfilerContext; | 
					
						
							|  |  |  |         ProfilerEntry *profEntry= pContext->ctxEntry; | 
					
						
							|  |  |  |         if (profEntry) | 
					
						
							|  |  |  |             Stop(pObj, pContext, profEntry); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             pObj->currentProfilerContext = pContext->previous; | 
					
						
							|  |  |  |         if (pContext) | 
					
						
							| 
									
										
										
										
											2013-07-07 16:21:41 +02:00
										 |  |  |             PyMem_Free(pContext); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler.disable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Stop collecting profiling information. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler_disable_impl(ProfilerObject *self) | 
					
						
							|  |  |  | /*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-18 12:47:22 -07:00
										 |  |  |     if (self->flags & POF_EXT_TIMER) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_RuntimeError, | 
					
						
							|  |  |  |                         "cannot disable profiler in external timer"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     if (self->flags & POF_ENABLED) { | 
					
						
							|  |  |  |         PyObject* result = NULL; | 
					
						
							| 
									
										
										
										
											2025-01-30 12:17:29 +01:00
										 |  |  |         PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring"); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!monitoring) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; callback_table[i].callback_method; i++) { | 
					
						
							|  |  |  |             result = PyObject_CallMethod(monitoring, "register_callback", "iiO", self->tool_id, | 
					
						
							|  |  |  |                                          (1 << callback_table[i].event), Py_None); | 
					
						
							|  |  |  |             if (!result) { | 
					
						
							|  |  |  |                 Py_DECREF(monitoring); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = PyObject_CallMethod(monitoring, "set_events", "ii", self->tool_id, 0); | 
					
						
							|  |  |  |         if (!result) { | 
					
						
							|  |  |  |             Py_DECREF(monitoring); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = PyObject_CallMethod(monitoring, "free_tool_id", "i", self->tool_id); | 
					
						
							|  |  |  |         if (!result) { | 
					
						
							|  |  |  |             Py_DECREF(monitoring); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_DECREF(monitoring); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self->flags &= ~POF_ENABLED; | 
					
						
							|  |  |  |         flush_unmatched(self); | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pending_exception(self)) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-23 09:47:21 +02:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler.clear | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | Clear all profiling information collected so far. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _lsprof_Profiler_clear_impl(ProfilerObject *self) | 
					
						
							|  |  |  | /*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     if (self->flags & POF_EXT_TIMER) { | 
					
						
							| 
									
										
										
										
											2024-07-18 12:47:22 -07:00
										 |  |  |         PyErr_SetString(PyExc_RuntimeError, | 
					
						
							|  |  |  |                         "cannot clear profiler in external timer"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     clearEntries(self); | 
					
						
							| 
									
										
										
										
											2017-01-23 09:47:21 +02:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 09:29:00 +02:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  | profiler_traverse(PyObject *op, visitproc visit, void *arg) | 
					
						
							| 
									
										
										
										
											2021-05-27 09:29:00 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  |     ProfilerObject *self = ProfilerObject_CAST(op); | 
					
						
							| 
									
										
										
										
											2021-05-27 09:29:00 +02:00
										 |  |  |     Py_VISIT(Py_TYPE(op)); | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  |     Py_VISIT(self->externalTimer); | 
					
						
							| 
									
										
										
										
											2021-05-27 09:29:00 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  | profiler_dealloc(PyObject *op) | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  |     ProfilerObject *self = ProfilerObject_CAST(op); | 
					
						
							|  |  |  |     PyObject_GC_UnTrack(self); | 
					
						
							|  |  |  |     if (self->flags & POF_ENABLED) { | 
					
						
							| 
									
										
										
										
											2021-10-13 14:09:13 +02:00
										 |  |  |         PyThreadState *tstate = _PyThreadState_GET(); | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |         if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) { | 
					
						
							| 
									
										
										
										
											2025-01-31 09:45:35 +01:00
										 |  |  |             PyErr_FormatUnraisable("Exception ignored while " | 
					
						
							|  |  |  |                                    "destroying _lsprof profiler"); | 
					
						
							| 
									
										
										
										
											2020-03-13 16:39:12 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  |     flush_unmatched(self); | 
					
						
							|  |  |  |     clearEntries(self); | 
					
						
							|  |  |  |     Py_XDECREF(self->externalTimer); | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(self); | 
					
						
							|  |  |  |     tp->tp_free(self); | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     Py_DECREF(tp); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _lsprof.Profiler.__init__ as profiler_init | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     timer: object(c_default='NULL') = None | 
					
						
							|  |  |  |     timeunit: double = 0.0 | 
					
						
							|  |  |  |     subcalls: bool = True | 
					
						
							|  |  |  |     builtins: bool = True | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  | Build a profiler object using the specified timer function. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The default timer is a fast built-in one based on real time. | 
					
						
							|  |  |  | For custom timer functions returning integers, 'timeunit' can | 
					
						
							|  |  |  | be a float specifying a scale (that is, how long each integer unit | 
					
						
							|  |  |  | is, in seconds). | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, | 
					
						
							|  |  |  |                    int subcalls, int builtins) | 
					
						
							|  |  |  | /*[clinic end generated code: output=ac523803ec9f9df2 input=8285ca746f96a414]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     self->externalTimerUnit = timeunit; | 
					
						
							|  |  |  |     Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); | 
					
						
							|  |  |  |     self->tool_id = PY_MONITORING_PROFILER_ID; | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-30 12:17:29 +01:00
										 |  |  |     PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring"); | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |     if (!monitoring) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     self->missing = PyObject_GetAttrString(monitoring, "MISSING"); | 
					
						
							|  |  |  |     if (!self->missing) { | 
					
						
							| 
									
										
										
										
											2023-05-05 10:38:47 -07:00
										 |  |  |         Py_DECREF(monitoring); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(monitoring); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef profiler_methods[] = { | 
					
						
							| 
									
										
										
										
											2020-09-21 07:40:42 -05:00
										 |  |  |     _LSPROF_PROFILER_GETSTATS_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     _LSPROF_PROFILER_ENABLE_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER_DISABLE_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER_CLEAR_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER__PYSTART_CALLBACK_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER__PYRETURN_CALLBACK_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER__CCALL_CALLBACK_METHODDEF | 
					
						
							|  |  |  |     _LSPROF_PROFILER__CRETURN_CALLBACK_METHODDEF | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL, NULL} | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  | static PyType_Slot _lsprof_profiler_type_spec_slots[] = { | 
					
						
							| 
									
										
										
										
											2024-11-04 19:18:21 +03:00
										 |  |  |     {Py_tp_doc, (void *)profiler_init__doc__}, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     {Py_tp_methods, profiler_methods}, | 
					
						
							|  |  |  |     {Py_tp_dealloc, profiler_dealloc}, | 
					
						
							|  |  |  |     {Py_tp_init, profiler_init}, | 
					
						
							| 
									
										
										
										
											2021-05-27 09:29:00 +02:00
										 |  |  |     {Py_tp_traverse, profiler_traverse}, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     {0, 0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec _lsprof_profiler_type_spec = { | 
					
						
							|  |  |  |     .name = "_lsprof.Profiler", | 
					
						
							|  |  |  |     .basicsize = sizeof(ProfilerObject), | 
					
						
							| 
									
										
										
										
											2021-06-17 12:06:09 +02:00
										 |  |  |     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | | 
					
						
							|  |  |  |               Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .slots = _lsprof_profiler_type_spec_slots, | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef moduleMethods[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL, NULL} | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  | static int | 
					
						
							|  |  |  | _lsprof_traverse(PyObject *module, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _lsprof_state *state = _lsprof_get_state(module); | 
					
						
							|  |  |  |     Py_VISIT(state->profiler_type); | 
					
						
							|  |  |  |     Py_VISIT(state->stats_entry_type); | 
					
						
							|  |  |  |     Py_VISIT(state->stats_subentry_type); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _lsprof_clear(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _lsprof_state *state = _lsprof_get_state(module); | 
					
						
							|  |  |  |     Py_CLEAR(state->profiler_type); | 
					
						
							|  |  |  |     Py_CLEAR(state->stats_entry_type); | 
					
						
							|  |  |  |     Py_CLEAR(state->stats_subentry_type); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | _lsprof_free(void *module) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-02-17 14:53:03 +01:00
										 |  |  |     (void)_lsprof_clear((PyObject *)module); | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _lsprof_exec(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _lsprof_state *state = PyModule_GetState(module); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state->profiler_type = (PyTypeObject *)PyType_FromModuleAndSpec( | 
					
						
							|  |  |  |         module, &_lsprof_profiler_type_spec, NULL); | 
					
						
							|  |  |  |     if (state->profiler_type == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyModule_AddType(module, state->profiler_type) < 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state->stats_entry_type = PyStructSequence_NewType(&profiler_entry_desc); | 
					
						
							|  |  |  |     if (state->stats_entry_type == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddType(module, state->stats_entry_type) < 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state->stats_subentry_type = PyStructSequence_NewType(&profiler_subentry_desc); | 
					
						
							|  |  |  |     if (state->stats_subentry_type == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddType(module, state->stats_subentry_type) < 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyModuleDef_Slot _lsprofslots[] = { | 
					
						
							|  |  |  |     {Py_mod_exec, _lsprof_exec}, | 
					
						
							| 
									
										
										
										
											2024-03-01 07:04:16 +08:00
										 |  |  |     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | 
					
						
							| 
									
										
										
										
											2024-05-03 08:30:55 -07:00
										 |  |  |     {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     {0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _lsprofmodule = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     .m_name = "_lsprof", | 
					
						
							|  |  |  |     .m_doc = "Fast profiler", | 
					
						
							|  |  |  |     .m_size = sizeof(_lsprof_state), | 
					
						
							|  |  |  |     .m_methods = moduleMethods, | 
					
						
							|  |  |  |     .m_slots = _lsprofslots, | 
					
						
							|  |  |  |     .m_traverse = _lsprof_traverse, | 
					
						
							|  |  |  |     .m_clear = _lsprof_clear, | 
					
						
							|  |  |  |     .m_free = _lsprof_free | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | PyMODINIT_FUNC | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | PyInit__lsprof(void) | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-23 05:33:21 -05:00
										 |  |  |     return PyModuleDef_Init(&_lsprofmodule); | 
					
						
							| 
									
										
										
										
											2006-02-08 12:53:56 +00:00
										 |  |  | } |