diff options
author | Brandt Bucher <brandtbucher@microsoft.com> | 2022-02-16 16:49:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-16 16:49:58 (GMT) |
commit | 580cd9ab2992b7df6f4815020b5841e14a5a6977 (patch) | |
tree | 54e5c2df22d105105d70cf12c4ffd780ca8cd6a0 | |
parent | a9da085015db8cbb81f660158864ac94fe6c67a2 (diff) | |
download | cpython-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.rst | 1 | ||||
-rw-r--r-- | Python/specialize.c | 115 |
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; |