From db9f04f17a7fa9ee794adb9e8ccdd4a24a8547b3 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 16 Dec 2022 11:22:33 +0000 Subject: [PATCH 1/3] Don't attempt to specialize for LOAD_ATTR on instance if class has attribute, improve stats. --- Python/specialize.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index d1a38450fff02a..acdaba95684140 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -340,6 +340,7 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28 #define SPEC_FAIL_ATTR_NOT_IN_KEYS 29 #define SPEC_FAIL_ATTR_NOT_IN_DICT 30 +#define SPEC_FAIL_ATTR_CLASS_ATTR 31 /* Binary subscr and store subscr */ @@ -814,15 +815,18 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) } case BUILTIN_CLASSMETHOD: case PYTHON_CLASSMETHOD: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ); + goto fail; case NON_OVERRIDING: case NON_DESCRIPTOR: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR); + goto fail; case ABSENT: - break; - } - if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR, - LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT)) - { - goto success; + if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR, + LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT)) + { + goto success; + } } fail: STAT_INC(LOAD_ATTR, failure); From 31ad53e700a5eee2ffa407199624a7f2afe49adf Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 16 Dec 2022 11:37:10 +0000 Subject: [PATCH 2/3] Further improvement to LOAD_ATTR and STORE_ATTR specialization stats. --- Include/pystats.h | 2 +- Python/specialize.c | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Include/pystats.h b/Include/pystats.h index 04630c9e0f92e5..25ed4bddc7240c 100644 --- a/Include/pystats.h +++ b/Include/pystats.h @@ -8,7 +8,7 @@ extern "C" { #ifdef Py_STATS -#define SPECIALIZATION_FAILURE_KINDS 32 +#define SPECIALIZATION_FAILURE_KINDS 36 /* Stats for determining who is calling PyEval_EvalFrame */ #define EVAL_CALL_TOTAL 0 diff --git a/Python/specialize.c b/Python/specialize.c index acdaba95684140..e20284b1b3a87f 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -340,7 +340,9 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28 #define SPEC_FAIL_ATTR_NOT_IN_KEYS 29 #define SPEC_FAIL_ATTR_NOT_IN_DICT 30 -#define SPEC_FAIL_ATTR_CLASS_ATTR 31 +#define SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE 31 +#define SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR 32 +#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ 33 /* Binary subscr and store subscr */ @@ -814,12 +816,16 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) goto success; } case BUILTIN_CLASSMETHOD: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ); + goto fail; case PYTHON_CLASSMETHOD: SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ); goto fail; case NON_OVERRIDING: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR); + goto fail; case NON_DESCRIPTOR: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR); + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE); goto fail; case ABSENT: if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR, @@ -905,16 +911,23 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN); goto fail; case BUILTIN_CLASSMETHOD: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ); + goto fail; case PYTHON_CLASSMETHOD: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ); + goto fail; case NON_OVERRIDING: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR); + goto fail; case NON_DESCRIPTOR: + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE); + goto fail; case ABSENT: - break; - } - if (specialize_dict_access(owner, instr, type, kind, name, STORE_ATTR, - STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT)) - { - goto success; + if (specialize_dict_access(owner, instr, type, kind, name, STORE_ATTR, + STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT)) + { + goto success; + } } fail: STAT_INC(STORE_ATTR, failure); From 05a9952dfe7f89f862924f50f88541002a2b40ad Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 16 Dec 2022 13:45:47 +0000 Subject: [PATCH 3/3] Refine stats for LOAD_ATTR with class attribute. --- Python/specialize.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index e20284b1b3a87f..2e135be010ff54 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -822,10 +822,16 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ); goto fail; case NON_OVERRIDING: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR); + SPECIALIZATION_FAIL(LOAD_ATTR, + (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) ? + SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR : + SPEC_FAIL_ATTR_NOT_MANAGED_DICT); goto fail; case NON_DESCRIPTOR: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE); + SPECIALIZATION_FAIL(LOAD_ATTR, + (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) ? + SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE : + SPEC_FAIL_ATTR_NOT_MANAGED_DICT); goto fail; case ABSENT: if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR,