https://github.com/python/cpython/commit/616b745b89a52a1d27123107718f85e65918afdc
commit: 616b745b89a52a1d27123107718f85e65918afdc
branch: main
author: Mark Shannon <[email protected]>
committer: gvanrossum <[email protected]>
date: 2024-05-06T21:21:06Z
summary:

GH-115709: Invalidate executors when a local variable is changed via 
frame.f_locals (#118639)

Also fix unrelated assert in debug Tier2/JIT builds.

files:
M Include/cpython/optimizer.h
M Lib/test/test_capi/test_opt.py
M Objects/frameobject.c
M Python/bytecodes.c
M Python/generated_cases.c.h

diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h
index 744a272251e75c..5f218d75b346a0 100644
--- a/Include/cpython/optimizer.h
+++ b/Include/cpython/optimizer.h
@@ -141,9 +141,6 @@ void _Py_ExecutorDetach(_PyExecutorObject *);
 void _Py_BloomFilter_Init(_PyBloomFilter *);
 void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);
 PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void 
*obj);
-PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj, int is_invalidation);
-PyAPI_FUNC(void) _Py_Executors_InvalidateAll(PyInterpreterState *interp, int 
is_invalidation);
-
 /* For testing */
 PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);
 PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(void);
@@ -151,6 +148,15 @@ PyAPI_FUNC(PyObject 
*)PyUnstable_Optimizer_NewUOpOptimizer(void);
 #define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3
 #define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6
 
+#ifdef _Py_TIER2
+PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj, int is_invalidation);
+PyAPI_FUNC(void) _Py_Executors_InvalidateAll(PyInterpreterState *interp, int 
is_invalidation);
+#else
+#  define _Py_Executors_InvalidateDependency(A, B, C) ((void)0)
+#  define _Py_Executors_InvalidateAll(A, B) ((void)0)
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 6e5b626e93291a..0491ff9b84d486 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1321,5 +1321,18 @@ def testfunc(n):
         self.assertIsNotNone(ex)
         self.assertIn("_FOR_ITER_GEN_FRAME", get_opnames(ex))
 
+    def test_modified_local_is_seen_by_optimized_code(self):
+        l = sys._getframe().f_locals
+        a = 1
+        s = 0
+        for j in range(1 << 10):
+            a + a
+            l["xa"[j >> 9]] = 1.0
+            s += a
+        self.assertIs(type(a), float)
+        self.assertIs(type(s), float)
+        self.assertEqual(s, 1024.0)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 869cdec8aa7062..26a04cbeea90bf 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -148,8 +148,9 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, 
PyObject *value)
     if (PyUnicode_CheckExact(key)) {
         int i = framelocalsproxy_getkeyindex(frame, key, false);
         if (i >= 0) {
-            _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
+            _Py_Executors_InvalidateDependency(PyInterpreterState_Get(), co, 
1);
 
+            _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
             PyObject *oldvalue = fast[i];
             PyObject *cell = NULL;
             if (kind == CO_FAST_FREE) {
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index b2a0dc030e20cc..b2ddec98e682f2 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2424,6 +2424,9 @@ dummy_func(
                 opcode = executor->vm_data.opcode;
                 oparg = (oparg & ~255) | executor->vm_data.oparg;
                 next_instr = this_instr;
+                if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
+                    PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
+                }
                 DISPATCH_GOTO();
             }
             tstate->previous_executor = Py_None;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 87098b0506522f..d3126b0c980723 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2673,6 +2673,9 @@
                 opcode = executor->vm_data.opcode;
                 oparg = (oparg & ~255) | executor->vm_data.oparg;
                 next_instr = this_instr;
+                if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
+                    PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
+                }
                 DISPATCH_GOTO();
             }
             tstate->previous_executor = Py_None;

_______________________________________________
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