summaryrefslogtreecommitdiffstats
path: root/Python/specialize.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-05-19 10:05:26 (GMT)
committerGitHub <noreply@github.com>2022-05-19 10:05:26 (GMT)
commite48ac9c1003c3816198cbfb6132a995150f9b048 (patch)
treebfe576152225f7f05da1506bbf1ca31f211823e9 /Python/specialize.c
parent41638967a0e0bf1114c9bba9454d081605b49009 (diff)
downloadcpython-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.c136
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));