summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@gmail.com>2009-02-25 02:25:04 (GMT)
committerJeffrey Yasskin <jyasskin@gmail.com>2009-02-25 02:25:04 (GMT)
commit9de7ec7868554e92700e4bda6c5f9d8fcad634dc (patch)
treece9c4c821286769b6057d94ea20e337ea726f60f /Python/ceval.c
parent0a68b01d649168f096fddd3cd8d433f2b8b6bb9e (diff)
downloadcpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.zip
cpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.tar.gz
cpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.tar.bz2
http://bugs.python.org/issue4715
This patch by Antoine Pitrou optimizes the bytecode for conditional branches by merging the following "POP_TOP" instruction into the conditional jump. For example, the list comprehension "[x for x in l if not x]" produced the following bytecode: 1 0 BUILD_LIST 0 3 LOAD_FAST 0 (.0) >> 6 FOR_ITER 23 (to 32) 9 STORE_FAST 1 (x) 12 LOAD_FAST 1 (x) 15 JUMP_IF_TRUE 10 (to 28) 18 POP_TOP 19 LOAD_FAST 1 (x) 22 LIST_APPEND 2 25 JUMP_ABSOLUTE 6 >> 28 POP_TOP 29 JUMP_ABSOLUTE 6 >> 32 RETURN_VALUE but after the patch it produces the following bytecode: 1 0 BUILD_LIST 0 3 LOAD_FAST 0 (.0) >> 6 FOR_ITER 18 (to 27) 9 STORE_FAST 1 (x) 12 LOAD_FAST 1 (x) 15 POP_JUMP_IF_TRUE 6 18 LOAD_FAST 1 (x) 21 LIST_APPEND 2 24 JUMP_ABSOLUTE 6 >> 27 RETURN_VALUE Notice that not only the code is shorter, but the conditional jump (POP_JUMP_IF_TRUE) jumps right to the start of the loop instead of going through the JUMP_ABSOLUTE at the end. "continue" statements are helped similarly. Furthermore, the old jump opcodes (JUMP_IF_FALSE, JUMP_IF_TRUE) have been replaced by two new opcodes: - JUMP_IF_TRUE_OR_POP, which jumps if true and pops otherwise - JUMP_IF_FALSE_OR_POP, which jumps if false and pops otherwise
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c80
1 files changed, 65 insertions, 15 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index e0ce92e..d1d6d1d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1295,7 +1295,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
SETLOCAL(oparg, v);
FAST_DISPATCH();
- PREDICTED(POP_TOP);
TARGET(POP_TOP)
v = POP();
Py_DECREF(v);
@@ -2204,8 +2203,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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);
DISPATCH();
TARGET(IMPORT_NAME)
@@ -2282,41 +2281,45 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
JUMPBY(oparg);
FAST_DISPATCH();
- PREDICTED_WITH_ARG(JUMP_IF_FALSE);
- TARGET(JUMP_IF_FALSE)
- w = TOP();
+ PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
+ TARGET(POP_JUMP_IF_FALSE)
+ w = POP();
if (w == Py_True) {
- PREDICT(POP_TOP);
+ Py_DECREF(w);
FAST_DISPATCH();
}
if (w == Py_False) {
- JUMPBY(oparg);
+ Py_DECREF(w);
+ JUMPTO(oparg);
FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
+ Py_DECREF(w);
if (err > 0)
err = 0;
else if (err == 0)
- JUMPBY(oparg);
+ JUMPTO(oparg);
else
break;
DISPATCH();
- PREDICTED_WITH_ARG(JUMP_IF_TRUE);
- TARGET(JUMP_IF_TRUE)
- w = TOP();
+ PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
+ TARGET(POP_JUMP_IF_TRUE)
+ w = POP();
if (w == Py_False) {
- PREDICT(POP_TOP);
+ Py_DECREF(w);
FAST_DISPATCH();
}
if (w == Py_True) {
- JUMPBY(oparg);
+ Py_DECREF(w);
+ JUMPTO(oparg);
FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
+ Py_DECREF(w);
if (err > 0) {
err = 0;
- JUMPBY(oparg);
+ JUMPTO(oparg);
}
else if (err == 0)
;
@@ -2324,6 +2327,53 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
DISPATCH();
+ TARGET(JUMP_IF_FALSE_OR_POP)
+ w = TOP();
+ if (w == Py_True) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ FAST_DISPATCH();
+ }
+ if (w == Py_False) {
+ JUMPTO(oparg);
+ FAST_DISPATCH();
+ }
+ err = PyObject_IsTrue(w);
+ if (err > 0) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ err = 0;
+ }
+ else if (err == 0)
+ JUMPTO(oparg);
+ else
+ break;
+ DISPATCH();
+
+ TARGET(JUMP_IF_TRUE_OR_POP)
+ w = TOP();
+ if (w == Py_False) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ FAST_DISPATCH();
+ }
+ if (w == Py_True) {
+ JUMPTO(oparg);
+ FAST_DISPATCH();
+ }
+ err = PyObject_IsTrue(w);
+ if (err > 0) {
+ err = 0;
+ JUMPTO(oparg);
+ }
+ else if (err == 0) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ }
+ else
+ break;
+ DISPATCH();
+
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
TARGET(JUMP_ABSOLUTE)
JUMPTO(oparg);