summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2022-04-11 09:40:24 (GMT)
committerGitHub <noreply@github.com>2022-04-11 09:40:24 (GMT)
commitdd207a6ac52d4bd9a71cf178fc1d5c17a6f07aff (patch)
treec196769c21e856595b8c90adc5205b2372234f02 /Python
parent98ff4a68773c49619d486c7e758ebbe1662f8387 (diff)
downloadcpython-dd207a6ac52d4bd9a71cf178fc1d5c17a6f07aff.zip
cpython-dd207a6ac52d4bd9a71cf178fc1d5c17a6f07aff.tar.gz
cpython-dd207a6ac52d4bd9a71cf178fc1d5c17a6f07aff.tar.bz2
bpo-47120: make POP_JUMP_IF_TRUE/FALSE/NONE/NOT_NONE relative (GH-32400)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c179
-rw-r--r--Python/compile.c91
-rw-r--r--Python/opcode_targets.h16
-rw-r--r--Python/specialize.c14
4 files changed, 225 insertions, 75 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index f3d1c10..b46b1ef 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3646,8 +3646,6 @@ handle_eval_breaker:
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
- PREDICT(POP_JUMP_IF_FALSE);
- PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
}
@@ -3670,7 +3668,7 @@ handle_eval_breaker:
TARGET(COMPARE_OP_FLOAT_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
+ // Combined: COMPARE_OP (float ? float) + POP_JUMP_(direction)_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
@@ -3688,22 +3686,31 @@ handle_eval_breaker:
STACK_SHRINK(2);
Py_DECREF(left);
Py_DECREF(right);
- assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
- int jump = (1 << (sign + 1)) & when_to_jump_mask;
+ assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE ||
+ opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_TRUE);
+ int jump = (9 << (sign + 1)) & when_to_jump_mask;
if (!jump) {
next_instr++;
- NOTRACE_DISPATCH();
}
- else {
- JUMPTO(oparg);
+ else if (jump >= 8) {
+ assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE);
+ JUMPBY(1 - oparg);
CHECK_EVAL_BREAKER();
- NOTRACE_DISPATCH();
}
+ else {
+ assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_FORWARD_IF_FALSE);
+ JUMPBY(1 + oparg);
+ }
+ NOTRACE_DISPATCH();
}
TARGET(COMPARE_OP_INT_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
+ // Combined: COMPARE_OP (int ? int) + POP_JUMP_(direction)_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
@@ -3722,24 +3729,33 @@ handle_eval_breaker:
STACK_SHRINK(2);
Py_DECREF(left);
Py_DECREF(right);
- assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
- int jump = (1 << (sign + 1)) & when_to_jump_mask;
+ assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE ||
+ opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_TRUE);
+ int jump = (9 << (sign + 1)) & when_to_jump_mask;
if (!jump) {
next_instr++;
- NOTRACE_DISPATCH();
}
- else {
- JUMPTO(oparg);
+ else if (jump >= 8) {
+ assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE);
+ JUMPBY(1 - oparg);
CHECK_EVAL_BREAKER();
- NOTRACE_DISPATCH();
}
+ else {
+ assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_FORWARD_IF_FALSE);
+ JUMPBY(1 + oparg);
+ }
+ NOTRACE_DISPATCH();
}
TARGET(COMPARE_OP_STR_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
+ // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_(direction)_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
- int invert = cache->mask;
+ int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
PyObject *left = SECOND();
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
@@ -3752,22 +3768,31 @@ handle_eval_breaker:
assert(oparg == Py_EQ || oparg == Py_NE);
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
- assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
+ assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE ||
+ opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_TRUE);
STACK_SHRINK(2);
Py_DECREF(left);
Py_DECREF(right);
assert(res == 0 || res == 1);
- assert(invert == 0 || invert == 1);
- int jump = res ^ invert;
+ int sign = 1 - res;
+ int jump = (9 << (sign + 1)) & when_to_jump_mask;
if (!jump) {
next_instr++;
- NOTRACE_DISPATCH();
}
- else {
- JUMPTO(oparg);
+ else if (jump >= 8) {
+ assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
+ opcode == POP_JUMP_BACKWARD_IF_FALSE);
+ JUMPBY(1 - oparg);
CHECK_EVAL_BREAKER();
- NOTRACE_DISPATCH();
}
+ else {
+ assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == POP_JUMP_FORWARD_IF_FALSE);
+ JUMPBY(1 + oparg);
+ }
+ NOTRACE_DISPATCH();
}
TARGET(IS_OP) {
@@ -3779,8 +3804,6 @@ handle_eval_breaker:
SET_TOP(b);
Py_DECREF(left);
Py_DECREF(right);
- PREDICT(POP_JUMP_IF_FALSE);
- PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
}
@@ -3796,8 +3819,6 @@ handle_eval_breaker:
PyObject *b = (res^oparg) ? Py_True : Py_False;
Py_INCREF(b);
PUSH(b);
- PREDICT(POP_JUMP_IF_FALSE);
- PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
}
@@ -3915,26 +3936,25 @@ handle_eval_breaker:
JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK);
}
- TARGET(POP_JUMP_IF_FALSE) {
- PREDICTED(POP_JUMP_IF_FALSE);
+ TARGET(POP_JUMP_BACKWARD_IF_FALSE) {
+ PREDICTED(POP_JUMP_BACKWARD_IF_FALSE);
PyObject *cond = POP();
- int err;
if (Py_IsTrue(cond)) {
Py_DECREF(cond);
DISPATCH();
}
if (Py_IsFalse(cond)) {
Py_DECREF(cond);
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
}
- err = PyObject_IsTrue(cond);
+ int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
if (err > 0)
;
else if (err == 0) {
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
}
else
@@ -3942,24 +3962,46 @@ handle_eval_breaker:
DISPATCH();
}
- TARGET(POP_JUMP_IF_TRUE) {
- PREDICTED(POP_JUMP_IF_TRUE);
+ TARGET(POP_JUMP_FORWARD_IF_FALSE) {
+ PREDICTED(POP_JUMP_FORWARD_IF_FALSE);
+ PyObject *cond = POP();
+ if (Py_IsTrue(cond)) {
+ Py_DECREF(cond);
+ }
+ else if (Py_IsFalse(cond)) {
+ Py_DECREF(cond);
+ JUMPBY(oparg);
+ }
+ else {
+ int err = PyObject_IsTrue(cond);
+ Py_DECREF(cond);
+ if (err > 0)
+ ;
+ else if (err == 0) {
+ JUMPBY(oparg);
+ }
+ else
+ goto error;
+ }
+ DISPATCH();
+ }
+
+ TARGET(POP_JUMP_BACKWARD_IF_TRUE) {
PyObject *cond = POP();
- int err;
if (Py_IsFalse(cond)) {
Py_DECREF(cond);
DISPATCH();
}
if (Py_IsTrue(cond)) {
Py_DECREF(cond);
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
}
- err = PyObject_IsTrue(cond);
+ int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
if (err > 0) {
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
}
else if (err == 0)
@@ -3969,11 +4011,34 @@ handle_eval_breaker:
DISPATCH();
}
- TARGET(POP_JUMP_IF_NOT_NONE) {
+ TARGET(POP_JUMP_FORWARD_IF_TRUE) {
+ PyObject *cond = POP();
+ if (Py_IsFalse(cond)) {
+ Py_DECREF(cond);
+ }
+ else if (Py_IsTrue(cond)) {
+ Py_DECREF(cond);
+ JUMPBY(oparg);
+ }
+ else {
+ int err = PyObject_IsTrue(cond);
+ Py_DECREF(cond);
+ if (err > 0) {
+ JUMPBY(oparg);
+ }
+ else if (err == 0)
+ ;
+ else
+ goto error;
+ }
+ DISPATCH();
+ }
+
+ TARGET(POP_JUMP_BACKWARD_IF_NOT_NONE) {
PyObject *value = POP();
if (!Py_IsNone(value)) {
Py_DECREF(value);
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
}
@@ -3981,11 +4046,20 @@ handle_eval_breaker:
DISPATCH();
}
- TARGET(POP_JUMP_IF_NONE) {
+ TARGET(POP_JUMP_FORWARD_IF_NOT_NONE) {
+ PyObject *value = POP();
+ if (!Py_IsNone(value)) {
+ JUMPBY(oparg);
+ }
+ Py_DECREF(value);
+ DISPATCH();
+ }
+
+ TARGET(POP_JUMP_BACKWARD_IF_NONE) {
PyObject *value = POP();
if (Py_IsNone(value)) {
Py_DECREF(value);
- JUMPTO(oparg);
+ JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
}
@@ -3993,6 +4067,15 @@ handle_eval_breaker:
DISPATCH();
}
+ TARGET(POP_JUMP_FORWARD_IF_NONE) {
+ PyObject *value = POP();
+ if (Py_IsNone(value)) {
+ JUMPBY(oparg);
+ }
+ Py_DECREF(value);
+ DISPATCH();
+ }
+
TARGET(JUMP_IF_FALSE_OR_POP) {
PyObject *cond = TOP();
int err;
@@ -4108,7 +4191,8 @@ handle_eval_breaker:
PyObject *res = match ? Py_True : Py_False;
Py_INCREF(res);
PUSH(res);
- PREDICT(POP_JUMP_IF_FALSE);
+ PREDICT(POP_JUMP_FORWARD_IF_FALSE);
+ PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
DISPATCH();
}
@@ -4118,7 +4202,8 @@ handle_eval_breaker:
PyObject *res = match ? Py_True : Py_False;
Py_INCREF(res);
PUSH(res);
- PREDICT(POP_JUMP_IF_FALSE);
+ PREDICT(POP_JUMP_FORWARD_IF_FALSE);
+ PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
DISPATCH();
}
diff --git a/Python/compile.c b/Python/compile.c
index f04ba9e..38cf5f3 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -78,8 +78,12 @@
#define POP_BLOCK -4
#define JUMP -5
#define JUMP_NO_INTERRUPT -6
+#define POP_JUMP_IF_FALSE -7
+#define POP_JUMP_IF_TRUE -8
+#define POP_JUMP_IF_NONE -9
+#define POP_JUMP_IF_NOT_NONE -10
-#define MIN_VIRTUAL_OPCODE -6
+#define MIN_VIRTUAL_OPCODE -10
#define MAX_ALLOWED_OPCODE 254
#define IS_WITHIN_OPCODE_RANGE(opcode) \
@@ -87,11 +91,36 @@
#define IS_VIRTUAL_OPCODE(opcode) ((opcode) < 0)
+#define IS_VIRTUAL_JUMP_OPCODE(opcode) \
+ ((opcode) == JUMP || \
+ (opcode) == JUMP_NO_INTERRUPT || \
+ (opcode) == POP_JUMP_IF_NONE || \
+ (opcode) == POP_JUMP_IF_NOT_NONE || \
+ (opcode) == POP_JUMP_IF_FALSE || \
+ (opcode) == POP_JUMP_IF_TRUE)
+
/* opcodes which are not emitted in codegen stage, only by the assembler */
#define IS_ASSEMBLER_OPCODE(opcode) \
((opcode) == JUMP_FORWARD || \
(opcode) == JUMP_BACKWARD || \
- (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
+ (opcode) == JUMP_BACKWARD_NO_INTERRUPT || \
+ (opcode) == POP_JUMP_FORWARD_IF_NONE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_NONE || \
+ (opcode) == POP_JUMP_FORWARD_IF_NOT_NONE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \
+ (opcode) == POP_JUMP_FORWARD_IF_TRUE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \
+ (opcode) == POP_JUMP_FORWARD_IF_FALSE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_FALSE)
+
+
+#define IS_BACKWARDS_JUMP_OPCODE(opcode) \
+ ((opcode) == JUMP_BACKWARD || \
+ (opcode) == JUMP_BACKWARD_NO_INTERRUPT || \
+ (opcode) == POP_JUMP_BACKWARD_IF_NONE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \
+ (opcode) == POP_JUMP_BACKWARD_IF_FALSE)
#define IS_TOP_LEVEL_AWAIT(c) ( \
@@ -156,7 +185,7 @@ is_block_push(struct instr *instr)
static inline int
is_jump(struct instr *i)
{
- return i->i_opcode == JUMP ||
+ return IS_VIRTUAL_JUMP_OPCODE(i->i_opcode) ||
is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
}
@@ -1027,10 +1056,18 @@ stack_effect(int opcode, int oparg, int jump)
case JUMP_IF_FALSE_OR_POP:
return jump ? 0 : -1;
- case POP_JUMP_IF_FALSE:
- case POP_JUMP_IF_TRUE:
+ case POP_JUMP_BACKWARD_IF_NONE:
+ case POP_JUMP_FORWARD_IF_NONE:
case POP_JUMP_IF_NONE:
+ case POP_JUMP_BACKWARD_IF_NOT_NONE:
+ case POP_JUMP_FORWARD_IF_NOT_NONE:
case POP_JUMP_IF_NOT_NONE:
+ case POP_JUMP_FORWARD_IF_FALSE:
+ case POP_JUMP_BACKWARD_IF_FALSE:
+ case POP_JUMP_IF_FALSE:
+ case POP_JUMP_FORWARD_IF_TRUE:
+ case POP_JUMP_BACKWARD_IF_TRUE:
+ case POP_JUMP_IF_TRUE:
return -1;
case LOAD_GLOBAL:
@@ -7609,14 +7646,33 @@ normalize_jumps(struct assembler *a)
}
struct instr *last = &b->b_instr[b->b_iused-1];
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
- if (last->i_opcode == JUMP) {
- bool is_forward = last->i_target->b_visited == 0;
- last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
- }
- if (last->i_opcode == JUMP_NO_INTERRUPT) {
+ if (is_jump(last)) {
bool is_forward = last->i_target->b_visited == 0;
- last->i_opcode = is_forward ?
- JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
+ switch(last->i_opcode) {
+ case JUMP:
+ last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
+ break;
+ case JUMP_NO_INTERRUPT:
+ last->i_opcode = is_forward ?
+ JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
+ break;
+ case POP_JUMP_IF_NOT_NONE:
+ last->i_opcode = is_forward ?
+ POP_JUMP_FORWARD_IF_NOT_NONE : POP_JUMP_BACKWARD_IF_NOT_NONE;
+ break;
+ case POP_JUMP_IF_NONE:
+ last->i_opcode = is_forward ?
+ POP_JUMP_FORWARD_IF_NONE : POP_JUMP_BACKWARD_IF_NONE;
+ break;
+ case POP_JUMP_IF_FALSE:
+ last->i_opcode = is_forward ?
+ POP_JUMP_FORWARD_IF_FALSE : POP_JUMP_BACKWARD_IF_FALSE;
+ break;
+ case POP_JUMP_IF_TRUE:
+ last->i_opcode = is_forward ?
+ POP_JUMP_FORWARD_IF_TRUE : POP_JUMP_BACKWARD_IF_TRUE;
+ break;
+ }
}
}
}
@@ -7652,16 +7708,17 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
instr->i_oparg = instr->i_target->b_offset;
if (is_relative_jump(instr)) {
if (instr->i_oparg < bsize) {
- assert(instr->i_opcode == JUMP_BACKWARD ||
- instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT);
+ assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
instr->i_oparg = bsize - instr->i_oparg;
}
else {
- assert(instr->i_opcode != JUMP_BACKWARD);
- assert(instr->i_opcode != JUMP_BACKWARD_NO_INTERRUPT);
+ assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
instr->i_oparg -= bsize;
}
}
+ else {
+ assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
+ }
if (instr_size(instr) != isize) {
extended_arg_recompile = 1;
}
@@ -8644,7 +8701,7 @@ apply_static_swaps(basicblock *block, int i)
static bool
jump_thread(struct instr *inst, struct instr *target, int opcode)
{
- assert(!IS_VIRTUAL_OPCODE(opcode) || opcode == JUMP);
+ assert(!IS_VIRTUAL_OPCODE(opcode) || IS_VIRTUAL_JUMP_OPCODE(opcode));
assert(is_jump(inst));
assert(is_jump(target));
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 064aa06..5268c4f 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -113,8 +113,8 @@ static void *opcode_targets[256] = {
&&TARGET_JUMP_IF_FALSE_OR_POP,
&&TARGET_JUMP_IF_TRUE_OR_POP,
&&TARGET_PRECALL_NO_KW_STR_1,
- &&TARGET_POP_JUMP_IF_FALSE,
- &&TARGET_POP_JUMP_IF_TRUE,
+ &&TARGET_POP_JUMP_FORWARD_IF_FALSE,
+ &&TARGET_POP_JUMP_FORWARD_IF_TRUE,
&&TARGET_LOAD_GLOBAL,
&&TARGET_IS_OP,
&&TARGET_CONTAINS_OP,
@@ -127,8 +127,8 @@ static void *opcode_targets[256] = {
&&TARGET_STORE_FAST,
&&TARGET_DELETE_FAST,
&&TARGET_PRECALL_NO_KW_TYPE_1,
- &&TARGET_POP_JUMP_IF_NOT_NONE,
- &&TARGET_POP_JUMP_IF_NONE,
+ &&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE,
+ &&TARGET_POP_JUMP_FORWARD_IF_NONE,
&&TARGET_RAISE_VARARGS,
&&TARGET_GET_AWAITABLE,
&&TARGET_MAKE_FUNCTION,
@@ -172,6 +172,10 @@ static void *opcode_targets[256] = {
&&TARGET_UNPACK_SEQUENCE_ADAPTIVE,
&&TARGET_CALL,
&&TARGET_KW_NAMES,
+ &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE,
+ &&TARGET_POP_JUMP_BACKWARD_IF_NONE,
+ &&TARGET_POP_JUMP_BACKWARD_IF_FALSE,
+ &&TARGET_POP_JUMP_BACKWARD_IF_TRUE,
&&TARGET_UNPACK_SEQUENCE_LIST,
&&TARGET_UNPACK_SEQUENCE_TUPLE,
&&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
@@ -250,9 +254,5 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_DO_TRACING
};
diff --git a/Python/specialize.c b/Python/specialize.c
index 36b0502..3a8b768 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1883,7 +1883,10 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
_PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]);
- if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) {
+ if (next_opcode != POP_JUMP_FORWARD_IF_FALSE &&
+ next_opcode != POP_JUMP_BACKWARD_IF_FALSE &&
+ next_opcode != POP_JUMP_FORWARD_IF_TRUE &&
+ next_opcode != POP_JUMP_BACKWARD_IF_TRUE) {
// Can't ever combine, so don't don't bother being adaptive (unless
// we're collecting stats, where it's more important to get accurate hit
// counts for the unadaptive version and each of the different failure
@@ -1901,9 +1904,14 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
}
assert(oparg <= Py_GE);
int when_to_jump_mask = compare_masks[oparg];
- if (next_opcode == POP_JUMP_IF_FALSE) {
+ if (next_opcode == POP_JUMP_FORWARD_IF_FALSE ||
+ next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask;
}
+ if (next_opcode == POP_JUMP_BACKWARD_IF_TRUE ||
+ next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
+ when_to_jump_mask <<= 3;
+ }
if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
goto failure;
@@ -1931,7 +1939,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
}
else {
_Py_SET_OPCODE(*instr, COMPARE_OP_STR_JUMP);
- cache->mask = (when_to_jump_mask & 2) == 0;
+ cache->mask = when_to_jump_mask;
goto success;
}
}