bpo-32925: Optimized iterating and containing test for literal lists … · python/cpython@3f7e9aa

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -3,6 +3,19 @@

33
44

from test.bytecode_helper import BytecodeTestCase

55
6+

def count_instr_recursively(f, opname):

7+

count = 0

8+

for instr in dis.get_instructions(f):

9+

if instr.opname == opname:

10+

count += 1

11+

if hasattr(f, '__code__'):

12+

f = f.__code__

13+

for c in f.co_consts:

14+

if hasattr(c, 'co_code'):

15+

count += count_instr_recursively(c, opname)

16+

return count

17+
18+
619

class TestTranforms(BytecodeTestCase):

720
821

def test_unot(self):

@@ -311,6 +324,17 @@ def test_constant_folding(self):

311324

self.assertFalse(instr.opname.startswith('BINARY_'))

312325

self.assertFalse(instr.opname.startswith('BUILD_'))

313326
327+

def test_in_literal_list(self):

328+

def containtest():

329+

return x in [a, b]

330+

self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0)

331+
332+

def test_iterate_literal_list(self):

333+

def forloop():

334+

for x in [a, b]:

335+

pass

336+

self.assertEqual(count_instr_recursively(forloop, 'BUILD_LIST'), 0)

337+
314338
315339

class TestBuglets(unittest.TestCase):

316340
Original file line numberDiff line numberDiff line change

@@ -0,0 +1,3 @@

1+

Optimized iterating and containing test for literal lists consisting of

2+

non-constants: ``x in [a, b]`` and ``for x in [a, b]``. The case of all

3+

constant elements already was optimized.

Original file line numberDiff line numberDiff line change

@@ -369,7 +369,8 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize)

369369

}

370370
371371

/* Change literal list or set of constants into constant

372-

tuple or frozenset respectively.

372+

tuple or frozenset respectively. Change literal list of

373+

non-constants into tuple.

373374

Used for right operand of "in" and "not in" tests and for iterable

374375

in "for" loop and comprehensions.

375376

*/

@@ -378,7 +379,21 @@ fold_iter(expr_ty arg, PyArena *arena, int optimize)

378379

{

379380

PyObject *newval;

380381

if (arg->kind == List_kind) {

381-

newval = make_const_tuple(arg->v.List.elts);

382+

/* First change a list into tuple. */

383+

asdl_seq *elts = arg->v.List.elts;

384+

Py_ssize_t n = asdl_seq_LEN(elts);

385+

for (Py_ssize_t i = 0; i < n; i++) {

386+

expr_ty e = (expr_ty)asdl_seq_GET(elts, i);

387+

if (e->kind == Starred_kind) {

388+

return 1;

389+

}

390+

}

391+

expr_context_ty ctx = arg->v.List.ctx;

392+

arg->kind = Tuple_kind;

393+

arg->v.Tuple.elts = elts;

394+

arg->v.Tuple.ctx = ctx;

395+

/* Try to create a constant tuple. */

396+

newval = make_const_tuple(elts);

382397

}

383398

else if (arg->kind == Set_kind) {

384399

newval = make_const_tuple(arg->v.Set.elts);