SF patch #910929: Optimize list comprehensions
Add a new opcode, LIST_APPEND, and apply it to the code generation for
list comprehensions. Reduces the per-loop overhead by about a third.
diff --git a/Doc/whatsnew/whatsnew24.tex b/Doc/whatsnew/whatsnew24.tex
index 24650fa..2a323ff 100644
--- a/Doc/whatsnew/whatsnew24.tex
+++ b/Doc/whatsnew/whatsnew24.tex
@@ -288,6 +288,10 @@
use as arguments to functionals:
\samp{map(mydict.__getitem__, keylist)}.
+\item Added an newcode opcode, \code{LIST_APPEND}, that simplifies
+ the generated bytecode for list comprehensions and speeds them up
+ by about a third.
+
\end{itemize}
The net result of the 2.4 optimizations is that Python 2.4 runs the
diff --git a/Include/opcode.h b/Include/opcode.h
index 2f3dd04..8df96b4 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -21,6 +21,7 @@
#define UNARY_INVERT 15
+#define LIST_APPEND 18
#define BINARY_POWER 19
#define BINARY_MULTIPLY 20
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 39d4bd2..ae9f6cc 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -56,6 +56,7 @@
def_op('UNARY_INVERT', 15)
+def_op('LIST_APPEND', 18)
def_op('BINARY_POWER', 19)
def_op('BINARY_MULTIPLY', 20)
diff --git a/Misc/NEWS b/Misc/NEWS
index 72232c8..f3554c3 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@
Core and builtins
-----------------
+- Implemented a newcode opcode, LIST_APPEND, that simplifies
+ the generated bytecode for list comprehensions and further
+ improves their performance (about 35%).
+
- Implemented rich comparisons for floats, which seems to make
comparisons involving NaNs somewhat less surprising when the
underlying C compiler actually implements C99 semantics.
diff --git a/Python/ceval.c b/Python/ceval.c
index 3371844..b20934c 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1225,6 +1225,15 @@
if (x != NULL) continue;
break;
+ case LIST_APPEND:
+ w = POP();
+ v = POP();
+ err = PyList_Append(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (err == 0) continue;
+ break;
+
case INPLACE_POWER:
w = POP();
v = TOP();
diff --git a/Python/compile.c b/Python/compile.c
index 04d8b65..f58fb83 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1552,8 +1552,7 @@
com_addop_varname(c, VAR_LOAD, t);
com_push(c, 1);
com_node(c, e);
- com_addoparg(c, CALL_FUNCTION, 1);
- com_addbyte(c, POP_TOP);
+ com_addbyte(c, LIST_APPEND);
com_pop(c, 2);
}
}
@@ -1569,7 +1568,6 @@
com_addoparg(c, BUILD_LIST, 0);
com_addbyte(c, DUP_TOP); /* leave the result on the stack */
com_push(c, 2);
- com_addop_name(c, LOAD_ATTR, "append");
com_addop_varname(c, VAR_STORE, tmpname);
com_pop(c, 1);
com_list_for(c, CHILD(n, 1), CHILD(n, 0), tmpname);