[Python-checkins] CVS: python/dist/src/Python ceval.c,2.259,2.260 pystate.c,2.17,2.18

Fred L. Drake fdrake@users.sourceforge.net
Tue, 03 Jul 2001 16:39:54 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv21594/Python

Modified Files:
	ceval.c pystate.c 
Log Message:
This change adjusts the profiling/tracing support so that the common
path (with no profile/trace function) through eval_code2() and
eval_frame() avoids several checks.

In the common cases of calls, returns, and exception propogation,
eval_code2() and eval_frame() used to test two values in the
thread-state: the profiling function and the tracing function.  With
this change, a flag is set in the thread-state if either of these is
active, allowing a single check to suffice when both are NULL.  This
also simplifies the code needed when either function is in use but is
already active (to avoid profiling/tracing the profiler/tracer); the
flag is set to 0 when the profile/trace code is entered, allowing the
same check to suffice for "already in the tracer" for call/return/
exception events.


Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.259
retrieving revision 2.260
diff -C2 -r2.259 -r2.260
*** ceval.c	2001/06/27 19:19:46	2.259
--- ceval.c	2001/07/03 23:39:52	2.260
***************
*** 1891,1896 ****
--- 1891,1899 ----
  			/* Inline call_trace() for performance: */
  			tstate->tracing++;
+ 			tstate->use_tracing = 0;
  			err = (tstate->c_tracefunc)(tstate->c_traceobj, f,
  						    PyTrace_LINE, Py_None);
+ 			tstate->use_tracing = (tstate->c_tracefunc
+ 					       || tstate->c_profilefunc);
  			tstate->tracing--;
  			break;
***************
*** 2143,2152 ****
  			PyTraceBack_Here(f);
  
! 			if (tstate->c_tracefunc)
! 				call_exc_trace(tstate->c_tracefunc,
! 					       tstate->c_traceobj, f);
! 			if (tstate->c_profilefunc)
! 				call_exc_trace(tstate->c_profilefunc,
! 					       tstate->c_profileobj, f);
  		}
  
--- 2146,2157 ----
  			PyTraceBack_Here(f);
  
! 			if (tstate->use_tracing) {
! 				if (tstate->c_tracefunc)
! 					call_exc_trace(tstate->c_tracefunc,
! 						       tstate->c_traceobj, f);
! 				if (tstate->c_profilefunc)
! 					call_exc_trace(tstate->c_profilefunc,
! 						       tstate->c_profileobj,f);
! 			}
  		}
  
***************
*** 2229,2236 ****
  		retval = NULL;
  
! 	if (tstate->c_tracefunc && !tstate->tracing) {
! 		if (why == WHY_RETURN || why == WHY_YIELD) {
! 			if (call_trace(tstate->c_tracefunc, tstate->c_traceobj,
! 				       f, PyTrace_RETURN, retval)) {
  				Py_XDECREF(retval);
  				retval = NULL;
--- 2234,2243 ----
  		retval = NULL;
  
! 	if (tstate->use_tracing) {
! 		if (tstate->c_tracefunc
! 		    && (why == WHY_RETURN || why == WHY_YIELD)) {
! 			if (call_trace(tstate->c_tracefunc,
! 				       tstate->c_traceobj, f,
! 				       PyTrace_RETURN, retval)) {
  				Py_XDECREF(retval);
  				retval = NULL;
***************
*** 2238,2250 ****
  			}
  		}
! 	}
! 
! 	if (tstate->c_profilefunc && !tstate->tracing
! 	    && (why == WHY_RETURN || why == WHY_YIELD)) {
! 		if (call_trace(tstate->c_profilefunc, tstate->c_profileobj,
! 			       f, PyTrace_RETURN, retval)) {
! 			Py_XDECREF(retval);
! 			retval = NULL;
! 			why = WHY_EXCEPTION;
  		}
  	}
--- 2245,2257 ----
  			}
  		}
! 		if (tstate->c_profilefunc
! 		    && (why == WHY_RETURN || why == WHY_YIELD)) {
! 			if (call_trace(tstate->c_profilefunc,
! 				       tstate->c_profileobj, f,
! 				       PyTrace_RETURN, retval)) {
! 				Py_XDECREF(retval);
! 				retval = NULL;
! 				why = WHY_EXCEPTION;
! 			}
  		}
  	}
***************
*** 2472,2504 ****
  	}
  
! 	if (tstate->c_tracefunc != NULL && !tstate->tracing) {
! 		/* tstate->sys_tracefunc, if defined, is a function that
! 		   will be called  on *every* entry to a code block.
! 		   Its return value, if not None, is a function that
! 		   will be called at the start of each executed line
! 		   of code.  (Actually, the function must return
! 		   itself in order to continue tracing.)
! 		   The trace functions are called with three arguments:
! 		   a pointer to the current frame, a string indicating
! 		   why the function is called, and an argument which
! 		   depends on the situation.  The global trace function
! 		   (sys.trace) is also called whenever an exception
! 		   is detected. */
! 		if (call_trace(tstate->c_tracefunc, tstate->c_traceobj,
! 			       f, PyTrace_CALL, Py_None)) {
! 			/* XXX Need way to compute arguments?? */
! 			/* Trace function raised an error */
! 			goto fail;
  		}
! 	}
! 
! 	if (tstate->c_profilefunc != NULL) {
! 		/* Similar for sys_profilefunc, except it needn't return
! 		   itself and isn't called for "line" events */
! 		if (call_trace(tstate->c_profilefunc, tstate->c_profileobj,
! 			       f, PyTrace_CALL, Py_None)) {
! 			/* XXX Need way to compute arguments?? */
! 			/* Profile function raised an error */
! 			goto fail;
  		}
  	}
--- 2479,2514 ----
  	}
  
! 	if (tstate->use_tracing) {
! 		if (tstate->c_tracefunc != NULL) {
! 			/* tstate->c_tracefunc, if defined, is a
! 			   function that will be called on *every* entry
! 			   to a code block.  Its return value, if not
! 			   None, is a function that will be called at
! 			   the start of each executed line of code.
! 			   (Actually, the function must return itself
! 			   in order to continue tracing.)  The trace
! 			   functions are called with three arguments:
! 			   a pointer to the current frame, a string
! 			   indicating why the function is called, and
! 			   an argument which depends on the situation.
! 			   The global trace function is also called
! 			   whenever an exception is detected. */
! 			if (call_trace(tstate->c_tracefunc, tstate->c_traceobj,
! 				       f, PyTrace_CALL, Py_None)) {
! 				/* XXX Need way to compute arguments?? */
! 				/* Trace function raised an error */
! 				goto fail;
! 			}
  		}
! 		if (tstate->c_profilefunc != NULL) {
! 			/* Similar for c_profilefunc, except it needn't
! 			   return itself and isn't called for "line" events */
! 			if (call_trace(tstate->c_profilefunc,
! 				       tstate->c_profileobj,
! 				       f, PyTrace_CALL, Py_None)) {
! 				/* XXX Need way to compute arguments?? */
! 				/* Profile function raised an error */
! 				goto fail;
! 			}
  		}
  	}
***************
*** 2804,2808 ****
--- 2814,2821 ----
  		return 0;
  	tstate->tracing++;
+ 	tstate->use_tracing = 0;
  	result = func(obj, frame, what, arg);
+ 	tstate->use_tracing = ((tstate->c_tracefunc != NULL)
+ 			       || (tstate->c_profilefunc != NULL));
  	tstate->tracing--;
  	return result;
***************
*** 2817,2823 ****
--- 2830,2838 ----
  	tstate->c_profilefunc = NULL;
  	tstate->c_profileobj = NULL;
+ 	tstate->use_tracing = tstate->c_tracefunc != NULL;
  	Py_XDECREF(temp);
  	tstate->c_profilefunc = func;
  	tstate->c_profileobj = arg;
+ 	tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);
  }
  
***************
*** 2830,2836 ****
--- 2845,2854 ----
  	tstate->c_tracefunc = NULL;
  	tstate->c_traceobj = NULL;
+ 	tstate->use_tracing = tstate->c_profilefunc != NULL;
  	Py_XDECREF(temp);
  	tstate->c_tracefunc = func;
  	tstate->c_traceobj = arg;
+ 	tstate->use_tracing = ((func != NULL)
+ 			       || (tstate->c_profilefunc != NULL));
  }
  

Index: pystate.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pystate.c,v
retrieving revision 2.17
retrieving revision 2.18
diff -C2 -r2.17 -r2.18
*** pystate.c	2001/06/27 19:19:46	2.17
--- pystate.c	2001/07/03 23:39:52	2.18
***************
*** 110,113 ****
--- 110,114 ----
  		tstate->ticker = 0;
  		tstate->tracing = 0;
+ 		tstate->use_tracing = 0;
  
  		tstate->dict = NULL;