mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-112075: Make instance attributes stored in inline "dict" thread safe (#114742)
Make instance attributes stored in inline "dict" thread safe on free-threaded builds
This commit is contained in:
parent
1446024124
commit
8b541c017e
13 changed files with 419 additions and 142 deletions
|
@ -6,6 +6,7 @@
|
|||
#include "pycore_call.h" // _PyObject_CallNoArgs()
|
||||
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
|
||||
#include "pycore_context.h" // _PyContextTokenMissing_Type
|
||||
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
|
||||
#include "pycore_descrobject.h" // _PyMethodWrapper_Type
|
||||
#include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes()
|
||||
#include "pycore_floatobject.h" // _PyFloat_DebugMallocStats()
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic
|
||||
#include "pycore_unionobject.h" // _PyUnion_Type
|
||||
|
||||
|
||||
#ifdef Py_LIMITED_API
|
||||
// Prevent recursive call _Py_IncRef() <=> Py_INCREF()
|
||||
# error "Py_LIMITED_API macro must not be defined"
|
||||
|
@ -1403,16 +1405,15 @@ _PyObject_GetDictPtr(PyObject *obj)
|
|||
if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
|
||||
return _PyObject_ComputedDictPointer(obj);
|
||||
}
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj);
|
||||
if (managed_dict->dict == NULL && Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
|
||||
PyDictObject *dict = (PyDictObject *)_PyObject_MakeDictFromInstanceAttributes(obj);
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(obj);
|
||||
if (dict == NULL && Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
|
||||
dict = _PyObject_MaterializeManagedDict(obj);
|
||||
if (dict == NULL) {
|
||||
PyErr_Clear();
|
||||
return NULL;
|
||||
}
|
||||
managed_dict->dict = dict;
|
||||
}
|
||||
return (PyObject **)&managed_dict->dict;
|
||||
return (PyObject **)&_PyObject_ManagedDictPointer(obj)->dict;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
@ -1480,10 +1481,9 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
|
|||
}
|
||||
}
|
||||
}
|
||||
PyObject *dict;
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) {
|
||||
PyDictValues *values = _PyObject_InlineValues(obj);
|
||||
PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name);
|
||||
PyObject *dict, *attr;
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) &&
|
||||
_PyObject_TryGetInstanceAttribute(obj, name, &attr)) {
|
||||
if (attr != NULL) {
|
||||
*method = attr;
|
||||
Py_XDECREF(descr);
|
||||
|
@ -1492,8 +1492,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
|
|||
dict = NULL;
|
||||
}
|
||||
else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
|
||||
PyManagedDictPointer* managed_dict = _PyObject_ManagedDictPointer(obj);
|
||||
dict = (PyObject *)managed_dict->dict;
|
||||
dict = (PyObject *)_PyObject_GetManagedDict(obj);
|
||||
}
|
||||
else {
|
||||
PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
|
||||
|
@ -1586,26 +1585,23 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
|
|||
}
|
||||
}
|
||||
if (dict == NULL) {
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) {
|
||||
PyDictValues *values = _PyObject_InlineValues(obj);
|
||||
if (PyUnicode_CheckExact(name)) {
|
||||
res = _PyObject_GetInstanceAttribute(obj, values, name);
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES)) {
|
||||
if (PyUnicode_CheckExact(name) &&
|
||||
_PyObject_TryGetInstanceAttribute(obj, name, &res)) {
|
||||
if (res != NULL) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dict = (PyObject *)_PyObject_MakeDictFromInstanceAttributes(obj);
|
||||
dict = (PyObject *)_PyObject_MaterializeManagedDict(obj);
|
||||
if (dict == NULL) {
|
||||
res = NULL;
|
||||
goto done;
|
||||
}
|
||||
_PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)dict;
|
||||
}
|
||||
}
|
||||
else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
|
||||
PyManagedDictPointer* managed_dict = _PyObject_ManagedDictPointer(obj);
|
||||
dict = (PyObject *)managed_dict->dict;
|
||||
dict = (PyObject *)_PyObject_GetManagedDict(obj);
|
||||
}
|
||||
else {
|
||||
PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
|
||||
|
@ -1700,12 +1696,13 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
|
|||
|
||||
if (dict == NULL) {
|
||||
PyObject **dictptr;
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) {
|
||||
res = _PyObject_StoreInstanceAttribute(
|
||||
obj, _PyObject_InlineValues(obj), name, value);
|
||||
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES)) {
|
||||
res = _PyObject_StoreInstanceAttribute(obj, name, value);
|
||||
goto error_check;
|
||||
}
|
||||
else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
|
||||
|
||||
if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj);
|
||||
dictptr = (PyObject **)&managed_dict->dict;
|
||||
}
|
||||
|
@ -1779,7 +1776,7 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
|
|||
PyObject **dictptr = _PyObject_GetDictPtr(obj);
|
||||
if (dictptr == NULL) {
|
||||
if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_INLINE_VALUES) &&
|
||||
_PyObject_ManagedDictPointer(obj)->dict == NULL
|
||||
_PyObject_GetManagedDict(obj) == NULL
|
||||
) {
|
||||
/* Was unable to convert to dict */
|
||||
PyErr_NoMemory();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue