summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrandt Bucher <brandtbucher@microsoft.com>2022-02-16 16:49:58 (GMT)
committerGitHub <noreply@github.com>2022-02-16 16:49:58 (GMT)
commit580cd9ab2992b7df6f4815020b5841e14a5a6977 (patch)
tree54e5c2df22d105105d70cf12c4ffd780ca8cd6a0
parenta9da085015db8cbb81f660158864ac94fe6c67a2 (diff)
downloadcpython-580cd9ab2992b7df6f4815020b5841e14a5a6977.zip
cpython-580cd9ab2992b7df6f4815020b5841e14a5a6977.tar.gz
cpython-580cd9ab2992b7df6f4815020b5841e14a5a6977.tar.bz2
bpo-46072: Add detailed failure stats for BINARY_OP (GH-31289)
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2022-02-11-13-47-58.bpo-46072.PDS6Ke.rst1
-rw-r--r--Python/specialize.c115
2 files changed, 104 insertions, 12 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-11-13-47-58.bpo-46072.PDS6Ke.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-11-13-47-58.bpo-46072.PDS6Ke.rst
new file mode 100644
index 0000000..aa9ea64
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-11-13-47-58.bpo-46072.PDS6Ke.rst
@@ -0,0 +1 @@
+Add more detailed specialization failure statistics for :opcode:`BINARY_OP`.
diff --git a/Python/specialize.c b/Python/specialize.c
index ab2363c..5fd7d09 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -552,9 +552,28 @@ initial_counter_value(void) {
#define SPEC_FAIL_SUBSCR_PY_OTHER 21
#define SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE 22
-/* Binary add */
-
-#define SPEC_FAIL_BINARY_OP_DIFFERENT_TYPES 12
+/* Binary op */
+
+#define SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES 8
+#define SPEC_FAIL_BINARY_OP_ADD_OTHER 9
+#define SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES 10
+#define SPEC_FAIL_BINARY_OP_AND_INT 11
+#define SPEC_FAIL_BINARY_OP_AND_OTHER 12
+#define SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE 13
+#define SPEC_FAIL_BINARY_OP_LSHIFT 14
+#define SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY 15
+#define SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES 16
+#define SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER 17
+#define SPEC_FAIL_BINARY_OP_OR 18
+#define SPEC_FAIL_BINARY_OP_POWER 19
+#define SPEC_FAIL_BINARY_OP_REMAINDER 20
+#define SPEC_FAIL_BINARY_OP_RSHIFT 21
+#define SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES 22
+#define SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER 23
+#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES 24
+#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT 25
+#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER 26
+#define SPEC_FAIL_BINARY_OP_XOR 27
/* Calls */
#define SPEC_FAIL_CALL_COMPLEX_PARAMETERS 9
@@ -1745,6 +1764,76 @@ _Py_Specialize_CallNoKw(
return 0;
}
+#ifdef Py_STATS
+static int
+binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
+{
+ switch (oparg) {
+ case NB_ADD:
+ case NB_INPLACE_ADD:
+ if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
+ return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
+ }
+ return SPEC_FAIL_BINARY_OP_ADD_OTHER;
+ case NB_AND:
+ case NB_INPLACE_AND:
+ if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
+ return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
+ }
+ if (PyLong_CheckExact(lhs)) {
+ return SPEC_FAIL_BINARY_OP_AND_INT;
+ }
+ return SPEC_FAIL_BINARY_OP_AND_OTHER;
+ case NB_FLOOR_DIVIDE:
+ case NB_INPLACE_FLOOR_DIVIDE:
+ return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
+ case NB_LSHIFT:
+ case NB_INPLACE_LSHIFT:
+ return SPEC_FAIL_BINARY_OP_LSHIFT;
+ case NB_MATRIX_MULTIPLY:
+ case NB_INPLACE_MATRIX_MULTIPLY:
+ return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
+ case NB_MULTIPLY:
+ case NB_INPLACE_MULTIPLY:
+ if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
+ return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
+ }
+ return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
+ case NB_OR:
+ case NB_INPLACE_OR:
+ return SPEC_FAIL_BINARY_OP_OR;
+ case NB_POWER:
+ case NB_INPLACE_POWER:
+ return SPEC_FAIL_BINARY_OP_POWER;
+ case NB_REMAINDER:
+ case NB_INPLACE_REMAINDER:
+ return SPEC_FAIL_BINARY_OP_REMAINDER;
+ case NB_RSHIFT:
+ case NB_INPLACE_RSHIFT:
+ return SPEC_FAIL_BINARY_OP_RSHIFT;
+ case NB_SUBTRACT:
+ case NB_INPLACE_SUBTRACT:
+ if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
+ return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
+ }
+ return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
+ case NB_TRUE_DIVIDE:
+ case NB_INPLACE_TRUE_DIVIDE:
+ if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
+ return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
+ }
+ if (PyFloat_CheckExact(lhs)) {
+ return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
+ }
+ return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
+ case NB_XOR:
+ case NB_INPLACE_XOR:
+ return SPEC_FAIL_BINARY_OP_XOR;
+ }
+ Py_UNREACHABLE();
+}
+#endif
+
void
_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
SpecializedCacheEntry *cache)
@@ -1754,8 +1843,7 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
case NB_ADD:
case NB_INPLACE_ADD:
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
- SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_BINARY_OP_DIFFERENT_TYPES);
- goto failure;
+ break;
}
if (PyUnicode_CheckExact(lhs)) {
if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) {
@@ -1780,8 +1868,7 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
case NB_MULTIPLY:
case NB_INPLACE_MULTIPLY:
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
- SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_BINARY_OP_DIFFERENT_TYPES);
- goto failure;
+ break;
}
if (PyLong_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT,
@@ -1797,8 +1884,7 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
case NB_SUBTRACT:
case NB_INPLACE_SUBTRACT:
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
- SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_BINARY_OP_DIFFERENT_TYPES);
- goto failure;
+ break;
}
if (PyLong_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT,
@@ -1811,14 +1897,19 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
goto success;
}
break;
+#ifndef Py_STATS
default:
// These operators don't have any available specializations. Rather
// than repeatedly attempting to specialize them, just convert them
- // back to BINARY_OP (while still recording a failure, of course)!
+ // back to BINARY_OP (unless we're collecting stats, where it's more
+ // important to get accurate hit counts for the unadaptive version
+ // and each of the different failure types):
*instr = _Py_MAKECODEUNIT(BINARY_OP, adaptive->original_oparg);
+ return;
+#endif
}
- SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER);
-failure:
+ SPECIALIZATION_FAIL(
+ BINARY_OP, binary_op_fail_kind(adaptive->original_oparg, lhs, rhs));
STAT_INC(BINARY_OP, failure);
cache_backoff(adaptive);
return;