[Python-checkins] r67839 - in python/branches/py3k: Doc/library/dis.rst Include/opcode.h Lib/opcode.py Lib/test/test_dis.py Misc/NEWS Python/ceval.c Python/compile.c Python/import.c

antoine.pitrou python-checkins at python.org
Thu Dec 18 12:06:26 CET 2008


Author: antoine.pitrou
Date: Thu Dec 18 12:06:25 2008
New Revision: 67839
Log:
Merged revisions 67818 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk
........
 r67818 | antoine.pitrou | 2008年12月17日 01:38:28 +0100 (mer., 17 déc. 2008) | 3 lines
 
 Issue #2183: Simplify and optimize bytecode for list comprehensions.
........
Modified:
 python/branches/py3k/ (props changed)
 python/branches/py3k/Doc/library/dis.rst
 python/branches/py3k/Include/opcode.h
 python/branches/py3k/Lib/opcode.py
 python/branches/py3k/Lib/test/test_dis.py
 python/branches/py3k/Misc/NEWS
 python/branches/py3k/Python/ceval.c
 python/branches/py3k/Python/compile.c
 python/branches/py3k/Python/import.c
Modified: python/branches/py3k/Doc/library/dis.rst
==============================================================================
--- python/branches/py3k/Doc/library/dis.rst	(original)
+++ python/branches/py3k/Doc/library/dis.rst	Thu Dec 18 12:06:25 2008
@@ -357,14 +357,25 @@
 address to jump to (which should be a ``FOR_ITER`` instruction).
 
 
-.. opcode:: SET_ADD ()
+.. opcode:: SET_ADD (i)
 
- Calls ``set.add(TOS1, TOS)``. Used to implement set comprehensions.
+ Calls ``set.add(TOS1[-i], TOS)``. Used to implement set comprehensions.
 
 
-.. opcode:: LIST_APPEND ()
+.. opcode:: LIST_APPEND (i)
 
- Calls ``list.append(TOS1, TOS)``. Used to implement list comprehensions.
+ Calls ``list.append(TOS[-i], TOS)``. Used to implement list comprehensions.
+
+
+.. opcode:: MAP_ADD (i)
+
+ Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict
+ comprehensions.
+
+
+For all of the SET_ADD, LIST_APPEND and MAP_ADD instructions, while the
+added value or key/value pair is popped off, the container object remains on
+the stack so that it is available for further iterations of the loop.
 
 
 .. opcode:: LOAD_LOCALS ()
Modified: python/branches/py3k/Include/opcode.h
==============================================================================
--- python/branches/py3k/Include/opcode.h	(original)
+++ python/branches/py3k/Include/opcode.h	Thu Dec 18 12:06:25 2008
@@ -21,8 +21,6 @@
 
 #define UNARY_INVERT	15
 
-#define SET_ADD	17
-#define LIST_APPEND	18
 #define BINARY_POWER	19
 
 #define BINARY_MULTIPLY	20
@@ -133,6 +131,10 @@
 /* Support for opargs more than 16 bits long */
 #define EXTENDED_ARG 143
 
+#define LIST_APPEND 145
+#define SET_ADD 146
+#define MAP_ADD 147
+
 
 /* EXCEPT_HANDLER is a special, implicit block type which is created when
 entering an except handler. It is not an opcode but we define it here
Modified: python/branches/py3k/Lib/opcode.py
==============================================================================
--- python/branches/py3k/Lib/opcode.py	(original)
+++ python/branches/py3k/Lib/opcode.py	Thu Dec 18 12:06:25 2008
@@ -57,8 +57,6 @@
 
 def_op('UNARY_INVERT', 15)
 
-def_op('SET_ADD', 17)
-def_op('LIST_APPEND', 18)
 def_op('BINARY_POWER', 19)
 def_op('BINARY_MULTIPLY', 20)
 
@@ -169,4 +167,9 @@
 def_op('EXTENDED_ARG', 143)
 EXTENDED_ARG = 143
 
+def_op('LIST_APPEND', 145)
+def_op('SET_ADD', 146)
+def_op('MAP_ADD', 147)
+
+
 del def_op, name_op, jrel_op, jabs_op
Modified: python/branches/py3k/Lib/test/test_dis.py
==============================================================================
--- python/branches/py3k/Lib/test/test_dis.py	(original)
+++ python/branches/py3k/Lib/test/test_dis.py	Thu Dec 18 12:06:25 2008
@@ -55,29 +55,25 @@
 
 dis_bug1333982 = """\
 %-4d 0 LOAD_CONST 1 (0)
- 3 JUMP_IF_TRUE 41 (to 47)
+ 3 JUMP_IF_TRUE 33 (to 39)
 6 POP_TOP
 7 LOAD_GLOBAL 0 (AssertionError)
 10 BUILD_LIST 0
- 13 DUP_TOP
- 14 STORE_FAST 1 (_[1])
- 17 LOAD_FAST 0 (x)
- 20 GET_ITER
- >> 21 FOR_ITER 13 (to 37)
- 24 STORE_FAST 2 (s)
- 27 LOAD_FAST 1 (_[1])
- 30 LOAD_FAST 2 (s)
- 33 LIST_APPEND
- 34 JUMP_ABSOLUTE 21
- >> 37 DELETE_FAST 1 (_[1])
-
- %-4d 40 LOAD_CONST 2 (1)
- 43 BINARY_ADD
- 44 RAISE_VARARGS 2
- >> 47 POP_TOP
+ 13 LOAD_FAST 0 (x)
+ 16 GET_ITER
+ >> 17 FOR_ITER 12 (to 32)
+ 20 STORE_FAST 1 (s)
+ 23 LOAD_FAST 1 (s)
+ 26 LIST_APPEND 2
+ 29 JUMP_ABSOLUTE 17
+
+ %-4d >> 32 LOAD_CONST 2 (1)
+ 35 BINARY_ADD
+ 36 RAISE_VARARGS 2
+ >> 39 POP_TOP
 
- %-4d 48 LOAD_CONST 0 (None)
- 51 RETURN_VALUE
+ %-4d 40 LOAD_CONST 0 (None)
+ 43 RETURN_VALUE
 """%(bug1333982.__code__.co_firstlineno + 1,
 bug1333982.__code__.co_firstlineno + 2,
 bug1333982.__code__.co_firstlineno + 3)
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Thu Dec 18 12:06:25 2008
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #2183: Simplify and optimize bytecode for list, dict and set
+ comprehensions. Original patch for list comprehensions by Neal Norwitz.
+
 - Issue #2467: gc.DEBUG_STATS reported invalid elapsed times. Also, always
 print elapsed times, not only when some objects are uncollectable /
 unreachable. Original patch by Neil Schemenauer.
Modified: python/branches/py3k/Python/ceval.c
==============================================================================
--- python/branches/py3k/Python/ceval.c	(original)
+++ python/branches/py3k/Python/ceval.c	Thu Dec 18 12:06:25 2008
@@ -1306,9 +1306,8 @@
 
 		case LIST_APPEND:
 			w = POP();
-			v = POP();
+			v = stack_pointer[-oparg];
 			err = PyList_Append(v, w);
-			Py_DECREF(v);
 			Py_DECREF(w);
 			if (err == 0) {
 				PREDICT(JUMP_ABSOLUTE);
@@ -1318,9 +1317,8 @@
 
 		case SET_ADD:
 			w = POP();
-			v = POP();
+			v = stack_pointer[-oparg];
 			err = PySet_Add(v, w);
-			Py_DECREF(v);
 			Py_DECREF(w);
 			if (err == 0) {
 				PREDICT(JUMP_ABSOLUTE);
@@ -1935,6 +1933,21 @@
 			if (err == 0) continue;
 			break;
 
+		case MAP_ADD:
+			w = TOP(); /* key */
+			u = SECOND(); /* value */
+			STACKADJ(-2);
+			v = stack_pointer[-oparg]; /* dict */
+			assert (PyDict_CheckExact(v));
+			err = PyDict_SetItem(v, w, u); /* v[w] = u */
+			Py_DECREF(u);
+			Py_DECREF(w);
+			if (err == 0) {
+				PREDICT(JUMP_ABSOLUTE);
+				continue;
+			}
+			break;
+
 		case LOAD_ATTR:
 			w = GETITEM(names, oparg);
 			v = TOP();
Modified: python/branches/py3k/Python/compile.c
==============================================================================
--- python/branches/py3k/Python/compile.c	(original)
+++ python/branches/py3k/Python/compile.c	Thu Dec 18 12:06:25 2008
@@ -707,6 +707,8 @@
 
 		case SET_ADD:
 		case LIST_APPEND:
+			return -1;
+		case MAP_ADD:
 			return -2;
 
 		case BINARY_POWER:
@@ -2823,7 +2825,7 @@
 */
 
 static int
-compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,
+compiler_comprehension_generator(struct compiler *c, 
 				 asdl_seq *generators, int gen_index, 
 				 expr_ty elt, expr_ty val, int type)
 {
@@ -2871,7 +2873,7 @@
 	} 
 
 	if (++gen_index < asdl_seq_LEN(generators))
-		if (!compiler_comprehension_generator(c, tmpname, 
+		if (!compiler_comprehension_generator(c, 
 						 generators, gen_index,
 						 elt, val, type))
 		return 0;
@@ -2886,27 +2888,19 @@
 			ADDOP(c, POP_TOP);
 			break;
 		case COMP_LISTCOMP:
-			if (!compiler_nameop(c, tmpname, Load))
-				return 0;
 			VISIT(c, expr, elt);
-			ADDOP(c, LIST_APPEND);
+			ADDOP_I(c, LIST_APPEND, gen_index + 1);
 			break;
 		case COMP_SETCOMP:
-			if (!compiler_nameop(c, tmpname, Load))
-				return 0;
 			VISIT(c, expr, elt);
-			ADDOP(c, SET_ADD);
+			ADDOP_I(c, SET_ADD, gen_index + 1);
 			break;
 		case COMP_DICTCOMP:
-			if (!compiler_nameop(c, tmpname, Load))
-				return 0;
 			/* With 'd[k] = v', v is evaluated before k, so we do
-			 the same. STORE_SUBSCR requires (item, map, key),
-			 so we still end up ROTing once. */
+			 the same. */
 			VISIT(c, expr, val);
-			ADDOP(c, ROT_TWO);
 			VISIT(c, expr, elt);
-			ADDOP(c, STORE_SUBSCR);
+			ADDOP_I(c, MAP_ADD, gen_index + 1);
 			break;
 		default:
 			return 0;
@@ -2932,7 +2926,6 @@
 		 asdl_seq *generators, expr_ty elt, expr_ty val)
 {
 	PyCodeObject *co = NULL;
-	identifier tmp = NULL;
 	expr_ty outermost_iter;
 
 	outermost_iter = ((comprehension_ty)
@@ -2943,9 +2936,6 @@
 	
 	if (type != COMP_GENEXP) {
 		int op;
-		tmp = compiler_new_tmpname(c);
-		if (!tmp)
-			goto error_in_scope;
 		switch (type) {
 		case COMP_LISTCOMP:
 			op = BUILD_LIST;
@@ -2963,12 +2953,9 @@
 		}
 
 		ADDOP_I(c, op, 0);
-		ADDOP(c, DUP_TOP);
-		if (!compiler_nameop(c, tmp, Store))
-			goto error_in_scope;
 	}
 	
-	if (!compiler_comprehension_generator(c, tmp, generators, 0, elt,
+	if (!compiler_comprehension_generator(c, generators, 0, elt,
 					 val, type))
 		goto error_in_scope;
 	
@@ -2984,7 +2971,6 @@
 	if (!compiler_make_closure(c, co, 0))
 		goto error;
 	Py_DECREF(co);
-	Py_XDECREF(tmp);
 
 	VISIT(c, expr, outermost_iter);
 	ADDOP(c, GET_ITER);
@@ -2994,7 +2980,6 @@
 	compiler_exit_scope(c);
 error:
 	Py_XDECREF(co);
-	Py_XDECREF(tmp);
 	return 0;
 }
 
Modified: python/branches/py3k/Python/import.c
==============================================================================
--- python/branches/py3k/Python/import.c	(original)
+++ python/branches/py3k/Python/import.c	Thu Dec 18 12:06:25 2008
@@ -87,8 +87,10 @@
 		 3102 (__file__ points to source file)
 Python 3.0a4: 3110 (WITH_CLEANUP optimization).
 Python 3.0a5: 3130 (lexical exception stacking, including POP_EXCEPT)
+ Python 3.1a0: 3140 (optimize list, set and dict comprehensions:
+			 change LIST_APPEND and SET_ADD, add MAP_ADD)
 */
-#define MAGIC (3130 | ((long)'\r'<<16) | ((long)'\n'<<24))
+#define MAGIC (3140 | ((long)'\r'<<16) | ((long)'\n'<<24))
 
 /* Magic word as global; note that _PyImport_Init() can change the
 value of this global to accommodate for alterations of how the


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /