summaryrefslogtreecommitdiffstats
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-10-24 16:44:38 (GMT)
committerGitHub <noreply@github.com>2024-10-24 16:44:38 (GMT)
commit3c4a7fa6178d852ccb73527aaa2d0a5e93022e89 (patch)
treee74c8d15c6dab8e3b58478aa5e0d9915477f83de /Objects/funcobject.c
parent5003ad5c5ea508f0dde1b374cd8bc6a481ad5c5d (diff)
downloadcpython-3c4a7fa6178d852ccb73527aaa2d0a5e93022e89.zip
cpython-3c4a7fa6178d852ccb73527aaa2d0a5e93022e89.tar.gz
cpython-3c4a7fa6178d852ccb73527aaa2d0a5e93022e89.tar.bz2
gh-124218: Avoid refcount contention on builtins module (GH-125847)
This replaces `_PyEval_BuiltinsFromGlobals` with `_PyDict_LoadBuiltinsFromGlobals`, which returns a new reference instead of a borrowed reference. Internally, the new function uses per-thread reference counting when possible to avoid contention on the refcount fields on the builtins module.
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c25
1 files changed, 3 insertions, 22 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 44fb4ac..e72a7d9 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -2,7 +2,6 @@
/* Function object implementation */
#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()
@@ -115,12 +114,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr)
}
_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);
- }
+ _Py_INCREF_BUILTINS(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);
@@ -153,8 +147,6 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
assert(PyDict_Check(globals));
_Py_INCREF_DICT(globals);
- PyThreadState *tstate = _PyThreadState_GET();
-
PyCodeObject *code_obj = (PyCodeObject *)code;
_Py_INCREF_CODE(code_obj);
@@ -188,16 +180,10 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
goto error;
}
- builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref
+ builtins = _PyDict_LoadBuiltinsFromGlobals(globals);
if (builtins == NULL) {
goto error;
}
- if (PyDict_Check(builtins)) {
- _Py_INCREF_DICT(builtins);
- }
- else {
- Py_INCREF(builtins);
- }
PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
if (op == NULL) {
@@ -1078,12 +1064,7 @@ func_clear(PyObject *self)
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_DECREF_BUILTINS(builtins);
}
Py_CLEAR(op->func_module);
Py_CLEAR(op->func_defaults);