diff -r c25b54be90ee Include/code.h --- a/Include/code.h Wed Mar 09 18:22:33 2011 -0500 +++ b/Include/code.h Thu Mar 10 20:03:28 2011 -0500 @@ -99,7 +99,7 @@ int lasti, PyAddrPair *bounds); #endif -PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts, +PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts, PyObject* constdict, PyObject *names, PyObject *lineno_obj); #ifdef __cplusplus diff -r c25b54be90ee Python/compile.c --- a/Python/compile.c Wed Mar 09 18:22:33 2011 -0500 +++ b/Python/compile.c Thu Mar 10 20:03:28 2011 -0500 @@ -892,8 +892,8 @@ return 1; } -static int -compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) +/* used in peephole.c */ +int _PyCode_AddObj(PyObject *dict, PyObject *o) { PyObject *t, *v; Py_ssize_t arg; @@ -965,6 +965,12 @@ } static int +compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) +{ + return _PyCode_AddObj(dict, o); +} + +static int compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, PyObject *o) { @@ -3960,7 +3966,7 @@ if (flags < 0) goto error; - bytecode = PyCode_Optimize(a->a_bytecode, consts, names, a->a_lnotab); + bytecode = PyCode_Optimize(a->a_bytecode, consts, c->u->u_consts, names, a->a_lnotab); if (!bytecode) goto error; diff -r c25b54be90ee Python/peephole.c --- a/Python/peephole.c Wed Mar 09 18:22:33 2011 -0500 +++ b/Python/peephole.c Thu Mar 10 20:03:28 2011 -0500 @@ -23,6 +23,27 @@ #define ISBASICBLOCK(blocks, start, bytes) \ (blocks[start]==blocks[start+bytes-1]) +/* from compile.c */ +extern int _PyCode_AddObj(PyObject *dict, PyObject *o); + +/* Helper to add a constant to constants list. + Reuses existing constant if possible, otherwise appends a new one. */ +static Py_ssize_t +add_const(PyObject *consts, PyObject *dict, PyObject *newconst) +{ + Py_ssize_t idx, size; + + idx = _PyCode_AddObj(dict, newconst); + size = PyList_GET_SIZE(consts); + /* newconst is already in dict or AddObj failed with -1? */ + if (idx < size) + return idx; + assert(idx == size); + if (PyList_Append(consts, newconst)) + return -1; + return size; +} + /* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n with LOAD_CONST (c1, c2, ... cn). The consts table must still be in list form so that the @@ -33,10 +54,10 @@ test; for BUILD_SET it assembles a frozenset rather than a tuple. */ static int -tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) +tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts, PyObject* constdict) { PyObject *newconst, *constant; - Py_ssize_t i, arg, len_consts; + Py_ssize_t i, arg, len_consts, newidx; /* Pre-conditions */ assert(PyList_CheckExact(consts)); @@ -69,7 +90,8 @@ } /* Append folded constant onto consts */ - if (PyList_Append(consts, newconst)) { + newidx = add_const(consts, constdict, newconst); + if (newidx < 0) { Py_DECREF(newconst); return 0; } @@ -79,7 +101,7 @@ add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */ memset(codestr, NOP, n*3); codestr[n*3] = LOAD_CONST; - SETARG(codestr, (n*3), len_consts); + SETARG(codestr, (n*3), newidx); return 1; } @@ -94,10 +116,10 @@ becoming large in the presence of code like: (None,)*1000. */ static int -fold_binops_on_constants(unsigned char *codestr, PyObject *consts) +fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject* constdict) { PyObject *newconst, *v, *w; - Py_ssize_t len_consts, size; + Py_ssize_t newidx, size; int opcode; /* Pre-conditions */ @@ -172,8 +194,8 @@ } /* Append folded constant into consts table */ - len_consts = PyList_GET_SIZE(consts); - if (PyList_Append(consts, newconst)) { + newidx = add_const(consts, constdict, newconst); + if (newidx < 0) { Py_DECREF(newconst); return 0; } @@ -182,15 +204,15 @@ /* Write NOP NOP NOP NOP LOAD_CONST newconst */ memset(codestr, NOP, 4); codestr[4] = LOAD_CONST; - SETARG(codestr, 4, len_consts); + SETARG(codestr, 4, newidx); return 1; } static int -fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts) +fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject* constdict) { PyObject *newconst=NULL, *v; - Py_ssize_t len_consts; + Py_ssize_t newidx; int opcode; /* Pre-conditions */ @@ -226,8 +248,8 @@ } /* Append folded constant into consts table */ - len_consts = PyList_GET_SIZE(consts); - if (PyList_Append(consts, newconst)) { + newidx = add_const(consts, constdict, newconst); + if (newidx < 0) { Py_DECREF(newconst); return 0; } @@ -236,7 +258,7 @@ /* Write NOP LOAD_CONST newconst */ codestr[0] = NOP; codestr[1] = LOAD_CONST; - SETARG(codestr, 1, len_consts); + SETARG(codestr, 1, newidx); return 1; } @@ -284,9 +306,9 @@ /* Helper to replace LOAD_NAME None/True/False with LOAD_CONST Returns: 0 if no change, 1 if change, -1 if error */ static int -load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts) +load_global(unsigned char *codestr, char *name, PyObject *consts, PyObject* constdict) { - Py_ssize_t j; + Py_ssize_t newidx; PyObject *obj; if (name == NULL) return 0; @@ -298,17 +320,11 @@ obj = Py_False; else return 0; - for (j = 0; j < PyList_GET_SIZE(consts); j++) { - if (PyList_GET_ITEM(consts, j) == obj) - break; - } - if (j == PyList_GET_SIZE(consts)) { - if (PyList_Append(consts, obj) < 0) - return -1; - } - assert(PyList_GET_ITEM(consts, j) == obj); - codestr[i] = LOAD_CONST; - SETARG(codestr, i, j); + newidx = add_const(consts, constdict, obj); + if (newidx < 0) + return -1; + codestr[0] = LOAD_CONST; + SETARG(codestr, 0, newidx); return 1; } @@ -330,8 +346,8 @@ a single pass. Line numbering is adjusted accordingly. */ PyObject * -PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, - PyObject *lineno_obj) +PyCode_Optimize(PyObject *code, PyObject* consts, PyObject* constdict, + PyObject *names, PyObject *lineno_obj) { Py_ssize_t i, j, codelen; int nops, h, adj; @@ -427,7 +443,7 @@ case LOAD_GLOBAL: j = GETARG(codestr, i); name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); - h = load_global(codestr, i, name, consts); + h = load_global(&codestr[i], name, consts, constdict); if (h < 0) goto exitError; else if (h == 0) @@ -468,7 +484,7 @@ ISBASICBLOCK(blocks, h, 3*(j+2)) && (GETARG(codestr,i+3)==6 || GETARG(codestr,i+3)==7))) && - tuple_of_constants(&codestr[h], j, consts)) { + tuple_of_constants(&codestr[h], j, consts, constdict)) { assert(codestr[i] == LOAD_CONST); cumlc = 1; break; @@ -506,7 +522,7 @@ case BINARY_OR: if (lastlc >= 2 && ISBASICBLOCK(blocks, i-6, 7) && - fold_binops_on_constants(&codestr[i-6], consts)) { + fold_binops_on_constants(&codestr[i-6], consts, constdict)) { i -= 2; assert(codestr[i] == LOAD_CONST); cumlc = 1; @@ -520,7 +536,7 @@ case UNARY_POSITIVE: if (lastlc >= 1 && ISBASICBLOCK(blocks, i-3, 4) && - fold_unaryops_on_constants(&codestr[i-3], consts)) { + fold_unaryops_on_constants(&codestr[i-3], consts, constdict)) { i -= 2; assert(codestr[i] == LOAD_CONST); cumlc = 1;