[Python-checkins] bpo-46532: Reduce number of memory writes to update call_shape.kwnames. (GH-31231)
markshannon
webhook-mailer at python.org
Thu Feb 10 07:58:00 EST 2022
https://github.com/python/cpython/commit/2cea8c29cf975a8ad7d8c3ff19d1e836c2d54707
commit: 2cea8c29cf975a8ad7d8c3ff19d1e836c2d54707
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2022-02-10T12:57:55Z
summary:
bpo-46532: Reduce number of memory writes to update call_shape.kwnames. (GH-31231)
files:
M Python/ceval.c
diff --git a/Python/ceval.c b/Python/ceval.c
index 7e19043c7aa64..c3703a75ce0ca 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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)) {
More information about the Python-checkins
mailing list