]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-113710: Fix optimization of globals using `_CHECK_FUNCTION` (GH-116460)
authorMark Shannon <mark@hotpy.org>
Fri, 8 Mar 2024 09:47:41 +0000 (09:47 +0000)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2024 09:47:41 +0000 (09:47 +0000)
Python/bytecodes.c
Python/executor_cases.c.h
Python/optimizer_analysis.c

index 0397d96e3f63ba91774b7110846e3617d10f2b37..bf9d2a316ceea0f47cc833364cc48ab26f400974 100644 (file)
@@ -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 */
index 26ac1593d534e4723a7b382a1accdb9ca04fcc82..ccd8fb32989e927ea69895c724f5f917557a8b61 100644 (file)
         }
 
         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;
         }
 
index 0f255272fbb2e665bae88b89f1b6d64892c25315..51ec14b718f2913a95b0eaaae7b3a42a87d555a1 100644 (file)
@@ -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;