diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bytecodes.c | 32 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 59 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 71 | ||||
-rw-r--r-- | Python/opcode_targets.h | 6 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 27 | ||||
-rw-r--r-- | Python/specialize.c | 40 |
6 files changed, 41 insertions, 194 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3276a4a..0397d96 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -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(); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 2e7b970..26ac159 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -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; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 54c4861..f5d125c 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -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; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 6b3846d..4061ba3 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -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, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index e438497..c88b251 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -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; diff --git a/Python/specialize.c b/Python/specialize.c index 5d339b8..b1f9eb7 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -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(); } -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); +#ifdef Py_STATS +static int containsop_fail_kind(PyObject *value) { if (PyUnicode_CheckExact(value)) { - instr->op.code = CONTAINS_OP_STR; - goto success; + return SPEC_FAIL_CONTAINS_OP_STR; } if (PyList_CheckExact(value)) { - instr->op.code = CONTAINS_OP_LIST; - goto success; + return SPEC_FAIL_CONTAINS_OP_LIST; } if (PyTuple_CheckExact(value)) { - instr->op.code = CONTAINS_OP_TUPLE; - goto success; + 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 (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); |