mirror of
https://github.com/python/cpython.git
synced 2025-10-17 12:18:23 +00:00
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
This commit is contained in:
parent
0a68b01d64
commit
9de7ec7868
9 changed files with 195 additions and 129 deletions
|
@ -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,44 +2281,95 @@ 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;
|
||||
JUMPTO(oparg);
|
||||
}
|
||||
else if (err == 0)
|
||||
;
|
||||
else
|
||||
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;
|
||||
JUMPBY(oparg);
|
||||
JUMPTO(oparg);
|
||||
}
|
||||
else if (err == 0) {
|
||||
STACKADJ(-1);
|
||||
Py_DECREF(w);
|
||||
}
|
||||
else if (err == 0)
|
||||
;
|
||||
else
|
||||
break;
|
||||
DISPATCH();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue