mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-24340: Fix estimation of the code stack size. (#5076)
This commit is contained in:
parent
b4ebaa7099
commit
d4864c61e3
6 changed files with 1507 additions and 1164 deletions
|
@ -672,7 +672,7 @@ if 1:
|
|||
compile("42", PathLike("test_compile_pathlike"), "single")
|
||||
|
||||
|
||||
class TestStackSize(unittest.TestCase):
|
||||
class TestExpressionStackSize(unittest.TestCase):
|
||||
# These tests check that the computed stack size for a code object
|
||||
# stays within reasonable bounds (see issue #21523 for an example
|
||||
# dysfunction).
|
||||
|
@ -710,5 +710,294 @@ class TestStackSize(unittest.TestCase):
|
|||
self.check_stack_size(code)
|
||||
|
||||
|
||||
class TestStackSizeStability(unittest.TestCase):
|
||||
# Check that repeating certain snippets doesn't increase the stack size
|
||||
# beyond what a single snippet requires.
|
||||
|
||||
def check_stack_size(self, snippet, async_=False):
|
||||
def compile_snippet(i):
|
||||
ns = {}
|
||||
script = """def func():\n""" + i * snippet
|
||||
if async_:
|
||||
script = "async " + script
|
||||
code = compile(script, "<script>", "exec")
|
||||
exec(code, ns, ns)
|
||||
return ns['func'].__code__
|
||||
|
||||
sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
|
||||
if len(set(sizes)) != 1:
|
||||
import dis, io
|
||||
out = io.StringIO()
|
||||
dis.dis(compile_snippet(1), file=out)
|
||||
self.fail("stack sizes diverge with # of consecutive snippets: "
|
||||
"%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
|
||||
|
||||
def test_if(self):
|
||||
snippet = """
|
||||
if x:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_if_else(self):
|
||||
snippet = """
|
||||
if x:
|
||||
a
|
||||
elif y:
|
||||
b
|
||||
else:
|
||||
c
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_try_except_bare(self):
|
||||
snippet = """
|
||||
try:
|
||||
a
|
||||
except:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_try_except_qualified(self):
|
||||
snippet = """
|
||||
try:
|
||||
a
|
||||
except ImportError:
|
||||
b
|
||||
except:
|
||||
c
|
||||
else:
|
||||
d
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_try_except_as(self):
|
||||
snippet = """
|
||||
try:
|
||||
a
|
||||
except ImportError as e:
|
||||
b
|
||||
except:
|
||||
c
|
||||
else:
|
||||
d
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_try_finally(self):
|
||||
snippet = """
|
||||
try:
|
||||
a
|
||||
finally:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_with(self):
|
||||
snippet = """
|
||||
with x as y:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_while_else(self):
|
||||
snippet = """
|
||||
while x:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_else(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_break_continue(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
if z:
|
||||
break
|
||||
elif u:
|
||||
continue
|
||||
else:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_break_continue_inside_try_finally_block(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
try:
|
||||
if z:
|
||||
break
|
||||
elif u:
|
||||
continue
|
||||
else:
|
||||
a
|
||||
finally:
|
||||
f
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_break_inside_finally_block(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
try:
|
||||
t
|
||||
finally:
|
||||
if z:
|
||||
break
|
||||
else:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_break_continue_inside_except_block(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
try:
|
||||
t
|
||||
except:
|
||||
if z:
|
||||
break
|
||||
elif u:
|
||||
continue
|
||||
else:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_for_break_continue_inside_with_block(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
with c:
|
||||
if z:
|
||||
break
|
||||
elif u:
|
||||
continue
|
||||
else:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_return_inside_try_finally_block(self):
|
||||
snippet = """
|
||||
try:
|
||||
if z:
|
||||
return
|
||||
else:
|
||||
a
|
||||
finally:
|
||||
f
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_return_inside_finally_block(self):
|
||||
snippet = """
|
||||
try:
|
||||
t
|
||||
finally:
|
||||
if z:
|
||||
return
|
||||
else:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_return_inside_except_block(self):
|
||||
snippet = """
|
||||
try:
|
||||
t
|
||||
except:
|
||||
if z:
|
||||
return
|
||||
else:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_return_inside_with_block(self):
|
||||
snippet = """
|
||||
with c:
|
||||
if z:
|
||||
return
|
||||
else:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet)
|
||||
|
||||
def test_async_with(self):
|
||||
snippet = """
|
||||
async with x as y:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet, async_=True)
|
||||
|
||||
def test_async_for(self):
|
||||
snippet = """
|
||||
async for x in y:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet, async_=True)
|
||||
|
||||
def test_async_for_else(self):
|
||||
snippet = """
|
||||
async for x in y:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet, async_=True)
|
||||
|
||||
def test_for_break_continue_inside_async_with_block(self):
|
||||
snippet = """
|
||||
for x in y:
|
||||
async with c:
|
||||
if z:
|
||||
break
|
||||
elif u:
|
||||
continue
|
||||
else:
|
||||
a
|
||||
else:
|
||||
b
|
||||
"""
|
||||
self.check_stack_size(snippet, async_=True)
|
||||
|
||||
def test_return_inside_async_with_block(self):
|
||||
snippet = """
|
||||
async with c:
|
||||
if z:
|
||||
return
|
||||
else:
|
||||
a
|
||||
"""
|
||||
self.check_stack_size(snippet, async_=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue