gh-127271: Replace use of PyCell_GET/SET (gh-127272)
* Replace uses of `PyCell_GET` and `PyCell_SET`. These macros are not safe to use in the free-threaded build. Use `PyCell_GetRef()` and `PyCell_SetTakeRef()` instead. * Since `PyCell_GetRef()` returns a strong rather than borrowed ref, some code restructuring was required, e.g. `frame_get_var()` returns a strong ref now. * Add critical sections to `PyCell_GET` and `PyCell_SET`. * Move critical_section.h earlier in the Python.h file. * Add `PyCell_GET` to the free-threading howto table of APIs that return borrowed refs. * Add additional unit tests for free-threading.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "pycore_moduleobject.h" // _PyModule_GetDict()
|
||||
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
|
||||
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
||||
#include "pycore_cell.h" // PyCell_GetRef() PyCell_SetTakeRef()
|
||||
#include "pycore_opcode_metadata.h" // _PyOpcode_Deopt, _PyOpcode_Caches
|
||||
|
||||
|
||||
@@ -187,11 +188,8 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
|
||||
}
|
||||
}
|
||||
if (cell != NULL) {
|
||||
PyObject *oldvalue_o = PyCell_GET(cell);
|
||||
if (value != oldvalue_o) {
|
||||
PyCell_SET(cell, Py_XNewRef(value));
|
||||
Py_XDECREF(oldvalue_o);
|
||||
}
|
||||
Py_XINCREF(value);
|
||||
PyCell_SetTakeRef((PyCellObject *)cell, value);
|
||||
} else if (value != PyStackRef_AsPyObjectBorrow(oldvalue)) {
|
||||
PyStackRef_XCLOSE(fast[i]);
|
||||
fast[i] = PyStackRef_FromPyObjectNew(value);
|
||||
@@ -1987,19 +1985,25 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
|
||||
if (kind & CO_FAST_FREE) {
|
||||
// The cell was set by COPY_FREE_VARS.
|
||||
assert(value != NULL && PyCell_Check(value));
|
||||
value = PyCell_GET(value);
|
||||
value = PyCell_GetRef((PyCellObject *)value);
|
||||
}
|
||||
else if (kind & CO_FAST_CELL) {
|
||||
if (value != NULL) {
|
||||
if (PyCell_Check(value)) {
|
||||
assert(!_PyFrame_IsIncomplete(frame));
|
||||
value = PyCell_GET(value);
|
||||
value = PyCell_GetRef((PyCellObject *)value);
|
||||
}
|
||||
else {
|
||||
// (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
|
||||
// with the initial value set when the frame was created...
|
||||
// (unlikely) ...or it was set via the f_locals proxy.
|
||||
Py_INCREF(value);
|
||||
}
|
||||
// (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
|
||||
// with the initial value set when the frame was created...
|
||||
// (unlikely) ...or it was set via the f_locals proxy.
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_XINCREF(value);
|
||||
}
|
||||
}
|
||||
*pvalue = value;
|
||||
return 1;
|
||||
@@ -2076,14 +2080,14 @@ PyFrame_GetVar(PyFrameObject *frame_obj, PyObject *name)
|
||||
continue;
|
||||
}
|
||||
|
||||
PyObject *value; // borrowed reference
|
||||
PyObject *value;
|
||||
if (!frame_get_var(frame, co, i, &value)) {
|
||||
break;
|
||||
}
|
||||
if (value == NULL) {
|
||||
break;
|
||||
}
|
||||
return Py_NewRef(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
|
||||
|
||||
Reference in New Issue
Block a user