Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 56640) +++ Python/ceval.c (working copy) @@ -2031,8 +2031,8 @@ Py_DECREF(w); SET_TOP(x); if (x == NULL) break; - PREDICT(JUMP_IF_FALSE); - PREDICT(JUMP_IF_TRUE); + PREDICT(JUMP_IF_FALSE_AND_POP); + PREDICT(JUMP_IF_TRUE_AND_POP); continue; case IMPORT_NAME: @@ -2105,7 +2105,6 @@ JUMPBY(oparg); goto fast_next_opcode; - PREDICTED_WITH_ARG(JUMP_IF_FALSE); case JUMP_IF_FALSE: w = TOP(); if (w == Py_True) { @@ -2125,7 +2124,6 @@ break; continue; - PREDICTED_WITH_ARG(JUMP_IF_TRUE); case JUMP_IF_TRUE: w = TOP(); if (w == Py_False) { @@ -2147,6 +2145,44 @@ break; continue; + PREDICTED_WITH_ARG(JUMP_IF_FALSE_AND_POP); + case JUMP_IF_FALSE_AND_POP: + w = POP(); + if (w == Py_True) + goto fast_next_opcode; + if (w == Py_False) { + JUMPBY(oparg); + goto fast_next_opcode; + } + err = PyObject_IsTrue(w); + if (err > 0) + err = 0; + else if (err == 0) + JUMPBY(oparg); + else + break; + continue; + + PREDICTED_WITH_ARG(JUMP_IF_TRUE_AND_POP); + case JUMP_IF_TRUE_AND_POP: + w = POP(); + if (w == Py_False) + goto fast_next_opcode; + if (w == Py_True) { + JUMPBY(oparg); + goto fast_next_opcode; + } + err = PyObject_IsTrue(w); + if (err > 0) { + err = 0; + JUMPBY(oparg); + } + else if (err == 0) + ; + else + break; + continue; + PREDICTED_WITH_ARG(JUMP_ABSOLUTE); case JUMP_ABSOLUTE: JUMPTO(oparg); Index: Python/peephole.c =================================================================== --- Python/peephole.c (revision 56640) +++ Python/peephole.c (working copy) @@ -248,6 +248,8 @@ case JUMP_IF_FALSE: case JUMP_IF_TRUE: case JUMP_ABSOLUTE: + case JUMP_IF_FALSE_AND_POP: + case JUMP_IF_TRUE_AND_POP: case CONTINUE_LOOP: case SETUP_LOOP: case SETUP_EXCEPT: @@ -599,6 +601,8 @@ case JUMP_FORWARD: case JUMP_IF_FALSE: case JUMP_IF_TRUE: + case JUMP_IF_FALSE_AND_POP: + case JUMP_IF_TRUE_AND_POP: case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: Index: Python/compile.c =================================================================== --- Python/compile.c (revision 56640) +++ Python/compile.c (working copy) @@ -824,6 +824,10 @@ case JUMP_ABSOLUTE: return 0; + case JUMP_IF_FALSE_AND_POP: + case JUMP_IF_TRUE_AND_POP: + return -1; + case LOAD_GLOBAL: return 1; @@ -1424,12 +1428,10 @@ if (next == NULL) return 0; VISIT(c, expr, e->v.IfExp.test); - ADDOP_JREL(c, JUMP_IF_FALSE, next); - ADDOP(c, POP_TOP); + ADDOP_JREL(c, JUMP_IF_FALSE_AND_POP, next); VISIT(c, expr, e->v.IfExp.body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, next); - ADDOP(c, POP_TOP); VISIT(c, expr, e->v.IfExp.orelse); compiler_use_next_block(c, end); return 1; @@ -1517,10 +1519,7 @@ end = compiler_new_block(c); if (end == NULL) return 0; - next = compiler_new_block(c); - if (next == NULL) - return 0; - + constant = expr_constant(s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... @@ -1531,15 +1530,20 @@ } else if (constant == 1) { VISIT_SEQ(c, stmt, s->v.If.body); } else { + if (s->v.If.orelse) { + next = compiler_new_block(c); + if (next == NULL) + return 0; + } else + next = end; VISIT(c, expr, s->v.If.test); - ADDOP_JREL(c, JUMP_IF_FALSE, next); - ADDOP(c, POP_TOP); + ADDOP_JREL(c, JUMP_IF_FALSE_AND_POP, next); VISIT_SEQ(c, stmt, s->v.If.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next); - ADDOP(c, POP_TOP); - if (s->v.If.orelse) + if (s->v.If.orelse) { + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, next); VISIT_SEQ(c, stmt, s->v.If.orelse); + } } compiler_use_next_block(c, end); return 1; @@ -1608,8 +1612,7 @@ return 0; if (constant == -1) { VISIT(c, expr, s->v.While.test); - ADDOP_JREL(c, JUMP_IF_FALSE, anchor); - ADDOP(c, POP_TOP); + ADDOP_JREL(c, JUMP_IF_FALSE_AND_POP, anchor); } VISIT_SEQ(c, stmt, s->v.While.body); ADDOP_JABS(c, JUMP_ABSOLUTE, loop); @@ -1620,7 +1623,6 @@ if (constant == -1) { compiler_use_next_block(c, anchor); - ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); } compiler_pop_fblock(c, LOOP, loop); @@ -1991,8 +1993,7 @@ end = compiler_new_block(c); if (end == NULL) return 0; - ADDOP_JREL(c, JUMP_IF_TRUE, end); - ADDOP(c, POP_TOP); + ADDOP_JREL(c, JUMP_IF_TRUE_AND_POP, end); ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); if (s->v.Assert.msg) { VISIT(c, expr, s->v.Assert.msg); @@ -2002,7 +2003,6 @@ ADDOP_I(c, RAISE_VARARGS, 1); } compiler_use_next_block(c, end); - ADDOP(c, POP_TOP); return 1; } Index: Include/opcode.h =================================================================== --- Include/opcode.h (revision 56640) +++ Include/opcode.h (working copy) @@ -108,6 +108,8 @@ #define JUMP_IF_FALSE 111 /* "" */ #define JUMP_IF_TRUE 112 /* "" */ #define JUMP_ABSOLUTE 113 /* Target byte offset from beginning of code */ +#define JUMP_IF_FALSE_AND_POP 114 /* Number of bytes to skip */ +#define JUMP_IF_TRUE_AND_POP 115 /* "" */ #define LOAD_GLOBAL 116 /* Index in name list */ Index: Lib/opcode.py =================================================================== --- Lib/opcode.py (revision 56640) +++ Lib/opcode.py (working copy) @@ -149,6 +149,8 @@ jrel_op('JUMP_IF_FALSE', 111) # "" jrel_op('JUMP_IF_TRUE', 112) # "" jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code +jrel_op('JUMP_IF_FALSE_AND_POP', 114) # Number of bytes to skip +jrel_op('JUMP_IF_TRUE_AND_POP', 115) # "" name_op('LOAD_GLOBAL', 116) # Index in name list