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[] =