mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
GH-105848: Replace KW_NAMES + CALL with LOAD_CONST + CALL_KW (GH-109300)
This commit is contained in:
parent
987b4bc087
commit
22e65eecaa
22 changed files with 719 additions and 508 deletions
|
@ -473,7 +473,6 @@ _PyCode_Quicken(PyCodeObject *code)
|
|||
#define SPEC_FAIL_CALL_STR 24
|
||||
#define SPEC_FAIL_CALL_CLASS_NO_VECTORCALL 25
|
||||
#define SPEC_FAIL_CALL_CLASS_MUTABLE 26
|
||||
#define SPEC_FAIL_CALL_KWNAMES 27
|
||||
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
|
||||
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
|
||||
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
|
||||
|
@ -1644,24 +1643,23 @@ get_init_for_simple_managed_python_class(PyTypeObject *tp)
|
|||
}
|
||||
|
||||
static int
|
||||
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames)
|
||||
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
|
||||
{
|
||||
assert(PyType_Check(callable));
|
||||
PyTypeObject *tp = _PyType_CAST(callable);
|
||||
if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
|
||||
int oparg = instr->op.arg;
|
||||
if (nargs == 1 && kwnames == NULL && oparg == 1) {
|
||||
if (nargs == 1 && oparg == 1) {
|
||||
if (tp == &PyUnicode_Type) {
|
||||
instr->op.code = CALL_NO_KW_STR_1;
|
||||
instr->op.code = CALL_STR_1;
|
||||
return 0;
|
||||
}
|
||||
else if (tp == &PyType_Type) {
|
||||
instr->op.code = CALL_NO_KW_TYPE_1;
|
||||
instr->op.code = CALL_TYPE_1;
|
||||
return 0;
|
||||
}
|
||||
else if (tp == &PyTuple_Type) {
|
||||
instr->op.code = CALL_NO_KW_TUPLE_1;
|
||||
instr->op.code = CALL_TUPLE_1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1680,13 +1678,9 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
|||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
||||
return -1;
|
||||
}
|
||||
if (kwnames) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
|
||||
return -1;
|
||||
}
|
||||
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
|
||||
write_u32(cache->func_version, tp->tp_version_tag);
|
||||
_Py_SET_OPCODE(*instr, CALL_NO_KW_ALLOC_AND_ENTER_INIT);
|
||||
_Py_SET_OPCODE(*instr, CALL_ALLOC_AND_ENTER_INIT);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
@ -1744,13 +1738,8 @@ meth_descr_call_fail_kind(int ml_flags)
|
|||
|
||||
static int
|
||||
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
|
||||
int nargs, PyObject *kwnames)
|
||||
int nargs)
|
||||
{
|
||||
if (kwnames) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (descr->d_method->ml_flags &
|
||||
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
|
||||
METH_KEYWORDS | METH_METHOD)) {
|
||||
|
@ -1759,7 +1748,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
|
|||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
||||
return -1;
|
||||
}
|
||||
instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS;
|
||||
instr->op.code = CALL_METHOD_DESCRIPTOR_NOARGS;
|
||||
return 0;
|
||||
}
|
||||
case METH_O: {
|
||||
|
@ -1773,14 +1762,14 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
|
|||
bool pop = (next.op.code == POP_TOP);
|
||||
int oparg = instr->op.arg;
|
||||
if ((PyObject *)descr == list_append && oparg == 1 && pop) {
|
||||
instr->op.code = CALL_NO_KW_LIST_APPEND;
|
||||
instr->op.code = CALL_LIST_APPEND;
|
||||
return 0;
|
||||
}
|
||||
instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_O;
|
||||
instr->op.code = CALL_METHOD_DESCRIPTOR_O;
|
||||
return 0;
|
||||
}
|
||||
case METH_FASTCALL: {
|
||||
instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_FAST;
|
||||
instr->op.code = CALL_METHOD_DESCRIPTOR_FAST;
|
||||
return 0;
|
||||
}
|
||||
case METH_FASTCALL | METH_KEYWORDS: {
|
||||
|
@ -1794,7 +1783,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
|
|||
|
||||
static int
|
||||
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames, bool bound_method)
|
||||
bool bound_method)
|
||||
{
|
||||
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
|
||||
PyCodeObject *code = (PyCodeObject *)func->func_code;
|
||||
|
@ -1804,10 +1793,6 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
|
|||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
|
||||
return -1;
|
||||
}
|
||||
if (kwnames) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
|
||||
return -1;
|
||||
}
|
||||
if (kind != SIMPLE_FUNCTION) {
|
||||
SPECIALIZATION_FAIL(CALL, kind);
|
||||
return -1;
|
||||
|
@ -1843,8 +1828,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
|
|||
}
|
||||
|
||||
static int
|
||||
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames)
|
||||
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
|
||||
{
|
||||
if (PyCFunction_GET_FUNCTION(callable) == NULL) {
|
||||
return 1;
|
||||
|
@ -1853,10 +1837,6 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
|||
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
|
||||
METH_KEYWORDS | METH_METHOD)) {
|
||||
case METH_O: {
|
||||
if (kwnames) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
|
||||
return -1;
|
||||
}
|
||||
if (nargs != 1) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
||||
return 1;
|
||||
|
@ -1864,26 +1844,22 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
|||
/* len(o) */
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
if (callable == interp->callable_cache.len) {
|
||||
instr->op.code = CALL_NO_KW_LEN;
|
||||
instr->op.code = CALL_LEN;
|
||||
return 0;
|
||||
}
|
||||
instr->op.code = CALL_NO_KW_BUILTIN_O;
|
||||
instr->op.code = CALL_BUILTIN_O;
|
||||
return 0;
|
||||
}
|
||||
case METH_FASTCALL: {
|
||||
if (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) {
|
||||
instr->op.code = CALL_NO_KW_ISINSTANCE;
|
||||
instr->op.code = CALL_ISINSTANCE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
instr->op.code = CALL_NO_KW_BUILTIN_FAST;
|
||||
instr->op.code = CALL_BUILTIN_FAST;
|
||||
return 0;
|
||||
}
|
||||
case METH_FASTCALL | METH_KEYWORDS: {
|
||||
|
@ -1924,12 +1900,8 @@ call_fail_kind(PyObject *callable)
|
|||
#endif // Py_STATS
|
||||
|
||||
|
||||
/* TODO:
|
||||
- Specialize calling classes.
|
||||
*/
|
||||
void
|
||||
_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames)
|
||||
_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
|
||||
{
|
||||
assert(ENABLE_SPECIALIZATION);
|
||||
assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
|
||||
|
@ -1937,25 +1909,23 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
|||
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
|
||||
int fail;
|
||||
if (PyCFunction_CheckExact(callable)) {
|
||||
fail = specialize_c_call(callable, instr, nargs, kwnames);
|
||||
fail = specialize_c_call(callable, instr, nargs);
|
||||
}
|
||||
else if (PyFunction_Check(callable)) {
|
||||
fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs,
|
||||
kwnames, false);
|
||||
fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
|
||||
}
|
||||
else if (PyType_Check(callable)) {
|
||||
fail = specialize_class_call(callable, instr, nargs, kwnames);
|
||||
fail = specialize_class_call(callable, instr, nargs);
|
||||
}
|
||||
else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
|
||||
fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
|
||||
instr, nargs, kwnames);
|
||||
fail = specialize_method_descriptor((PyMethodDescrObject *)callable, instr, nargs);
|
||||
}
|
||||
else if (PyMethod_Check(callable)) {
|
||||
PyObject *func = ((PyMethodObject *)callable)->im_func;
|
||||
if (PyFunction_Check(func)) {
|
||||
fail = specialize_py_call((PyFunctionObject *)func,
|
||||
instr, nargs+1, kwnames, true);
|
||||
} else {
|
||||
fail = specialize_py_call((PyFunctionObject *)func, instr, nargs+1, true);
|
||||
}
|
||||
else {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
|
||||
fail = -1;
|
||||
}
|
||||
|
@ -2491,7 +2461,7 @@ success:
|
|||
}
|
||||
|
||||
/* Code init cleanup.
|
||||
* CALL_NO_KW_ALLOC_AND_ENTER_INIT will set up
|
||||
* CALL_ALLOC_AND_ENTER_INIT will set up
|
||||
* the frame to execute the EXIT_INIT_CHECK
|
||||
* instruction.
|
||||
* Ends with a RESUME so that it is not traced.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue