Skip to content

Commit 9076455

Browse files
authored
GH-90043: Handle NaNs in COMPARE_OP_FLOAT_JUMP (GH-100278)
1 parent d4052d8 commit 9076455

File tree

4 files changed

+23
-24
lines changed

4 files changed

+23
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Handle NaNs when specializing :opcode:`COMPARE_OP` for :class:`float`
2+
values.

Python/bytecodes.c

+5-7
Original file line numberDiff line numberDiff line change
@@ -2024,13 +2024,11 @@ dummy_func(
20242024
// Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
20252025
DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
20262026
DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
2027+
STAT_INC(COMPARE_OP, hit);
20272028
double dleft = PyFloat_AS_DOUBLE(left);
20282029
double dright = PyFloat_AS_DOUBLE(right);
2029-
// 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
2030-
int sign_ish = 2*(dleft > dright) + 2 - (dleft < dright);
2031-
DEOPT_IF(isnan(dleft), COMPARE_OP);
2032-
DEOPT_IF(isnan(dright), COMPARE_OP);
2033-
STAT_INC(COMPARE_OP, hit);
2030+
// 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask
2031+
int sign_ish = 1 << (2 * (dleft >= dright) + (dleft <= dright));
20342032
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
20352033
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
20362034
jump = sign_ish & when_to_jump_mask;
@@ -2057,8 +2055,8 @@ dummy_func(
20572055
assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1);
20582056
Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0];
20592057
Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0];
2060-
// 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
2061-
int sign_ish = 2*(ileft > iright) + 2 - (ileft < iright);
2058+
// 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask
2059+
int sign_ish = 1 << (2 * (ileft >= iright) + (ileft <= iright));
20622060
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
20632061
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
20642062
jump = sign_ish & when_to_jump_mask;

Python/generated_cases.c.h

+5-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

+11-10
Original file line numberDiff line numberDiff line change
@@ -1951,15 +1951,16 @@ compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
19511951

19521952

19531953
static int compare_masks[] = {
1954-
// 1-bit: jump if less than
1955-
// 2-bit: jump if equal
1954+
// 1-bit: jump if unordered
1955+
// 2-bit: jump if less
19561956
// 4-bit: jump if greater
1957-
[Py_LT] = 1 | 0 | 0,
1958-
[Py_LE] = 1 | 2 | 0,
1959-
[Py_EQ] = 0 | 2 | 0,
1960-
[Py_NE] = 1 | 0 | 4,
1961-
[Py_GT] = 0 | 0 | 4,
1962-
[Py_GE] = 0 | 2 | 4,
1957+
// 8-bit: jump if equal
1958+
[Py_LT] = 0 | 2 | 0 | 0,
1959+
[Py_LE] = 0 | 2 | 0 | 8,
1960+
[Py_EQ] = 0 | 0 | 0 | 8,
1961+
[Py_NE] = 1 | 2 | 4 | 0,
1962+
[Py_GT] = 0 | 0 | 4 | 0,
1963+
[Py_GE] = 0 | 0 | 4 | 8,
19631964
};
19641965

19651966
void
@@ -1980,7 +1981,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
19801981
assert(oparg <= Py_GE);
19811982
int when_to_jump_mask = compare_masks[oparg];
19821983
if (next_opcode == POP_JUMP_IF_FALSE) {
1983-
when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask;
1984+
when_to_jump_mask = (1 | 2 | 4 | 8) & ~when_to_jump_mask;
19841985
}
19851986
if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
19861987
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
@@ -2009,7 +2010,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
20092010
}
20102011
else {
20112012
_py_set_opcode(instr, COMPARE_OP_STR_JUMP);
2012-
cache->mask = (when_to_jump_mask & 2) == 0;
2013+
cache->mask = (when_to_jump_mask & 8) == 0;
20132014
goto success;
20142015
}
20152016
}

0 commit comments

Comments
 (0)