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
109static 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
153static 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
187bad:
188    Py_XDECREF(py_srcfile);
189    Py_XDECREF(py_funcname);
190
191    return py_code;
192}
193
194#endif /* CYTHON_PROFILE */
195