From 0a8562ed4f9b2e74a2c1b20943b6859ccdfa5971 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 12:41:08 -0400 Subject: [PATCH 1/8] gh-109176: replace _PyFrame_OpAlreadyRan by a check that the frame is complete. Pretend that cells are not set in an incomplete frame --- Objects/frameobject.c | 44 ++++++++++--------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 64fded85de1468..59ed606fff1173 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1828,32 +1828,6 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, return f; } -static int -_PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg) -{ - // This only works when opcode is a non-quickened form: - assert(_PyOpcode_Deopt[opcode] == opcode); - int check_oparg = 0; - for (_Py_CODEUNIT *instruction = _PyCode_CODE(_PyFrame_GetCode(frame)); - instruction < frame->instr_ptr; instruction++) - { - int check_opcode = _PyOpcode_Deopt[instruction->op.code]; - check_oparg |= instruction->op.arg; - if (check_opcode == opcode && check_oparg == oparg) { - return 1; - } - if (check_opcode == EXTENDED_ARG) { - check_oparg <<= 8; - } - else { - check_oparg = 0; - } - instruction += _PyOpcode_Caches[check_opcode]; - } - return 0; -} - - // Initialize frame free variables if needed static void frame_init_get_vars(_PyInterpreterFrame *frame) @@ -1907,15 +1881,17 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i, value = PyCell_GET(value); } else if (kind & CO_FAST_CELL) { - // Note that no *_DEREF ops can happen before MAKE_CELL - // executes. So there's no need to duplicate the work - // that MAKE_CELL would otherwise do later, if it hasn't - // run yet. if (value != NULL) { - if (PyCell_Check(value) && - _PyFrame_OpAlreadyRan(frame, MAKE_CELL, i)) { - // (likely) MAKE_CELL must have executed already. - value = PyCell_GET(value); + if (PyCell_Check(value)) { + if (!_PyFrame_IsIncomplete(frame)) { + // (likely) MAKE_CELL must have executed already. + value = PyCell_GET(value); + } + else { + // (unlikely) MAKE_CELL may not have run, to be on the + // safe side, pretend that the cell variable is not set. + value = NULL; + } } // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL), // with the initial value set when the frame was created... From 7c726d538a6c732f1c90cba6cae0773d317082ec Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 19:07:18 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst new file mode 100644 index 00000000000000..f77050f8637426 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst @@ -0,0 +1 @@ +Cell variables now always appear as unset on an incomplete frame. From af0a968f904494e16fde4da4aa936483293c85c3 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:09:44 -0400 Subject: [PATCH 3/8] assert not incomplete --- Objects/frameobject.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 59ed606fff1173..fc8d6c7a7aee89 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1883,15 +1883,8 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i, else if (kind & CO_FAST_CELL) { if (value != NULL) { if (PyCell_Check(value)) { - if (!_PyFrame_IsIncomplete(frame)) { - // (likely) MAKE_CELL must have executed already. - value = PyCell_GET(value); - } - else { - // (unlikely) MAKE_CELL may not have run, to be on the - // safe side, pretend that the cell variable is not set. - value = NULL; - } + assert(!_PyFrame_IsIncomplete(frame)); + value = PyCell_GET(value); } // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL), // with the initial value set when the frame was created... From caaac17567e2d59c048a0627313b0c7b3b6a46af Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:16:22 -0400 Subject: [PATCH 4/8] =?UTF-8?q?Revert=20"=F0=9F=93=9C=F0=9F=A4=96=20Added?= =?UTF-8?q?=20by=20blurb=5Fit."?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7c726d538a6c732f1c90cba6cae0773d317082ec. --- .../2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst deleted file mode 100644 index f77050f8637426..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst +++ /dev/null @@ -1 +0,0 @@ -Cell variables now always appear as unset on an incomplete frame. From 9fc67eb89c22ee131b7d60fdfc666071256b9466 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:17:48 -0400 Subject: [PATCH 5/8] =?UTF-8?q?Revert=20"Revert=20"=F0=9F=93=9C?= =?UTF-8?q?=F0=9F=A4=96=20Added=20by=20blurb=5Fit.""?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit caaac17567e2d59c048a0627313b0c7b3b6a46af. --- .../2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst new file mode 100644 index 00000000000000..f77050f8637426 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst @@ -0,0 +1 @@ +Cell variables now always appear as unset on an incomplete frame. From 607bd7e4eb4ef702c9ebc384e5406e19f7844152 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:17:56 -0400 Subject: [PATCH 6/8] Revert "assert not incomplete" This reverts commit af0a968f904494e16fde4da4aa936483293c85c3. --- Objects/frameobject.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index fc8d6c7a7aee89..59ed606fff1173 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1883,8 +1883,15 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i, else if (kind & CO_FAST_CELL) { if (value != NULL) { if (PyCell_Check(value)) { - assert(!_PyFrame_IsIncomplete(frame)); - value = PyCell_GET(value); + if (!_PyFrame_IsIncomplete(frame)) { + // (likely) MAKE_CELL must have executed already. + value = PyCell_GET(value); + } + else { + // (unlikely) MAKE_CELL may not have run, to be on the + // safe side, pretend that the cell variable is not set. + value = NULL; + } } // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL), // with the initial value set when the frame was created... From da06c43130bc0c5d1cdbfa329aa9f06dd889740a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:23:02 -0400 Subject: [PATCH 7/8] Revert "Revert "assert not incomplete"" This reverts commit 607bd7e4eb4ef702c9ebc384e5406e19f7844152. --- Objects/frameobject.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 59ed606fff1173..fc8d6c7a7aee89 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1883,15 +1883,8 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i, else if (kind & CO_FAST_CELL) { if (value != NULL) { if (PyCell_Check(value)) { - if (!_PyFrame_IsIncomplete(frame)) { - // (likely) MAKE_CELL must have executed already. - value = PyCell_GET(value); - } - else { - // (unlikely) MAKE_CELL may not have run, to be on the - // safe side, pretend that the cell variable is not set. - value = NULL; - } + assert(!_PyFrame_IsIncomplete(frame)); + value = PyCell_GET(value); } // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL), // with the initial value set when the frame was created... From 168aeb7bc1bf7a70d5729c14c624c179dd9894b4 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 20 May 2024 17:23:10 -0400 Subject: [PATCH 8/8] =?UTF-8?q?Revert=20"Revert=20"Revert=20"=F0=9F=93=9C?= =?UTF-8?q?=F0=9F=A4=96=20Added=20by=20blurb=5Fit."""?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9fc67eb89c22ee131b7d60fdfc666071256b9466. --- .../2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst deleted file mode 100644 index f77050f8637426..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2024-05-20-19-07-15.gh-issue-109176.gg71VG.rst +++ /dev/null @@ -1 +0,0 @@ -Cell variables now always appear as unset on an incomplete frame.