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