gh-134584: Eliminate redundant refcounting from _LOAD_ATTR_INSTANCE_VALUE (GH-142769)

Signed-off-by: Manjusaka <me@manjusaka.me>
This commit is contained in:
Nadeshiko Manju 2025-12-17 05:39:20 +09:00 committed by GitHub
parent 92d4aeafd5
commit 6ee51a36b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 451 additions and 331 deletions

View file

@ -2356,7 +2356,7 @@ dummy_func(
DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid));
}
op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, o)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
@ -2370,7 +2370,8 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
PyStackRef_CLOSE(owner);
o = owner;
DEAD(owner);
}
macro(LOAD_ATTR_INSTANCE_VALUE) =
@ -2378,6 +2379,7 @@ dummy_func(
_GUARD_TYPE_VERSION +
_CHECK_MANAGED_OBJECT_HAS_VALUES +
_LOAD_ATTR_INSTANCE_VALUE +
POP_TOP +
unused/5 +
_PUSH_NULL_CONDITIONAL;

View file

@ -8096,11 +8096,51 @@
break;
}
case _LOAD_ATTR_INSTANCE_VALUE_r11: {
case _LOAD_ATTR_INSTANCE_VALUE_r02: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef owner;
_PyStackRef attr;
_PyStackRef o;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
if (attr_o == NULL) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
#ifdef Py_GIL_DISABLED
int increfed = _Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr);
if (!increfed) {
if (true) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
}
#else
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
o = owner;
_tos_cache1 = o;
_tos_cache0 = attr;
SET_CURRENT_CACHED_VALUES(2);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _LOAD_ATTR_INSTANCE_VALUE_r12: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef owner;
_PyStackRef attr;
_PyStackRef o;
_PyStackRef _stack_item_0 = _tos_cache0;
owner = _stack_item_0;
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
@ -8127,18 +8167,54 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
stack_pointer[0] = attr;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(owner);
stack_pointer = _PyFrame_GetStackPointer(frame);
o = owner;
_tos_cache1 = o;
_tos_cache0 = attr;
_tos_cache1 = PyStackRef_ZERO_BITS;
_tos_cache2 = PyStackRef_ZERO_BITS;
SET_CURRENT_CACHED_VALUES(1);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
SET_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _LOAD_ATTR_INSTANCE_VALUE_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef owner;
_PyStackRef attr;
_PyStackRef o;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
owner = _stack_item_1;
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr);
if (attr_o == NULL) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = owner;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
#ifdef Py_GIL_DISABLED
int increfed = _Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr);
if (!increfed) {
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = owner;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
}
#else
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
o = owner;
_tos_cache2 = o;
_tos_cache1 = attr;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}

View file

@ -7889,6 +7889,8 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
_PyStackRef attr;
_PyStackRef o;
_PyStackRef value;
_PyStackRef *null;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
@ -7938,9 +7940,14 @@
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
o = owner;
}
// _POP_TOP
{
value = o;
stack_pointer[-1] = attr;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(owner);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
/* Skip 5 cache entries */

View file

@ -570,9 +570,10 @@ dummy_func(void) {
assert(oparg >= 2);
}
op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr)) {
op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, o)) {
attr = sym_new_not_null(ctx);
(void)offset;
o = owner;
}
op(_LOAD_ATTR_MODULE, (dict_version/2, index/1, owner -- attr)) {

View file

@ -1566,11 +1566,19 @@
}
case _LOAD_ATTR_INSTANCE_VALUE: {
JitOptRef owner;
JitOptRef attr;
JitOptRef o;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
(void)offset;
o = owner;
CHECK_STACK_BOUNDS(1);
stack_pointer[-1] = attr;
stack_pointer[0] = o;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}