Skip to content

Commit 5c930a2

Browse files
authored
gh-115999: Enable free-threaded specialization of LOAD_CONST (#129365)
Enable free-threaded specialization of LOAD_CONST.
1 parent 7893908 commit 5c930a2

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

Lib/test/test_opcache.py

+14
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,20 @@ def compare_op_str():
17731773
self.assert_specialized(compare_op_str, "COMPARE_OP_STR")
17741774
self.assert_no_opcode(compare_op_str, "COMPARE_OP")
17751775

1776+
@cpython_only
1777+
@requires_specialization_ft
1778+
def test_load_const(self):
1779+
def load_const():
1780+
def unused(): pass
1781+
# Currently, the empty tuple is immortal, and the otherwise
1782+
# unused nested function's code object is mortal. This test will
1783+
# have to use different values if either of that changes.
1784+
return ()
1785+
1786+
load_const()
1787+
self.assert_specialized(load_const, "LOAD_CONST_IMMORTAL")
1788+
self.assert_specialized(load_const, "LOAD_CONST_MORTAL")
1789+
self.assert_no_opcode(load_const, "LOAD_CONST")
17761790

17771791
if __name__ == "__main__":
17781792
unittest.main()

Python/bytecodes.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,20 @@ dummy_func(
294294
* marshalling can intern strings and make them immortal. */
295295
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
296296
value = PyStackRef_FromPyObjectNew(obj);
297-
#if ENABLE_SPECIALIZATION
297+
#if ENABLE_SPECIALIZATION_FT
298+
#ifdef Py_GIL_DISABLED
299+
uint8_t expected = LOAD_CONST;
300+
if (!_Py_atomic_compare_exchange_uint8(
301+
&this_instr->op.code, &expected,
302+
_Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL)) {
303+
// We might lose a race with instrumentation, which we don't care about.
304+
assert(expected >= MIN_INSTRUMENTED_OPCODE);
305+
}
306+
#else
298307
if (this_instr->op.code == LOAD_CONST) {
299308
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
300309
}
310+
#endif
301311
#endif
302312
}
303313

@@ -2558,7 +2568,7 @@ dummy_func(
25582568
}
25592569
OPCODE_DEFERRED_INC(COMPARE_OP);
25602570
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
2561-
#endif /* ENABLE_SPECIALIZATION */
2571+
#endif /* ENABLE_SPECIALIZATION_FT */
25622572
}
25632573

25642574
op(_COMPARE_OP, (left, right -- res)) {

Python/generated_cases.c.h

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

Tools/cases_generator/analyzer.py

+1
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
634634
"_Py_STR",
635635
"_Py_TryIncrefCompare",
636636
"_Py_TryIncrefCompareStackRef",
637+
"_Py_atomic_compare_exchange_uint8",
637638
"_Py_atomic_load_ptr_acquire",
638639
"_Py_atomic_load_uintptr_relaxed",
639640
"_Py_set_eval_breaker_bit",

0 commit comments

Comments
 (0)