gh-115999: Enable free-threaded specialization of LOAD_CONST (#129365)
Enable free-threaded specialization of LOAD_CONST.
This commit is contained in:
parent
789390872b
commit
5c930a26fb
@ -1773,6 +1773,20 @@ class TestSpecializer(TestBase):
|
|||||||
self.assert_specialized(compare_op_str, "COMPARE_OP_STR")
|
self.assert_specialized(compare_op_str, "COMPARE_OP_STR")
|
||||||
self.assert_no_opcode(compare_op_str, "COMPARE_OP")
|
self.assert_no_opcode(compare_op_str, "COMPARE_OP")
|
||||||
|
|
||||||
|
@cpython_only
|
||||||
|
@requires_specialization_ft
|
||||||
|
def test_load_const(self):
|
||||||
|
def load_const():
|
||||||
|
def unused(): pass
|
||||||
|
# Currently, the empty tuple is immortal, and the otherwise
|
||||||
|
# unused nested function's code object is mortal. This test will
|
||||||
|
# have to use different values if either of that changes.
|
||||||
|
return ()
|
||||||
|
|
||||||
|
load_const()
|
||||||
|
self.assert_specialized(load_const, "LOAD_CONST_IMMORTAL")
|
||||||
|
self.assert_specialized(load_const, "LOAD_CONST_MORTAL")
|
||||||
|
self.assert_no_opcode(load_const, "LOAD_CONST")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -294,10 +294,20 @@ dummy_func(
|
|||||||
* marshalling can intern strings and make them immortal. */
|
* marshalling can intern strings and make them immortal. */
|
||||||
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
|
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
|
||||||
value = PyStackRef_FromPyObjectNew(obj);
|
value = PyStackRef_FromPyObjectNew(obj);
|
||||||
#if ENABLE_SPECIALIZATION
|
#if ENABLE_SPECIALIZATION_FT
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
uint8_t expected = LOAD_CONST;
|
||||||
|
if (!_Py_atomic_compare_exchange_uint8(
|
||||||
|
&this_instr->op.code, &expected,
|
||||||
|
_Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL)) {
|
||||||
|
// We might lose a race with instrumentation, which we don't care about.
|
||||||
|
assert(expected >= MIN_INSTRUMENTED_OPCODE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (this_instr->op.code == LOAD_CONST) {
|
if (this_instr->op.code == LOAD_CONST) {
|
||||||
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
|
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2558,7 +2568,7 @@ dummy_func(
|
|||||||
}
|
}
|
||||||
OPCODE_DEFERRED_INC(COMPARE_OP);
|
OPCODE_DEFERRED_INC(COMPARE_OP);
|
||||||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_COMPARE_OP, (left, right -- res)) {
|
op(_COMPARE_OP, (left, right -- res)) {
|
||||||
|
14
Python/generated_cases.c.h
generated
14
Python/generated_cases.c.h
generated
@ -3318,7 +3318,7 @@
|
|||||||
}
|
}
|
||||||
OPCODE_DEFERRED_INC(COMPARE_OP);
|
OPCODE_DEFERRED_INC(COMPARE_OP);
|
||||||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||||
}
|
}
|
||||||
// _COMPARE_OP
|
// _COMPARE_OP
|
||||||
{
|
{
|
||||||
@ -6035,11 +6035,21 @@
|
|||||||
* marshalling can intern strings and make them immortal. */
|
* marshalling can intern strings and make them immortal. */
|
||||||
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
|
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
|
||||||
value = PyStackRef_FromPyObjectNew(obj);
|
value = PyStackRef_FromPyObjectNew(obj);
|
||||||
#if ENABLE_SPECIALIZATION
|
#if ENABLE_SPECIALIZATION_FT
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
uint8_t expected = LOAD_CONST;
|
||||||
|
if (!_Py_atomic_compare_exchange_uint8(
|
||||||
|
&this_instr->op.code, &expected,
|
||||||
|
_Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL)) {
|
||||||
|
// We might lose a race with instrumentation, which we don't care about.
|
||||||
|
assert(expected >= MIN_INSTRUMENTED_OPCODE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (this_instr->op.code == LOAD_CONST) {
|
if (this_instr->op.code == LOAD_CONST) {
|
||||||
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
|
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
stack_pointer[0] = value;
|
stack_pointer[0] = value;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
@ -634,6 +634,7 @@ NON_ESCAPING_FUNCTIONS = (
|
|||||||
"_Py_STR",
|
"_Py_STR",
|
||||||
"_Py_TryIncrefCompare",
|
"_Py_TryIncrefCompare",
|
||||||
"_Py_TryIncrefCompareStackRef",
|
"_Py_TryIncrefCompareStackRef",
|
||||||
|
"_Py_atomic_compare_exchange_uint8",
|
||||||
"_Py_atomic_load_ptr_acquire",
|
"_Py_atomic_load_ptr_acquire",
|
||||||
"_Py_atomic_load_uintptr_relaxed",
|
"_Py_atomic_load_uintptr_relaxed",
|
||||||
"_Py_set_eval_breaker_bit",
|
"_Py_set_eval_breaker_bit",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user