gh-124218: Use per-thread reference counting for globals and builtins (#125713)

Use per-thread refcounting for the reference from function objects to
the globals and builtins dictionaries.
This commit is contained in:
Sam Gross 2024-10-21 12:51:29 -04:00 committed by GitHub
parent d880c83ff7
commit 9b0bfba2a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 115 additions and 11 deletions

View file

@ -3,6 +3,7 @@
#include "Python.h"
#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals()
#include "pycore_dict.h" // _Py_INCREF_DICT()
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
@ -112,8 +113,15 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr)
Py_XDECREF(module);
return NULL;
}
op->func_globals = Py_NewRef(constr->fc_globals);
op->func_builtins = Py_NewRef(constr->fc_builtins);
_Py_INCREF_DICT(constr->fc_globals);
op->func_globals = constr->fc_globals;
if (PyDict_Check(constr->fc_builtins)) {
_Py_INCREF_DICT(constr->fc_builtins);
}
else {
Py_INCREF(constr->fc_builtins);
}
op->func_builtins = constr->fc_builtins;
op->func_name = Py_NewRef(constr->fc_name);
op->func_qualname = Py_NewRef(constr->fc_qualname);
_Py_INCREF_CODE((PyCodeObject *)constr->fc_code);
@ -143,7 +151,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
{
assert(globals != NULL);
assert(PyDict_Check(globals));
Py_INCREF(globals);
_Py_INCREF_DICT(globals);
PyThreadState *tstate = _PyThreadState_GET();
@ -184,7 +192,12 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
if (builtins == NULL) {
goto error;
}
Py_INCREF(builtins);
if (PyDict_Check(builtins)) {
_Py_INCREF_DICT(builtins);
}
else {
Py_INCREF(builtins);
}
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
if (op == NULL) {
@ -1057,8 +1070,21 @@ func_clear(PyObject *self)
{
PyFunctionObject *op = _PyFunction_CAST(self);
func_clear_version(_PyInterpreterState_GET(), op);
Py_CLEAR(op->func_globals);
Py_CLEAR(op->func_builtins);
PyObject *globals = op->func_globals;
op->func_globals = NULL;
if (globals != NULL) {
_Py_DECREF_DICT(globals);
}
PyObject *builtins = op->func_builtins;
op->func_builtins = NULL;
if (builtins != NULL) {
if (PyDict_Check(builtins)) {
_Py_DECREF_DICT(builtins);
}
else {
Py_DECREF(builtins);
}
}
Py_CLEAR(op->func_module);
Py_CLEAR(op->func_defaults);
Py_CLEAR(op->func_kwdefaults);