Do not fold a constant if a large sequence will result.

Saves space in the presence of code like: (None,)*10000
This commit is contained in:
Raymond Hettinger 2005-01-26 12:50:05 +00:00
parent c560a00966
commit 9feb267caf
2 changed files with 19 additions and 5 deletions

View file

@ -129,6 +129,10 @@ class TestTranforms(unittest.TestCase):
self.assert_('(2)' in asm) self.assert_('(2)' in asm)
self.assert_("('b')" in asm) self.assert_("('b')" in asm)
# Verify that large sequences do not result from folding
asm = dis_single('a="x"*1000')
self.assert_('(1000)' in asm)
def test_elim_extra_return(self): def test_elim_extra_return(self):
# RETURN LOAD_CONST None RETURN --> RETURN # RETURN LOAD_CONST None RETURN --> RETURN
def f(x): def f(x):

View file

@ -444,12 +444,16 @@ tuple_of_constants(unsigned char *codestr, int n, PyObject *consts)
The consts table must still be in list form so that the The consts table must still be in list form so that the
new constant can be appended. new constant can be appended.
Called with codestr pointing to the first LOAD_CONST. Called with codestr pointing to the first LOAD_CONST.
Abandons the transformation if the folding fails (i.e. 1+'a'). */ Abandons the transformation if the folding fails (i.e. 1+'a').
If the new constant is a sequence, only folds when the size
is below a threshold value. That keeps pyc files from
becoming large in the presence of code like: (None,)*1000.
*/
static int static int
fold_binops_on_constants(unsigned char *codestr, PyObject *consts) fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
{ {
PyObject *newconst, *v, *w; PyObject *newconst, *v, *w;
int len_consts, opcode; int len_consts, opcode, size;
/* Pre-conditions */ /* Pre-conditions */
assert(PyList_CheckExact(consts)); assert(PyList_CheckExact(consts));
@ -468,8 +472,8 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
newconst = PyNumber_Multiply(v, w); newconst = PyNumber_Multiply(v, w);
break; break;
case BINARY_DIVIDE: case BINARY_DIVIDE:
/* XXX care is needed to fold this operation statically: /* Cannot fold this operation statically since
the result might depend on the run-time presence of the -Qnew flag */ the result can depend on the run-time presence of the -Qnew flag */
return 0; return 0;
case BINARY_TRUE_DIVIDE: case BINARY_TRUE_DIVIDE:
newconst = PyNumber_TrueDivide(v, w); newconst = PyNumber_TrueDivide(v, w);
@ -513,6 +517,13 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
PyErr_Clear(); PyErr_Clear();
return 0; return 0;
} }
size = PyObject_Size(newconst);
if (size == -1)
PyErr_Clear();
else if (size > 20) {
Py_DECREF(newconst);
return 0;
}
/* Append folded constant into consts table */ /* Append folded constant into consts table */
len_consts = PyList_GET_SIZE(consts); len_consts = PyList_GET_SIZE(consts);
@ -733,7 +744,6 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
case BINARY_POWER: case BINARY_POWER:
case BINARY_MULTIPLY: case BINARY_MULTIPLY:
case BINARY_DIVIDE:
case BINARY_TRUE_DIVIDE: case BINARY_TRUE_DIVIDE:
case BINARY_FLOOR_DIVIDE: case BINARY_FLOOR_DIVIDE:
case BINARY_MODULO: case BINARY_MODULO: