Commit 3f7e9aa2 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-32925: Optimized iterating and containing test for literal lists (GH-5842)

consisting of non-constants: `x in [a, b]` and `for x in [a, b]`.
The case of all constant elements already was optimized.
parent 4e244250
...@@ -3,6 +3,19 @@ import unittest ...@@ -3,6 +3,19 @@ import unittest
from test.bytecode_helper import BytecodeTestCase from test.bytecode_helper import BytecodeTestCase
def count_instr_recursively(f, opname):
count = 0
for instr in dis.get_instructions(f):
if instr.opname == opname:
count += 1
if hasattr(f, '__code__'):
f = f.__code__
for c in f.co_consts:
if hasattr(c, 'co_code'):
count += count_instr_recursively(c, opname)
return count
class TestTranforms(BytecodeTestCase): class TestTranforms(BytecodeTestCase):
def test_unot(self): def test_unot(self):
...@@ -311,6 +324,17 @@ class TestTranforms(BytecodeTestCase): ...@@ -311,6 +324,17 @@ class TestTranforms(BytecodeTestCase):
self.assertFalse(instr.opname.startswith('BINARY_')) self.assertFalse(instr.opname.startswith('BINARY_'))
self.assertFalse(instr.opname.startswith('BUILD_')) self.assertFalse(instr.opname.startswith('BUILD_'))
def test_in_literal_list(self):
def containtest():
return x in [a, b]
self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0)
def test_iterate_literal_list(self):
def forloop():
for x in [a, b]:
pass
self.assertEqual(count_instr_recursively(forloop, 'BUILD_LIST'), 0)
class TestBuglets(unittest.TestCase): class TestBuglets(unittest.TestCase):
......
Optimized iterating and containing test for literal lists consisting of
non-constants: ``x in [a, b]`` and ``for x in [a, b]``. The case of all
constant elements already was optimized.
...@@ -369,7 +369,8 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize) ...@@ -369,7 +369,8 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize)
} }
/* Change literal list or set of constants into constant /* Change literal list or set of constants into constant
tuple or frozenset respectively. tuple or frozenset respectively. Change literal list of
non-constants into tuple.
Used for right operand of "in" and "not in" tests and for iterable Used for right operand of "in" and "not in" tests and for iterable
in "for" loop and comprehensions. in "for" loop and comprehensions.
*/ */
...@@ -378,7 +379,21 @@ fold_iter(expr_ty arg, PyArena *arena, int optimize) ...@@ -378,7 +379,21 @@ fold_iter(expr_ty arg, PyArena *arena, int optimize)
{ {
PyObject *newval; PyObject *newval;
if (arg->kind == List_kind) { if (arg->kind == List_kind) {
newval = make_const_tuple(arg->v.List.elts); /* First change a list into tuple. */
asdl_seq *elts = arg->v.List.elts;
Py_ssize_t n = asdl_seq_LEN(elts);
for (Py_ssize_t i = 0; i < n; i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
if (e->kind == Starred_kind) {
return 1;
}
}
expr_context_ty ctx = arg->v.List.ctx;
arg->kind = Tuple_kind;
arg->v.Tuple.elts = elts;
arg->v.Tuple.ctx = ctx;
/* Try to create a constant tuple. */
newval = make_const_tuple(elts);
} }
else if (arg->kind == Set_kind) { else if (arg->kind == Set_kind) {
newval = make_const_tuple(arg->v.Set.elts); newval = make_const_tuple(arg->v.Set.elts);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment