[Python-checkins] python/dist/src/Python compile.c,2.340,2.341
rhettinger at users.sourceforge.net
rhettinger at users.sourceforge.net
Sun Feb 6 23:05:44 CET 2005
Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26507/Python
Modified Files:
compile.c
Log Message:
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.
Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.340
retrieving revision 2.341
diff -u -d -r2.340 -r2.341
--- compile.c 26 Jan 2005 12:50:04 -0000 2.340
+++ compile.c 6 Feb 2005 22:05:38 -0000 2.341
@@ -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))
More information about the Python-checkins
mailing list