14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h"
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "compile.h"
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "frameobject.h"
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "structseq.h"
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "rotatingtree.h"
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if !defined(HAVE_LONG_LONG)
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#error "This module requires long longs!"
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** Selection of a high-precision timer ***/
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <windows.h>
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimer(void)
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    LARGE_INTEGER li;
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    QueryPerformanceCounter(&li);
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return li.QuadPart;
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic double
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimerUnit(void)
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    LARGE_INTEGER li;
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (QueryPerformanceFrequency(&li))
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 1.0 / li.QuadPart;
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0.000001;  /* unlikely */
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else  /* !MS_WINDOWS */
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef HAVE_GETTIMEOFDAY
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#error "This module requires gettimeofday() on non-Windows platforms!"
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if (defined(PYOS_OS2) && defined(PYCC_GCC))
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/time.h>
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/resource.h>
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/times.h>
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimer(void)
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    struct timeval tv;
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG ret;
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef GETTIMEOFDAY_NO_TZ
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    gettimeofday(&tv);
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    gettimeofday(&tv, (struct timezone *)NULL);
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ret = tv.tv_sec;
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ret = ret * 1000000 + tv.tv_usec;
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return ret;
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic double
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimerUnit(void)
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0.000001;
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif  /* MS_WINDOWS */
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/************************************************************/
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Written by Brett Rosen and Ted Czotter */
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstruct _ProfilerEntry;
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* represents a function called from another function */
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerSubEntry {
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    rotating_node_t header;
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG tt;
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG it;
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long callcount;
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long recursivecallcount;
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long recursionLevel;
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerSubEntry;
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* represents a function or user defined block */
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerEntry {
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    rotating_node_t header;
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG tt; /* total time in this entry */
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG it; /* inline time in this entry (not in subcalls) */
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long callcount; /* how many times this was called */
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long recursivecallcount; /* how many times called recursively */
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    long recursionLevel;
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    rotating_node_t *calls;
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerEntry;
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerContext {
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG t0;
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG subt;
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    struct _ProfilerContext *previous;
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *ctxEntry;
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerContext;
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_HEAD
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    rotating_node_t *profilerEntries;
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerContext *currentProfilerContext;
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerContext *freelistProfilerContext;
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int flags;
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *externalTimer;
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    double externalTimerUnit;
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerObject;
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_ENABLED     0x001
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_SUBCALLS    0x002
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_BUILTINS    0x004
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_NOMEMORY    0x100
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstaticforward PyTypeObject PyProfiler_Type;
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type)
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PyProfiler_CheckExact(op) (Py_TYPE(op) == &PyProfiler_Type)
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** External Timers ***/
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define DOUBLE_TIMER_PRECISION   4294967296.0
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *empty_tuple;
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj)
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG result;
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *o = PyObject_Call(pObj->externalTimer, empty_tuple, NULL);
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (o == NULL) {
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_WriteUnraisable(pObj->externalTimer);
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pObj->externalTimerUnit > 0.0) {
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* interpret the result as an integer that will be scaled
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           in profiler_getstats() */
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = PyLong_AsLongLong(o);
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* interpret the result as a double measured in seconds.
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           As the profiler works with PY_LONG_LONG internally
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           we convert it to a large integer */
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        double val = PyFloat_AsDouble(o);
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* error handling delayed to the code below */
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result = (PY_LONG_LONG) (val * DOUBLE_TIMER_PRECISION);
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(o);
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyErr_Occurred()) {
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_WriteUnraisable(pObj->externalTimer);
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return result;
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define CALL_TIMER(pObj)        ((pObj)->externalTimer ?                \
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                        CallExternalTimer(pObj) :       \
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                        hpTimer())
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** ProfilerObject ***/
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnormalizeUserObj(PyObject *obj)
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyCFunctionObject *fn;
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyCFunction_Check(obj)) {
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(obj);
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return obj;
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* Replace built-in function objects with a descriptive string
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       because of built-in methods -- keeping a reference to
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       __self__ is probably not a good idea. */
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    fn = (PyCFunctionObject *)obj;
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (fn->m_self == NULL) {
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* built-in function: look up the module name */
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *mod = fn->m_module;
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        char *modname;
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (mod && PyString_Check(mod)) {
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            modname = PyString_AS_STRING(mod);
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else if (mod && PyModule_Check(mod)) {
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            modname = PyModule_GetName(mod);
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (modname == NULL) {
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyErr_Clear();
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                modname = "__builtin__";
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else {
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            modname = "__builtin__";
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (strcmp(modname, "__builtin__") != 0)
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return PyString_FromFormat("<%s.%s>",
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       modname,
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       fn->m_ml->ml_name);
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return PyString_FromFormat("<%s>",
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       fn->m_ml->ml_name);
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* built-in method: try to return
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            repr(getattr(type(__self__), __name__))
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        */
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *self = fn->m_self;
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyObject *name = PyString_FromString(fn->m_ml->ml_name);
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (name != NULL) {
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            PyObject *mo = _PyType_Lookup(Py_TYPE(self), name);
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_XINCREF(mo);
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(name);
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (mo != NULL) {
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                PyObject *res = PyObject_Repr(mo);
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                Py_DECREF(mo);
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (res != NULL)
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return res;
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            }
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Clear();
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return PyString_FromFormat("<built-in method %s>",
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   fn->m_ml->ml_name);
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerEntry*
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnewProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj)
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *self;
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (ProfilerEntry*) malloc(sizeof(ProfilerEntry));
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL) {
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags |= POF_NOMEMORY;
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    userObj = normalizeUserObj(userObj);
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (userObj == NULL) {
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_Clear();
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        free(self);
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags |= POF_NOMEMORY;
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->header.key = key;
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->userObj = userObj;
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->tt = 0;
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->it = 0;
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->callcount = 0;
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->recursivecallcount = 0;
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->recursionLevel = 0;
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->calls = EMPTY_ROTATING_TREE;
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    RotatingTree_Add(&pObj->profilerEntries, &self->header);
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return self;
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerEntry*
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetEntry(ProfilerObject *pObj, void *key)
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key);
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerSubEntry *
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry)
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls,
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                                (void *)entry);
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerSubEntry *
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnewSubEntry(ProfilerObject *pObj,  ProfilerEntry *caller, ProfilerEntry* entry)
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerSubEntry *self;
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self = (ProfilerSubEntry*) malloc(sizeof(ProfilerSubEntry));
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self == NULL) {
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags |= POF_NOMEMORY;
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->header.key = (void *)entry;
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->tt = 0;
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->it = 0;
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->callcount = 0;
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->recursivecallcount = 0;
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->recursionLevel = 0;
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    RotatingTree_Add(&caller->calls, &self->header);
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return self;
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int freeSubEntry(rotating_node_t *header, void *arg)
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerSubEntry *subentry = (ProfilerSubEntry*) header;
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    free(subentry);
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int freeEntry(rotating_node_t *header, void *arg)
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *entry = (ProfilerEntry*) header;
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    RotatingTree_Enum(entry->calls, freeSubEntry, NULL);
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(entry->userObj);
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    free(entry);
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void clearEntries(ProfilerObject *pObj)
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL);
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->profilerEntries = EMPTY_ROTATING_TREE;
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* release the memory hold by the ProfilerContexts */
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pObj->currentProfilerContext) {
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        free(pObj->currentProfilerContext);
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->currentProfilerContext = NULL;
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (pObj->freelistProfilerContext) {
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerContext *c = pObj->freelistProfilerContext;
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->freelistProfilerContext = c->previous;
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        free(c);
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->freelistProfilerContext = NULL;
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminitContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->ctxEntry = entry;
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->subt = 0;
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->previous = pObj->currentProfilerContext;
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->currentProfilerContext = self;
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ++entry->recursionLevel;
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ((pObj->flags & POF_SUBCALLS) && self->previous) {
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* find or create an entry for me in my caller's entry */
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerEntry *caller = self->previous->ctxEntry;
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (subentry == NULL)
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            subentry = newSubEntry(pObj, caller, entry);
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (subentry)
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ++subentry->recursionLevel;
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->t0 = CALL_TIMER(pObj);
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG tt = CALL_TIMER(pObj) - self->t0;
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PY_LONG_LONG it = tt - self->subt;
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (self->previous)
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self->previous->subt += tt;
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->currentProfilerContext = self->previous;
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (--entry->recursionLevel == 0)
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        entry->tt += tt;
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ++entry->recursivecallcount;
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    entry->it += it;
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    entry->callcount++;
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ((pObj->flags & POF_SUBCALLS) && self->previous) {
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* find or create an entry for me in my caller's entry */
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerEntry *caller = self->previous->ctxEntry;
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (subentry) {
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if (--subentry->recursionLevel == 0)
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                subentry->tt += tt;
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ++subentry->recursivecallcount;
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            subentry->it += it;
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ++subentry->callcount;
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmptrace_enter_call(PyObject *self, void *key, PyObject *userObj)
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* entering a call to the function identified by 'key'
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       (which can be a PyCodeObject or a PyMethodDef pointer) */
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerObject *pObj = (ProfilerObject*)self;
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *profEntry;
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerContext *pContext;
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* In the case of entering a generator expression frame via a
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * throw (gen_send_ex(.., 1)), we may already have an
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * Exception set here. We must not mess around with this
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * exception, and some of the code under here assumes that
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * PyErr_* is its own to mess around with, so we have to
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm     * save and restore any current exception. */
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *last_type, *last_value, *last_tb;
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyErr_Fetch(&last_type, &last_value, &last_tb);
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profEntry = getEntry(pObj, key);
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (profEntry == NULL) {
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        profEntry = newProfilerEntry(pObj, key, userObj);
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (profEntry == NULL)
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto restorePyerr;
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* grab a ProfilerContext out of the free list */
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pContext = pObj->freelistProfilerContext;
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pContext) {
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->freelistProfilerContext = pContext->previous;
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        /* free list exhausted, allocate a new one */
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pContext = (ProfilerContext*)
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            malloc(sizeof(ProfilerContext));
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (pContext == NULL) {
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pObj->flags |= POF_NOMEMORY;
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            goto restorePyerr;
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    initContext(pObj, pContext, profEntry);
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmrestorePyerr:
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyErr_Restore(last_type, last_value, last_tb);
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmptrace_leave_call(PyObject *self, void *key)
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* leaving a call to the function identified by 'key' */
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerObject *pObj = (ProfilerObject*)self;
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *profEntry;
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerContext *pContext;
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pContext = pObj->currentProfilerContext;
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pContext == NULL)
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profEntry = getEntry(pObj, key);
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (profEntry) {
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Stop(pObj, pContext, profEntry);
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->currentProfilerContext = pContext->previous;
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* put pContext into the free list */
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pContext->previous = pObj->freelistProfilerContext;
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->freelistProfilerContext = pContext;
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_callback(PyObject *self, PyFrameObject *frame, int what,
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  PyObject *arg)
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    switch (what) {
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* the 'frame' of a called function is about to start its execution */
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case PyTrace_CALL:
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ptrace_enter_call(self, (void *)frame->f_code,
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                (PyObject *)frame->f_code);
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        break;
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* the 'frame' of a called function is about to finish
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       (either normally or with an exception) */
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case PyTrace_RETURN:
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ptrace_leave_call(self, (void *)frame->f_code);
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        break;
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* case PyTrace_EXCEPTION:
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        If the exception results in the function exiting, a
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyTrace_RETURN event will be generated, so we don't need to
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handle it. */
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef PyTrace_C_CALL   /* not defined in Python <= 2.3 */
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* the Python function 'frame' is issuing a call to the built-in
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       function 'arg' */
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case PyTrace_C_CALL:
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            && PyCFunction_Check(arg)) {
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ptrace_enter_call(self,
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              ((PyCFunctionObject *)arg)->m_ml,
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              arg);
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        break;
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    /* the call to the built-in function 'arg' is returning into its
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       caller 'frame' */
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case PyTrace_C_RETURN:              /* ...normally */
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    case PyTrace_C_EXCEPTION:           /* ...with an exception set */
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            && PyCFunction_Check(arg)) {
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ptrace_leave_call(self,
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              ((PyCFunctionObject *)arg)->m_ml);
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        break;
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    default:
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        break;
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpending_exception(ProfilerObject *pObj)
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pObj->flags & POF_NOMEMORY) {
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags -= POF_NOMEMORY;
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_MemoryError,
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "memory was exhausted while profiling");
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/************************************************************/
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Field profiler_entry_fields[] = {
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"code",         "code object or built-in function name"},
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"callcount",    "how many times this was called"},
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reccallcount", "how many times called recursively"},
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"totaltime",    "total time in this entry"},
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"inlinetime",   "inline time in this entry (not in subcalls)"},
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"calls",        "details of the calls"},
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {0}
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Field profiler_subentry_fields[] = {
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"code",         "called code object or built-in function name"},
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"callcount",    "how many times this is called"},
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"reccallcount", "how many times this is called recursively"},
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"totaltime",    "total time spent in this call"},
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"inlinetime",   "inline time (not in further subcalls)"},
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {0}
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Desc profiler_entry_desc = {
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_lsprof.profiler_entry", /* name */
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    NULL, /* doc */
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profiler_entry_fields,
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    6
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Desc profiler_subentry_desc = {
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_lsprof.profiler_subentry", /* name */
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    NULL, /* doc */
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profiler_subentry_fields,
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    5
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int initialized;
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject StatsEntryType;
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject StatsSubEntryType;
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct {
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *list;
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *sublist;
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    double factor;
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} statscollector_t;
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int statsForSubEntry(rotating_node_t *node, void *arg)
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerSubEntry *sentry = (ProfilerSubEntry*) node;
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    statscollector_t *collect = (statscollector_t*) arg;
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key;
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int err;
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *sinfo;
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType,
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  "((Olldd))",
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  entry->userObj,
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  sentry->callcount,
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  sentry->recursivecallcount,
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  collect->factor * sentry->tt,
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  collect->factor * sentry->it);
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (sinfo == NULL)
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    err = PyList_Append(collect->sublist, sinfo);
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(sinfo);
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return err;
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int statsForEntry(rotating_node_t *node, void *arg)
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ProfilerEntry *entry = (ProfilerEntry*) node;
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    statscollector_t *collect = (statscollector_t*) arg;
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *info;
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int err;
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (entry->callcount == 0)
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return 0;   /* skip */
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (entry->calls != EMPTY_ROTATING_TREE) {
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        collect->sublist = PyList_New(0);
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (collect->sublist == NULL)
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (RotatingTree_Enum(entry->calls,
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              statsForSubEntry, collect) != 0) {
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Py_DECREF(collect->sublist);
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return -1;
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        }
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else {
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_INCREF(Py_None);
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        collect->sublist = Py_None;
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    info = PyObject_CallFunction((PyObject*) &StatsEntryType,
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 "((OllddO))",
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 entry->userObj,
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 entry->callcount,
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 entry->recursivecallcount,
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 collect->factor * entry->tt,
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 collect->factor * entry->it,
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                 collect->sublist);
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(collect->sublist);
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (info == NULL)
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    err = PyList_Append(collect->list, info);
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_DECREF(info);
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return err;
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(getstats_doc, "\
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetstats() -> list of profiler_entry objects\n\
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturn all information collected by the profiler.\n\
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEach profiler_entry is a tuple-like object with the\n\
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfollowing attributes:\n\
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    code          code object\n\
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    callcount     how many times this was called\n\
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    reccallcount  how many times called recursively\n\
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    totaltime     total time in this entry\n\
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    inlinetime    inline time in this entry (not in subcalls)\n\
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    calls         details of the calls\n\
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThe calls attribute is either None or a list of\n\
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_subentry objects:\n\
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    code          called code object\n\
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    callcount     how many times this is called\n\
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    reccallcount  how many times this is called recursively\n\
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    totaltime     total time spent in this call\n\
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    inlinetime    inline time (not in further subcalls)\n\
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm");
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject*
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_getstats(ProfilerObject *pObj, PyObject* noarg)
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    statscollector_t collect;
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pending_exception(pObj))
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!pObj->externalTimer)
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        collect.factor = hpTimerUnit();
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (pObj->externalTimerUnit > 0.0)
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        collect.factor = pObj->externalTimerUnit;
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        collect.factor = 1.0 / DOUBLE_TIMER_PRECISION;
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    collect.list = PyList_New(0);
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (collect.list == NULL)
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect)
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        != 0) {
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        Py_DECREF(collect.list);
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return collect.list;
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsetSubcalls(ProfilerObject *pObj, int nvalue)
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (nvalue == 0)
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags &= ~POF_SUBCALLS;
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (nvalue > 0)
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags |=  POF_SUBCALLS;
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsetBuiltins(ProfilerObject *pObj, int nvalue)
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (nvalue == 0)
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags &= ~POF_BUILTINS;
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else if (nvalue > 0) {
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef PyTrace_C_CALL
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyErr_SetString(PyExc_ValueError,
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        "builtins=True requires Python >= 2.4");
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pObj->flags |=  POF_BUILTINS;
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(enable_doc, "\
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmenable(subcalls=True, builtins=True)\n\
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStart collecting profiling information.\n\
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf 'subcalls' is True, also records for each function\n\
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatistics separated according to its current caller.\n\
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf 'builtins' is True, records the time spent in\n\
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuilt-in functions separately from their caller.\n\
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm");
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject*
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds)
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int subcalls = -1;
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int builtins = -1;
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    static char *kwlist[] = {"subcalls", "builtins", 0};
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable",
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     kwlist, &subcalls, &builtins))
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0)
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyEval_SetProfile(profiler_callback, (PyObject*)self);
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->flags |= POF_ENABLED;
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(Py_None);
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Py_None;
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmflush_unmatched(ProfilerObject *pObj)
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while (pObj->currentProfilerContext) {
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerContext *pContext = pObj->currentProfilerContext;
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ProfilerEntry *profEntry= pContext->ctxEntry;
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (profEntry)
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            Stop(pObj, pContext, profEntry);
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pObj->currentProfilerContext = pContext->previous;
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (pContext)
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            free(pContext);
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(disable_doc, "\
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdisable()\n\
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStop collecting profiling information.\n\
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm");
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject*
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_disable(ProfilerObject *self, PyObject* noarg)
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    self->flags &= ~POF_ENABLED;
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyEval_SetProfile(NULL, NULL);
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    flush_unmatched(self);
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (pending_exception(self))
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NULL;
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(Py_None);
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Py_None;
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(clear_doc, "\
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclear()\n\
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmClear all profiling information collected so far.\n\
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm");
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject*
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_clear(ProfilerObject *pObj, PyObject* noarg)
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    clearEntries(pObj);
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF(Py_None);
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return Py_None;
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_dealloc(ProfilerObject *op)
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (op->flags & POF_ENABLED)
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyEval_SetProfile(NULL, NULL);
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    flush_unmatched(op);
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    clearEntries(op);
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(op->externalTimer);
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TYPE(op)->tp_free(op);
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw)
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *o;
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *timer = NULL;
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    double timeunit = 0.0;
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int subcalls = 1;
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef PyTrace_C_CALL
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int builtins = 1;
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    int builtins = 0;
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    static char *kwlist[] = {"timer", "timeunit",
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                   "subcalls", "builtins", 0};
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist,
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     &timer, &timeunit,
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     &subcalls, &builtins))
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0)
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return -1;
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    o = pObj->externalTimer;
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->externalTimer = timer;
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XINCREF(timer);
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_XDECREF(o);
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    pObj->externalTimerUnit = timeunit;
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0;
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef profiler_methods[] = {
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"getstats",    (PyCFunction)profiler_getstats,
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS,                        getstats_doc},
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"enable",          (PyCFunction)profiler_enable,
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_VARARGS | METH_KEYWORDS,       enable_doc},
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"disable",         (PyCFunction)profiler_disable,
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS,                        disable_doc},
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {"clear",           (PyCFunction)profiler_clear,
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    METH_NOARGS,                        clear_doc},
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL}
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(profiler_doc, "\
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmProfiler(custom_timer=None, time_unit=None, subcalls=True, builtins=True)\n\
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Builds a profiler object using the specified timer function.\n\
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    The default timer is a fast built-in one based on real time.\n\
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    For custom timer functions returning integers, time_unit can\n\
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    be a float specifying a scale (i.e. how long each integer unit\n\
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    is, in seconds).\n\
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm");
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatichere PyTypeObject PyProfiler_Type = {
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_HEAD_INIT(NULL)
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* ob_size */
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    "_lsprof.Profiler",                     /* tp_name */
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sizeof(ProfilerObject),                 /* tp_basicsize */
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_itemsize */
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (destructor)profiler_dealloc,           /* tp_dealloc */
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_print */
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_getattr */
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_setattr */
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_compare */
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_repr */
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_as_number */
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_as_sequence */
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_as_mapping */
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_hash */
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_call */
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_str */
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_getattro */
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_setattro */
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_as_buffer */
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profiler_doc,                           /* tp_doc */
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_traverse */
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_clear */
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_richcompare */
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_weaklistoffset */
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_iter */
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_iternext */
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    profiler_methods,                       /* tp_methods */
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_members */
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_getset */
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_base */
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_dict */
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_descr_get */
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_descr_set */
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    0,                                      /* tp_dictoffset */
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    (initproc)profiler_init,                /* tp_init */
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyType_GenericAlloc,                    /* tp_alloc */
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyType_GenericNew,                      /* tp_new */
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject_Del,                           /* tp_free */
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef moduleMethods[] = {
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    {NULL, NULL}
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm};
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyMODINIT_FUNC
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminit_lsprof(void)
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyObject *module, *d;
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    module = Py_InitModule3("_lsprof", moduleMethods, "Fast profiler");
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (module == NULL)
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    d = PyModule_GetDict(module);
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (PyType_Ready(&PyProfiler_Type) < 0)
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return;
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type);
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (!initialized) {
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyStructSequence_InitType(&StatsEntryType,
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  &profiler_entry_desc);
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PyStructSequence_InitType(&StatsSubEntryType,
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  &profiler_subentry_desc);
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    }
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF((PyObject*) &StatsEntryType);
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    Py_INCREF((PyObject*) &StatsSubEntryType);
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyModule_AddObject(module, "profiler_entry",
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       (PyObject*) &StatsEntryType);
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    PyModule_AddObject(module, "profiler_subentry",
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       (PyObject*) &StatsSubEntryType);
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    empty_tuple = PyTuple_New(0);
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    initialized = 1;
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}
893