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.
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index fe880d5..76d40bf 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -196,20 +196,120 @@
 \n\
 Set the current default string encoding used by the Unicode implementation.";
 
-extern int _PyTrace_Init(void);
+/*
+ * Cached interned string objects used for calling the profile and
+ * trace functions.  Initialized by trace_init().
+ */
+static PyObject *whatstrings[4] = {NULL, NULL, NULL, NULL};
+
+static int
+trace_init(void)
+{
+	static char *whatnames[4] = {"call", "exception", "line", "return"};
+	PyObject *name;
+	int i;
+	for (i = 0; i < 4; ++i) {
+		if (whatstrings[i] == NULL) {
+			name = PyString_InternFromString(whatnames[i]);
+			if (name == NULL)
+				return -1;
+			whatstrings[i] = name;
+                }
+	}
+	return 0;
+}
+
+
+static PyObject *
+call_trampoline(PyThreadState *tstate, PyObject* callback,
+		PyFrameObject *frame, int what, PyObject *arg)
+{
+	PyObject *args = PyTuple_New(3);
+	PyObject *whatstr;
+	PyObject *result;
+
+	if (args == NULL)
+		return NULL;
+	Py_INCREF(frame);
+	whatstr = whatstrings[what];
+	Py_INCREF(whatstr);
+	if (arg == NULL)
+		arg = Py_None;
+	Py_INCREF(arg);
+	PyTuple_SET_ITEM(args, 0, (PyObject *)frame);
+	PyTuple_SET_ITEM(args, 1, whatstr);
+	PyTuple_SET_ITEM(args, 2, arg);
+
+	/* call the Python-level function */
+	PyFrame_FastToLocals(frame);
+	result = PyEval_CallObject(callback, args);
+	PyFrame_LocalsToFast(frame, 1);
+	if (result == NULL)
+		PyTraceBack_Here(frame);
+
+	/* cleanup */
+	Py_DECREF(args);
+	return result;
+}
+
+static int
+profile_trampoline(PyObject *self, PyFrameObject *frame,
+		   int what, PyObject *arg)
+{
+	PyThreadState *tstate = frame->f_tstate;
+	PyObject *result;
+
+	result = call_trampoline(tstate, self, frame, what, arg);
+	if (result == NULL) {
+		PyEval_SetProfile(NULL, NULL);
+		return -1;
+	}
+	Py_DECREF(result);
+	return 0;
+}
+
+static int
+trace_trampoline(PyObject *self, PyFrameObject *frame,
+		 int what, PyObject *arg)
+{
+	PyThreadState *tstate = frame->f_tstate;
+	PyObject *callback;
+	PyObject *result;
+
+	if (what == PyTrace_CALL)
+		callback = self;
+	else
+		callback = frame->f_trace;
+	if (callback == NULL)
+		return 0;
+	result = call_trampoline(tstate, callback, frame, what, arg);
+	if (result == NULL) {
+		PyEval_SetTrace(NULL, NULL);
+		Py_XDECREF(frame->f_trace);
+		frame->f_trace = NULL;
+		return -1;
+	}
+	if (result != Py_None) {
+		PyObject *temp = frame->f_trace;
+		frame->f_trace = NULL;
+		Py_XDECREF(temp);
+		frame->f_trace = result;
+	}
+	else {
+		Py_DECREF(result);
+	}
+	return 0;
+}
 
 static PyObject *
 sys_settrace(PyObject *self, PyObject *args)
 {
-	PyThreadState *tstate = PyThreadState_Get();
-	if (_PyTrace_Init() == -1)
+	if (trace_init() == -1)
 		return NULL;
 	if (args == Py_None)
-		args = NULL;
+		PyEval_SetTrace(NULL, NULL);
 	else
-		Py_XINCREF(args);
-	Py_XDECREF(tstate->sys_tracefunc);
-	tstate->sys_tracefunc = args;
+		PyEval_SetTrace(trace_trampoline, args);
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -223,15 +323,12 @@
 static PyObject *
 sys_setprofile(PyObject *self, PyObject *args)
 {
-	PyThreadState *tstate = PyThreadState_Get();
-	if (_PyTrace_Init() == -1)
+	if (trace_init() == -1)
 		return NULL;
 	if (args == Py_None)
-		args = NULL;
+		PyEval_SetProfile(NULL, NULL);
 	else
-		Py_XINCREF(args);
-	Py_XDECREF(tstate->sys_profilefunc);
-	tstate->sys_profilefunc = args;
+		PyEval_SetProfile(profile_trampoline, args);
 	Py_INCREF(Py_None);
 	return Py_None;
 }