@@ -1345,63 +1345,42 @@ add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache)
13451345
13461346/*
13471347 Walk basic block backwards starting from "start" trying to collect "size" number of
1348- subsequent constants from instructions loading constants into new tuple ignoring NOP's in between.
1348+ subsequent instructions that load constants into instruciton array "seq" ignoring NOP's in between.
1349+ Caller must make sure that length of "seq" is sufficient to fit in at least "size" instructions.
13491350
1350- Returns ERROR on error and sets "seq" to NULL.
1351- Returns SUCCESS on success and sets "seq" to NULL if failed to collect requested number of constants.
1352- Returns SUCCESS on success and sets "seq" to resulting tuple if succeeded to collect requested number of constants.
1351+ Returns boolean indicating whether succeeded to collect requested number of instructions.
13531352*/
1354- static int
1355- get_constant_sequence (basicblock * bb , int start , int size ,
1356- PyObject * consts , PyObject * * seq )
1353+ static bool
1354+ get_const_sequence_instructions (basicblock * bb , int start , cfg_instr * * seq , int size )
13571355{
13581356 assert (start < bb -> b_iused );
1359- * seq = NULL ;
1360- PyObject * res = PyTuple_New ((Py_ssize_t )size );
1361- if (res == NULL ) {
1362- return ERROR ;
1363- }
1357+ assert (size >= 0 );
1358+ assert (size <= STACK_USE_GUIDELINE );
1359+
13641360 for (; start >= 0 && size > 0 ; start -- ) {
13651361 cfg_instr * instr = & bb -> b_instr [start ];
13661362 if (instr -> i_opcode == NOP ) {
13671363 continue ;
13681364 }
13691365 if (!loads_const (instr -> i_opcode )) {
1370- break ;
1371- }
1372- PyObject * constant = get_const_value (instr -> i_opcode , instr -> i_oparg , consts );
1373- if (constant == NULL ) {
1374- Py_DECREF (res );
1375- return ERROR ;
1366+ return false;
13761367 }
1377- PyTuple_SET_ITEM ( res , -- size , constant ) ;
1368+ seq [ -- size ] = instr ;
13781369 }
1379- if (size > 0 ) {
1380- Py_DECREF (res );
1381- }
1382- else {
1383- * seq = res ;
1384- }
1385- return SUCCESS ;
1370+
1371+ return size == 0 ;
13861372}
13871373
13881374/*
1389- Walk basic block backwards starting from "start" and change "count" number of
1390- non-NOP instructions to NOP's and set their location to NO_LOCATION .
1375+ Change every instruction in "instrs" NOP and set it's location to NO_LOCATION.
1376+ Caller must make sure "instrs" has at least "size" elements .
13911377*/
1392- static void
1393- nop_out (basicblock * bb , int start , int count )
1394- {
1395- assert (start < bb -> b_iused );
1396- for (; count > 0 ; start -- ) {
1397- assert (start >= 0 );
1398- cfg_instr * instr = & bb -> b_instr [start ];
1399- if (instr -> i_opcode == NOP ) {
1400- continue ;
1401- }
1378+ static void nop_out (basicblock * bb , cfg_instr * * instrs , int size ) {
1379+ for (int i = 0 ; i < size ; i ++ ) {
1380+ cfg_instr * instr = instrs [i ];
1381+ assert (instr -> i_opcode != NOP );
14021382 INSTR_SET_OP0 (instr , NOP );
14031383 INSTR_SET_LOC (instr , NO_LOCATION );
1404- count -- ;
14051384 }
14061385}
14071386
@@ -1437,19 +1416,39 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const
14371416 /* Pre-conditions */
14381417 assert (PyDict_CheckExact (const_cache ));
14391418 assert (PyList_CheckExact (consts ));
1419+
14401420 cfg_instr * instr = & bb -> b_instr [i ];
14411421 assert (instr -> i_opcode == BUILD_TUPLE );
1422+
14421423 int seq_size = instr -> i_oparg ;
1443- PyObject * newconst ;
1444- RETURN_IF_ERROR (get_constant_sequence (bb , i - 1 , seq_size , consts , & newconst ));
1445- if (newconst == NULL ) {
1424+ if (seq_size > STACK_USE_GUIDELINE ) {
1425+ return SUCCESS ;
1426+ }
1427+
1428+ cfg_instr * seq [STACK_USE_GUIDELINE ];
1429+ if (!get_const_sequence_instructions (bb , i - 1 , seq , seq_size )) {
14461430 /* not a const sequence */
14471431 return SUCCESS ;
14481432 }
1449- assert (PyTuple_Size (newconst ) == seq_size );
1450- RETURN_IF_ERROR (instr_make_load_const (instr , newconst , consts , const_cache ));
1451- nop_out (bb , i - 1 , seq_size );
1452- return SUCCESS ;
1433+
1434+ PyObject * newconst = PyTuple_New ((Py_ssize_t )seq_size );
1435+ if (newconst == NULL ) {
1436+ return ERROR ;
1437+ }
1438+
1439+ for (int i = 0 ; i < seq_size ; i ++ ) {
1440+ cfg_instr * inst = seq [i ];
1441+ assert (loads_const (inst -> i_opcode ));
1442+ PyObject * constant = get_const_value (inst -> i_opcode , inst -> i_oparg , consts );
1443+ if (constant == NULL ) {
1444+ Py_DECREF (newconst );
1445+ return ERROR ;
1446+ }
1447+ PyTuple_SET_ITEM (newconst , i , constant );
1448+ }
1449+
1450+ nop_out (bb , seq , seq_size );
1451+ return instr_make_load_const (instr , newconst , consts , const_cache );
14531452}
14541453
14551454#define MIN_CONST_SEQUENCE_SIZE 3
@@ -1470,23 +1469,43 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
14701469{
14711470 assert (PyDict_CheckExact (const_cache ));
14721471 assert (PyList_CheckExact (consts ));
1472+
14731473 cfg_instr * instr = & bb -> b_instr [i ];
14741474 assert (instr -> i_opcode == BUILD_LIST || instr -> i_opcode == BUILD_SET );
1475+
14751476 bool contains_or_iter = nextop == GET_ITER || nextop == CONTAINS_OP ;
14761477 int seq_size = instr -> i_oparg ;
1477- if (seq_size < MIN_CONST_SEQUENCE_SIZE && !contains_or_iter ) {
1478+ if (seq_size > STACK_USE_GUIDELINE ||
1479+ (seq_size < MIN_CONST_SEQUENCE_SIZE && !contains_or_iter ))
1480+ {
14781481 return SUCCESS ;
14791482 }
1480- PyObject * newconst ;
1481- RETURN_IF_ERROR ( get_constant_sequence ( bb , i - 1 , seq_size , consts , & newconst )) ;
1482- if (newconst == NULL ) { /* not a const sequence */
1483+
1484+ cfg_instr * seq [ STACK_USE_GUIDELINE ] ;
1485+ if (! get_const_sequence_instructions ( bb , i - 1 , seq , seq_size )) { /* not a const sequence */
14831486 if (contains_or_iter && instr -> i_opcode == BUILD_LIST ) {
14841487 /* iterate over a tuple instead of list */
14851488 INSTR_SET_OP1 (instr , BUILD_TUPLE , instr -> i_oparg );
14861489 }
14871490 return SUCCESS ;
14881491 }
1489- assert (PyTuple_Size (newconst ) == seq_size );
1492+
1493+ PyObject * newconst = PyTuple_New ((Py_ssize_t )seq_size );
1494+ if (newconst == NULL ) {
1495+ return ERROR ;
1496+ }
1497+
1498+ for (int i = 0 ; i < seq_size ; i ++ ) {
1499+ cfg_instr * inst = seq [i ];
1500+ assert (loads_const (inst -> i_opcode ));
1501+ PyObject * constant = get_const_value (inst -> i_opcode , inst -> i_oparg , consts );
1502+ if (constant == NULL ) {
1503+ Py_DECREF (newconst );
1504+ return ERROR ;
1505+ }
1506+ PyTuple_SET_ITEM (newconst , i , constant );
1507+ }
1508+
14901509 if (instr -> i_opcode == BUILD_SET ) {
14911510 PyObject * frozenset = PyFrozenSet_New (newconst );
14921511 if (frozenset == NULL ) {
@@ -1495,9 +1514,11 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
14951514 }
14961515 Py_SETREF (newconst , frozenset );
14971516 }
1517+
14981518 int index = add_const (newconst , consts , const_cache );
14991519 RETURN_IF_ERROR (index );
1500- nop_out (bb , i - 1 , seq_size );
1520+ nop_out (bb , seq , seq_size );
1521+
15011522 if (contains_or_iter ) {
15021523 INSTR_SET_OP1 (instr , LOAD_CONST , index );
15031524 }
@@ -1696,29 +1717,44 @@ fold_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache)
16961717 #define BINOP_OPERAND_COUNT 2
16971718 assert (PyDict_CheckExact (const_cache ));
16981719 assert (PyList_CheckExact (consts ));
1720+
16991721 cfg_instr * binop = & bb -> b_instr [i ];
17001722 assert (binop -> i_opcode == BINARY_OP );
1701- PyObject * pair ;
1702- RETURN_IF_ERROR ( get_constant_sequence ( bb , i - 1 , BINOP_OPERAND_COUNT , consts , & pair )) ;
1703- if (pair == NULL ) {
1723+
1724+ cfg_instr * seq [ BINOP_OPERAND_COUNT ] ;
1725+ if (! get_const_sequence_instructions ( bb , i - 1 , seq , BINOP_OPERAND_COUNT ) ) {
17041726 /* not a const sequence */
17051727 return SUCCESS ;
17061728 }
1707- assert (PyTuple_Size (pair ) == BINOP_OPERAND_COUNT );
1708- PyObject * left = PyTuple_GET_ITEM (pair , 0 );
1709- PyObject * right = PyTuple_GET_ITEM (pair , 1 );
1729+
1730+ cfg_instr * first = seq [0 ];
1731+ assert (loads_const (first -> i_opcode ));
1732+ PyObject * left = get_const_value (first -> i_opcode , first -> i_oparg , consts );
1733+ if (left == NULL ) {
1734+ return ERROR ;
1735+ }
1736+
1737+ cfg_instr * second = seq [1 ];
1738+ assert (loads_const (second -> i_opcode ));
1739+ PyObject * right = get_const_value (second -> i_opcode , second -> i_oparg , consts );
1740+ if (right == NULL ) {
1741+ Py_DECREF (left );
1742+ return ERROR ;
1743+ }
1744+
17101745 PyObject * newconst = eval_const_binop (left , binop -> i_oparg , right );
1711- Py_DECREF (pair );
1746+ Py_DECREF (left );
1747+ Py_DECREF (right );
17121748 if (newconst == NULL ) {
17131749 if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt )) {
17141750 return ERROR ;
17151751 }
17161752 PyErr_Clear ();
17171753 return SUCCESS ;
17181754 }
1719- RETURN_IF_ERROR ( instr_make_load_const ( binop , newconst , consts , const_cache ));
1720- nop_out (bb , i - 1 , BINOP_OPERAND_COUNT );
1721- return SUCCESS ;
1755+
1756+ nop_out (bb , seq , BINOP_OPERAND_COUNT );
1757+ return instr_make_load_const ( binop , newconst , consts , const_cache ) ;
17221758}
17231759
17241760static PyObject *
@@ -1765,30 +1801,39 @@ fold_const_unaryop(basicblock *bb, int i, PyObject *consts, PyObject *const_cach
17651801 #define UNARYOP_OPERAND_COUNT 1
17661802 assert (PyDict_CheckExact (const_cache ));
17671803 assert (PyList_CheckExact (consts ));
1768- cfg_instr * instr = & bb -> b_instr [i ];
1769- PyObject * seq ;
1770- RETURN_IF_ERROR ( get_constant_sequence ( bb , i - 1 , UNARYOP_OPERAND_COUNT , consts , & seq )) ;
1771- if (seq == NULL ) {
1804+ cfg_instr * unaryop = & bb -> b_instr [i ];
1805+
1806+ cfg_instr * instr ;
1807+ if (! get_const_sequence_instructions ( bb , i - 1 , & instr , UNARYOP_OPERAND_COUNT ) ) {
17721808 /* not a const */
17731809 return SUCCESS ;
17741810 }
1775- assert (PyTuple_Size (seq ) == UNARYOP_OPERAND_COUNT );
1776- PyObject * operand = PyTuple_GET_ITEM (seq , 0 );
1777- PyObject * newconst = eval_const_unaryop (operand , instr -> i_opcode , instr -> i_oparg );
1778- Py_DECREF (seq );
1811+
1812+ assert (loads_const (instr -> i_opcode ));
1813+ PyObject * operand = get_const_value (
1814+ instr -> i_opcode ,
1815+ instr -> i_oparg ,
1816+ consts
1817+ );
1818+ if (operand == NULL ) {
1819+ return ERROR ;
1820+ }
1821+
1822+ PyObject * newconst = eval_const_unaryop (operand , unaryop -> i_opcode , unaryop -> i_oparg );
1823+ Py_DECREF (operand );
17791824 if (newconst == NULL ) {
17801825 if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt )) {
17811826 return ERROR ;
17821827 }
17831828 PyErr_Clear ();
17841829 return SUCCESS ;
17851830 }
1786- if (instr -> i_opcode == UNARY_NOT ) {
1831+
1832+ if (unaryop -> i_opcode == UNARY_NOT ) {
17871833 assert (PyBool_Check (newconst ));
17881834 }
1789- RETURN_IF_ERROR (instr_make_load_const (instr , newconst , consts , const_cache ));
1790- nop_out (bb , i - 1 , UNARYOP_OPERAND_COUNT );
1791- return SUCCESS ;
1835+ nop_out (bb , & instr , UNARYOP_OPERAND_COUNT );
1836+ return instr_make_load_const (unaryop , newconst , consts , const_cache );
17921837}
17931838
17941839#define VISITED (-1)
0 commit comments