1 /////////////// Profile.proto ///////////////
2 //@requires: Exceptions.c::PyErrFetchRestore
3 //@substitute: naming
4
5 // Note that cPython ignores PyTrace_EXCEPTION,
6 // but maybe some other profilers don't.
7
8 #ifndef CYTHON_PROFILE
9 #if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
10 #define CYTHON_PROFILE 0
11 #else
12 #define CYTHON_PROFILE 1
13 #endif
14 #endif
15
16 #ifndef CYTHON_TRACE_NOGIL
17 #define CYTHON_TRACE_NOGIL 0
18 #else
19 #if CYTHON_TRACE_NOGIL && !defined(CYTHON_TRACE)
20 #define CYTHON_TRACE 1
21 #endif
22 #endif
23
24 #ifndef CYTHON_TRACE
25 #define CYTHON_TRACE 0
26 #endif
27
28 #if CYTHON_TRACE
29 #undef CYTHON_PROFILE_REUSE_FRAME
30 #endif
31
32 #ifndef CYTHON_PROFILE_REUSE_FRAME
33 #define CYTHON_PROFILE_REUSE_FRAME 0
34 #endif
35
36 #if CYTHON_PROFILE || CYTHON_TRACE
37
38 #include "compile.h"
39 #include "frameobject.h"
40 #include "traceback.h"
41
42 #if CYTHON_PROFILE_REUSE_FRAME
43 #define CYTHON_FRAME_MODIFIER static
44 #define CYTHON_FRAME_DEL(frame)
45 #else
46 #define CYTHON_FRAME_MODIFIER
47 #define CYTHON_FRAME_DEL(frame) Py_CLEAR(frame)
48 #endif
49
50 #define __Pyx_TraceDeclarations \
51 static PyCodeObject *$frame_code_cname = NULL; \
52 CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL; \
53 int __Pyx_use_tracing = 0;
54
55 #define __Pyx_TraceFrameInit(codeobj) \
56 if (codeobj) $frame_code_cname = (PyCodeObject*) codeobj;
57
58 #if PY_VERSION_HEX >= 0x030a00b1
59 #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \
60 (unlikely((tstate)->cframe->use_tracing) && \
61 (!(check_tracing) || !(tstate)->tracing) && \
62 (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc)))
63
64 #define __Pyx_SetTracing(tstate, enable) \
65 (tstate)->cframe->use_tracing = (enable)
66
67 #else
68 #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \
69 (unlikely((tstate)->use_tracing) && \
70 (!(check_tracing) || !(tstate)->tracing) && \
71 (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc)))
72
73 #define __Pyx_SetTracing(tstate, enable) \
74 (tstate)->use_tracing = (enable)
75 #endif
76
77 #ifdef WITH_THREAD
78 #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) \
79 if (nogil) { \
80 if (CYTHON_TRACE_NOGIL) { \
81 PyThreadState *tstate; \
82 PyGILState_STATE state = PyGILState_Ensure(); \
83 tstate = __Pyx_PyThreadState_Current; \
84 if (__Pyx_IsTracing(tstate, 1, 1)) { \
85 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \
86 } \
87 PyGILState_Release(state); \
88 if (unlikely(__Pyx_use_tracing < 0)) goto_error; \
89 } \
90 } else { \
91 PyThreadState* tstate = PyThreadState_GET(); \
92 if (__Pyx_IsTracing(tstate, 1, 1)) { \
93 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \
94 if (unlikely(__Pyx_use_tracing < 0)) goto_error; \
95 } \
96 }
97 #else
98 #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) \
99 { PyThreadState* tstate = PyThreadState_GET(); \
100 if (__Pyx_IsTracing(tstate, 1, 1)) { \
101 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \
102 if (unlikely(__Pyx_use_tracing < 0)) goto_error; \
103 } \
104 }
105 #endif
106
107 #define __Pyx_TraceException() \
108 if (likely(!__Pyx_use_tracing)); else { \
109 PyThreadState* tstate = __Pyx_PyThreadState_Current; \
110 if (__Pyx_IsTracing(tstate, 0, 1)) { \
111 tstate->tracing++; \
112 __Pyx_SetTracing(tstate, 0); \
113 PyObject *exc_info = __Pyx_GetExceptionTuple(tstate); \
114 if (exc_info) { \
115 if (CYTHON_TRACE && tstate->c_tracefunc) \
116 tstate->c_tracefunc( \
117 tstate->c_traceobj, $frame_cname, PyTrace_EXCEPTION, exc_info); \
118 tstate->c_profilefunc( \
119 tstate->c_profileobj, $frame_cname, PyTrace_EXCEPTION, exc_info); \
120 Py_DECREF(exc_info); \
121 } \
122 __Pyx_SetTracing(tstate, 1); \
123 tstate->tracing--; \
124 } \
125 }
126
__Pyx_call_return_trace_func(PyThreadState * tstate,PyFrameObject * frame,PyObject * result)127 static void __Pyx_call_return_trace_func(PyThreadState *tstate, PyFrameObject *frame, PyObject *result) {
128 PyObject *type, *value, *traceback;
129 __Pyx_ErrFetchInState(tstate, &type, &value, &traceback);
130 tstate->tracing++;
131 __Pyx_SetTracing(tstate, 0);
132 if (CYTHON_TRACE && tstate->c_tracefunc)
133 tstate->c_tracefunc(tstate->c_traceobj, frame, PyTrace_RETURN, result);
134 if (tstate->c_profilefunc)
135 tstate->c_profilefunc(tstate->c_profileobj, frame, PyTrace_RETURN, result);
136 CYTHON_FRAME_DEL(frame);
137 __Pyx_SetTracing(tstate, 1);
138 tstate->tracing--;
139 __Pyx_ErrRestoreInState(tstate, type, value, traceback);
140 }
141
142 #ifdef WITH_THREAD
143 #define __Pyx_TraceReturn(result, nogil) \
144 if (likely(!__Pyx_use_tracing)); else { \
145 if (nogil) { \
146 if (CYTHON_TRACE_NOGIL) { \
147 PyThreadState *tstate; \
148 PyGILState_STATE state = PyGILState_Ensure(); \
149 tstate = __Pyx_PyThreadState_Current; \
150 if (__Pyx_IsTracing(tstate, 0, 0)) { \
151 __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \
152 } \
153 PyGILState_Release(state); \
154 } \
155 } else { \
156 PyThreadState* tstate = __Pyx_PyThreadState_Current; \
157 if (__Pyx_IsTracing(tstate, 0, 0)) { \
158 __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \
159 } \
160 } \
161 }
162 #else
163 #define __Pyx_TraceReturn(result, nogil) \
164 if (likely(!__Pyx_use_tracing)); else { \
165 PyThreadState* tstate = __Pyx_PyThreadState_Current; \
166 if (__Pyx_IsTracing(tstate, 0, 0)) { \
167 __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \
168 } \
169 }
170 #endif
171
172 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
173 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, PyThreadState* tstate, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
174
175 #else
176
177 #define __Pyx_TraceDeclarations
178 #define __Pyx_TraceFrameInit(codeobj)
179 // mark error label as used to avoid compiler warnings
180 #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) if ((1)); else goto_error;
181 #define __Pyx_TraceException()
182 #define __Pyx_TraceReturn(result, nogil)
183
184 #endif /* CYTHON_PROFILE */
185
186 #if CYTHON_TRACE
187 // see call_trace_protected() in CPython's ceval.c
__Pyx_call_line_trace_func(PyThreadState * tstate,PyFrameObject * frame,int lineno)188 static int __Pyx_call_line_trace_func(PyThreadState *tstate, PyFrameObject *frame, int lineno) {
189 int ret;
190 PyObject *type, *value, *traceback;
191 __Pyx_ErrFetchInState(tstate, &type, &value, &traceback);
192 __Pyx_PyFrame_SetLineNumber(frame, lineno);
193 tstate->tracing++;
194 __Pyx_SetTracing(tstate, 0);
195
196 ret = tstate->c_tracefunc(tstate->c_traceobj, frame, PyTrace_LINE, NULL);
197
198 __Pyx_SetTracing(tstate, 1);
199 tstate->tracing--;
200 if (likely(!ret)) {
201 __Pyx_ErrRestoreInState(tstate, type, value, traceback);
202 } else {
203 Py_XDECREF(type);
204 Py_XDECREF(value);
205 Py_XDECREF(traceback);
206 }
207 return ret;
208 }
209
210 #ifdef WITH_THREAD
211 #define __Pyx_TraceLine(lineno, nogil, goto_error) \
212 if (likely(!__Pyx_use_tracing)); else { \
213 if (nogil) { \
214 if (CYTHON_TRACE_NOGIL) { \
215 int ret = 0; \
216 PyThreadState *tstate; \
217 PyGILState_STATE state = PyGILState_Ensure(); \
218 tstate = __Pyx_PyThreadState_Current; \
219 if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
220 ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
221 } \
222 PyGILState_Release(state); \
223 if (unlikely(ret)) goto_error; \
224 } \
225 } else { \
226 PyThreadState* tstate = __Pyx_PyThreadState_Current; \
227 if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
228 int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
229 if (unlikely(ret)) goto_error; \
230 } \
231 } \
232 }
233 #else
234 #define __Pyx_TraceLine(lineno, nogil, goto_error) \
235 if (likely(!__Pyx_use_tracing)); else { \
236 PyThreadState* tstate = __Pyx_PyThreadState_Current; \
237 if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
238 int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
239 if (unlikely(ret)) goto_error; \
240 } \
241 }
242 #endif
243 #else
244 // mark error label as used to avoid compiler warnings
245 #define __Pyx_TraceLine(lineno, nogil, goto_error) if ((1)); else goto_error;
246 #endif
247
248 /////////////// Profile ///////////////
249 //@substitute: naming
250
251 #if CYTHON_PROFILE
252
__Pyx_TraceSetupAndCall(PyCodeObject ** code,PyFrameObject ** frame,PyThreadState * tstate,const char * funcname,const char * srcfile,int firstlineno)253 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
254 PyFrameObject** frame,
255 PyThreadState* tstate,
256 const char *funcname,
257 const char *srcfile,
258 int firstlineno) {
259 PyObject *type, *value, *traceback;
260 int retval;
261 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
262 if (*code == NULL) {
263 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
264 if (*code == NULL) return 0;
265 }
266 *frame = PyFrame_New(
267 tstate, /*PyThreadState *tstate*/
268 *code, /*PyCodeObject *code*/
269 $moddict_cname, /*PyObject *globals*/
270 0 /*PyObject *locals*/
271 );
272 if (*frame == NULL) return 0;
273 if (CYTHON_TRACE && (*frame)->f_trace == NULL) {
274 // this enables "f_lineno" lookup, at least in CPython ...
275 Py_INCREF(Py_None);
276 (*frame)->f_trace = Py_None;
277 }
278 #if PY_VERSION_HEX < 0x030400B1
279 } else {
280 (*frame)->f_tstate = tstate;
281 #endif
282 }
283 __Pyx_PyFrame_SetLineNumber(*frame, firstlineno);
284
285 retval = 1;
286 tstate->tracing++;
287 __Pyx_SetTracing(tstate, 0);
288 __Pyx_ErrFetchInState(tstate, &type, &value, &traceback);
289
290 #if CYTHON_TRACE
291 if (tstate->c_tracefunc)
292 retval = tstate->c_tracefunc(tstate->c_traceobj, *frame, PyTrace_CALL, NULL) == 0;
293 if (retval && tstate->c_profilefunc)
294 #endif
295 retval = tstate->c_profilefunc(tstate->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
296
297 __Pyx_SetTracing(tstate, (tstate->c_profilefunc || (CYTHON_TRACE && tstate->c_tracefunc)));
298 tstate->tracing--;
299 if (retval) {
300 __Pyx_ErrRestoreInState(tstate, type, value, traceback);
301 return __Pyx_IsTracing(tstate, 0, 0) && retval;
302 } else {
303 Py_XDECREF(type);
304 Py_XDECREF(value);
305 Py_XDECREF(traceback);
306 return -1;
307 }
308 }
309
__Pyx_createFrameCodeObject(const char * funcname,const char * srcfile,int firstlineno)310 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
311 PyCodeObject *py_code = 0;
312
313 #if PY_MAJOR_VERSION >= 3
314 py_code = PyCode_NewEmpty(srcfile, funcname, firstlineno);
315 // make CPython use a fresh dict for "f_locals" at need (see GH #1836)
316 if (likely(py_code)) {
317 py_code->co_flags |= CO_OPTIMIZED | CO_NEWLOCALS;
318 }
319 #else
320 PyObject *py_srcfile = 0;
321 PyObject *py_funcname = 0;
322
323 py_funcname = PyString_FromString(funcname);
324 if (unlikely(!py_funcname)) goto bad;
325 py_srcfile = PyString_FromString(srcfile);
326 if (unlikely(!py_srcfile)) goto bad;
327
328 py_code = PyCode_New(
329 0, /*int argcount,*/
330 0, /*int nlocals,*/
331 0, /*int stacksize,*/
332 // make CPython use a fresh dict for "f_locals" at need (see GH #1836)
333 CO_OPTIMIZED | CO_NEWLOCALS, /*int flags,*/
334 $empty_bytes, /*PyObject *code,*/
335 $empty_tuple, /*PyObject *consts,*/
336 $empty_tuple, /*PyObject *names,*/
337 $empty_tuple, /*PyObject *varnames,*/
338 $empty_tuple, /*PyObject *freevars,*/
339 $empty_tuple, /*PyObject *cellvars,*/
340 py_srcfile, /*PyObject *filename,*/
341 py_funcname, /*PyObject *name,*/
342 firstlineno, /*int firstlineno,*/
343 $empty_bytes /*PyObject *lnotab*/
344 );
345
346 bad:
347 Py_XDECREF(py_srcfile);
348 Py_XDECREF(py_funcname);
349 #endif
350
351 return py_code;
352 }
353
354 #endif /* CYTHON_PROFILE */
355