Skip to content

bpo-45609: More specialization stats for STORE_SUBSCR #30193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 68 additions & 3 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,13 @@ initial_counter_value(void) {
#define SPEC_FAIL_BUFFER_SLICE 16
#define SPEC_FAIL_SEQUENCE_INT 17

/* Store subscr */
#define SPEC_FAIL_BYTEARRAY_INT 18
#define SPEC_FAIL_BYTEARRAY_SLICE 19
#define SPEC_FAIL_PY_SIMPLE 20
#define SPEC_FAIL_PY_OTHER 21
#define SPEC_FAIL_DICT_SUBCLASS_NO_OVERRIDE 22

/* Binary add */

#define SPEC_FAIL_NON_FUNCTION_SCOPE 11
Expand Down Expand Up @@ -1253,15 +1260,73 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
goto fail;
}
}
else if (container_type == &PyDict_Type) {
if (container_type == &PyDict_Type) {
*instr = _Py_MAKECODEUNIT(STORE_SUBSCR_DICT,
initial_counter_value());
goto success;
}
else {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
#ifdef Py_STATS
PyMappingMethods *as_mapping = container_type->tp_as_mapping;
if (as_mapping && (as_mapping->mp_ass_subscript
== PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_DICT_SUBCLASS_NO_OVERRIDE);
goto fail;
}
if (PyObject_CheckBuffer(container)) {
if (PyLong_CheckExact(sub) && (((size_t)Py_SIZE(sub)) > 1)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
}
else if (strcmp(container_type->tp_name, "array.array") == 0) {
if (PyLong_CheckExact(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_ARRAY_INT);
}
else if (PySlice_Check(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_ARRAY_SLICE);
}
else {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
}
}
else if (PyByteArray_CheckExact(container)) {
if (PyLong_CheckExact(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BYTEARRAY_INT);
}
else if (PySlice_Check(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BYTEARRAY_SLICE);
}
else {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
}
}
else {
if (PyLong_CheckExact(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BUFFER_INT);
}
else if (PySlice_Check(sub)) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BUFFER_SLICE);
}
else {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
}
}
goto fail;
}
_Py_IDENTIFIER(__setitem__);
PyObject *descriptor = _PyType_LookupId(container_type, &PyId___setitem__);
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
PyFunctionObject *func = (PyFunctionObject *)descriptor;
PyCodeObject *code = (PyCodeObject *)func->func_code;
int kind = function_kind(code);
if (kind == SIMPLE_FUNCTION) {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_PY_SIMPLE);
}
else {
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_PY_OTHER);
}
goto fail;
}
#endif
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
fail:
STAT_INC(STORE_SUBSCR, failure);
assert(!PyErr_Occurred());
Expand Down
4 changes: 2 additions & 2 deletions Tools/scripts/summarize_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
def print_specialization_stats(name, family_stats):
if "specialization.deferred" not in family_stats:
return
total = sum(family_stats[kind] for kind in TOTAL)
total = sum(family_stats.get(kind, 0) for kind in TOTAL)
if total == 0:
return
print(name+":")
Expand All @@ -44,7 +44,7 @@ def print_specialization_stats(name, family_stats):
for key in ("specialization.success", "specialization.failure"):
label = key[len("specialization."):]
print(f" {label}:{family_stats.get(key, 0):>12}")
total_failures = family_stats["specialization.failure"]
total_failures = family_stats.get("specialization.failure", 0)
failure_kinds = [ 0 ] * 30
for key in family_stats:
if not key.startswith("specialization.failure_kind"):
Expand Down