From 365b6ccc43dbff5bb7bf65ea88413f93b12e48f2 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 11:10:37 +0100 Subject: [PATCH 01/10] Remove potentially unsafe uses of NOTRACE_DISPATCH. --- Python/ceval.c | 103 +++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index af47e091bc7f0b..dca560cc3ce3f4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -716,10 +716,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH_GOTO(); \ } -#define NOTRACE_DISPATCH_SAME_OPARG() \ +#define DISPATCH_SAME_OPARG() \ { \ opcode = _Py_OPCODE(*next_instr); \ PRE_DISPATCH_GOTO(); \ + opcode |= cframe.use_tracing OR_DTRACE_LINE; \ DISPATCH_GOTO(); \ } @@ -1237,7 +1238,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(value != NULL); Py_INCREF(value); PUSH(value); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(STORE_FAST__STORE_FAST) { @@ -1247,7 +1248,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int next_instr++; value = POP(); SETLOCAL(oparg, value); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_CONST__LOAD_FAST) { @@ -1339,7 +1340,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_MULTIPLY_FLOAT) { @@ -1360,7 +1361,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_SUBTRACT_INT) { @@ -1379,7 +1380,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_SUBTRACT_FLOAT) { @@ -1399,7 +1400,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_ADD_UNICODE) { @@ -1418,7 +1419,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { @@ -1454,7 +1455,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_ADD_FLOAT) { @@ -1475,7 +1476,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_OP_ADD_INT) { @@ -1494,7 +1495,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_SUBSCR) { @@ -1560,7 +1561,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_SUBSCR, deferred); @@ -1591,7 +1592,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(list); JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_SUBSCR_TUPLE_INT) { @@ -1616,7 +1617,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(tuple); JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BINARY_SUBSCR_DICT) { @@ -1724,7 +1725,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreSubscr(container, sub, next_instr) < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_SUBSCR, deferred); @@ -1756,7 +1757,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(list); JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(STORE_SUBSCR_DICT) { @@ -2238,7 +2239,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *seq = TOP(); next_instr--; _Py_Specialize_UnpackSequence(seq, next_instr, oparg); - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(UNPACK_SEQUENCE, deferred); @@ -2256,7 +2257,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0))); Py_DECREF(seq); JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(UNPACK_SEQUENCE_TUPLE) { @@ -2271,7 +2272,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } Py_DECREF(seq); JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(UNPACK_SEQUENCE_LIST) { @@ -2286,7 +2287,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } Py_DECREF(seq); JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(UNPACK_EX) { @@ -2481,7 +2482,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_GLOBAL, deferred); @@ -2508,7 +2509,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_GROW(push_null+1); Py_INCREF(res); SET_TOP(res); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_GLOBAL_BUILTIN) { @@ -2533,7 +2534,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_GROW(push_null+1); Py_INCREF(res); SET_TOP(res); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(DELETE_FAST) { @@ -2942,7 +2943,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_LoadAttr(owner, next_instr, name) < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(LOAD_ATTR, deferred); @@ -2973,7 +2974,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_MODULE) { @@ -2998,7 +2999,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_WITH_HINT) { @@ -3037,7 +3038,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_SLOT) { @@ -3059,7 +3060,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_CLASS) { @@ -3082,7 +3083,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); Py_DECREF(cls); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_PROPERTY) { @@ -3171,7 +3172,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_Py_Specialize_StoreAttr(owner, next_instr, name) < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(STORE_ATTR, deferred); @@ -3206,7 +3207,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_STORE_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(STORE_ATTR_WITH_HINT) { @@ -3255,7 +3256,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int dict->ma_version_tag = DICT_NEXT_VERSION(); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_STORE_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(STORE_ATTR_SLOT) { @@ -3275,7 +3276,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_XDECREF(old_value); Py_DECREF(owner); JUMPBY(INLINE_CACHE_ENTRIES_STORE_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(COMPARE_OP) { @@ -3302,7 +3303,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *left = SECOND(); next_instr--; _Py_Specialize_CompareOp(left, right, next_instr, oparg); - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(COMPARE_OP, deferred); @@ -3339,7 +3340,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int else { JUMPBY(1 + oparg); } - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(COMPARE_OP_INT_JUMP) { @@ -3371,7 +3372,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int else { JUMPBY(1 + oparg); } - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(COMPARE_OP_STR_JUMP) { @@ -3404,7 +3405,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int else { JUMPBY(1 + oparg); } - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(IS_OP) { @@ -3829,7 +3830,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (ADAPTIVE_COUNTER_IS_ZERO(cache)) { next_instr--; _Py_Specialize_ForIter(TOP(), next_instr); - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(FOR_ITER, deferred); @@ -3850,7 +3851,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_INCREF(next); PUSH(next); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); - NOTRACE_DISPATCH(); + DISPATCH(); } it->it_seq = NULL; Py_DECREF(seq); @@ -3858,7 +3859,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(1); Py_DECREF(it); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(FOR_ITER_RANGE) { @@ -3872,7 +3873,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(1); Py_DECREF(r); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); - NOTRACE_DISPATCH(); + DISPATCH(); } long value = (long)(r->start + (unsigned long)(r->index++) * r->step); @@ -3881,7 +3882,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(BEFORE_ASYNC_WITH) { @@ -4028,7 +4029,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); PUSH(self); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_METHOD_WITH_DICT) { @@ -4056,7 +4057,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); PUSH(self); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_METHOD_NO_DICT) { @@ -4075,7 +4076,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); PUSH(self); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_ATTR_METHOD_LAZY_DICT) { @@ -4098,7 +4099,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int SET_TOP(res); PUSH(self); JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { @@ -4208,7 +4209,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (err < 0) { goto error; } - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(CALL, deferred); @@ -4305,7 +4306,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(obj); STACK_SHRINK(2); SET_TOP(res); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(CALL_NO_KW_STR_1) { @@ -4575,7 +4576,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(2); Py_DECREF(list); Py_DECREF(callable); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { @@ -4947,7 +4948,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *rhs = TOP(); next_instr--; _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0)); - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } else { STAT_INC(BINARY_OP, deferred); @@ -4985,7 +4986,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(oparg); oparg <<= 8; oparg |= _Py_OPARG(*next_instr); - NOTRACE_DISPATCH_SAME_OPARG(); + DISPATCH_SAME_OPARG(); } TARGET(CACHE) { From 7785d401de1f7c226fd6a197ae0271e7e3b560d0 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 11:57:50 +0100 Subject: [PATCH 02/10] Add test to check that tracing is respected in specialized code. Thanks to Brandt Bucher for the test idea. --- Lib/test/test_dynamic.py | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index e896fc703c9a8b..0b18c7cbcd0756 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -149,5 +149,47 @@ def __missing__(self, key): for _ in range(30): self.assertEqual(sum_func(), expected) +class TestTracing(unittest.TestCase): + + def setUp(self): + self.addCleanup(sys.settrace, sys.gettrace()) + sys.settrace(None) + + def test_after_specialization(self): + + def trace(frame, event, arg): + return trace + + turn_on_trace = False + + class C: + def __init__(self, x): + self.x = x + def __del__(self): + if turn_on_trace: + sys.settrace(trace) + + def f(): + # LOAD_GLOBAL[_BUILTIN] immediately follows the call to C.__del__ + C(0).x, len + + def g(): + # BINARY_SUSCR[_TUPLE_INT] immediately follows the call to C.__del__ + [0][C(0).x] + + def h(): + # BINARY_OP[_ADD_INT] immediately follows the call to C.__del__ + 0 + C(0).x + + for func in (f, g, h): + for _ in range(58): + func() + turn_on_trace = True + func() + turn_on_trace = False + + + + if __name__ == "__main__": unittest.main() From 85e58446e6c2bce1902371427cc299e62538b599 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 12:02:25 +0100 Subject: [PATCH 03/10] Add news. --- .../2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst new file mode 100644 index 00000000000000..63d9a0921782f2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst @@ -0,0 +1,3 @@ +Ensure that tracing ,``sys.setrace()``, is turned on immediately. In +pre-release versions of 3.11, some tracing events might have been lost when +turning on tracing in a ``__del__`` method or interrupt. From 3dd9966b758898ce9342c3948d903c8874a66bd1 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 12:05:15 +0100 Subject: [PATCH 04/10] Turn tracing off again after check. --- Lib/test/test_dynamic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 0b18c7cbcd0756..978cc3c9f398f8 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -186,6 +186,7 @@ def h(): func() turn_on_trace = True func() + sys.settrace(None) turn_on_trace = False From 5cfaab684ed65696787563a2f128af0a2dd8bd58 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 12:19:12 +0100 Subject: [PATCH 05/10] Remove all remaining uses of NOTRACE_DISPATCH() as they might be unsafe. --- Python/ceval.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index dca560cc3ce3f4..cbe046191aa791 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -699,12 +699,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #define PRE_DISPATCH_GOTO() ((void)0) #endif -#define NOTRACE_DISPATCH() \ - { \ - NEXTOPARG(); \ - PRE_DISPATCH_GOTO(); \ - DISPATCH_GOTO(); \ - } /* Do interpreter dispatch accounting for tracing and instrumentation */ #define DISPATCH() \ @@ -1213,7 +1207,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(value != NULL); Py_INCREF(value); PUSH(value); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(LOAD_FAST__LOAD_CONST) { @@ -1226,7 +1220,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int value = GETITEM(consts, oparg); Py_INCREF(value); PUSH(value); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(STORE_FAST__LOAD_FAST) { @@ -1261,7 +1255,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(value != NULL); Py_INCREF(value); PUSH(value); - NOTRACE_DISPATCH(); + DISPATCH(); } TARGET(POP_TOP) { From 5872b7afe488765d8498d254b9bd902578c44d78 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 16:38:49 +0100 Subject: [PATCH 06/10] Update Lib/test/test_dynamic.py Co-authored-by: Brandt Bucher --- Lib/test/test_dynamic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 978cc3c9f398f8..87b72342357767 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -174,7 +174,7 @@ def f(): C(0).x, len def g(): - # BINARY_SUSCR[_TUPLE_INT] immediately follows the call to C.__del__ + # BINARY_SUSCR[_LIST_INT] immediately follows the call to C.__del__ [0][C(0).x] def h(): From 7ff1782a22e41600cc3d9cd4653e954e9cdf8be7 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 16:38:59 +0100 Subject: [PATCH 07/10] Update Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst Co-authored-by: Brandt Bucher --- .../2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst index 63d9a0921782f2..e0fbd8761aa335 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-12-02-11.gh-issue-96636.YvN-K6.rst @@ -1,3 +1,3 @@ -Ensure that tracing ,``sys.setrace()``, is turned on immediately. In +Ensure that tracing, ``sys.setrace()``, is turned on immediately. In pre-release versions of 3.11, some tracing events might have been lost when turning on tracing in a ``__del__`` method or interrupt. From ff834d615c13dfcbb546dea931e2de9d0e8229e3 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 7 Sep 2022 16:39:34 +0100 Subject: [PATCH 08/10] Update Lib/test/test_dynamic.py Co-authored-by: Brandt Bucher --- Lib/test/test_dynamic.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 87b72342357767..01585810c80866 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -182,12 +182,13 @@ def h(): 0 + C(0).x for func in (f, g, h): - for _ in range(58): + with self.subTest(func.__name__): + for _ in range(58): + func() + turn_on_trace = True func() - turn_on_trace = True - func() - sys.settrace(None) - turn_on_trace = False + sys.settrace(None) + turn_on_trace = False From 72540d45532ce4329ac05b475bdb0f8f7e5f70c0 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 8 Sep 2022 11:05:51 +0100 Subject: [PATCH 09/10] Fixup spacing --- Lib/test/test_dynamic.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 01585810c80866..25544dea14df3a 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -149,6 +149,7 @@ def __missing__(self, key): for _ in range(30): self.assertEqual(sum_func(), expected) + class TestTracing(unittest.TestCase): def setUp(self): @@ -191,7 +192,5 @@ def h(): turn_on_trace = False - - if __name__ == "__main__": unittest.main() From 011edc7fbde3c485c15554b2554df3fd05eb82be Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 8 Sep 2022 11:32:33 +0100 Subject: [PATCH 10/10] Make sure that we don't double-trace instructions with extended args. --- Python/ceval.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index cbe046191aa791..1a1b24434bad89 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4977,10 +4977,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(EXTENDED_ARG_QUICK) { + assert(cframe.use_tracing == 0); assert(oparg); - oparg <<= 8; - oparg |= _Py_OPARG(*next_instr); - DISPATCH_SAME_OPARG(); + int oldoparg = oparg; + NEXTOPARG(); + oparg |= oldoparg << 8; + DISPATCH_GOTO(); } TARGET(CACHE) {