gh-136125: Use _PyObject_GetMethodStackRef for LOAD_ATTR (GH-136127)

This commit is contained in:
Ken Jin 2025-07-02 01:20:46 +08:00 committed by GitHub
parent 17cf0a343b
commit e0d6500b2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 29 additions and 32 deletions

View file

@ -918,7 +918,7 @@ extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *,
extern unsigned int extern unsigned int
_PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out); _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out);
extern int _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj, PyAPI_FUNC(int) _PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj,
PyObject *name, _PyStackRef *method); PyObject *name, _PyStackRef *method);
// Cache the provided init method in the specialization cache of type if the // Cache the provided init method in the specialization cache of type if the

View file

@ -2327,19 +2327,18 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION_FT */ #endif /* ENABLE_SPECIALIZATION_FT */
} }
op(_LOAD_ATTR, (owner -- attr, self_or_null[oparg&1])) { op(_LOAD_ATTR, (owner -- attr[1], self_or_null[oparg&1])) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
if (oparg & 1) { if (oparg & 1) {
/* Designed to work in tandem with CALL, pushes two values. */ /* Designed to work in tandem with CALL, pushes two values. */
attr_o = NULL; *attr = PyStackRef_NULL;
int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, attr);
if (is_meth) { if (is_meth) {
/* We can bypass temporary bound method object. /* We can bypass temporary bound method object.
meth is unbound method and obj is self. meth is unbound method and obj is self.
meth | self | arg1 | ... | argN meth | self | arg1 | ... | argN
*/ */
assert(attr_o != NULL); // No errors on this branch assert(!PyStackRef_IsNull(*attr)); // No errors on this branch
self_or_null[0] = owner; // Transfer ownership self_or_null[0] = owner; // Transfer ownership
DEAD(owner); DEAD(owner);
} }
@ -2351,17 +2350,17 @@ dummy_func(
meth | NULL | arg1 | ... | argN meth | NULL | arg1 | ... | argN
*/ */
PyStackRef_CLOSE(owner); PyStackRef_CLOSE(owner);
ERROR_IF(attr_o == NULL); ERROR_IF(PyStackRef_IsNull(*attr));
self_or_null[0] = PyStackRef_NULL; self_or_null[0] = PyStackRef_NULL;
} }
} }
else { else {
/* Classic, pushes one value. */ /* Classic, pushes one value. */
attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
PyStackRef_CLOSE(owner); PyStackRef_CLOSE(owner);
ERROR_IF(attr_o == NULL); ERROR_IF(attr_o == NULL);
*attr = PyStackRef_FromPyObjectSteal(attr_o);
} }
attr = PyStackRef_FromPyObjectSteal(attr_o);
} }
macro(LOAD_ATTR) = macro(LOAD_ATTR) =

View file

@ -3301,20 +3301,20 @@
case _LOAD_ATTR: { case _LOAD_ATTR: {
_PyStackRef owner; _PyStackRef owner;
_PyStackRef attr; _PyStackRef *attr;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
oparg = CURRENT_OPARG(); oparg = CURRENT_OPARG();
owner = stack_pointer[-1]; owner = stack_pointer[-1];
attr = &stack_pointer[-1];
self_or_null = &stack_pointer[0]; self_or_null = &stack_pointer[0];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
if (oparg & 1) { if (oparg & 1) {
attr_o = NULL; *attr = PyStackRef_NULL;
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, attr);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
if (is_meth) { if (is_meth) {
assert(attr_o != NULL); assert(!PyStackRef_IsNull(*attr));
self_or_null[0] = owner; self_or_null[0] = owner;
} }
else { else {
@ -3323,7 +3323,7 @@
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(owner); PyStackRef_CLOSE(owner);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
if (attr_o == NULL) { if (PyStackRef_IsNull(*attr)) {
JUMP_TO_ERROR(); JUMP_TO_ERROR();
} }
self_or_null[0] = PyStackRef_NULL; self_or_null[0] = PyStackRef_NULL;
@ -3332,7 +3332,7 @@
} }
else { else {
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -1; stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
@ -3342,10 +3342,9 @@
if (attr_o == NULL) { if (attr_o == NULL) {
JUMP_TO_ERROR(); JUMP_TO_ERROR();
} }
*attr = PyStackRef_FromPyObjectSteal(attr_o);
stack_pointer += 1; stack_pointer += 1;
} }
attr = PyStackRef_FromPyObjectSteal(attr_o);
stack_pointer[-1] = attr;
stack_pointer += (oparg&1); stack_pointer += (oparg&1);
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
break; break;

View file

@ -7941,7 +7941,7 @@
_Py_CODEUNIT* const this_instr = next_instr - 10; _Py_CODEUNIT* const this_instr = next_instr - 10;
(void)this_instr; (void)this_instr;
_PyStackRef owner; _PyStackRef owner;
_PyStackRef attr; _PyStackRef *attr;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
// _SPECIALIZE_LOAD_ATTR // _SPECIALIZE_LOAD_ATTR
{ {
@ -7964,16 +7964,16 @@
/* Skip 8 cache entries */ /* Skip 8 cache entries */
// _LOAD_ATTR // _LOAD_ATTR
{ {
attr = &stack_pointer[-1];
self_or_null = &stack_pointer[0]; self_or_null = &stack_pointer[0];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
PyObject *attr_o;
if (oparg & 1) { if (oparg & 1) {
attr_o = NULL; *attr = PyStackRef_NULL;
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, attr);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
if (is_meth) { if (is_meth) {
assert(attr_o != NULL); assert(!PyStackRef_IsNull(*attr));
self_or_null[0] = owner; self_or_null[0] = owner;
} }
else { else {
@ -7982,7 +7982,7 @@
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(owner); PyStackRef_CLOSE(owner);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
if (attr_o == NULL) { if (PyStackRef_IsNull(*attr)) {
JUMP_TO_LABEL(error); JUMP_TO_LABEL(error);
} }
self_or_null[0] = PyStackRef_NULL; self_or_null[0] = PyStackRef_NULL;
@ -7991,7 +7991,7 @@
} }
else { else {
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); PyObject *attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -1; stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
@ -8001,11 +8001,10 @@
if (attr_o == NULL) { if (attr_o == NULL) {
JUMP_TO_LABEL(error); JUMP_TO_LABEL(error);
} }
*attr = PyStackRef_FromPyObjectSteal(attr_o);
stack_pointer += 1; stack_pointer += 1;
} }
attr = PyStackRef_FromPyObjectSteal(attr_o);
} }
stack_pointer[-1] = attr;
stack_pointer += (oparg&1); stack_pointer += (oparg&1);
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
DISPATCH(); DISPATCH();

View file

@ -590,9 +590,9 @@ dummy_func(void) {
} }
} }
op(_LOAD_ATTR, (owner -- attr, self_or_null[oparg&1])) { op(_LOAD_ATTR, (owner -- attr[1], self_or_null[oparg&1])) {
(void)owner; (void)owner;
attr = sym_new_not_null(ctx); *attr = sym_new_not_null(ctx);
if (oparg & 1) { if (oparg & 1) {
self_or_null[0] = sym_new_unknown(ctx); self_or_null[0] = sym_new_unknown(ctx);
} }

View file

@ -1414,16 +1414,16 @@
case _LOAD_ATTR: { case _LOAD_ATTR: {
JitOptRef owner; JitOptRef owner;
JitOptRef attr; JitOptRef *attr;
JitOptRef *self_or_null; JitOptRef *self_or_null;
owner = stack_pointer[-1]; owner = stack_pointer[-1];
attr = &stack_pointer[-1];
self_or_null = &stack_pointer[0]; self_or_null = &stack_pointer[0];
(void)owner; (void)owner;
attr = sym_new_not_null(ctx); *attr = sym_new_not_null(ctx);
if (oparg & 1) { if (oparg & 1) {
self_or_null[0] = sym_new_unknown(ctx); self_or_null[0] = sym_new_unknown(ctx);
} }
stack_pointer[-1] = attr;
stack_pointer += (oparg&1); stack_pointer += (oparg&1);
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
break; break;