mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
4e2442505c
commit
3f7e9aa2ef
|
@ -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):
|
||||||
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):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue