Skip to content

Commit ae73cc0

Browse files
yoneymeta-codesync[bot]
authored andcommitted
Use atomic loads for vectorcall checks in 3.14 interpreter
Summary: In free-threaded builds, the JIT can modify a function's vectorcall field concurrently with the interpreter reading it. Wrap `vectorcall == _PyFunction_Vectorcall` checks with `FT_ATOMIC_LOAD_PTR_RELAXED`. ThreadSanitizer: data race fbcode/cinderx/Interpreter/3.14/Includes/generated_cases.c.h:1577 in Ci_EvalFrame ================== ```` Reviewed By: DinoV Differential Revision: D100068060 fbshipit-source-id: e9a05bd28314122a360a500213a26fee18da0b9b
1 parent f7d3f3f commit ae73cc0

2 files changed

Lines changed: 27 additions & 9 deletions

File tree

cinderx/Interpreter/3.14/Includes/generated_cases.c.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,9 @@
15741574
}
15751575
if (Py_TYPE(callable_o) == &PyFunction_Type &&
15761576
!IS_PEP523_HOOKED(tstate) &&
1577-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
1577+
FT_ATOMIC_LOAD_PTR_RELAXED(
1578+
((PyFunctionObject *)callable_o)->vectorcall) ==
1579+
_PyFunction_Vectorcall)
15781580
{
15791581
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
15801582
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
@@ -2629,7 +2631,9 @@
26292631
else {
26302632
if (Py_TYPE(func) == &PyFunction_Type &&
26312633
!IS_PEP523_HOOKED(tstate) &&
2632-
((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
2634+
FT_ATOMIC_LOAD_PTR_RELAXED(
2635+
((PyFunctionObject *)func)->vectorcall) ==
2636+
_PyFunction_Vectorcall) {
26332637
PyObject *callargs = PyStackRef_AsPyObjectSteal(callargs_st);
26342638
assert(PyTuple_CheckExact(callargs));
26352639
PyObject *kwargs = PyStackRef_IsNull(kwargs_st) ? NULL : PyStackRef_AsPyObjectSteal(kwargs_st);
@@ -2910,7 +2914,9 @@
29102914
int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o);
29112915
if (Py_TYPE(callable_o) == &PyFunction_Type &&
29122916
!IS_PEP523_HOOKED(tstate) &&
2913-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
2917+
FT_ATOMIC_LOAD_PTR_RELAXED(
2918+
((PyFunctionObject *)callable_o)->vectorcall) ==
2919+
_PyFunction_Vectorcall)
29142920
{
29152921
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
29162922
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
@@ -7973,7 +7979,9 @@
79737979
}
79747980
if (Py_TYPE(callable_o) == &PyFunction_Type &&
79757981
!IS_PEP523_HOOKED(tstate) &&
7976-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
7982+
FT_ATOMIC_LOAD_PTR_RELAXED(
7983+
((PyFunctionObject *)callable_o)->vectorcall) ==
7984+
_PyFunction_Vectorcall)
79777985
{
79787986
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
79797987
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
@@ -8189,7 +8197,9 @@
81898197
else {
81908198
if (Py_TYPE(func) == &PyFunction_Type &&
81918199
!IS_PEP523_HOOKED(tstate) &&
8192-
((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
8200+
FT_ATOMIC_LOAD_PTR_RELAXED(
8201+
((PyFunctionObject *)func)->vectorcall) ==
8202+
_PyFunction_Vectorcall) {
81938203
PyObject *callargs = PyStackRef_AsPyObjectSteal(callargs_st);
81948204
assert(PyTuple_CheckExact(callargs));
81958205
PyObject *kwargs = PyStackRef_IsNull(kwargs_st) ? NULL : PyStackRef_AsPyObjectSteal(kwargs_st);
@@ -8342,7 +8352,9 @@
83428352
int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o);
83438353
if (Py_TYPE(callable_o) == &PyFunction_Type &&
83448354
!IS_PEP523_HOOKED(tstate) &&
8345-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
8355+
FT_ATOMIC_LOAD_PTR_RELAXED(
8356+
((PyFunctionObject *)callable_o)->vectorcall) ==
8357+
_PyFunction_Vectorcall)
83468358
{
83478359
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
83488360
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));

cinderx/Interpreter/3.14/cinder-bytecodes.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ dummy_func(
187187
// Check if the call can be inlined or not
188188
if (Py_TYPE(callable_o) == &PyFunction_Type &&
189189
!IS_PEP523_HOOKED(tstate) &&
190-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
190+
FT_ATOMIC_LOAD_PTR_RELAXED(
191+
((PyFunctionObject *)callable_o)->vectorcall) ==
192+
_PyFunction_Vectorcall)
191193
{
192194
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
193195
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
@@ -281,7 +283,9 @@ dummy_func(
281283
// Check if the call can be inlined or not
282284
if (Py_TYPE(callable_o) == &PyFunction_Type &&
283285
!IS_PEP523_HOOKED(tstate) &&
284-
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
286+
FT_ATOMIC_LOAD_PTR_RELAXED(
287+
((PyFunctionObject *)callable_o)->vectorcall) ==
288+
_PyFunction_Vectorcall)
285289
{
286290
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
287291
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
@@ -380,7 +384,9 @@ dummy_func(
380384
else {
381385
if (Py_TYPE(func) == &PyFunction_Type &&
382386
!IS_PEP523_HOOKED(tstate) &&
383-
((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
387+
FT_ATOMIC_LOAD_PTR_RELAXED(
388+
((PyFunctionObject *)func)->vectorcall) ==
389+
_PyFunction_Vectorcall) {
384390
PyObject *callargs = PyStackRef_AsPyObjectSteal(callargs_st);
385391
assert(PyTuple_CheckExact(callargs));
386392
PyObject *kwargs = PyStackRef_IsNull(kwargs_st) ? NULL : PyStackRef_AsPyObjectSteal(kwargs_st);

0 commit comments

Comments
 (0)