Skip to content

Commit 8f93dd8

Browse files
Yhg1scorona10
andauthored
gh-115999: Add free-threaded specialization for COMPARE_OP (#126410)
Add free-threaded specialization for COMPARE_OP, and tests for COMPARE_OP specialization in general. Co-authored-by: Donghee Na <[email protected]>
1 parent a734c1e commit 8f93dd8

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

Lib/test/test_opcache.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,39 @@ def __getitem__(self, item):
15981598
self.assert_specialized(binary_subscr_getitems, "BINARY_SUBSCR_GETITEM")
15991599
self.assert_no_opcode(binary_subscr_getitems, "BINARY_SUBSCR")
16001600

1601+
@cpython_only
1602+
@requires_specialization_ft
1603+
def test_compare_op(self):
1604+
def compare_op_int():
1605+
for _ in range(100):
1606+
a, b = 1, 2
1607+
c = a == b
1608+
self.assertFalse(c)
1609+
1610+
compare_op_int()
1611+
self.assert_specialized(compare_op_int, "COMPARE_OP_INT")
1612+
self.assert_no_opcode(compare_op_int, "COMPARE_OP")
1613+
1614+
def compare_op_float():
1615+
for _ in range(100):
1616+
a, b = 1.0, 2.0
1617+
c = a == b
1618+
self.assertFalse(c)
1619+
1620+
compare_op_float()
1621+
self.assert_specialized(compare_op_float, "COMPARE_OP_FLOAT")
1622+
self.assert_no_opcode(compare_op_float, "COMPARE_OP")
1623+
1624+
def compare_op_str():
1625+
for _ in range(100):
1626+
a, b = "spam", "ham"
1627+
c = a == b
1628+
self.assertFalse(c)
1629+
1630+
compare_op_str()
1631+
self.assert_specialized(compare_op_str, "COMPARE_OP_STR")
1632+
self.assert_no_opcode(compare_op_str, "COMPARE_OP")
1633+
16011634

16021635
if __name__ == "__main__":
16031636
unittest.main()

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2464,7 +2464,7 @@ dummy_func(
24642464
};
24652465

24662466
specializing op(_SPECIALIZE_COMPARE_OP, (counter/1, left, right -- left, right)) {
2467-
#if ENABLE_SPECIALIZATION
2467+
#if ENABLE_SPECIALIZATION_FT
24682468
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
24692469
next_instr = this_instr;
24702470
_Py_Specialize_CompareOp(left, right, next_instr, oparg);

Python/generated_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,23 +2480,23 @@ _Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *i
24802480
{
24812481
PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
24822482
PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2483+
uint8_t specialized_op;
24832484

2484-
assert(ENABLE_SPECIALIZATION);
2485+
assert(ENABLE_SPECIALIZATION_FT);
24852486
assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
24862487
// All of these specializations compute boolean values, so they're all valid
24872488
// regardless of the fifth-lowest oparg bit.
2488-
_PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
24892489
if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
24902490
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
24912491
goto failure;
24922492
}
24932493
if (PyFloat_CheckExact(lhs)) {
2494-
instr->op.code = COMPARE_OP_FLOAT;
2494+
specialized_op = COMPARE_OP_FLOAT;
24952495
goto success;
24962496
}
24972497
if (PyLong_CheckExact(lhs)) {
24982498
if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2499-
instr->op.code = COMPARE_OP_INT;
2499+
specialized_op = COMPARE_OP_INT;
25002500
goto success;
25012501
}
25022502
else {
@@ -2511,19 +2511,16 @@ _Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *i
25112511
goto failure;
25122512
}
25132513
else {
2514-
instr->op.code = COMPARE_OP_STR;
2514+
specialized_op = COMPARE_OP_STR;
25152515
goto success;
25162516
}
25172517
}
25182518
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
25192519
failure:
2520-
STAT_INC(COMPARE_OP, failure);
2521-
instr->op.code = COMPARE_OP;
2522-
cache->counter = adaptive_counter_backoff(cache->counter);
2520+
unspecialize(instr);
25232521
return;
25242522
success:
2525-
STAT_INC(COMPARE_OP, success);
2526-
cache->counter = adaptive_counter_cooldown();
2523+
specialize(instr, specialized_op);
25272524
}
25282525

25292526
#ifdef Py_STATS

0 commit comments

Comments
 (0)