diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2002-08-16 18:36:11 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2002-08-16 18:36:11 (GMT) |
commit | 192690e2d21f90a2725dceec62f99bba26a9faf1 (patch) | |
tree | a73a1ff2e3530cab9376c7d6c22c671bff8defaf | |
parent | aca139d17dbdaa41c78204dbab14bd1c7d888542 (diff) | |
download | cpython-192690e2d21f90a2725dceec62f99bba26a9faf1.zip cpython-192690e2d21f90a2725dceec62f99bba26a9faf1.tar.gz cpython-192690e2d21f90a2725dceec62f99bba26a9faf1.tar.bz2 |
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.
-rw-r--r-- | Python/ceval.c | 88 |
1 files changed, 33 insertions, 55 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 54114fc..4f24bab 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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,61 +3224,11 @@ 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) { PyObject *co = PyFunction_GET_CODE(func); |