gh-134584: Eliminate redundant refcounting in JIT for MATCH_CLASS (GH-144821)

This commit is contained in:
Sacul 2026-03-14 20:00:18 +08:00 committed by GitHub
parent 97968564b6
commit 798070d8ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1155 additions and 1070 deletions

View file

@ -3254,7 +3254,7 @@ dummy_func(
len = PyStackRef_FromPyObjectSteal(len_o);
}
inst(MATCH_CLASS, (subject, type, names -- attrs)) {
op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) {
// Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or
// None on failure.
assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names)));
@ -3262,17 +3262,24 @@ dummy_func(
PyStackRef_AsPyObjectBorrow(subject),
PyStackRef_AsPyObjectBorrow(type), oparg,
PyStackRef_AsPyObjectBorrow(names));
DECREF_INPUTS();
if (attrs_o) {
assert(PyTuple_CheckExact(attrs_o)); // Success!
attrs = PyStackRef_FromPyObjectSteal(attrs_o);
}
else {
ERROR_IF(_PyErr_Occurred(tstate)); // Error!
if (_PyErr_Occurred(tstate)) { // Error!
ERROR_NO_POP();
}
attrs = PyStackRef_None; // Failure!
}
s = subject;
tp = type;
n = names;
INPUTS_DEAD();
}
macro(MATCH_CLASS) = _MATCH_CLASS + POP_TOP + POP_TOP + POP_TOP;
inst(MATCH_MAPPING, (subject -- subject, res)) {
int match = PyStackRef_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
res = match ? PyStackRef_True : PyStackRef_False;

View file

@ -11292,13 +11292,16 @@
break;
}
case _MATCH_CLASS_r31: {
case _MATCH_CLASS_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef names;
_PyStackRef type;
_PyStackRef subject;
_PyStackRef attrs;
_PyStackRef s;
_PyStackRef tp;
_PyStackRef n;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
_PyStackRef _stack_item_2 = _tos_cache2;
@ -11317,21 +11320,7 @@
PyStackRef_AsPyObjectBorrow(subject),
PyStackRef_AsPyObjectBorrow(type), oparg,
PyStackRef_AsPyObjectBorrow(names));
_PyStackRef tmp = names;
names = PyStackRef_NULL;
stack_pointer[-1] = names;
PyStackRef_CLOSE(tmp);
tmp = type;
type = PyStackRef_NULL;
stack_pointer[-2] = type;
PyStackRef_CLOSE(tmp);
tmp = subject;
subject = PyStackRef_NULL;
stack_pointer[-3] = subject;
PyStackRef_CLOSE(tmp);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -3;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
if (attrs_o) {
assert(PyTuple_CheckExact(attrs_o));
attrs = PyStackRef_FromPyObjectSteal(attrs_o);
@ -11343,10 +11332,16 @@
}
attrs = PyStackRef_None;
}
_tos_cache0 = attrs;
_tos_cache1 = PyStackRef_ZERO_BITS;
_tos_cache2 = PyStackRef_ZERO_BITS;
SET_CURRENT_CACHED_VALUES(1);
s = subject;
tp = type;
n = names;
_tos_cache2 = n;
_tos_cache1 = tp;
_tos_cache0 = s;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer[-3] = attrs;
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}

View file

@ -9982,43 +9982,64 @@
_PyStackRef type;
_PyStackRef names;
_PyStackRef attrs;
names = stack_pointer[-1];
type = stack_pointer[-2];
subject = stack_pointer[-3];
assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names)));
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *attrs_o = _PyEval_MatchClass(tstate,
PyStackRef_AsPyObjectBorrow(subject),
PyStackRef_AsPyObjectBorrow(type), oparg,
PyStackRef_AsPyObjectBorrow(names));
_PyStackRef tmp = names;
names = PyStackRef_NULL;
stack_pointer[-1] = names;
PyStackRef_CLOSE(tmp);
tmp = type;
type = PyStackRef_NULL;
stack_pointer[-2] = type;
PyStackRef_CLOSE(tmp);
tmp = subject;
subject = PyStackRef_NULL;
stack_pointer[-3] = subject;
PyStackRef_CLOSE(tmp);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -3;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
if (attrs_o) {
assert(PyTuple_CheckExact(attrs_o));
attrs = PyStackRef_FromPyObjectSteal(attrs_o);
}
else {
if (_PyErr_Occurred(tstate)) {
JUMP_TO_LABEL(error);
_PyStackRef s;
_PyStackRef tp;
_PyStackRef n;
_PyStackRef value;
// _MATCH_CLASS
{
names = stack_pointer[-1];
type = stack_pointer[-2];
subject = stack_pointer[-3];
assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names)));
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *attrs_o = _PyEval_MatchClass(tstate,
PyStackRef_AsPyObjectBorrow(subject),
PyStackRef_AsPyObjectBorrow(type), oparg,
PyStackRef_AsPyObjectBorrow(names));
stack_pointer = _PyFrame_GetStackPointer(frame);
if (attrs_o) {
assert(PyTuple_CheckExact(attrs_o));
attrs = PyStackRef_FromPyObjectSteal(attrs_o);
}
attrs = PyStackRef_None;
else {
if (_PyErr_Occurred(tstate)) {
JUMP_TO_LABEL(error);
}
attrs = PyStackRef_None;
}
s = subject;
tp = type;
n = names;
}
// _POP_TOP
{
value = n;
stack_pointer[-3] = attrs;
stack_pointer[-2] = s;
stack_pointer[-1] = tp;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
// _POP_TOP
{
value = tp;
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
// _POP_TOP
{
value = s;
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
stack_pointer[0] = attrs;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
DISPATCH();
}

View file

@ -1710,6 +1710,13 @@ dummy_func(void) {
ss = sub_st;
}
op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) {
attrs = sym_new_not_null(ctx);
s = subject;
tp = type;
n = names;
}
op(_RECORD_TOS, (tos -- tos)) {
sym_set_recorded_value(tos, (PyObject *)this_instr->operand0);
}

View file

@ -2649,11 +2649,26 @@
}
case _MATCH_CLASS: {
JitOptRef names;
JitOptRef type;
JitOptRef subject;
JitOptRef attrs;
JitOptRef s;
JitOptRef tp;
JitOptRef n;
names = stack_pointer[-1];
type = stack_pointer[-2];
subject = stack_pointer[-3];
attrs = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(-2);
s = subject;
tp = type;
n = names;
CHECK_STACK_BOUNDS(1);
stack_pointer[-3] = attrs;
stack_pointer += -2;
stack_pointer[-2] = s;
stack_pointer[-1] = tp;
stack_pointer[0] = n;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}