https://github.com/python/cpython/commit/0003285c8d78f0b463f2acc164655456fcfc3206
commit: 0003285c8d78f0b463f2acc164655456fcfc3206
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2024-03-08T09:47:41Z
summary:
GH-113710: Fix optimization of globals using `_CHECK_FUNCTION` (GH-116460)
files:
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/optimizer_analysis.c
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 0397d96e3f63ba..bf9d2a316ceea0 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4096,8 +4096,9 @@ dummy_func(
null = NULL;
}
- tier2 op(_CHECK_FUNCTION, (func/4 -- )) {
- DEOPT_IF(frame->f_funcobj != func);
+ tier2 op(_CHECK_FUNCTION, (func_version/2 -- )) {
+ assert(PyFunction_Check(frame->f_funcobj));
+ DEOPT_IF(((PyFunctionObject *)frame->f_funcobj)->func_version !=
func_version);
}
/* Internal -- for testing executors */
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 26ac1593d534e4..ccd8fb32989e92 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3829,8 +3829,9 @@
}
case _CHECK_FUNCTION: {
- PyObject *func = (PyObject *)CURRENT_OPERAND();
- if (frame->f_funcobj != func) goto deoptimize;
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
+ assert(PyFunction_Check(frame->f_funcobj));
+ if (((PyFunctionObject *)frame->f_funcobj)->func_version !=
func_version) goto deoptimize;
break;
}
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 0f255272fbb2e6..51ec14b718f291 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -141,9 +141,11 @@ remove_globals(_PyInterpreterFrame *frame,
_PyUOpInstruction *buffer,
return 1;
}
PyObject *globals = frame->f_globals;
- assert(PyFunction_Check(((PyFunctionObject *)frame->f_funcobj)));
- assert(((PyFunctionObject *)frame->f_funcobj)->func_builtins == builtins);
- assert(((PyFunctionObject *)frame->f_funcobj)->func_globals == globals);
+ PyFunctionObject *function = (PyFunctionObject *)frame->f_funcobj;
+ assert(PyFunction_Check(function));
+ assert(function->func_builtins == builtins);
+ assert(function->func_globals == globals);
+ uint32_t function_version =
_PyFunction_GetVersionForCurrentState(function);
/* In order to treat globals as constants, we need to
* know that the globals dict is the one we expected, and
* that it hasn't changed
@@ -181,7 +183,7 @@ remove_globals(_PyInterpreterFrame *frame,
_PyUOpInstruction *buffer,
}
else {
buffer[pc].opcode = _CHECK_FUNCTION;
- buffer[pc].operand = (uintptr_t)builtins;
+ buffer[pc].operand = function_version;
function_checked |= 1;
}
break;
@@ -203,7 +205,7 @@ remove_globals(_PyInterpreterFrame *frame,
_PyUOpInstruction *buffer,
}
else {
buffer[pc].opcode = _CHECK_FUNCTION;
- buffer[pc].operand = (uintptr_t)globals;
+ buffer[pc].operand = function_version;
function_checked |= 1;
}
break;
@@ -227,7 +229,8 @@ remove_globals(_PyInterpreterFrame *frame,
_PyUOpInstruction *buffer,
return 1;
}
assert(PyFunction_Check(func));
- if (prechecked_function_version == func->func_version) {
+ function_version = func->func_version;
+ if (prechecked_function_version == function_version) {
function_checked |= 1;
}
prechecked_function_version = 0;
@@ -245,6 +248,7 @@ remove_globals(_PyInterpreterFrame *frame,
_PyUOpInstruction *buffer,
function_checked >>= 1;
PyFunctionObject *func = (PyFunctionObject
*)buffer[pc].operand;
assert(PyFunction_Check(func));
+ function_version = func->func_version;
globals = func->func_globals;
builtins = func->func_builtins;
break;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]