mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +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
|
@ -1947,15 +1947,13 @@ dummy_func(
|
|||
|
||||
op(_CHECK_ATTR_WITH_HINT, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(dict == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) {
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
|
@ -2072,14 +2070,15 @@ dummy_func(
|
|||
op(_GUARD_DORV_NO_DICT, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict);
|
||||
DEOPT_IF(_PyObject_GetManagedDict(owner));
|
||||
DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) {
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
assert(_PyObject_GetManagedDict(owner) == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
|
@ -2088,6 +2087,7 @@ dummy_func(
|
|||
else {
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
|
||||
Py_DECREF(owner);
|
||||
}
|
||||
|
||||
|
@ -2102,8 +2102,7 @@ dummy_func(
|
|||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(dict == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
|
|
10
Python/executor_cases.c.h
generated
10
Python/executor_cases.c.h
generated
|
@ -1998,8 +1998,7 @@
|
|||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
if (dict == NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
|
@ -2015,8 +2014,7 @@
|
|||
oparg = CURRENT_OPARG();
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t hint = (uint16_t)CURRENT_OPERAND();
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
if (hint >= (size_t)dict->ma_keys->dk_nentries) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
|
@ -2159,7 +2157,7 @@
|
|||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
if (_PyObject_ManagedDictPointer(owner)->dict) {
|
||||
if (_PyObject_GetManagedDict(owner)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
|
@ -2177,7 +2175,7 @@
|
|||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND();
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
assert(_PyObject_GetManagedDict(owner) == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
|
|
13
Python/generated_cases.c.h
generated
13
Python/generated_cases.c.h
generated
|
@ -4017,16 +4017,14 @@
|
|||
// _CHECK_ATTR_WITH_HINT
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(dict == NULL, LOAD_ATTR);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
}
|
||||
// _LOAD_ATTR_WITH_HINT
|
||||
{
|
||||
uint16_t hint = read_u16(&this_instr[4].cache);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
|
@ -5309,7 +5307,7 @@
|
|||
{
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict, STORE_ATTR);
|
||||
DEOPT_IF(_PyObject_GetManagedDict(owner), STORE_ATTR);
|
||||
DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0, STORE_ATTR);
|
||||
}
|
||||
// _STORE_ATTR_INSTANCE_VALUE
|
||||
|
@ -5317,7 +5315,7 @@
|
|||
{
|
||||
uint16_t index = read_u16(&this_instr[4].cache);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
assert(_PyObject_GetManagedDict(owner) == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
|
@ -5380,8 +5378,7 @@
|
|||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
DEOPT_IF(dict == NULL, STORE_ATTR);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
|
|
|
@ -852,8 +852,7 @@ specialize_dict_access(
|
|||
instr->op.code = values_op;
|
||||
}
|
||||
else {
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner);
|
||||
if (dict == NULL || !PyDict_CheckExact(dict)) {
|
||||
SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue