diff options
author | Mark Shannon <mark@hotpy.org> | 2022-05-19 10:05:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-19 10:05:26 (GMT) |
commit | e48ac9c1003c3816198cbfb6132a995150f9b048 (patch) | |
tree | bfe576152225f7f05da1506bbf1ca31f211823e9 /Python/specialize.c | |
parent | 41638967a0e0bf1114c9bba9454d081605b49009 (diff) | |
download | cpython-e48ac9c1003c3816198cbfb6132a995150f9b048.zip cpython-e48ac9c1003c3816198cbfb6132a995150f9b048.tar.gz cpython-e48ac9c1003c3816198cbfb6132a995150f9b048.tar.bz2 |
GH-90690: Remove `PRECALL` instruction (GH-92925)
Diffstat (limited to 'Python/specialize.c')
-rw-r--r-- | Python/specialize.c | 136 |
1 files changed, 58 insertions, 78 deletions
diff --git a/Python/specialize.c b/Python/specialize.c index 5469285..9579369 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -24,7 +24,6 @@ uint8_t _PyOpcode_Adaptive[256] = { [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE, [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE, [CALL] = CALL_ADAPTIVE, - [PRECALL] = PRECALL_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, [COMPARE_OP] = COMPARE_OP_ADAPTIVE, @@ -121,7 +120,6 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, BINARY_OP, "binary_op"); err += add_stat_dict(stats, COMPARE_OP, "compare_op"); err += add_stat_dict(stats, UNPACK_SEQUENCE, "unpack_sequence"); - err += add_stat_dict(stats, PRECALL, "precall"); if (err < 0) { Py_DECREF(stats); return NULL; @@ -1358,38 +1356,39 @@ success: static int specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames, int oparg) + PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); PyTypeObject *tp = _PyType_CAST(callable); if (tp->tp_new == PyBaseObject_Type.tp_new) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_PYTHON_CLASS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PYTHON_CLASS); return -1; } if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { + int oparg = _Py_OPARG(*instr); if (nargs == 1 && kwnames == NULL && oparg == 1) { if (tp == &PyUnicode_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_STR_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_STR_1); return 0; } else if (tp == &PyType_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_TYPE_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_TYPE_1); return 0; } else if (tp == &PyTuple_Type) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_TUPLE_1); + _Py_SET_OPCODE(*instr, CALL_NO_KW_TUPLE_1); return 0; } } if (tp->tp_vectorcall != NULL) { - _Py_SET_OPCODE(*instr, PRECALL_BUILTIN_CLASS); + _Py_SET_OPCODE(*instr, CALL_BUILTIN_CLASS); return 0; } - SPECIALIZATION_FAIL(PRECALL, tp == &PyUnicode_Type ? + SPECIALIZATION_FAIL(CALL, tp == &PyUnicode_Type ? SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL); return -1; } - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_CLASS_MUTABLE); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_CLASS_MUTABLE); return -1; } @@ -1419,11 +1418,11 @@ builtin_call_fail_kind(int ml_flags) static int specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, - int nargs, PyObject *kwnames, int oparg) + int nargs, PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } @@ -1432,45 +1431,45 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr, METH_KEYWORDS | METH_METHOD)) { case METH_NOARGS: { if (nargs != 1) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS); return 0; } case METH_O: { if (nargs != 2) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return -1; } PyInterpreterState *interp = _PyInterpreterState_GET(); PyObject *list_append = interp->callable_cache.list_append; - _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_PRECALL + 1 - + INLINE_CACHE_ENTRIES_CALL + 1]; + _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1]; bool pop = (_Py_OPCODE(next) == POP_TOP); + int oparg = _Py_OPARG(*instr); if ((PyObject *)descr == list_append && oparg == 1 && pop) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_LIST_APPEND); + _Py_SET_OPCODE(*instr, CALL_NO_KW_LIST_APPEND); return 0; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_O); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_O); return 0; } case METH_FASTCALL: { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST); + _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_FAST); return 0; } case METH_FASTCALL|METH_KEYWORDS: { - _Py_SET_OPCODE(*instr, PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); + _Py_SET_OPCODE(*instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); return 0; } } - SPECIALIZATION_FAIL(PRECALL, builtin_call_fail_kind(descr->d_method->ml_flags)); + SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(descr->d_method->ml_flags)); return -1; } static int specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) + PyObject *kwnames, bool bound_method) { _PyCallCache *cache = (_PyCallCache *)(instr + 1); assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); @@ -1512,7 +1511,11 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, write_u32(cache->func_version, version); cache->min_args = min_args; if (argcount == nargs) { - _Py_SET_OPCODE(*instr, CALL_PY_EXACT_ARGS); + _Py_SET_OPCODE(*instr, bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS); + } + else if (bound_method) { + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD); + return -1; } else { _Py_SET_OPCODE(*instr, CALL_PY_WITH_DEFAULTS); @@ -1524,7 +1527,7 @@ static int specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames) { - assert(_Py_OPCODE(*instr) == PRECALL_ADAPTIVE); + assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE); if (PyCFunction_GET_FUNCTION(callable) == NULL) { return 1; } @@ -1533,44 +1536,44 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, METH_KEYWORDS | METH_METHOD)) { case METH_O: { if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } if (nargs != 1) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); return 1; } /* len(o) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.len) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_LEN); + _Py_SET_OPCODE(*instr, CALL_NO_KW_LEN); return 0; } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_BUILTIN_O); + _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_O); return 0; } case METH_FASTCALL: { if (kwnames) { - SPECIALIZATION_FAIL(PRECALL, SPEC_FAIL_CALL_KWNAMES); + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES); return -1; } if (nargs == 2) { /* isinstance(o1, o2) */ PyInterpreterState *interp = _PyInterpreterState_GET(); if (callable == interp->callable_cache.isinstance) { - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_ISINSTANCE); + _Py_SET_OPCODE(*instr, CALL_NO_KW_ISINSTANCE); return 0; } } - _Py_SET_OPCODE(*instr, PRECALL_NO_KW_BUILTIN_FAST); + _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_FAST); return 0; } case METH_FASTCALL | METH_KEYWORDS: { - _Py_SET_OPCODE(*instr, PRECALL_BUILTIN_FAST_WITH_KEYWORDS); + _Py_SET_OPCODE(*instr, CALL_BUILTIN_FAST_WITH_KEYWORDS); return 0; } default: - SPECIALIZATION_FAIL(PRECALL, + SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable))); return 1; } @@ -1618,62 +1621,39 @@ call_fail_kind(PyObject *callable) #endif +/* TODO: + - Specialize calling classes. +*/ int -_Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames, int oparg) +_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, + PyObject *kwnames) { - assert(_PyOpcode_Caches[PRECALL] == INLINE_CACHE_ENTRIES_PRECALL); - _PyPrecallCache *cache = (_PyPrecallCache *)(instr + 1); + assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); + _PyCallCache *cache = (_PyCallCache *)(instr + 1); int fail; if (PyCFunction_CheckExact(callable)) { fail = specialize_c_call(callable, instr, nargs, kwnames); } else if (PyFunction_Check(callable)) { - _Py_SET_OPCODE(*instr, PRECALL_PYFUNC); - fail = 0; + fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, + kwnames, false); } else if (PyType_Check(callable)) { - fail = specialize_class_call(callable, instr, nargs, kwnames, oparg); + fail = specialize_class_call(callable, instr, nargs, kwnames); } else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) { fail = specialize_method_descriptor((PyMethodDescrObject *)callable, - instr, nargs, kwnames, oparg); + instr, nargs, kwnames); } else if (Py_TYPE(callable) == &PyMethod_Type) { - _Py_SET_OPCODE(*instr, PRECALL_BOUND_METHOD); - fail = 0; - } - else { - SPECIALIZATION_FAIL(PRECALL, call_fail_kind(callable)); - fail = -1; - } - if (fail) { - STAT_INC(PRECALL, failure); - assert(!PyErr_Occurred()); - cache->counter = ADAPTIVE_CACHE_BACKOFF; - } - else { - STAT_INC(PRECALL, success); - assert(!PyErr_Occurred()); - cache->counter = initial_counter_value(); - } - return 0; -} - - -/* TODO: - - Specialize calling classes. -*/ -int -_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, - PyObject *kwnames) -{ - assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL); - _PyCallCache *cache = (_PyCallCache *)(instr + 1); - int fail; - if (PyFunction_Check(callable)) { - fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, - kwnames); + PyObject *func = ((PyMethodObject *)callable)->im_func; + if (PyFunction_Check(func)) { + fail = specialize_py_call((PyFunctionObject *)func, + instr, nargs+1, kwnames, true); + } else { + SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD); + fail = -1; + } } else { SPECIALIZATION_FAIL(CALL, call_fail_kind(callable)); |