Mercurial > cpython-lru_cache-weakref
diff Python/compile.c @ 34547:835b645a168f legacy-trunk
Transform "x in (1,2,3)" to "x in frozenset([1,2,3])".
Inspired by Skip's idea to recognize the throw-away nature of sequences
in this context and to transform their type to one with better performance.
| author | Raymond Hettinger <python@rcn.com> |
|---|---|
| date | Sun, 06 Feb 2005 22:05:42 +0000 |
| parents | bda933873758 |
| children | cd04f2d18a6f |
line wrap: on
line diff
--- a/Python/compile.c Sun Feb 06 06:57:08 2005 +0000 +++ b/Python/compile.c Sun Feb 06 22:05:42 2005 +0000 @@ -540,6 +540,47 @@ return 1; } +/* Replace LOAD_CONST tuple with LOAD_CONST frozenset in the context + of a single-use constant for "in" and "not in" tests. +*/ +int +try_set_conversion(unsigned char *codestr, PyObject *consts) +{ + PyObject *newconst, *constant; + int arg, len_consts; + + /* Pre-conditions */ + assert(PyList_CheckExact(consts)); + assert(codestr[0] == LOAD_CONST); + assert(codestr[3] == COMPARE_OP); + assert(GETARG(codestr, 3) == 6 || GETARG(codestr, 3) == 7); + + /* Attempt to convert constant to a frozenset. Bail-out with no + changes if the tuple contains unhashable values. */ + arg = GETARG(codestr, 0); + constant = PyList_GET_ITEM(consts, arg); + if (constant->ob_type != &PyTuple_Type) + return 0; + newconst = PyObject_CallFunctionObjArgs( + (PyObject *)&PyFrozenSet_Type, constant, NULL); + if (newconst == NULL) { + PyErr_Clear(); + return 0; + } + + /* Append new constant onto consts list.*/ + len_consts = PyList_GET_SIZE(consts); + if (PyList_Append(consts, newconst)) { + Py_DECREF(newconst); + return 0; + } + Py_DECREF(newconst); + + /* Write new LOAD_CONST newconst on top of LOAD_CONST oldconst */ + SETARG(codestr, 0, len_consts); + return 1; +} + static unsigned int * markblocks(unsigned char *code, int len) { @@ -665,9 +706,15 @@ /* not a is b --> a is not b not a in b --> a not in b not a is not b --> a is b - not a not in b --> a in b */ + not a not in b --> a in b + + a in c --> a in frozenset(c) + where c is a constant tuple of hashable values + */ case COMPARE_OP: j = GETARG(codestr, i); + if (lastlc >= 1 && (j == 6 || j == 7) && ISBASICBLOCK(blocks,i-3,6)) + try_set_conversion(&codestr[i-3], consts); if (j < 6 || j > 9 || codestr[i+3] != UNARY_NOT || !ISBASICBLOCK(blocks,i,4))
