mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Instead of initializing & interning the strings passed to the profile
and trace functions lazily, which incurs extra argument pushing and checks in the C overhead for profiling/tracing, create the strings semi-lazily when the Python code first registers a profile or trace function. This simplifies the trampoline into the profile/trace functions.
This commit is contained in:
		
							parent
							
								
									70128a1ba6
								
							
						
					
					
						commit
						d083839fb4
					
				
					 2 changed files with 48 additions and 26 deletions
				
			
		|  | @ -62,7 +62,7 @@ static int prtrace(PyObject *, char *); | |||
| #endif | ||||
| static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); | ||||
| static int call_trace(PyObject **, PyObject **, | ||||
| 		      PyFrameObject *, char *, PyObject **, PyObject *); | ||||
| 		      PyFrameObject *, PyObject *, PyObject *); | ||||
| static PyObject *loop_subscript(PyObject *, PyObject *); | ||||
| static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); | ||||
| static int assign_slice(PyObject *, PyObject *, | ||||
|  | @ -654,7 +654,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, | |||
| 		   (sys.trace) is also called whenever an exception | ||||
| 		   is detected. */ | ||||
| 		if (call_trace(&tstate->sys_tracefunc, | ||||
| 			       &f->f_trace, f, "call", &str_call, | ||||
| 			       &f->f_trace, f, str_call, | ||||
| 			       Py_None/*XXX how to compute arguments now?*/)) { | ||||
| 			/* Trace function raised an error */ | ||||
| 			goto fail; | ||||
|  | @ -665,7 +665,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, | |||
| 		/* Similar for sys_profilefunc, except it needn't return
 | ||||
| 		   itself and isn't called for "line" events */ | ||||
| 		if (call_trace(&tstate->sys_profilefunc, | ||||
| 			       (PyObject**)0, f, "call", &str_call, | ||||
| 			       (PyObject**)0, f, str_call, | ||||
| 			       Py_None/*XXX*/)) { | ||||
| 			goto fail; | ||||
| 		} | ||||
|  | @ -1961,7 +1961,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, | |||
| 			/* Trace each line of code reached */ | ||||
| 			f->f_lasti = INSTR_OFFSET(); | ||||
| 			err = call_trace(&f->f_trace, &f->f_trace, | ||||
| 					 f, "line", &str_line, Py_None); | ||||
| 					 f, str_line, Py_None); | ||||
| 			break; | ||||
| 
 | ||||
| 		case CALL_FUNCTION: | ||||
|  | @ -2306,7 +2306,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, | |||
| 	if (f->f_trace) { | ||||
| 		if (why == WHY_RETURN) { | ||||
| 			if (call_trace(&f->f_trace, &f->f_trace, f, | ||||
| 				       "return", &str_return, retval)) { | ||||
| 				       str_return, retval)) { | ||||
| 				Py_XDECREF(retval); | ||||
| 				retval = NULL; | ||||
| 				why = WHY_EXCEPTION; | ||||
|  | @ -2316,7 +2316,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, | |||
| 
 | ||||
| 	if (tstate->sys_profilefunc && why == WHY_RETURN) { | ||||
| 		if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, | ||||
| 			       f, "return", &str_return, retval)) { | ||||
| 			       f, str_return, retval)) { | ||||
| 			Py_XDECREF(retval); | ||||
| 			retval = NULL; | ||||
| 			why = WHY_EXCEPTION; | ||||
|  | @ -2584,8 +2584,7 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) | |||
| 		PyErr_Restore(type, value, traceback); | ||||
| 		return; | ||||
| 	} | ||||
| 	err = call_trace(p_trace, p_newtrace, f, | ||||
| 			 "exception", &str_exception, arg); | ||||
| 	err = call_trace(p_trace, p_newtrace, f, str_exception, arg); | ||||
| 	Py_DECREF(arg); | ||||
| 	if (err == 0) | ||||
| 		PyErr_Restore(type, value, traceback); | ||||
|  | @ -2601,18 +2600,15 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) | |||
|    PyObject **p_newtrace: in/out; may be NULL; | ||||
|   				may point to NULL variable; | ||||
|  				may be same variable as p_newtrace | ||||
|    PyObject **p_omsg: in/out; may not be NULL; | ||||
| 				if non-null & *p_omsg == NULL, will be | ||||
| 				initialized with an interned string | ||||
| 				corresponding to msg. | ||||
|    PyObject *msg: in; must not be NULL | ||||
| */ | ||||
| 
 | ||||
| static int | ||||
| call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, | ||||
| 	   char *msg, PyObject **p_omsg, PyObject *arg) | ||||
| 	   PyObject *msg, PyObject *arg) | ||||
| { | ||||
| 	PyThreadState *tstate = f->f_tstate; | ||||
| 	PyObject *args, *what; | ||||
| 	PyObject *args; | ||||
| 	PyObject *res = NULL; | ||||
| 
 | ||||
| 	if (tstate->tracing) { | ||||
|  | @ -2627,20 +2623,10 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, | |||
| 	args = PyTuple_New(3); | ||||
| 	if (args == NULL) | ||||
| 		goto cleanup; | ||||
| 	if (*p_omsg != NULL) { | ||||
| 		what = *p_omsg; | ||||
| 		Py_INCREF(what); | ||||
| 	} | ||||
| 	else { | ||||
| 		what = PyString_InternFromString(msg); | ||||
| 		if (what == NULL) | ||||
| 			goto cleanup; | ||||
| 		*p_omsg = what; | ||||
| 		Py_INCREF(what); | ||||
| 	} | ||||
| 	Py_INCREF(msg); | ||||
| 	Py_INCREF(f); | ||||
| 	PyTuple_SET_ITEM(args, 0, (PyObject *)f); | ||||
| 	PyTuple_SET_ITEM(args, 1, what); | ||||
| 	PyTuple_SET_ITEM(args, 1, msg); | ||||
| 	if (arg == NULL) | ||||
| 		arg = Py_None; | ||||
| 	Py_INCREF(arg); | ||||
|  | @ -2686,6 +2672,36 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Initialize the strings that get passed to the profile and trace functions;
 | ||||
|  * this avoids doing this while we're actually profiling/tracing. | ||||
|  */ | ||||
| int | ||||
| _PyTrace_Init(void) | ||||
| { | ||||
| 	if (str_call == NULL) { | ||||
| 		str_call = PyString_InternFromString("call"); | ||||
| 		if (str_call == NULL) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	if (str_exception == NULL) { | ||||
| 		str_exception = PyString_InternFromString("exception"); | ||||
| 		if (str_exception == NULL) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	if (str_line == NULL) { | ||||
| 		str_line = PyString_InternFromString("line"); | ||||
| 		if (str_line == NULL) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	if (str_return == NULL) { | ||||
| 		str_return = PyString_InternFromString("return"); | ||||
| 		if (str_return == NULL) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| PyObject * | ||||
| PyEval_GetBuiltins(void) | ||||
| { | ||||
|  |  | |||
|  | @ -196,10 +196,14 @@ static char setdefaultencoding_doc[] = | |||
| \n\ | ||||
| Set the current default string encoding used by the Unicode implementation."; | ||||
| 
 | ||||
| extern int _PyTrace_Init(void); | ||||
| 
 | ||||
| static PyObject * | ||||
| sys_settrace(PyObject *self, PyObject *args) | ||||
| { | ||||
| 	PyThreadState *tstate = PyThreadState_Get(); | ||||
| 	if (_PyTrace_Init() == -1) | ||||
| 		return NULL; | ||||
| 	if (args == Py_None) | ||||
| 		args = NULL; | ||||
| 	else | ||||
|  | @ -220,6 +224,8 @@ static PyObject * | |||
| sys_setprofile(PyObject *self, PyObject *args) | ||||
| { | ||||
| 	PyThreadState *tstate = PyThreadState_Get(); | ||||
| 	if (_PyTrace_Init() == -1) | ||||
| 		return NULL; | ||||
| 	if (args == Py_None) | ||||
| 		args = NULL; | ||||
| 	else | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fred Drake
						Fred Drake