https://github.com/python/cpython/commit/5d997b5d4ef95e1164cb04e4c13d47dd5b71f2ec
commit: 5d997b5d4ef95e1164cb04e4c13d47dd5b71f2ec
branch: 3.12
author: Irit Katriel <[email protected]>
committer: iritkatriel <[email protected]>
date: 2024-06-18T10:45:40+01:00
summary:
[3.12] gh-119897: Revert buggy optimization which was removed in 3.13 (#120467)
files:
M Include/internal/pycore_frame.h
M Lib/test/test_cprofile.py
M Lib/test/test_generators.py
M Lib/test/test_sys_setprofile.py
M Objects/genobject.c
M Python/frame.c
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index ad7d74c5dd2b9f..bfe4a759bac078 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -213,9 +213,6 @@ _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
return _PyFrame_MakeAndSetFrameObject(frame);
}
-void
-_PyFrame_ClearLocals(_PyInterpreterFrame *frame);
-
/* Clears all references in the frame.
* If take is non-zero, then the _PyInterpreterFrame frame
* may be transferred to the frame object it references
diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py
index 27e8a767903777..3056fe84dac5dd 100644
--- a/Lib/test/test_cprofile.py
+++ b/Lib/test/test_cprofile.py
@@ -83,8 +83,8 @@ def test_throw(self):
for func, (cc, nc, _, _, _) in pr.stats.items():
if func[2] == "<genexpr>":
- self.assertEqual(cc, 1)
- self.assertEqual(nc, 1)
+ self.assertEqual(cc, 2)
+ self.assertEqual(nc, 2)
class TestCommandLine(unittest.TestCase):
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index e0da9152c33954..83ca8a6096c646 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -6,6 +6,7 @@
import unittest
import weakref
import inspect
+import types
from test import support
@@ -89,9 +90,12 @@ def gen():
self.assertEqual(gc.garbage, old_garbage)
def test_lambda_generator(self):
- # Issue #23192: Test that a lambda returning a generator behaves
+ # bpo-23192, gh-119897: Test that a lambda returning a generator
behaves
# like the equivalent function
f = lambda: (yield 1)
+ self.assertIsInstance(f(), types.GeneratorType)
+ self.assertEqual(next(f()), 1)
+
def g(): return (yield 1)
# test 'yield from'
@@ -450,26 +454,6 @@ def g():
self.assertIsInstance(cm.exception.value, StopIteration)
self.assertEqual(cm.exception.value.value, 2)
- def test_close_releases_frame_locals(self):
- # See gh-118272
-
- class Foo:
- pass
-
- f = Foo()
- f_wr = weakref.ref(f)
-
- def genfn():
- a = f
- yield
-
- g = genfn()
- next(g)
- del f
- g.close()
- support.gc_collect()
- self.assertIsNone(f_wr())
-
class GeneratorThrowTest(unittest.TestCase):
diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py
index bb8adc8b555cb4..9e8936630de920 100644
--- a/Lib/test/test_sys_setprofile.py
+++ b/Lib/test/test_sys_setprofile.py
@@ -265,6 +265,10 @@ def g(p):
f_ident = ident(f)
g_ident = ident(g)
self.check_events(g, [(1, 'call', g_ident),
+ (2, 'call', f_ident),
+ (2, 'return', f_ident),
+ # once more; the generator is being garbage
collected
+ # and it will do a PY_THROW
(2, 'call', f_ident),
(2, 'return', f_ident),
(1, 'return', g_ident),
diff --git a/Objects/genobject.c b/Objects/genobject.c
index dc034a4b723472..474abe1094be72 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -374,6 +374,7 @@ static PyObject *
gen_close(PyGenObject *gen, PyObject *args)
{
PyObject *retval;
+ PyObject *yf = _PyGen_yf(gen);
int err = 0;
if (gen->gi_frame_state == FRAME_CREATED) {
@@ -383,7 +384,6 @@ gen_close(PyGenObject *gen, PyObject *args)
if (gen->gi_frame_state >= FRAME_COMPLETED) {
Py_RETURN_NONE;
}
- PyObject *yf = _PyGen_yf(gen);
if (yf) {
PyFrameState state = gen->gi_frame_state;
gen->gi_frame_state = FRAME_EXECUTING;
@@ -396,14 +396,12 @@ gen_close(PyGenObject *gen, PyObject *args)
* YIELD_VALUE if the debugger has changed the lineno. */
if (err == 0 && is_yield(frame->prev_instr)) {
assert(is_resume(frame->prev_instr + 1));
- int exception_handler_depth = frame->prev_instr[0].op.arg;
+ int exception_handler_depth = frame->prev_instr[0].op.code;
assert(exception_handler_depth > 0);
/* We can safely ignore the outermost try block
* as it automatically generated to handle
* StopIteration. */
if (exception_handler_depth == 1) {
- gen->gi_frame_state = FRAME_COMPLETED;
- _PyFrame_ClearLocals((_PyInterpreterFrame *)gen->gi_iframe);
Py_RETURN_NONE;
}
}
diff --git a/Python/frame.c b/Python/frame.c
index a49215fa44a796..b84fd9b6a9380a 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -115,18 +115,6 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame
*frame)
}
}
-void
-_PyFrame_ClearLocals(_PyInterpreterFrame *frame)
-{
- assert(frame->stacktop >= 0);
- int stacktop = frame->stacktop;
- frame->stacktop = 0;
- for (int i = 0; i < stacktop; i++) {
- Py_XDECREF(frame->localsplus[i]);
- }
- Py_CLEAR(frame->f_locals);
-}
-
void
_PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
{
@@ -147,8 +135,12 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
}
Py_DECREF(f);
}
- _PyFrame_ClearLocals(frame);
+ assert(frame->stacktop >= 0);
+ for (int i = 0; i < frame->stacktop; i++) {
+ Py_XDECREF(frame->localsplus[i]);
+ }
Py_XDECREF(frame->frame_obj);
+ Py_XDECREF(frame->f_locals);
Py_DECREF(frame->f_funcobj);
}
_______________________________________________
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]