diff options
-rw-r--r-- | Include/methodobject.h | 5 | ||||
-rw-r--r-- | Objects/methodobject.c | 70 | ||||
-rw-r--r-- | Python/ceval.c | 238 |
3 files changed, 58 insertions, 255 deletions
diff --git a/Include/methodobject.h b/Include/methodobject.h index a205011..e47ebea 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -14,6 +14,7 @@ extern DL_IMPORT(PyTypeObject) PyCFunction_Type; typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*PyNoArgsFunction)(PyObject *); extern DL_IMPORT(PyCFunction) PyCFunction_GetFunction(PyObject *); extern DL_IMPORT(PyObject *) PyCFunction_GetSelf(PyObject *); @@ -27,6 +28,7 @@ extern DL_IMPORT(int) PyCFunction_GetFlags(PyObject *); (((PyCFunctionObject *)func) -> m_self) #define PyCFunction_GET_FLAGS(func) \ (((PyCFunctionObject *)func) -> m_ml -> ml_flags) +extern DL_IMPORT(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); struct PyMethodDef { char *ml_name; @@ -44,6 +46,9 @@ extern DL_IMPORT(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); #define METH_OLDARGS 0x0000 #define METH_VARARGS 0x0001 #define METH_KEYWORDS 0x0002 +/* METH_NOARGS and METH_O must not be combined with any other flag. */ +#define METH_NOARGS 0x0004 +#define METH_O 0x0008 typedef struct PyMethodChain { PyMethodDef *methods; /* Methods of this type */ diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 56fbcc2..9d43044 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -56,6 +56,40 @@ PyCFunction_GetFlags(PyObject *op) return ((PyCFunctionObject *)op) -> m_ml -> ml_flags; } +PyObject * +PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) +{ + PyCFunctionObject* f = (PyCFunctionObject*)func; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + + if (flags & METH_KEYWORDS) { + return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); + } + if (kw != NULL && PyDict_Size(kw) != 0) { + PyErr_Format(PyExc_TypeError, + "%.200s() takes no keyword arguments", + f->m_ml->ml_name); + return NULL; + } + if (flags & METH_VARARGS) { + return (*meth)(self, arg); + } + if (!(flags & METH_VARARGS)) { + /* the really old style */ + int size = PyTuple_GET_SIZE(arg); + if (size == 1) + arg = PyTuple_GET_ITEM(arg, 0); + else if (size == 0) + arg = NULL; + return (*meth)(self, arg); + } + /* should never get here ??? */ + PyErr_BadInternalCall(); + return NULL; +} + /* Methods (the standard built-in methods, that is) */ static void @@ -163,40 +197,6 @@ meth_hash(PyCFunctionObject *a) return x; } -static PyObject * -meth_call(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyCFunctionObject* f = (PyCFunctionObject*)func; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - - if (flags & METH_KEYWORDS) { - return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); - } - if (kw != NULL && PyDict_Size(kw) != 0) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes no keyword arguments", - f->m_ml->ml_name); - return NULL; - } - if (flags & METH_VARARGS) { - return (*meth)(self, arg); - } - if (!(flags & METH_VARARGS)) { - /* the really old style */ - int size = PyTuple_GET_SIZE(arg); - if (size == 1) - arg = PyTuple_GET_ITEM(arg, 0); - else if (size == 0) - arg = NULL; - return (*meth)(self, arg); - } - /* should never get here ??? */ - PyErr_BadInternalCall(); - return NULL; -} - PyTypeObject PyCFunction_Type = { PyObject_HEAD_INIT(&PyType_Type) @@ -214,7 +214,7 @@ PyTypeObject PyCFunction_Type = { 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)meth_hash, /* tp_hash */ - meth_call, /* tp_call */ + PyCFunction_Call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ diff --git a/Python/ceval.c b/Python/ceval.c index bf85f11..7e98a25 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -34,11 +34,6 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *); /* Forward declarations */ static PyObject *eval_frame(PyFrameObject *); -static PyObject *call_object(PyObject *, PyObject *, PyObject *); -static PyObject *call_cfunction(PyObject *, PyObject *, PyObject *); -static PyObject *call_instance(PyObject *, PyObject *, PyObject *); -static PyObject *call_method(PyObject *, PyObject *, PyObject *); -static PyObject *call_eval_code2(PyObject *, PyObject *, PyObject *); static PyObject *fast_function(PyObject *, PyObject ***, int, int, int); static PyObject *fast_cfunction(PyObject *, PyObject ***, int); static PyObject *do_call(PyObject *, PyObject ***, int, int); @@ -1949,11 +1944,11 @@ eval_frame(PyFrameObject *f) else if (flags == METH_VARARGS) { PyObject *callargs; callargs = load_args(&stack_pointer, na); - x = call_cfunction(func, callargs, NULL); + x = PyCFunction_Call(func, callargs, NULL); Py_XDECREF(callargs); - } else if (flags == 0) - x = fast_cfunction(func, - &stack_pointer, na); + } else if (!(flags & METH_KEYWORDS)) + x = fast_cfunction(func, + &stack_pointer, na); } else { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { @@ -2307,7 +2302,8 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, PyObject *x, *u; if (globals == NULL) { - PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals"); + PyErr_SetString(PyExc_SystemError, + "PyEval_EvalCodeEx: NULL globals"); return NULL; } @@ -3000,20 +2996,6 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) return result; } -/* How often is each kind of object called? The answer depends on the - program. An instrumented PyObject_Call() was used to run the Python - regression test suite. The results were: - 4200000 PyCFunctions - 390000 fast_function() calls - 94000 other functions - 480000 all functions (sum of prev two) - 150000 methods - 100000 classes - - Tests on other bodies of code show that PyCFunctions are still - most common, but not by such a large margin. -*/ - char * PyEval_GetFuncName(PyObject *func) { @@ -3051,190 +3033,6 @@ PyEval_GetFuncDesc(PyObject *func) } } -static PyObject * -call_object(PyObject *func, PyObject *arg, PyObject *kw) -{ - ternaryfunc call; - PyObject *result; - - if (PyMethod_Check(func)) - result = call_method(func, arg, kw); - else if (PyFunction_Check(func)) - result = call_eval_code2(func, arg, kw); - else if (PyCFunction_Check(func)) - result = call_cfunction(func, arg, kw); - else if (PyClass_Check(func)) - result = PyInstance_New(func, arg, kw); - else if (PyInstance_Check(func)) - result = call_instance(func, arg, kw); - else if ((call = func->ob_type->tp_call) != NULL) - result = (*call)(func, arg, kw); - else { - PyErr_Format(PyExc_TypeError, - "object of type '%.100s' is not callable", - func->ob_type->tp_name); - return NULL; - } - if (result == NULL && !PyErr_Occurred()) - PyErr_SetString(PyExc_SystemError, - "NULL result without error in call_object"); - - return result; -} - -static PyObject * -call_cfunction(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyCFunctionObject* f = (PyCFunctionObject*)func; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - - if (flags & METH_KEYWORDS) { - return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); - } - if (kw != NULL && PyDict_Size(kw) != 0) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes no keyword arguments", - f->m_ml->ml_name); - return NULL; - } - if (flags & METH_VARARGS) { - return (*meth)(self, arg); - } - if (!(flags & METH_VARARGS)) { - /* the really old style */ - int size = PyTuple_GET_SIZE(arg); - if (size == 1) - arg = PyTuple_GET_ITEM(arg, 0); - else if (size == 0) - arg = NULL; - return (*meth)(self, arg); - } - /* should never get here ??? */ - PyErr_BadInternalCall(); - return NULL; -} - -static PyObject * -call_instance(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyObject *res, *call = PyObject_GetAttrString(func, "__call__"); - if (call == NULL) { - PyInstanceObject *inst = (PyInstanceObject*) func; - PyErr_Clear(); - PyErr_Format(PyExc_AttributeError, - "%.200s instance has no __call__ method", - PyString_AsString(inst->in_class->cl_name)); - return NULL; - } - res = call_object(call, arg, kw); - Py_DECREF(call); - return res; -} - -static PyObject * -call_method(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyObject *self = PyMethod_GET_SELF(func); - PyObject *class = PyMethod_GET_CLASS(func); - PyObject *result; - - func = PyMethod_GET_FUNCTION(func); - if (self == NULL) { - /* Unbound methods must be called with an instance of - the class (or a derived class) as first argument */ - int ok; - if (PyTuple_Size(arg) >= 1) - self = PyTuple_GET_ITEM(arg, 0); - if (self == NULL) - ok = 0; - else { - ok = PyObject_IsInstance(self, class); - if (ok < 0) - return NULL; - } - if (!ok) { - PyErr_Format(PyExc_TypeError, - "unbound method %s%s must be " - "called with instance as first argument", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - return NULL; - } - Py_INCREF(arg); - } - else { - int argcount = PyTuple_Size(arg); - PyObject *newarg = PyTuple_New(argcount + 1); - int i; - if (newarg == NULL) - return NULL; - Py_INCREF(self); - PyTuple_SET_ITEM(newarg, 0, self); - for (i = 0; i < argcount; i++) { - PyObject *v = PyTuple_GET_ITEM(arg, i); - Py_XINCREF(v); - PyTuple_SET_ITEM(newarg, i+1, v); - } - arg = newarg; - } - result = call_object(func, arg, kw); - Py_DECREF(arg); - return result; -} - -static PyObject * -call_eval_code2(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyObject *result; - PyObject *argdefs; - PyObject **d, **k; - int nk, nd; - - argdefs = PyFunction_GET_DEFAULTS(func); - if (argdefs != NULL && PyTuple_Check(argdefs)) { - d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); - nd = PyTuple_Size(argdefs); - } - else { - d = NULL; - nd = 0; - } - - if (kw != NULL) { - int pos, i; - nk = PyDict_Size(kw); - k = PyMem_NEW(PyObject *, 2*nk); - if (k == NULL) { - PyErr_NoMemory(); - Py_DECREF(arg); - return NULL; - } - pos = i = 0; - while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) - i += 2; - nk = i/2; - /* XXX This is broken if the caller deletes dict items! */ - } - else { - k = NULL; - nk = 0; - } - - result = PyEval_EvalCodeEx( - (PyCodeObject *)PyFunction_GET_CODE(func), - PyFunction_GET_GLOBALS(func), (PyObject *)NULL, - &PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg), - k, nk, d, nd, - PyFunction_GET_CLOSURE(func)); - - if (k != NULL) - PyMem_DEL(k); - - return result; -} - #define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) /* The two fast_xxx() functions optimize calls for which no argument @@ -3249,18 +3047,18 @@ fast_cfunction(PyObject *func, PyObject ***pp_stack, int na) PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); - 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; + 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; } } |