mirror of https://github.com/python/cpython
GH-115709: Invalidate executors when a local variable is changed via frame.f_locals (#118639)
Also fix unrelated assert in debug Tier2/JIT builds.
This commit is contained in:
parent
00d913c671
commit
616b745b89
|
@ -141,9 +141,6 @@ void _Py_ExecutorDetach(_PyExecutorObject *);
|
||||||
void _Py_BloomFilter_Init(_PyBloomFilter *);
|
void _Py_BloomFilter_Init(_PyBloomFilter *);
|
||||||
void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);
|
void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);
|
||||||
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, 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 */
|
/* For testing */
|
||||||
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);
|
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);
|
||||||
PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(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_BUILTINS_MODIFICATIONS 3
|
||||||
#define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1321,5 +1321,18 @@ class TestUopsOptimization(unittest.TestCase):
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
self.assertIn("_FOR_ITER_GEN_FRAME", get_opnames(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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -148,8 +148,9 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
|
||||||
if (PyUnicode_CheckExact(key)) {
|
if (PyUnicode_CheckExact(key)) {
|
||||||
int i = framelocalsproxy_getkeyindex(frame, key, false);
|
int i = framelocalsproxy_getkeyindex(frame, key, false);
|
||||||
if (i >= 0) {
|
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 *oldvalue = fast[i];
|
||||||
PyObject *cell = NULL;
|
PyObject *cell = NULL;
|
||||||
if (kind == CO_FAST_FREE) {
|
if (kind == CO_FAST_FREE) {
|
||||||
|
|
|
@ -2424,6 +2424,9 @@ dummy_func(
|
||||||
opcode = executor->vm_data.opcode;
|
opcode = executor->vm_data.opcode;
|
||||||
oparg = (oparg & ~255) | executor->vm_data.oparg;
|
oparg = (oparg & ~255) | executor->vm_data.oparg;
|
||||||
next_instr = this_instr;
|
next_instr = this_instr;
|
||||||
|
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
|
||||||
|
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||||
|
}
|
||||||
DISPATCH_GOTO();
|
DISPATCH_GOTO();
|
||||||
}
|
}
|
||||||
tstate->previous_executor = Py_None;
|
tstate->previous_executor = Py_None;
|
||||||
|
|
|
@ -2673,6 +2673,9 @@
|
||||||
opcode = executor->vm_data.opcode;
|
opcode = executor->vm_data.opcode;
|
||||||
oparg = (oparg & ~255) | executor->vm_data.oparg;
|
oparg = (oparg & ~255) | executor->vm_data.oparg;
|
||||||
next_instr = this_instr;
|
next_instr = this_instr;
|
||||||
|
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
|
||||||
|
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||||
|
}
|
||||||
DISPATCH_GOTO();
|
DISPATCH_GOTO();
|
||||||
}
|
}
|
||||||
tstate->previous_executor = Py_None;
|
tstate->previous_executor = Py_None;
|
||||||
|
|
Loading…
Reference in New Issue