Skip to content

Commit 7537f60

Browse files
authored
bpo-45609: More specialization stats for STORE_SUBSCR (GH-30193)
1 parent 7d7817c commit 7537f60

File tree

2 files changed

+70
-5
lines changed

2 files changed

+70
-5
lines changed

Python/specialize.c

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,13 @@ initial_counter_value(void) {
486486
#define SPEC_FAIL_BUFFER_SLICE 16
487487
#define SPEC_FAIL_SEQUENCE_INT 17
488488

489+
/* Store subscr */
490+
#define SPEC_FAIL_BYTEARRAY_INT 18
491+
#define SPEC_FAIL_BYTEARRAY_SLICE 19
492+
#define SPEC_FAIL_PY_SIMPLE 20
493+
#define SPEC_FAIL_PY_OTHER 21
494+
#define SPEC_FAIL_DICT_SUBCLASS_NO_OVERRIDE 22
495+
489496
/* Binary add */
490497

491498
#define SPEC_FAIL_NON_FUNCTION_SCOPE 11
@@ -1253,15 +1260,73 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
12531260
goto fail;
12541261
}
12551262
}
1256-
else if (container_type == &PyDict_Type) {
1263+
if (container_type == &PyDict_Type) {
12571264
*instr = _Py_MAKECODEUNIT(STORE_SUBSCR_DICT,
12581265
initial_counter_value());
12591266
goto success;
12601267
}
1261-
else {
1262-
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1268+
#ifdef Py_STATS
1269+
PyMappingMethods *as_mapping = container_type->tp_as_mapping;
1270+
if (as_mapping && (as_mapping->mp_ass_subscript
1271+
== PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
1272+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_DICT_SUBCLASS_NO_OVERRIDE);
12631273
goto fail;
12641274
}
1275+
if (PyObject_CheckBuffer(container)) {
1276+
if (PyLong_CheckExact(sub) && (((size_t)Py_SIZE(sub)) > 1)) {
1277+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1278+
}
1279+
else if (strcmp(container_type->tp_name, "array.array") == 0) {
1280+
if (PyLong_CheckExact(sub)) {
1281+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_ARRAY_INT);
1282+
}
1283+
else if (PySlice_Check(sub)) {
1284+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_ARRAY_SLICE);
1285+
}
1286+
else {
1287+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1288+
}
1289+
}
1290+
else if (PyByteArray_CheckExact(container)) {
1291+
if (PyLong_CheckExact(sub)) {
1292+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BYTEARRAY_INT);
1293+
}
1294+
else if (PySlice_Check(sub)) {
1295+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BYTEARRAY_SLICE);
1296+
}
1297+
else {
1298+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1299+
}
1300+
}
1301+
else {
1302+
if (PyLong_CheckExact(sub)) {
1303+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BUFFER_INT);
1304+
}
1305+
else if (PySlice_Check(sub)) {
1306+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_BUFFER_SLICE);
1307+
}
1308+
else {
1309+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1310+
}
1311+
}
1312+
goto fail;
1313+
}
1314+
_Py_IDENTIFIER(__setitem__);
1315+
PyObject *descriptor = _PyType_LookupId(container_type, &PyId___setitem__);
1316+
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1317+
PyFunctionObject *func = (PyFunctionObject *)descriptor;
1318+
PyCodeObject *code = (PyCodeObject *)func->func_code;
1319+
int kind = function_kind(code);
1320+
if (kind == SIMPLE_FUNCTION) {
1321+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_PY_SIMPLE);
1322+
}
1323+
else {
1324+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_PY_OTHER);
1325+
}
1326+
goto fail;
1327+
}
1328+
#endif
1329+
SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
12651330
fail:
12661331
STAT_INC(STORE_SUBSCR, failure);
12671332
assert(!PyErr_Occurred());

Tools/scripts/summarize_stats.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
def print_specialization_stats(name, family_stats):
2929
if "specialization.deferred" not in family_stats:
3030
return
31-
total = sum(family_stats[kind] for kind in TOTAL)
31+
total = sum(family_stats.get(kind, 0) for kind in TOTAL)
3232
if total == 0:
3333
return
3434
print(name+":")
@@ -44,7 +44,7 @@ def print_specialization_stats(name, family_stats):
4444
for key in ("specialization.success", "specialization.failure"):
4545
label = key[len("specialization."):]
4646
print(f" {label}:{family_stats.get(key, 0):>12}")
47-
total_failures = family_stats["specialization.failure"]
47+
total_failures = family_stats.get("specialization.failure", 0)
4848
failure_kinds = [ 0 ] * 30
4949
for key in family_stats:
5050
if not key.startswith("specialization.failure_kind"):

0 commit comments

Comments
 (0)