mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
[3.12] gh-119897: Revert buggy optimization which was removed in 3.13 (#120467)
This commit is contained in:
parent
4b53ea822c
commit
5d997b5d4e
6 changed files with 18 additions and 43 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue