POP_JUMP_IF_TRUE and POP_JUMP_IF_FALSE implicitly convert their argument to a boolean before choosing which way to branch.
"Explicit is better than implicit"
If we make the conversion explicit:
POP_JUMP_IF_TRUE becomes TO_BOOL; POP_JUMP_IF_IS_TRUE
Where TO_BOOL converts TOS to a boolean and POP_JUMP_IF_IS_TRUE performs the jump:
inst(TO_BOOL, (x -- b)) {
if (PyBool_Check(x)) {
b = x;
}
else {
int err = PyObject_IsTrue(x);
DECREF(x);
ERROR_IF(err < 0, error);
b = err ? Py_True : Py_False;
Py_INCREF(b);
}
}
TO_BOOL should specialize nicely.
inst(POP_JUMP_IF_IS_TRUE, (cond -- )) {
_Py_DECREF_NO_DEALLOC(cond);
if (cond == Py_True) {
JUMPBY(oparg);
}
}
Compare-and-branch
Now consider how this combines with compares:
| Branch? |
No compare |
Compare |
| No |
--- |
COMPARE_OP |
| Yes |
TO_BOOL ; POP_JUMP_IF_IS_TRUE |
COMPARE_OP; TO_BOOL; POP_JUMP_IF_IS_TRUE |
Now, all of the current specializations, and almost all of the possible specializations of COMPARE_OP produce a boolean value.
We take advantage of that by combining COMPARE_OP and TO_BOOL by using remaining bit of the oparg to indicate whether we should convert the result to a boolean:
inst(COMPARE_OP, (unused/1, left, right -- res)) {
res = PyObject_RichCompare(left, right, oparg>>4);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
if (oparg & TO_BOOL_BIT) {
/* convert to boolean, as TO_BOOL above */
}
}
The above version of COMPARE_OP specializes as effectively as before, removes the bool conversion from POP_JUMP_IF_TRUE and makes the conversion to bool explicit, which should help specialization.
POP_JUMP_IF_TRUEandPOP_JUMP_IF_FALSEimplicitly convert their argument to a boolean before choosing which way to branch."Explicit is better than implicit"
If we make the conversion explicit:
POP_JUMP_IF_TRUEbecomesTO_BOOL; POP_JUMP_IF_IS_TRUEWhere
TO_BOOLconverts TOS to a boolean andPOP_JUMP_IF_IS_TRUEperforms the jump:TO_BOOLshould specialize nicely.Compare-and-branch
Now consider how this combines with compares:
Now, all of the current specializations, and almost all of the possible specializations of
COMPARE_OPproduce a boolean value.We take advantage of that by combining
COMPARE_OPandTO_BOOLby using remaining bit of the oparg to indicate whether we should convert the result to a boolean:The above version of
COMPARE_OPspecializes as effectively as before, removes the bool conversion fromPOP_JUMP_IF_TRUEand makes the conversion toboolexplicit, which should help specialization.