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.
This commit is contained in:
Jeffrey Yasskin 2009-02-28 19:03:21 +00:00
parent de28d6841e
commit 68d6852006
11 changed files with 228 additions and 178 deletions

View file

@ -764,8 +764,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* 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 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
SETLOCAL(oparg, v);
goto fast_next_opcode;
PREDICTED(POP_TOP);
case POP_TOP:
v = POP();
Py_DECREF(v);
@ -2220,8 +2219,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);
continue;
case IMPORT_NAME:
@ -2298,44 +2297,95 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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(JUMP_IF_TRUE);
case JUMP_IF_TRUE:
w = TOP();
PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
case POP_JUMP_IF_TRUE:
w = POP();
if (w == Py_False) {
PREDICT(POP_TOP);
Py_DECREF(w);
goto fast_next_opcode;
}
if (w == Py_True) {
JUMPBY(oparg);
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;
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) {
STACKADJ(-1);
Py_DECREF(w);
goto fast_next_opcode;
}
if (w == Py_True) {
JUMPTO(oparg);
goto fast_next_opcode;
}
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;
continue;