• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
__Pyx_TraceSetupAndCall(PyCodeObject ** code,PyFrameObject ** frame,const char * funcname,const char * srcfile,int firstlineno)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 
__Pyx_createFrameCodeObject(const char * funcname,const char * srcfile,int firstlineno)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