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]

Reply via email to