diff Python/ceval.c @ 51920:ef8fe9088696 legacy-trunk

Backport r69961 to trunk, replacing JUMP_IF_{TRUE,FALSE} with POP_JUMP_IF_{TRUE,FALSE} and JUMP_IF_{TRUE,FALSE}_OR_POP. This avoids executing a POP_TOP on each conditional and sometimes allows the peephole optimizer to skip a JUMP_ABSOLUTE entirely. It speeds up list comprehensions significantly.
author Jeffrey Yasskin <jyasskin@gmail.com>
date Sat, 28 Feb 2009 19:03:21 +0000
parents 0848ebb8f9c8
children 9ef683d41c9b
line wrap: on
line diff
--- a/Python/ceval.c	Sat Feb 28 15:50:40 2009 +0000
+++ b/Python/ceval.c	Sat Feb 28 19:03:21 2009 +0000
@@ -764,8 +764,8 @@
 /* OpCode prediction macros
 	Some opcodes tend to come in pairs thus making it possible to
 	predict the second code when the first is run.  For example,
-	COMPARE_OP is often followed by JUMP_IF_FALSE or JUMP_IF_TRUE.  And,
-	those opcodes are often followed by a POP_TOP.
+	GET_ITER is often followed by FOR_ITER. And FOR_ITER is often
+	followed by STORE_FAST or UNPACK_SEQUENCE.
 
 	Verifying the prediction costs a single high-speed test of a register
 	variable against a constant.  If the pairing was good, then the
@@ -1110,7 +1110,6 @@
 			SETLOCAL(oparg, v);
 			goto fast_next_opcode;
 
-		PREDICTED(POP_TOP);
 		case POP_TOP:
 			v = POP();
 			Py_DECREF(v);
@@ -2220,8 +2219,8 @@
 			Py_DECREF(w);
 			SET_TOP(x);
 			if (x == NULL) break;
-			PREDICT(JUMP_IF_FALSE);
-			PREDICT(JUMP_IF_TRUE);
+			PREDICT(POP_JUMP_IF_FALSE);
+			PREDICT(POP_JUMP_IF_TRUE);
 			continue;
 
 		case IMPORT_NAME:
@@ -2298,44 +2297,95 @@
 			JUMPBY(oparg);
 			goto fast_next_opcode;
 
-		PREDICTED_WITH_ARG(JUMP_IF_FALSE);
-		case JUMP_IF_FALSE:
-			w = TOP();
+		PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
+		case POP_JUMP_IF_FALSE:
+			w = POP();
 			if (w == Py_True) {
-				PREDICT(POP_TOP);
+				Py_DECREF(w);
 				goto fast_next_opcode;
 			}
 			if (w == Py_False) {
-				JUMPBY(oparg);
+				Py_DECREF(w);
+				JUMPTO(oparg);
 				goto fast_next_opcode;
 			}
 			err = PyObject_IsTrue(w);
+			Py_DECREF(w);
 			if (err > 0)
 				err = 0;
 			else if (err == 0)
-				JUMPBY(oparg);
+				JUMPTO(oparg);
+			else
+				break;
+			continue;
+
+		PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
+		case POP_JUMP_IF_TRUE:
+			w = POP();
+			if (w == Py_False) {
+				Py_DECREF(w);
+				goto fast_next_opcode;
+			}
+			if (w == Py_True) {
+				Py_DECREF(w);
+				JUMPTO(oparg);
+				goto fast_next_opcode;
+			}
+			err = PyObject_IsTrue(w);
+			Py_DECREF(w);
+			if (err > 0) {
+				err = 0;
+				JUMPTO(oparg);
+			}
+			else if (err == 0)
+				;
 			else
 				break;
 			continue;
 
-		PREDICTED_WITH_ARG(JUMP_IF_TRUE);
-		case JUMP_IF_TRUE:
+		case JUMP_IF_FALSE_OR_POP:
+			w = TOP();
+			if (w == Py_True) {
+				STACKADJ(-1);
+				Py_DECREF(w);
+				goto fast_next_opcode;
+			}
+			if (w == Py_False) {
+				JUMPTO(oparg);
+				goto fast_next_opcode;
+			}
+			err = PyObject_IsTrue(w);
+			if (err > 0) {
+				STACKADJ(-1);
+				Py_DECREF(w);
+				err = 0;
+			}
+			else if (err == 0)
+				JUMPTO(oparg);
+			else
+				break;
+			continue;
+
+		case JUMP_IF_TRUE_OR_POP:
 			w = TOP();
 			if (w == Py_False) {
-				PREDICT(POP_TOP);
+				STACKADJ(-1);
+				Py_DECREF(w);
 				goto fast_next_opcode;
 			}
 			if (w == Py_True) {
-				JUMPBY(oparg);
+				JUMPTO(oparg);
 				goto fast_next_opcode;
 			}
 			err = PyObject_IsTrue(w);
 			if (err > 0) {
 				err = 0;
-				JUMPBY(oparg);
+				JUMPTO(oparg);
 			}
-			else if (err == 0)
-				;
+			else if (err == 0) {
+				STACKADJ(-1);
+				Py_DECREF(w);
+			}
 			else
 				break;
 			continue;