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);