Skip to content

Commit a840c5d

Browse files
Unbind methods at _LOAD_ATTR time eagerly for better specialization
1 parent aee63e2 commit a840c5d

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

Lib/test/test_opcache.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,27 @@ class MyList(list): pass
20082008
self.assert_no_opcode(my_list_append, "CALL_LIST_APPEND")
20092009
self.assert_no_opcode(my_list_append, "CALL")
20102010

2011+
@cpython_only
2012+
@requires_specialization
2013+
def test_load_and_call_classmethod(self):
2014+
2015+
r = range(_testinternalcapi.SPECIALIZATION_THRESHOLD)
2016+
2017+
class C:
2018+
@classmethod
2019+
def val(self):
2020+
return 1
2021+
2022+
def class_method_call():
2023+
for _ in r:
2024+
C.val()
2025+
2026+
class_method_call()
2027+
# gh-148608: To improve specialization, the classmethod should've become unbound.
2028+
self.assert_specialized(class_method_call, "CALL_PY_EXACT_ARGS")
2029+
self.assert_no_opcode(class_method_call, "CALL_BOUND_METHOD_EXACT_ARGS")
2030+
self.assert_no_opcode(class_method_call, "CALL")
2031+
20112032
@cpython_only
20122033
@requires_specialization
20132034
def test_load_attr_module_with_getattr(self):

Objects/object.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,15 @@ _PyObject_GetMethodStackRef(PyThreadState *ts, _PyStackRef *self,
17731773
PyObject *res = PyObject_GetAttr(obj, name);
17741774
PyStackRef_CLEAR(*self);
17751775
if (res != NULL) {
1776+
// gh-148608: If it's a method, unbind it right now to improve
1777+
// specialization later on.
1778+
if (Py_IS_TYPE(res, &PyMethod_Type)) {
1779+
PyMethodObject *as_meth = ((PyMethodObject *)res);
1780+
*method = PyStackRef_FromPyObjectNew(as_meth->im_func);
1781+
*self = PyStackRef_FromPyObjectNew(as_meth->im_self);
1782+
Py_DECREF(res);
1783+
return 1;
1784+
}
17761785
*method = PyStackRef_FromPyObjectSteal(res);
17771786
return 0;
17781787
}

0 commit comments

Comments
 (0)