mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-46532: Reduce number of memory writes to update call_shape.kwnames. (GH-31231)
This commit is contained in:
		
							parent
							
								
									012e77eb5c
								
							
						
					
					
						commit
						2cea8c29cf
					
				
					 1 changed files with 15 additions and 7 deletions
				
			
		|  | @ -1615,7 +1615,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
| 
 | ||||
|     CFrame cframe; | ||||
|     CallShape call_shape; | ||||
|     call_shape.kwnames = NULL; // Borrowed reference
 | ||||
|     call_shape.kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
 | ||||
|     /* The following three values are always set by the PRECALL instructions.
 | ||||
|        They are set here to keep the compiler happy. */ | ||||
|     call_shape.postcall_shrink = 0; | ||||
|     call_shape.total_args = 0; | ||||
|     call_shape.callable = NULL; // Strong reference
 | ||||
|  | @ -4446,7 +4448,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|             call_shape.postcall_shrink = 1; | ||||
| 
 | ||||
|             call_shape.total_args = oparg; | ||||
|             call_shape.kwnames = NULL; | ||||
|             assert(call_shape.kwnames == NULL); | ||||
| #ifdef Py_STATS | ||||
|             extern int _PySpecialization_ClassifyCallable(PyObject *); | ||||
|             _py_stats.opcode_stats[PRECALL_FUNCTION].specialization.failure++; | ||||
|  | @ -4490,12 +4492,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|             call_shape.postcall_shrink = 2-is_method; | ||||
| 
 | ||||
|             call_shape.total_args = nargs; | ||||
|             call_shape.kwnames = NULL; | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             DISPATCH(); | ||||
|         } | ||||
| 
 | ||||
|         TARGET(KW_NAMES) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             assert(oparg < PyTuple_GET_SIZE(consts)); | ||||
|             call_shape.kwnames = GETITEM(consts, oparg); | ||||
|             DISPATCH(); | ||||
|  | @ -4531,6 +4532,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|                     tstate, (PyFunctionObject *)function, locals, | ||||
|                     stack_pointer, positional_args, call_shape.kwnames | ||||
|                 ); | ||||
|                 call_shape.kwnames = NULL; | ||||
|                 STACK_SHRINK(call_shape.postcall_shrink); | ||||
|                 // The frame has stolen all the arguments from the stack,
 | ||||
|                 // so there is no need to clean them up.
 | ||||
|  | @ -4556,6 +4558,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|                     positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, | ||||
|                     call_shape.kwnames); | ||||
|             } | ||||
|             call_shape.kwnames = NULL; | ||||
|             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); | ||||
|             Py_DECREF(function); | ||||
|             /* Clear the stack */ | ||||
|  | @ -4597,6 +4600,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|         } | ||||
| 
 | ||||
|         TARGET(CALL_PY_EXACT_ARGS) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             SpecializedCacheEntry *caches = GET_CACHE(); | ||||
|             int argcount = call_shape.total_args; | ||||
|             DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL); | ||||
|  | @ -4625,6 +4629,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|         } | ||||
| 
 | ||||
|         TARGET(CALL_PY_WITH_DEFAULTS) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             SpecializedCacheEntry *caches = GET_CACHE(); | ||||
|             int argcount = call_shape.total_args; | ||||
|             DEOPT_IF(!PyFunction_Check(call_shape.callable), CALL); | ||||
|  | @ -4661,9 +4666,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|         } | ||||
| 
 | ||||
|         TARGET(CALL_NO_KW_TYPE_1) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             assert(cframe.use_tracing == 0); | ||||
|             DEOPT_IF(call_shape.total_args != 1, CALL); | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             PyObject *obj = TOP(); | ||||
|             PyObject *callable = SECOND(); | ||||
|             DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); | ||||
|  | @ -4676,13 +4681,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|         } | ||||
| 
 | ||||
|         TARGET(CALL_NO_KW_STR_1) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             assert(cframe.use_tracing == 0); | ||||
|             DEOPT_IF(!PyType_Check(call_shape.callable), CALL); | ||||
|             PyTypeObject *tp = (PyTypeObject *)call_shape.callable; | ||||
|             DEOPT_IF(call_shape.total_args != 1, CALL); | ||||
|             DEOPT_IF(tp != &PyUnicode_Type, CALL); | ||||
|             STAT_INC(CALL, hit); | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             PyObject *arg = TOP(); | ||||
|             PyObject *res = PyObject_Str(arg); | ||||
|             Py_DECREF(arg); | ||||
|  | @ -4696,12 +4701,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|         } | ||||
| 
 | ||||
|         TARGET(CALL_NO_KW_TUPLE_1) { | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             DEOPT_IF(!PyType_Check(call_shape.callable), CALL); | ||||
|             PyTypeObject *tp = (PyTypeObject *)call_shape.callable; | ||||
|             DEOPT_IF(call_shape.total_args != 1, CALL); | ||||
|             DEOPT_IF(tp != &PyTuple_Type, CALL); | ||||
|             STAT_INC(CALL, hit); | ||||
|             assert(call_shape.kwnames == NULL); | ||||
|             PyObject *arg = TOP(); | ||||
|             PyObject *res = PySequence_Tuple(arg); | ||||
|             Py_DECREF(arg); | ||||
|  | @ -4724,6 +4729,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|             int nargs = call_shape.total_args - kwnames_len; | ||||
|             STACK_SHRINK(call_shape.total_args); | ||||
|             PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, nargs, call_shape.kwnames); | ||||
|             call_shape.kwnames = NULL; | ||||
|             /* Free the arguments. */ | ||||
|             for (int i = 0; i < call_shape.total_args; i++) { | ||||
|                 Py_DECREF(stack_pointer[i]); | ||||
|  | @ -4833,6 +4839,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr | |||
|                 call_shape.kwnames | ||||
|             ); | ||||
|             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); | ||||
|             call_shape.kwnames = NULL; | ||||
| 
 | ||||
|             /* Free the arguments. */ | ||||
|             for (int i = 0; i < call_shape.total_args; i++) { | ||||
|  | @ -5398,6 +5405,7 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) | |||
|         } | ||||
| 
 | ||||
| error: | ||||
|         call_shape.kwnames = NULL; | ||||
|         /* Double-check exception status. */ | ||||
| #ifdef NDEBUG | ||||
|         if (!_PyErr_Occurred(tstate)) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon