mirror of
https://github.com/python/cpython.git
synced 2025-07-19 09:15:34 +00:00
gh-116381: Remove bad specializations, add fail stats (GH-116464)
* Remove bad specializations, add fail stats
This commit is contained in:
parent
4298d69d4b
commit
41457c7fdb
16 changed files with 125 additions and 320 deletions
|
@ -2238,11 +2238,8 @@ dummy_func(
|
|||
}
|
||||
|
||||
family(CONTAINS_OP, INLINE_CACHE_ENTRIES_CONTAINS_OP) = {
|
||||
CONTAINS_OP_LIST,
|
||||
CONTAINS_OP_SET,
|
||||
CONTAINS_OP_TUPLE,
|
||||
CONTAINS_OP_DICT,
|
||||
CONTAINS_OP_STR,
|
||||
};
|
||||
|
||||
op(_CONTAINS_OP, (left, right -- b)) {
|
||||
|
@ -2266,46 +2263,25 @@ dummy_func(
|
|||
|
||||
macro(CONTAINS_OP) = _SPECIALIZE_CONTAINS_OP + _CONTAINS_OP;
|
||||
|
||||
inst(CONTAINS_OP_LIST, (unused/1, left, right -- b)) {
|
||||
DEOPT_IF(!PyList_CheckExact(right));
|
||||
int res = _PyList_Contains(right, left);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res < 0, error);
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
inst(CONTAINS_OP_SET, (unused/1, left, right -- b)) {
|
||||
DEOPT_IF(!PySet_CheckExact(right));
|
||||
DEOPT_IF(!(PySet_CheckExact(right) || PyFrozenSet_CheckExact(right)));
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
// Note: both set and frozenset use the same seq_contains method!
|
||||
int res = _PySet_Contains((PySetObject *)right, left);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res < 0, error);
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
inst(CONTAINS_OP_TUPLE, (unused/1, left, right -- b)) {
|
||||
DEOPT_IF(!PyTuple_CheckExact(right));
|
||||
int res = _PyTuple_Contains((PyTupleObject *)right, left);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res < 0, error);
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
inst(CONTAINS_OP_DICT, (unused/1, left, right -- b)) {
|
||||
DEOPT_IF(!PyDict_CheckExact(right));
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
int res = PyDict_Contains(right, left);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res < 0, error);
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
inst(CONTAINS_OP_STR, (unused/1, left, right -- b)) {
|
||||
DEOPT_IF(!PyUnicode_CheckExact(right));
|
||||
int res = PyUnicode_Contains(right, left);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res < 0, error);
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
inst(CHECK_EG_MATCH, (exc_value, match_type -- rest, match)) {
|
||||
if (_PyEval_CheckExceptStarTypeValid(tstate, match_type) < 0) {
|
||||
DECREF_INPUTS();
|
||||
|
|
59
Python/executor_cases.c.h
generated
59
Python/executor_cases.c.h
generated
|
@ -2189,24 +2189,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_LIST: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
oparg = CURRENT_OPARG();
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (!PyList_CheckExact(right)) goto deoptimize;
|
||||
int res = _PyList_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error_tier_two;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_SET: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
|
@ -2214,7 +2196,9 @@
|
|||
oparg = CURRENT_OPARG();
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (!PySet_CheckExact(right)) goto deoptimize;
|
||||
if (!(PySet_CheckExact(right) || PyFrozenSet_CheckExact(right))) goto deoptimize;
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
// Note: both set and frozenset use the same seq_contains method!
|
||||
int res = _PySet_Contains((PySetObject *)right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
|
@ -2225,24 +2209,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_TUPLE: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
oparg = CURRENT_OPARG();
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (!PyTuple_CheckExact(right)) goto deoptimize;
|
||||
int res = _PyTuple_Contains((PyTupleObject *)right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error_tier_two;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_DICT: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
|
@ -2251,6 +2217,7 @@
|
|||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (!PyDict_CheckExact(right)) goto deoptimize;
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
int res = PyDict_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
|
@ -2261,24 +2228,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_STR: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
oparg = CURRENT_OPARG();
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (!PyUnicode_CheckExact(right)) goto deoptimize;
|
||||
int res = PyUnicode_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error_tier_two;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CHECK_EG_MATCH: {
|
||||
PyObject *match_type;
|
||||
PyObject *exc_value;
|
||||
|
|
71
Python/generated_cases.c.h
generated
71
Python/generated_cases.c.h
generated
|
@ -2176,6 +2176,7 @@
|
|||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
DEOPT_IF(!PyDict_CheckExact(right), CONTAINS_OP);
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
int res = PyDict_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
|
@ -2186,28 +2187,6 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CONTAINS_OP_LIST) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(CONTAINS_OP_LIST);
|
||||
static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size");
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
/* Skip 1 cache entry */
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
DEOPT_IF(!PyList_CheckExact(right), CONTAINS_OP);
|
||||
int res = _PyList_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CONTAINS_OP_SET) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
|
@ -2219,7 +2198,9 @@
|
|||
/* Skip 1 cache entry */
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
DEOPT_IF(!PySet_CheckExact(right), CONTAINS_OP);
|
||||
DEOPT_IF(!(PySet_CheckExact(right) || PyFrozenSet_CheckExact(right)), CONTAINS_OP);
|
||||
STAT_INC(CONTAINS_OP, hit);
|
||||
// Note: both set and frozenset use the same seq_contains method!
|
||||
int res = _PySet_Contains((PySetObject *)right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
|
@ -2230,50 +2211,6 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CONTAINS_OP_STR) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(CONTAINS_OP_STR);
|
||||
static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size");
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
/* Skip 1 cache entry */
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
DEOPT_IF(!PyUnicode_CheckExact(right), CONTAINS_OP);
|
||||
int res = PyUnicode_Contains(right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CONTAINS_OP_TUPLE) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(CONTAINS_OP_TUPLE);
|
||||
static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size");
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
PyObject *b;
|
||||
/* Skip 1 cache entry */
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
DEOPT_IF(!PyTuple_CheckExact(right), CONTAINS_OP);
|
||||
int res = _PyTuple_Contains((PyTupleObject *)right, left);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
if (res < 0) goto pop_2_error;
|
||||
b = (res ^ oparg) ? Py_True : Py_False;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(CONVERT_VALUE) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
|
|
6
Python/opcode_targets.h
generated
6
Python/opcode_targets.h
generated
|
@ -183,10 +183,7 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_COMPARE_OP_INT,
|
||||
&&TARGET_COMPARE_OP_STR,
|
||||
&&TARGET_CONTAINS_OP_DICT,
|
||||
&&TARGET_CONTAINS_OP_LIST,
|
||||
&&TARGET_CONTAINS_OP_SET,
|
||||
&&TARGET_CONTAINS_OP_STR,
|
||||
&&TARGET_CONTAINS_OP_TUPLE,
|
||||
&&TARGET_FOR_ITER_GEN,
|
||||
&&TARGET_FOR_ITER_LIST,
|
||||
&&TARGET_FOR_ITER_RANGE,
|
||||
|
@ -235,6 +232,9 @@ static void *opcode_targets[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INSTRUMENTED_RESUME,
|
||||
&&TARGET_INSTRUMENTED_END_FOR,
|
||||
&&TARGET_INSTRUMENTED_END_SEND,
|
||||
|
|
27
Python/optimizer_cases.c.h
generated
27
Python/optimizer_cases.c.h
generated
|
@ -1218,15 +1218,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_LIST: {
|
||||
_Py_UopsSymbol *b;
|
||||
b = sym_new_unknown(ctx);
|
||||
if (b == NULL) goto out_of_space;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_SET: {
|
||||
_Py_UopsSymbol *b;
|
||||
b = sym_new_unknown(ctx);
|
||||
|
@ -1236,15 +1227,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_TUPLE: {
|
||||
_Py_UopsSymbol *b;
|
||||
b = sym_new_unknown(ctx);
|
||||
if (b == NULL) goto out_of_space;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_DICT: {
|
||||
_Py_UopsSymbol *b;
|
||||
b = sym_new_unknown(ctx);
|
||||
|
@ -1254,15 +1236,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CONTAINS_OP_STR: {
|
||||
_Py_UopsSymbol *b;
|
||||
b = sym_new_unknown(ctx);
|
||||
if (b == NULL) goto out_of_space;
|
||||
stack_pointer[-2] = b;
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CHECK_EG_MATCH: {
|
||||
_Py_UopsSymbol *rest;
|
||||
_Py_UopsSymbol *match;
|
||||
|
|
|
@ -600,6 +600,12 @@ _PyCode_Quicken(PyCodeObject *code)
|
|||
#define SPEC_FAIL_TO_BOOL_SET 17
|
||||
#define SPEC_FAIL_TO_BOOL_TUPLE 18
|
||||
|
||||
// CONTAINS_OP
|
||||
#define SPEC_FAIL_CONTAINS_OP_STR 9
|
||||
#define SPEC_FAIL_CONTAINS_OP_TUPLE 10
|
||||
#define SPEC_FAIL_CONTAINS_OP_LIST 11
|
||||
#define SPEC_FAIL_CONTAINS_OP_USER_CLASS 12
|
||||
|
||||
static int function_kind(PyCodeObject *code);
|
||||
static bool function_check_args(PyObject *o, int expected_argcount, int opcode);
|
||||
static uint32_t function_get_version(PyObject *o, int opcode);
|
||||
|
@ -2562,34 +2568,40 @@ success:
|
|||
cache->counter = adaptive_counter_cooldown();
|
||||
}
|
||||
|
||||
#ifdef Py_STATS
|
||||
static int containsop_fail_kind(PyObject *value) {
|
||||
if (PyUnicode_CheckExact(value)) {
|
||||
return SPEC_FAIL_CONTAINS_OP_STR;
|
||||
}
|
||||
if (PyList_CheckExact(value)) {
|
||||
return SPEC_FAIL_CONTAINS_OP_LIST;
|
||||
}
|
||||
if (PyTuple_CheckExact(value)) {
|
||||
return SPEC_FAIL_CONTAINS_OP_TUPLE;
|
||||
}
|
||||
if (PyType_Check(value)) {
|
||||
return SPEC_FAIL_CONTAINS_OP_USER_CLASS;
|
||||
}
|
||||
return SPEC_FAIL_OTHER;
|
||||
}
|
||||
#endif // Py_STATS
|
||||
|
||||
void
|
||||
_Py_Specialize_ContainsOp(PyObject *value, _Py_CODEUNIT *instr)
|
||||
{
|
||||
assert(ENABLE_SPECIALIZATION);
|
||||
assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
_PyContainsOpCache *cache = (_PyContainsOpCache *)(instr + 1);
|
||||
if (PyUnicode_CheckExact(value)) {
|
||||
instr->op.code = CONTAINS_OP_STR;
|
||||
goto success;
|
||||
}
|
||||
if (PyList_CheckExact(value)) {
|
||||
instr->op.code = CONTAINS_OP_LIST;
|
||||
goto success;
|
||||
}
|
||||
if (PyTuple_CheckExact(value)) {
|
||||
instr->op.code = CONTAINS_OP_TUPLE;
|
||||
goto success;
|
||||
}
|
||||
if (PyDict_CheckExact(value)) {
|
||||
instr->op.code = CONTAINS_OP_DICT;
|
||||
goto success;
|
||||
}
|
||||
if (PySet_CheckExact(value)) {
|
||||
if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
|
||||
instr->op.code = CONTAINS_OP_SET;
|
||||
goto success;
|
||||
}
|
||||
|
||||
|
||||
SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
|
||||
STAT_INC(CONTAINS_OP, failure);
|
||||
instr->op.code = CONTAINS_OP;
|
||||
cache->counter = adaptive_counter_backoff(cache->counter);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue