mirror of
https://github.com/python/cpython.git
synced 2026-06-28 11:50:50 +00:00
gh-152238: Revert gh-150490 and gh-152200. (gh-152232)
Revert commits:
gh-151593: Fix dead lock in PyDict insert_split_key() (#152200)
gh-150490: Raise PyType_Modified for insertion into split dictionary (#150489)
For gh-150489, it violates locking discipline and results in deadlocks,
gh-151593 is an example of it being hit in CI. The attempted fix
gh-152200 avoids the deadlock but introduces a data-race. The race
window is small but can be triggered with pure Python code.
This commit is contained in:
parent
5a549e82b8
commit
9626ef87f4
12 changed files with 1412 additions and 1308 deletions
|
|
@ -4270,6 +4270,13 @@ dummy_func(
|
|||
EXIT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid));
|
||||
}
|
||||
|
||||
op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) {
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version);
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
|
|
@ -4286,7 +4293,7 @@ dummy_func(
|
|||
_RECORD_TOS_TYPE +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
|
||||
unused/2 +
|
||||
_GUARD_KEYS_VERSION +
|
||||
_LOAD_ATTR_METHOD_WITH_VALUES;
|
||||
|
||||
op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
|
||||
|
|
@ -4320,7 +4327,7 @@ dummy_func(
|
|||
_RECORD_TOS_TYPE +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
|
||||
unused/2 +
|
||||
_GUARD_KEYS_VERSION +
|
||||
_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
|
||||
|
||||
op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
|
||||
|
|
|
|||
97
Python/executor_cases.c.h
generated
97
Python/executor_cases.c.h
generated
|
|
@ -16508,6 +16508,103 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION_r01: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
_PyStackRef owner;
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION_r11: {
|
||||
CHECK_CURRENT_CACHED_VALUES(1);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
_PyStackRef owner;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
owner = _stack_item_0;
|
||||
uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION_r22: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
_PyStackRef owner;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
owner = _stack_item_1;
|
||||
uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION_r33: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
_PyStackRef owner;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
owner = _stack_item_2;
|
||||
uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_WITH_VALUES_r02: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__);
|
||||
|
|
|
|||
26
Python/generated_cases.c.h
generated
26
Python/generated_cases.c.h
generated
|
|
@ -9255,7 +9255,18 @@
|
|||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
// _GUARD_KEYS_VERSION
|
||||
{
|
||||
uint32_t keys_version = read_u32(&this_instr[4].cache);
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
}
|
||||
// _LOAD_ATTR_METHOD_WITH_VALUES
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
|
|
@ -9440,7 +9451,18 @@
|
|||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
// _GUARD_KEYS_VERSION
|
||||
{
|
||||
uint32_t keys_version = read_u32(&this_instr[4].cache);
|
||||
PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
PyDictKeysObject *keys = owner_heap_type->ht_cached_keys;
|
||||
if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
}
|
||||
// _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
|
|
|
|||
4
Python/optimizer_cases.c.h
generated
4
Python/optimizer_cases.c.h
generated
|
|
@ -3941,6 +3941,10 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_WITH_VALUES: {
|
||||
JitOptRef owner;
|
||||
JitOptRef attr;
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,7 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
|
|||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
|
||||
return 0;
|
||||
}
|
||||
write_u32(cache->keys_version, shared_keys_version);
|
||||
specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue