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