diff options
author | Jeffrey Yasskin <jyasskin@gmail.com> | 2009-02-25 02:25:04 (GMT) |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@gmail.com> | 2009-02-25 02:25:04 (GMT) |
commit | 9de7ec7868554e92700e4bda6c5f9d8fcad634dc (patch) | |
tree | ce9c4c821286769b6057d94ea20e337ea726f60f /Python/ceval.c | |
parent | 0a68b01d649168f096fddd3cd8d433f2b8b6bb9e (diff) | |
download | cpython-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.c | 80 |
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); |