mirror of
https://github.com/python/cpython.git
synced 2024-11-24 10:24:35 +08:00
Inline fast_cfunction() in new call_function().
Also, don't handle METH_OLDARGS on the fast path. All the interesting builtins have been converted to use METH_NOARGS, METH_O, or METH_VARARGS. Result is another 1-2% speedup. If I can cobble together 10 of these, it might make a difference.
This commit is contained in:
parent
aca139d17d
commit
192690e2d2
@ -35,7 +35,6 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
|
||||
static PyObject *eval_frame(PyFrameObject *);
|
||||
static PyObject *call_function(PyObject ***, int);
|
||||
static PyObject *fast_function(PyObject *, PyObject ***, int, int, int);
|
||||
static PyObject *fast_cfunction(PyObject *, PyObject ***, int);
|
||||
static PyObject *do_call(PyObject *, PyObject ***, int, int);
|
||||
static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int);
|
||||
static PyObject *update_keyword_args(PyObject *, int, PyObject ***,PyObject *);
|
||||
@ -3146,6 +3145,21 @@ PyEval_GetFuncDesc(PyObject *func)
|
||||
|
||||
#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
|
||||
|
||||
void
|
||||
err_args(PyObject *func, int flags, int nargs)
|
||||
{
|
||||
if (flags & METH_NOARGS)
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes 1 argument (%d given)",
|
||||
((PyCFunctionObject *)func)->m_ml->ml_name,
|
||||
nargs);
|
||||
else
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no arguments (%d given)",
|
||||
((PyCFunctionObject *)func)->m_ml->ml_name,
|
||||
nargs);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
call_function(PyObject ***pp_stack, int oparg)
|
||||
{
|
||||
@ -3162,13 +3176,27 @@ call_function(PyObject ***pp_stack, int oparg)
|
||||
*/
|
||||
if (PyCFunction_Check(func) && nk == 0) {
|
||||
int flags = PyCFunction_GET_FLAGS(func);
|
||||
if (flags & (METH_VARARGS | METH_KEYWORDS)) {
|
||||
if (flags & (METH_NOARGS | METH_O)) {
|
||||
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
|
||||
PyObject *self = PyCFunction_GET_SELF(func);
|
||||
if (flags & METH_NOARGS && na == 0)
|
||||
x = (*meth)(self, NULL);
|
||||
else if (flags & METH_O && na == 1) {
|
||||
PyObject *arg = EXT_POP(*pp_stack);
|
||||
x = (*meth)(self, arg);
|
||||
Py_DECREF(arg);
|
||||
}
|
||||
else {
|
||||
err_args(func, flags, na);
|
||||
x = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyObject *callargs;
|
||||
callargs = load_args(pp_stack, na);
|
||||
x = PyCFunction_Call(func, callargs, NULL);
|
||||
Py_XDECREF(callargs);
|
||||
} else
|
||||
x = fast_cfunction(func, pp_stack, na);
|
||||
}
|
||||
} else {
|
||||
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
|
||||
/* optimize access to bound methods */
|
||||
@ -3196,60 +3224,10 @@ call_function(PyObject ***pp_stack, int oparg)
|
||||
return x;
|
||||
}
|
||||
|
||||
/* The two fast_xxx() functions optimize calls for which no argument
|
||||
/* The fast_function() function optimize calls for which no argument
|
||||
tuple is necessary; the objects are passed directly from the stack.
|
||||
fast_cfunction() is called for METH_OLDARGS functions.
|
||||
fast_function() is for functions with no special argument handling.
|
||||
*/
|
||||
|
||||
static PyObject *
|
||||
fast_cfunction(PyObject *func, PyObject ***pp_stack, int na)
|
||||
{
|
||||
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
|
||||
PyObject *self = PyCFunction_GET_SELF(func);
|
||||
int flags = PyCFunction_GET_FLAGS(func);
|
||||
|
||||
switch (flags) {
|
||||
case METH_OLDARGS:
|
||||
if (na == 0)
|
||||
return (*meth)(self, NULL);
|
||||
else if (na == 1) {
|
||||
PyObject *arg = EXT_POP(*pp_stack);
|
||||
PyObject *result = (*meth)(self, arg);
|
||||
Py_DECREF(arg);
|
||||
return result;
|
||||
} else {
|
||||
PyObject *args = load_args(pp_stack, na);
|
||||
PyObject *result = (*meth)(self, args);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
}
|
||||
case METH_NOARGS:
|
||||
if (na == 0)
|
||||
return (*meth)(self, NULL);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes no arguments (%d given)",
|
||||
((PyCFunctionObject*)func)->m_ml->ml_name, na);
|
||||
return NULL;
|
||||
case METH_O:
|
||||
if (na == 1) {
|
||||
PyObject *arg = EXT_POP(*pp_stack);
|
||||
PyObject *result = (*meth)(self, arg);
|
||||
Py_DECREF(arg);
|
||||
return result;
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s() takes exactly one argument (%d given)",
|
||||
((PyCFunctionObject*)func)->m_ml->ml_name, na);
|
||||
return NULL;
|
||||
default:
|
||||
fprintf(stderr, "%.200s() flags = %d\n",
|
||||
((PyCFunctionObject*)func)->m_ml->ml_name, flags);
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user