[Python-checkins] python/dist/src/Python ceval.c,2.354,2.355

rhettinger@users.sourceforge.net rhettinger@users.sourceforge.net
2003年3月15日 19:11:07 -0800


Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1:/tmp/cvs-serv12161
Modified Files:
	ceval.c 
Log Message:
Introduced macros for a simple opcode prediction protocol.
Applied to common cases:
 COMPARE_OP is often followed by a JUMP_IF.
 JUMP_IF is usually followed by POP_TOP.
Shows improved timings on PyStone, PyBench, and specific tests
using timeit.py:
 python timeit.py -s "x=1" "if x==1: pass"
 python timeit.py -s "x=1" "if x==2: pass"
 python timeit.py -s "x=1" "if x: pass"
 python timeit.py -s "x=100" "while x!=1: x-=1"
Potential future candidates:
 GET_ITER predicts FOR_ITER
 FOR_ITER predicts STORE_FAST or UNPACK_SEQUENCE
Also, applied missing goto fast_next_opcode to DUP_TOPX.
Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.354
retrieving revision 2.355
diff -C2 -d -r2.354 -r2.355
*** ceval.c	14 Mar 2003 01:37:42 -0000	2.354
--- ceval.c	16 Mar 2003 03:11:04 -0000	2.355
***************
*** 603,606 ****
--- 603,626 ----
 #define JUMPBY(x)	(next_instr += (x))
 
+ /* 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.
+ 
+ 	Verifying the prediction costs a single high-speed test of register
+ 	variable against a constant. If the pairing was good, then the odds
+ 	processor has a high likelihood of making its own successful branch
+ 	prediction which results in a nearly zero overhead transition to the
+ 	next opcode.
+ 
+ 	A successful prediction saves a trip through the eval-loop including
+ 	its two unpredictable branches, the HASARG test and the switch-case.
+ */
+ 
+ #define PREDICT(op)	if (*next_instr == op) goto PRED_##op
+ #define PREDICTED(op)		PRED_##op: next_instr++
+ #define PREDICTED_WITH_ARG(op)	PRED_##op: oparg = (next_instr += 3, (next_instr[-1]<<8) + next_instr[-2])
+ 
 /* Stack manipulation macros */
 
***************
*** 874,877 ****
--- 894,898 ----
 			goto fast_next_opcode;
 
+ 		PREDICTED(POP_TOP);
 		case POP_TOP:
 			v = POP();
***************
*** 921,925 ****
 				SET_TOP(x);
 				SET_SECOND(w);
! 				continue;
 			} else if (oparg == 3) {
 				x = TOP();
--- 942,946 ----
 				SET_TOP(x);
 				SET_SECOND(w);
! 				goto fast_next_opcode;
 			} else if (oparg == 3) {
 				x = TOP();
***************
*** 933,937 ****
 				SET_SECOND(w);
 				SET_THIRD(v);
! 				continue;
 			}
 			Py_FatalError("invalid argument to DUP_TOPX"
--- 954,958 ----
 				SET_SECOND(w);
 				SET_THIRD(v);
! 				goto fast_next_opcode;
 			}
 			Py_FatalError("invalid argument to DUP_TOPX"
***************
*** 1919,1924 ****
 			Py_DECREF(w);
 			SET_TOP(x);
! 			if (x != NULL) continue;
! 			break;
 
 		case IMPORT_NAME:
--- 1940,1947 ----
 			Py_DECREF(w);
 			SET_TOP(x);
! 			if (x == NULL) break;
! 			PREDICT(JUMP_IF_FALSE);
! 			PREDICT(JUMP_IF_TRUE);
! 			continue;
 
 		case IMPORT_NAME:
***************
*** 1975,1982 ****
 			goto fast_next_opcode;
 
 		case JUMP_IF_FALSE:
 			w = TOP();
! 			if (w == Py_True)
 				goto fast_next_opcode;
 			if (w == Py_False) {
 				JUMPBY(oparg);
--- 1998,2008 ----
 			goto fast_next_opcode;
 
+ 		PREDICTED_WITH_ARG(JUMP_IF_FALSE);
 		case JUMP_IF_FALSE:
 			w = TOP();
! 			if (w == Py_True) {
! 				PREDICT(POP_TOP);
 				goto fast_next_opcode;
+ 			}
 			if (w == Py_False) {
 				JUMPBY(oparg);
***************
*** 1992,1999 ****
 			continue;
 
 		case JUMP_IF_TRUE:
 			w = TOP();
! 			if (w == Py_False)
 				goto fast_next_opcode;
 			if (w == Py_True) {
 				JUMPBY(oparg);
--- 2018,2028 ----
 			continue;
 
+ 		PREDICTED_WITH_ARG(JUMP_IF_TRUE);
 		case JUMP_IF_TRUE:
 			w = TOP();
! 			if (w == Py_False) {
! 				PREDICT(POP_TOP);
 				goto fast_next_opcode;
+ 			}
 			if (w == Py_True) {
 				JUMPBY(oparg);

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