summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-12-16 15:41:23 (GMT)
committerGitHub <noreply@github.com>2022-12-16 15:41:23 (GMT)
commit289c1126dd59e5daae59a7ee8a0aca547c1e351e (patch)
treea2ffdceb124f4047fe5f1eb44db5f96cf4905ceb
parent0415cf895f96ae3f896f1f25f0c030a820845e13 (diff)
downloadcpython-289c1126dd59e5daae59a7ee8a0aca547c1e351e.zip
cpython-289c1126dd59e5daae59a7ee8a0aca547c1e351e.tar.gz
cpython-289c1126dd59e5daae59a7ee8a0aca547c1e351e.tar.bz2
Better stats for `LOAD_ATTR` and `STORE_ATTR` (GH-100295)
* Don't attempt to specialize for LOAD_ATTR on instance if class has attribute * Improvement to LOAD_ATTR and STORE_ATTR specialization stats.
-rw-r--r--Include/pystats.h2
-rw-r--r--Python/specialize.c47
2 files changed, 36 insertions, 13 deletions
diff --git a/Include/pystats.h b/Include/pystats.h
index 04630c9..25ed4bd 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 d1a3845..2e135be 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -340,6 +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_SIMPLE 31
+#define SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR 32
+#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ 33
/* Binary subscr and store subscr */
@@ -813,16 +816,29 @@ _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,
+ (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,
+ (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) ?
+ SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE :
+ SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
+ 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);
@@ -901,16 +917,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);