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.
diff --git a/Python/ceval.c b/Python/ceval.c
index 702380d..79eb0ad 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1890,8 +1890,11 @@
 			f->f_lasti = INSTR_OFFSET();
 			/* 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;
 
@@ -2142,12 +2145,14 @@
 				f->f_lasti -= 2;
 			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);
+			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);
+			}
 		}
 
 		/* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
@@ -2228,24 +2233,26 @@
 	if (why != WHY_RETURN && why != WHY_YIELD)
 		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)) {
+	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;
 				why = WHY_EXCEPTION;
 			}
 		}
-	}
-
-	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;
+		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;
+			}
 		}
 	}
 
@@ -2471,35 +2478,38 @@
 		}
 	}
 
-	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->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 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;
+		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;
+			}
 		}
 	}
 
@@ -2803,7 +2813,10 @@
 	if (tstate->tracing)
 		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;
 }
@@ -2816,9 +2829,11 @@
 	Py_XINCREF(arg);
 	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);
 }
 
 void
@@ -2829,9 +2844,12 @@
 	Py_XINCREF(arg);
 	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));
 }
 
 PyObject *