Skip to content

Commit 77bab2e

Browse files
Specialize for classmethod in LOAD_ATTR_CLASS
1 parent a840c5d commit 77bab2e

File tree

11 files changed

+204
-89
lines changed

11 files changed

+204
-89
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_ids.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_opcache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,8 +2024,8 @@ def class_method_call():
20242024
C.val()
20252025

20262026
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")
2027+
# gh-148608: To improve specialization, the classmethod should be unbound.
2028+
self.assert_specialized(class_method_call, "LOAD_ATTR_CLASS")
20292029
self.assert_no_opcode(class_method_call, "CALL_BOUND_METHOD_EXACT_ARGS")
20302030
self.assert_no_opcode(class_method_call, "CALL")
20312031

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 58 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,27 +2949,40 @@ dummy_func(
29492949
EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(((PyTypeObject *)owner_o)->tp_version_tag) != type_version);
29502950
}
29512951

2952-
op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
2952+
// This can't use _PUSH_NULL_CONDITIONAL as it requires swapping self in certain cases.
2953+
op(_LOAD_ATTR_CLASS, (descr_tagged/4, owner -- attr, self_or_null[oparg&1])) {
29532954
STAT_INC(LOAD_ATTR, hit);
2955+
PyObject *descr = (PyObject *)((uintptr_t)descr_tagged & (~1));
2956+
int use_self = ((uintptr_t)descr_tagged & 1);
29542957
assert(descr != NULL);
29552958
attr = PyStackRef_FromPyObjectNew(descr);
2956-
DECREF_INPUTS();
2959+
if (oparg & 1) {
2960+
if (use_self) {
2961+
self_or_null[0] = owner;
2962+
DEAD(owner);
2963+
}
2964+
else {
2965+
self_or_null[0] = PyStackRef_NULL;
2966+
PyStackRef_CLOSE(owner);
2967+
}
2968+
}
2969+
else {
2970+
PyStackRef_CLOSE(owner);
2971+
}
29572972
}
29582973

29592974
macro(LOAD_ATTR_CLASS) =
29602975
unused/1 +
29612976
_CHECK_ATTR_CLASS +
29622977
unused/2 +
2963-
_LOAD_ATTR_CLASS +
2964-
_PUSH_NULL_CONDITIONAL;
2978+
_LOAD_ATTR_CLASS;
29652979

29662980
macro(LOAD_ATTR_CLASS_WITH_METACLASS_CHECK) =
29672981
unused/1 +
29682982
_RECORD_TOS_TYPE +
29692983
_GUARD_TYPE_VERSION +
29702984
_CHECK_ATTR_CLASS +
2971-
_LOAD_ATTR_CLASS +
2972-
_PUSH_NULL_CONDITIONAL;
2985+
_LOAD_ATTR_CLASS;
29732986

29742987
op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) {
29752988
assert((oparg & 1) == 0);

Python/executor_cases.c.h

Lines changed: 35 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)