Mercurial > cpython-lru_cache-weakref
comparison Python/sysmodule.c @ 18326:e427afb5637f legacy-trunk
Revise the interface to the profiling and tracing support for the
Python interpreter.
This change adds two new C-level APIs: PyEval_SetProfile() and
PyEval_SetTrace(). These can be used to install profile and trace
functions implemented in C, which can operate at much higher speeds
than Python-based functions. The overhead for calling a C-based
profile function is a very small fraction of a percent of the overhead
involved in calling a Python-based function.
The machinery required to call a Python-based profile or trace
function been moved to sysmodule.c, where sys.setprofile() and
sys.setprofile() simply become users of the new interface.
As a side effect, SF bug #436058 is fixed; there is no longer a
_PyTrace_Init() function to declare.
| author | Fred Drake <fdrake@acm.org> |
|---|---|
| date | Wed, 27 Jun 2001 19:19:46 +0000 |
| parents | 982163c4e9d2 |
| children | 064de84385ca |
comparison
equal
deleted
inserted
replaced
| 18325:fb35b3a22604 | 18326:e427afb5637f |
|---|---|
| 194 static char setdefaultencoding_doc[] = | 194 static char setdefaultencoding_doc[] = |
| 195 "setdefaultencoding(encoding)\n\ | 195 "setdefaultencoding(encoding)\n\ |
| 196 \n\ | 196 \n\ |
| 197 Set the current default string encoding used by the Unicode implementation."; | 197 Set the current default string encoding used by the Unicode implementation."; |
| 198 | 198 |
| 199 extern int _PyTrace_Init(void); | 199 /* |
| 200 * Cached interned string objects used for calling the profile and | |
| 201 * trace functions. Initialized by trace_init(). | |
| 202 */ | |
| 203 static PyObject *whatstrings[4] = {NULL, NULL, NULL, NULL}; | |
| 204 | |
| 205 static int | |
| 206 trace_init(void) | |
| 207 { | |
| 208 static char *whatnames[4] = {"call", "exception", "line", "return"}; | |
| 209 PyObject *name; | |
| 210 int i; | |
| 211 for (i = 0; i < 4; ++i) { | |
| 212 if (whatstrings[i] == NULL) { | |
| 213 name = PyString_InternFromString(whatnames[i]); | |
| 214 if (name == NULL) | |
| 215 return -1; | |
| 216 whatstrings[i] = name; | |
| 217 } | |
| 218 } | |
| 219 return 0; | |
| 220 } | |
| 221 | |
| 222 | |
| 223 static PyObject * | |
| 224 call_trampoline(PyThreadState *tstate, PyObject* callback, | |
| 225 PyFrameObject *frame, int what, PyObject *arg) | |
| 226 { | |
| 227 PyObject *args = PyTuple_New(3); | |
| 228 PyObject *whatstr; | |
| 229 PyObject *result; | |
| 230 | |
| 231 if (args == NULL) | |
| 232 return NULL; | |
| 233 Py_INCREF(frame); | |
| 234 whatstr = whatstrings[what]; | |
| 235 Py_INCREF(whatstr); | |
| 236 if (arg == NULL) | |
| 237 arg = Py_None; | |
| 238 Py_INCREF(arg); | |
| 239 PyTuple_SET_ITEM(args, 0, (PyObject *)frame); | |
| 240 PyTuple_SET_ITEM(args, 1, whatstr); | |
| 241 PyTuple_SET_ITEM(args, 2, arg); | |
| 242 | |
| 243 /* call the Python-level function */ | |
| 244 PyFrame_FastToLocals(frame); | |
| 245 result = PyEval_CallObject(callback, args); | |
| 246 PyFrame_LocalsToFast(frame, 1); | |
| 247 if (result == NULL) | |
| 248 PyTraceBack_Here(frame); | |
| 249 | |
| 250 /* cleanup */ | |
| 251 Py_DECREF(args); | |
| 252 return result; | |
| 253 } | |
| 254 | |
| 255 static int | |
| 256 profile_trampoline(PyObject *self, PyFrameObject *frame, | |
| 257 int what, PyObject *arg) | |
| 258 { | |
| 259 PyThreadState *tstate = frame->f_tstate; | |
| 260 PyObject *result; | |
| 261 | |
| 262 result = call_trampoline(tstate, self, frame, what, arg); | |
| 263 if (result == NULL) { | |
| 264 PyEval_SetProfile(NULL, NULL); | |
| 265 return -1; | |
| 266 } | |
| 267 Py_DECREF(result); | |
| 268 return 0; | |
| 269 } | |
| 270 | |
| 271 static int | |
| 272 trace_trampoline(PyObject *self, PyFrameObject *frame, | |
| 273 int what, PyObject *arg) | |
| 274 { | |
| 275 PyThreadState *tstate = frame->f_tstate; | |
| 276 PyObject *callback; | |
| 277 PyObject *result; | |
| 278 | |
| 279 if (what == PyTrace_CALL) | |
| 280 callback = self; | |
| 281 else | |
| 282 callback = frame->f_trace; | |
| 283 if (callback == NULL) | |
| 284 return 0; | |
| 285 result = call_trampoline(tstate, callback, frame, what, arg); | |
| 286 if (result == NULL) { | |
| 287 PyEval_SetTrace(NULL, NULL); | |
| 288 Py_XDECREF(frame->f_trace); | |
| 289 frame->f_trace = NULL; | |
| 290 return -1; | |
| 291 } | |
| 292 if (result != Py_None) { | |
| 293 PyObject *temp = frame->f_trace; | |
| 294 frame->f_trace = NULL; | |
| 295 Py_XDECREF(temp); | |
| 296 frame->f_trace = result; | |
| 297 } | |
| 298 else { | |
| 299 Py_DECREF(result); | |
| 300 } | |
| 301 return 0; | |
| 302 } | |
| 200 | 303 |
| 201 static PyObject * | 304 static PyObject * |
| 202 sys_settrace(PyObject *self, PyObject *args) | 305 sys_settrace(PyObject *self, PyObject *args) |
| 203 { | 306 { |
| 204 PyThreadState *tstate = PyThreadState_Get(); | 307 if (trace_init() == -1) |
| 205 if (_PyTrace_Init() == -1) | |
| 206 return NULL; | 308 return NULL; |
| 207 if (args == Py_None) | 309 if (args == Py_None) |
| 208 args = NULL; | 310 PyEval_SetTrace(NULL, NULL); |
| 209 else | 311 else |
| 210 Py_XINCREF(args); | 312 PyEval_SetTrace(trace_trampoline, args); |
| 211 Py_XDECREF(tstate->sys_tracefunc); | |
| 212 tstate->sys_tracefunc = args; | |
| 213 Py_INCREF(Py_None); | 313 Py_INCREF(Py_None); |
| 214 return Py_None; | 314 return Py_None; |
| 215 } | 315 } |
| 216 | 316 |
| 217 static char settrace_doc[] = | 317 static char settrace_doc[] = |
| 221 function call. See the debugger chapter in the library manual."; | 321 function call. See the debugger chapter in the library manual."; |
| 222 | 322 |
| 223 static PyObject * | 323 static PyObject * |
| 224 sys_setprofile(PyObject *self, PyObject *args) | 324 sys_setprofile(PyObject *self, PyObject *args) |
| 225 { | 325 { |
| 226 PyThreadState *tstate = PyThreadState_Get(); | 326 if (trace_init() == -1) |
| 227 if (_PyTrace_Init() == -1) | |
| 228 return NULL; | 327 return NULL; |
| 229 if (args == Py_None) | 328 if (args == Py_None) |
| 230 args = NULL; | 329 PyEval_SetProfile(NULL, NULL); |
| 231 else | 330 else |
| 232 Py_XINCREF(args); | 331 PyEval_SetProfile(profile_trampoline, args); |
| 233 Py_XDECREF(tstate->sys_profilefunc); | |
| 234 tstate->sys_profilefunc = args; | |
| 235 Py_INCREF(Py_None); | 332 Py_INCREF(Py_None); |
| 236 return Py_None; | 333 return Py_None; |
| 237 } | 334 } |
| 238 | 335 |
| 239 static char setprofile_doc[] = | 336 static char setprofile_doc[] = |
