Home | History | Annotate | Download | only in Utility
      1 /////////////// Profile.proto ///////////////
      2 //@substitute: naming
      3 
      4 // Note that cPython ignores PyTrace_EXCEPTION,
      5 // but maybe some other profilers don't.
      6 
      7 #ifndef CYTHON_PROFILE
      8   #define CYTHON_PROFILE 1
      9 #endif
     10 
     11 #ifndef CYTHON_TRACE
     12   #define CYTHON_TRACE 0
     13 #endif
     14 
     15 #if CYTHON_TRACE
     16   #undef CYTHON_PROFILE_REUSE_FRAME
     17 #endif
     18 
     19 #ifndef CYTHON_PROFILE_REUSE_FRAME
     20   #define CYTHON_PROFILE_REUSE_FRAME 0
     21 #endif
     22 
     23 #if CYTHON_PROFILE || CYTHON_TRACE
     24 
     25   #include "compile.h"
     26   #include "frameobject.h"
     27   #include "traceback.h"
     28 
     29   #if CYTHON_PROFILE_REUSE_FRAME
     30     #define CYTHON_FRAME_MODIFIER static
     31     #define CYTHON_FRAME_DEL
     32   #else
     33     #define CYTHON_FRAME_MODIFIER
     34     #define CYTHON_FRAME_DEL Py_CLEAR($frame_cname)
     35   #endif
     36 
     37   #define __Pyx_TraceDeclarations                                     \
     38   static PyCodeObject *$frame_code_cname = NULL;                      \
     39   CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL;           \
     40   int __Pyx_use_tracing = 0;
     41 
     42   #define __Pyx_TraceCall(funcname, srcfile, firstlineno)                            \
     43   if (unlikely(PyThreadState_GET()->use_tracing &&                                   \
     44           (PyThreadState_GET()->c_profilefunc || (CYTHON_TRACE && PyThreadState_GET()->c_tracefunc)))) {      \
     45       __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, funcname, srcfile, firstlineno);  \
     46   }
     47 
     48   #define __Pyx_TraceException()                                                           \
     49   if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing &&                   \
     50           (PyThreadState_GET()->c_profilefunc || (CYTHON_TRACE && PyThreadState_GET()->c_tracefunc))) {  \
     51       PyThreadState* tstate = PyThreadState_GET();                                         \
     52       tstate->use_tracing = 0;                                                             \
     53       PyObject *exc_info = __Pyx_GetExceptionTuple();                                      \
     54       if (exc_info) {                                                                      \
     55           if (CYTHON_TRACE && tstate->c_tracefunc)                                         \
     56               tstate->c_tracefunc(                                                         \
     57                   tstate->c_traceobj, $frame_cname, PyTrace_EXCEPTION, exc_info);          \
     58           tstate->c_profilefunc(                                                           \
     59               tstate->c_profileobj, $frame_cname, PyTrace_EXCEPTION, exc_info);            \
     60           Py_DECREF(exc_info);                                                             \
     61       }                                                                                    \
     62       tstate->use_tracing = 1;                                                             \
     63   }
     64 
     65   #define __Pyx_TraceReturn(result)                                                  \
     66   if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing) {             \
     67       PyThreadState* tstate = PyThreadState_GET();                                   \
     68       tstate->use_tracing = 0;                                                        \
     69       if (CYTHON_TRACE && tstate->c_tracefunc)                                       \
     70           tstate->c_tracefunc(                                                       \
     71               tstate->c_traceobj, $frame_cname, PyTrace_RETURN, (PyObject*)result);  \
     72       if (tstate->c_profilefunc)                                                     \
     73           tstate->c_profilefunc(                                                     \
     74               tstate->c_profileobj, $frame_cname, PyTrace_RETURN, (PyObject*)result);  \
     75       CYTHON_FRAME_DEL;                                                              \
     76       tstate->use_tracing = 1;                                                       \
     77   }
     78 
     79   static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
     80   static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
     81 
     82 #else
     83 
     84   #define __Pyx_TraceDeclarations
     85   #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
     86   #define __Pyx_TraceException()
     87   #define __Pyx_TraceReturn(result)
     88 
     89 #endif /* CYTHON_PROFILE */
     90 
     91 #if CYTHON_TRACE
     92   #define __Pyx_TraceLine(lineno)                                                          \
     93   if (unlikely(__Pyx_use_tracing) && unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_tracefunc)) {    \
     94       PyThreadState* tstate = PyThreadState_GET();                                         \
     95       $frame_cname->f_lineno = lineno;                                                     \
     96       tstate->use_tracing = 0;                                                             \
     97       tstate->c_tracefunc(tstate->c_traceobj, $frame_cname, PyTrace_LINE, NULL);           \
     98       tstate->use_tracing = 1;                                                             \
     99   }
    100 #else
    101   #define __Pyx_TraceLine(lineno)
    102 #endif
    103 
    104 /////////////// Profile ///////////////
    105 //@substitute: naming
    106 
    107 #if CYTHON_PROFILE
    108 
    109 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
    110                                    PyFrameObject** frame,
    111                                    const char *funcname,
    112                                    const char *srcfile,
    113                                    int firstlineno) {
    114     int retval;
    115     PyThreadState* tstate = PyThreadState_GET();
    116     if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
    117         if (*code == NULL) {
    118             *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
    119             if (*code == NULL) return 0;
    120         }
    121         *frame = PyFrame_New(
    122             tstate,                          /*PyThreadState *tstate*/
    123             *code,                           /*PyCodeObject *code*/
    124             $moddict_cname,                  /*PyObject *globals*/
    125             0                                /*PyObject *locals*/
    126         );
    127         if (*frame == NULL) return 0;
    128         if (CYTHON_TRACE && (*frame)->f_trace == NULL) {
    129             // this enables "f_lineno" lookup, at least in CPython ...
    130             Py_INCREF(Py_None);
    131             (*frame)->f_trace = Py_None;
    132         }
    133 #if PY_VERSION_HEX < 0x030400B1
    134     } else {
    135         (*frame)->f_tstate = tstate;
    136 #endif
    137     }
    138     (*frame)->f_lineno = firstlineno;
    139     tstate->use_tracing = 0;
    140     #if CYTHON_TRACE
    141     if (tstate->c_tracefunc)
    142         tstate->c_tracefunc(tstate->c_traceobj, *frame, PyTrace_CALL, NULL);
    143     if (!tstate->c_profilefunc)
    144         retval = 1;
    145     else
    146     #endif
    147         retval = tstate->c_profilefunc(tstate->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
    148     tstate->use_tracing = (tstate->c_profilefunc ||
    149                            (CYTHON_TRACE && tstate->c_tracefunc));
    150     return tstate->use_tracing && retval;
    151 }
    152 
    153 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
    154     PyObject *py_srcfile = 0;
    155     PyObject *py_funcname = 0;
    156     PyCodeObject *py_code = 0;
    157 
    158     #if PY_MAJOR_VERSION < 3
    159     py_funcname = PyString_FromString(funcname);
    160     py_srcfile = PyString_FromString(srcfile);
    161     #else
    162     py_funcname = PyUnicode_FromString(funcname);
    163     py_srcfile = PyUnicode_FromString(srcfile);
    164     #endif
    165     if (!py_funcname | !py_srcfile) goto bad;
    166 
    167     py_code = PyCode_New(
    168         0,                /*int argcount,*/
    169         #if PY_MAJOR_VERSION >= 3
    170         0,                /*int kwonlyargcount,*/
    171         #endif
    172         0,                /*int nlocals,*/
    173         0,                /*int stacksize,*/
    174         0,                /*int flags,*/
    175         $empty_bytes,     /*PyObject *code,*/
    176         $empty_tuple,     /*PyObject *consts,*/
    177         $empty_tuple,     /*PyObject *names,*/
    178         $empty_tuple,     /*PyObject *varnames,*/
    179         $empty_tuple,     /*PyObject *freevars,*/
    180         $empty_tuple,     /*PyObject *cellvars,*/
    181         py_srcfile,       /*PyObject *filename,*/
    182         py_funcname,      /*PyObject *name,*/
    183         firstlineno,      /*int firstlineno,*/
    184         $empty_bytes      /*PyObject *lnotab*/
    185     );
    186 
    187 bad:
    188     Py_XDECREF(py_srcfile);
    189     Py_XDECREF(py_funcname);
    190 
    191     return py_code;
    192 }
    193 
    194 #endif /* CYTHON_PROFILE */
    195