? Python/.bltinmodule.c.swp ? Python/.ceval.c.swp ? Python/ceval.c.exact ? Python/ceval.c.working Index: Include/methodobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/methodobject.h,v retrieving revision 2.28 diff -w -u -r2.28 methodobject.h --- Include/methodobject.h 28 Oct 2004 16:31:58 -0000 2.28 +++ Include/methodobject.h 24 Jan 2005 23:27:40 -0000 @@ -28,6 +28,10 @@ done, so use with care. */ #define PyCFunction_GET_FUNCTION(func) \ (((PyCFunctionObject *)func) -> m_ml -> ml_meth) +#define PyCFunction_GET_MIN_ARGS(func) \ + (((PyCFunctionObject *)func) -> m_ml -> ml_min_args) +#define PyCFunction_GET_MAX_ARGS(func) \ + (((PyCFunctionObject *)func) -> m_ml -> ml_max_args) #define PyCFunction_GET_SELF(func) \ (((PyCFunctionObject *)func) -> m_self) #define PyCFunction_GET_FLAGS(func) \ @@ -40,6 +44,8 @@ int ml_flags; /* Combination of METH_xxx flags, which mostly describe the args expected by the C func */ char *ml_doc; /* The __doc__ attribute, or NULL */ + int ml_min_args; /* The minimum # args to pass when METH_ARGS */ + int ml_max_args; /* The maximum # args to pass when METH_ARGS */ }; typedef struct PyMethodDef PyMethodDef; @@ -70,6 +76,13 @@ #define METH_COEXIST 0x0040 +/* METH_ARGS cannot be used with: + METH_OLDARGS, METH_VARARGS, METH_NOARGS, or METH_O + Its purpose is to expand the arguments when calling the function + rather than passing a tuple as the second argument. +*/ +#define METH_ARGS 0x0080 + typedef struct PyMethodChain { PyMethodDef *methods; /* Methods of this type */ struct PyMethodChain *link; /* NULL or base type */ Index: Objects/methodobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v retrieving revision 2.48 diff -w -u -r2.48 methodobject.c --- Objects/methodobject.c 13 Dec 2003 11:26:11 -0000 2.48 +++ Objects/methodobject.c 24 Jan 2005 23:27:40 -0000 @@ -6,6 +6,9 @@ static PyCFunctionObject *free_list = NULL; +static PyObject* +new_fast_function(PyObject *func, PyObject *self, PyObject *arg); + PyObject * PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) { @@ -97,6 +100,21 @@ return NULL; } break; + case METH_ARGS: + if (kw == NULL || PyDict_Size(kw) == 0) { + size = PyTuple_GET_SIZE(arg); + if (size >= f->m_ml->ml_min_args && + size <= f->m_ml->ml_max_args) + return new_fast_function(func, self, arg); + PyErr_Format(PyExc_TypeError, + "%.200s() takes %d-%d arguments (%d given)", + f->m_ml->ml_name, + f->m_ml->ml_min_args, + f->m_ml->ml_max_args, + size); + return NULL; + } + break; case METH_OLDARGS: /* the really old style */ if (kw == NULL || PyDict_Size(kw) == 0) { @@ -117,6 +135,68 @@ return NULL; } + +/* XXX: copied (and modified) from Python/celva.c */ + +typedef PyObject *(*PyCVarArgFunction)(PyObject*, ...); + +static PyObject* +new_fast_function(PyObject *func, PyObject *self, PyObject *args) { + PyObject *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, + *arg4 = NULL, *arg5 = NULL, *arg6 = NULL, + *arg7 = NULL, *arg8 = NULL, *arg9 = NULL; + PyCVarArgFunction meth = + (PyCVarArgFunction) PyCFunction_GET_FUNCTION(func); + + /* XXX: need to determine best # of args to support */ + + /* XXX: If we know that na == max_args, this can be optimized + by having a single switch, which should save me a moderage win + */ + + /* handle varargs, note that if na > 0 each case falls through */ + switch (PyTuple_GET_SIZE(args)) { + case 0: break; + case 9: arg9 = PyTuple_GET_ITEM(args, 8); + case 8: arg8 = PyTuple_GET_ITEM(args, 7); + case 7: arg7 = PyTuple_GET_ITEM(args, 6); + case 6: arg6 = PyTuple_GET_ITEM(args, 5); + case 5: arg5 = PyTuple_GET_ITEM(args, 4); + case 4: arg4 = PyTuple_GET_ITEM(args, 3); + case 3: arg3 = PyTuple_GET_ITEM(args, 2); + case 2: arg2 = PyTuple_GET_ITEM(args, 1); + case 1: arg1 = PyTuple_GET_ITEM(args, 0); + break; + + default: + // FIXME: raise SystemError + fprintf(stderr, "FIXME: methodobject: busted METH_ARGS, na=%d\n", + PyTuple_GET_SIZE(args)); + return NULL; + } + + // FIXME: it would be nice to handle the DECREFs here + // so they are unwound and we don't need a loop + switch (PyCFunction_GET_MAX_ARGS(func)) { + case 0: return (*meth)(self); + case 1: return (*meth)(self, arg1); + case 2: return (*meth)(self, arg1, arg2); + case 3: return (*meth)(self, arg1, arg2, arg3); + case 4: return (*meth)(self, arg1, arg2, arg3, arg4); + case 5: return (*meth)(self, arg1, arg2, arg3, arg4, arg5); + case 6: return (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6); + case 7: return (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + case 8: return (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + case 9: return (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + + default: + // FIXME: raise SystemError + fprintf(stderr, "FIXME: methodobject: busted METH_ARGS, max args=%d\n", + PyCFunction_GET_MAX_ARGS(func)); + return NULL; + } +} + /* Methods (the standard built-in methods, that is) */ static void Index: Objects/descrobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v retrieving revision 2.38 diff -w -u -r2.38 descrobject.c --- Objects/descrobject.c 13 Dec 2003 11:58:56 -0000 2.38 +++ Objects/descrobject.c 24 Jan 2005 23:27:40 -0000 @@ -716,12 +716,10 @@ } static PyObject * -proxy_get(proxyobject *pp, PyObject *args) +proxy_get(proxyobject *pp, PyObject *key, PyObject *def) { - PyObject *key, *def = Py_None; - - if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) - return NULL; + if (def == NULL) + def = Py_None; return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def); } @@ -767,26 +765,26 @@ } static PyMethodDef proxy_methods[] = { - {"has_key", (PyCFunction)proxy_has_key, METH_O, - PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")}, - {"get", (PyCFunction)proxy_get, METH_VARARGS, + {"has_key", (PyCFunction)proxy_has_key, METH_ARGS, + PyDoc_STR("D.has_key(k) -> True if D has a key k, else False"), 1, 1}, + {"get", (PyCFunction)proxy_get, METH_ARGS, PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d." - " d defaults to None.")}, - {"keys", (PyCFunction)proxy_keys, METH_NOARGS, - PyDoc_STR("D.keys() -> list of D's keys")}, - {"values", (PyCFunction)proxy_values, METH_NOARGS, - PyDoc_STR("D.values() -> list of D's values")}, - {"items", (PyCFunction)proxy_items, METH_NOARGS, - PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")}, - {"iterkeys", (PyCFunction)proxy_iterkeys, METH_NOARGS, - PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")}, - {"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS, - PyDoc_STR("D.itervalues() -> an iterator over the values of D")}, - {"iteritems", (PyCFunction)proxy_iteritems, METH_NOARGS, + " d defaults to None."), 1, 2}, + {"keys", (PyCFunction)proxy_keys, METH_ARGS, + PyDoc_STR("D.keys() -> list of D's keys"), 0, 0}, + {"values", (PyCFunction)proxy_values, METH_ARGS, + PyDoc_STR("D.values() -> list of D's values"), 0, 0}, + {"items", (PyCFunction)proxy_items, METH_ARGS, + PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples"), 0, 0}, + {"iterkeys", (PyCFunction)proxy_iterkeys, METH_ARGS, + PyDoc_STR("D.iterkeys() -> an iterator over the keys of D"), 0, 0}, + {"itervalues",(PyCFunction)proxy_itervalues, METH_ARGS, + PyDoc_STR("D.itervalues() -> an iterator over the values of D"), 0, 0}, + {"iteritems", (PyCFunction)proxy_iteritems, METH_ARGS, PyDoc_STR("D.iteritems() ->" - " an iterator over the (key, value) items of D")}, - {"copy", (PyCFunction)proxy_copy, METH_NOARGS, - PyDoc_STR("D.copy() -> a shallow copy of D")}, + " an iterator over the (key, value) items of D"), 0, 0}, + {"copy", (PyCFunction)proxy_copy, METH_ARGS, + PyDoc_STR("D.copy() -> a shallow copy of D"), 0, 0}, {0} }; Index: Objects/stringobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v retrieving revision 2.226 diff -w -u -r2.226 stringobject.c --- Objects/stringobject.c 26 Oct 2004 01:52:37 -0000 2.226 +++ Objects/stringobject.c 24 Jan 2005 23:27:41 -0000 @@ -2219,7 +2219,7 @@ translation table, which must be a string of length 256."); static PyObject * -string_translate(PyStringObject *self, PyObject *args) +string_translate(PyStringObject *self, PyObject *tableobj, PyObject *delobj) { register char *input, *output; register const char *table; @@ -2229,11 +2229,6 @@ int inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; - PyObject *tableobj, *delobj = NULL; - - if (!PyArg_UnpackTuple(args, "translate", 1, 2, - &tableobj, &delobj)) - return NULL; if (PyString_Check(tableobj)) { table1 = PyString_AS_STRING(tableobj); @@ -3142,7 +3137,7 @@ otherwise."); static PyObject* -string_istitle(PyStringObject *self, PyObject *uncased) +string_istitle(PyStringObject *self) { register const unsigned char *p = (unsigned char *) PyString_AS_STRING(self); @@ -3255,20 +3250,20 @@ string_methods[] = { /* Counterparts of the obsolete stropmodule functions; except string.maketrans(). */ - {"join", (PyCFunction)string_join, METH_O, join__doc__}, + {"join", (PyCFunction)string_join, METH_ARGS, join__doc__, 1, 1}, {"split", (PyCFunction)string_split, METH_VARARGS, split__doc__}, {"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__}, - {"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__}, - {"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__}, - {"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__}, - {"isupper", (PyCFunction)string_isupper, METH_NOARGS, isupper__doc__}, - {"isspace", (PyCFunction)string_isspace, METH_NOARGS, isspace__doc__}, - {"isdigit", (PyCFunction)string_isdigit, METH_NOARGS, isdigit__doc__}, - {"istitle", (PyCFunction)string_istitle, METH_NOARGS, istitle__doc__}, - {"isalpha", (PyCFunction)string_isalpha, METH_NOARGS, isalpha__doc__}, - {"isalnum", (PyCFunction)string_isalnum, METH_NOARGS, isalnum__doc__}, - {"capitalize", (PyCFunction)string_capitalize, METH_NOARGS, - capitalize__doc__}, + {"lower", (PyCFunction)string_lower, METH_ARGS, lower__doc__, 0, 0}, + {"upper", (PyCFunction)string_upper, METH_ARGS, upper__doc__, 0, 0}, + {"islower", (PyCFunction)string_islower, METH_ARGS, islower__doc__, 0, 0}, + {"isupper", (PyCFunction)string_isupper, METH_ARGS, isupper__doc__, 0, 0}, + {"isspace", (PyCFunction)string_isspace, METH_ARGS, isspace__doc__, 0, 0}, + {"isdigit", (PyCFunction)string_isdigit, METH_ARGS, isdigit__doc__, 0, 0}, + {"istitle", (PyCFunction)string_istitle, METH_ARGS, istitle__doc__, 0, 0}, + {"isalpha", (PyCFunction)string_isalpha, METH_ARGS, isalpha__doc__, 0, 0}, + {"isalnum", (PyCFunction)string_isalnum, METH_ARGS, isalnum__doc__, 0, 0}, + {"capitalize", (PyCFunction)string_capitalize, METH_ARGS, + capitalize__doc__, 0, 0}, {"count", (PyCFunction)string_count, METH_VARARGS, count__doc__}, {"endswith", (PyCFunction)string_endswith, METH_VARARGS, endswith__doc__}, @@ -3282,11 +3277,11 @@ {"startswith", (PyCFunction)string_startswith, METH_VARARGS, startswith__doc__}, {"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__}, - {"swapcase", (PyCFunction)string_swapcase, METH_NOARGS, - swapcase__doc__}, - {"translate", (PyCFunction)string_translate, METH_VARARGS, - translate__doc__}, - {"title", (PyCFunction)string_title, METH_NOARGS, title__doc__}, + {"swapcase", (PyCFunction)string_swapcase, METH_ARGS, + swapcase__doc__, 0, 0}, + {"translate", (PyCFunction)string_translate, METH_ARGS, + translate__doc__, 1, 2}, + {"title", (PyCFunction)string_title, METH_ARGS, title__doc__, 0, 0}, {"ljust", (PyCFunction)string_ljust, METH_VARARGS, ljust__doc__}, {"rjust", (PyCFunction)string_rjust, METH_VARARGS, rjust__doc__}, {"center", (PyCFunction)string_center, METH_VARARGS, center__doc__}, @@ -3297,7 +3292,7 @@ expandtabs__doc__}, {"splitlines", (PyCFunction)string_splitlines, METH_VARARGS, splitlines__doc__}, - {"__getnewargs__", (PyCFunction)string_getnewargs, METH_NOARGS}, + {"__getnewargs__", (PyCFunction)string_getnewargs, METH_ARGS, NULL, 0, 0}, {NULL, NULL} /* sentinel */ }; Index: Python/bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.320 diff -w -u -r2.320 bltinmodule.c --- Python/bltinmodule.c 7 Dec 2004 00:25:35 -0000 2.320 +++ Python/bltinmodule.c 24 Jan 2005 23:27:42 -0000 @@ -128,15 +128,12 @@ static PyObject * -builtin_filter(PyObject *self, PyObject *args) +builtin_filter(PyObject *self, PyObject *func, PyObject *seq) { - PyObject *func, *seq, *result, *it, *arg; + PyObject *result, *it, *arg; int len; /* guess for result list size */ register int j; - if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) - return NULL; - /* Strings and tuples return a result of the same type. */ if (PyString_Check(seq)) return filterstring(func, seq); @@ -245,12 +242,12 @@ "or string, return the same type, else return a list."); static PyObject * -builtin_chr(PyObject *self, PyObject *args) +builtin_chr(PyObject *self, PyObject *arg) { - long x; + long x = PyInt_AsLong(arg); char s[1]; - if (!PyArg_ParseTuple(args, "l:chr", &x)) + if (x == -1 && PyErr_Occurred()) return NULL; if (x < 0 || x >= 256) { PyErr_SetString(PyExc_ValueError, @@ -269,11 +266,10 @@ #ifdef Py_USING_UNICODE static PyObject * -builtin_unichr(PyObject *self, PyObject *args) +builtin_unichr(PyObject *self, PyObject *arg) { - long x; - - if (!PyArg_ParseTuple(args, "l:unichr", &x)) + long x = PyInt_AsLong(arg); + if (x == -1 && PyErr_Occurred()) return NULL; return PyUnicode_FromOrdinal(x); @@ -287,13 +283,9 @@ static PyObject * -builtin_cmp(PyObject *self, PyObject *args) +builtin_cmp(PyObject *self, PyObject *a, PyObject *b) { - PyObject *a, *b; int c; - - if (!PyArg_UnpackTuple(args, "cmp", 2, 2, &a, &b)) - return NULL; if (PyObject_Cmp(a, b, &c) < 0) return NULL; return PyInt_FromLong((long)c); @@ -306,13 +298,10 @@ static PyObject * -builtin_coerce(PyObject *self, PyObject *args) +builtin_coerce(PyObject *self, PyObject *v, PyObject *w) { - PyObject *v, *w; PyObject *res; - if (!PyArg_UnpackTuple(args, "coerce", 2, 2, &v, &w)) - return NULL; if (PyNumber_Coerce(&v, &w) < 0) return NULL; res = PyTuple_Pack(2, v, w); @@ -409,12 +398,8 @@ in addition to any features explicitly specified."); static PyObject * -builtin_dir(PyObject *self, PyObject *args) +builtin_dir(PyObject *self, PyObject *arg) { - PyObject *arg = NULL; - - if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) - return NULL; return PyObject_Dir(arg); } @@ -432,12 +417,8 @@ " attributes of its class's base classes."); static PyObject * -builtin_divmod(PyObject *self, PyObject *args) +builtin_divmod(PyObject *self, PyObject *v, PyObject *w) { - PyObject *v, *w; - - if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) - return NULL; return PyNumber_Divmod(v, w); } @@ -448,15 +429,16 @@ static PyObject * -builtin_eval(PyObject *self, PyObject *args) +builtin_eval(PyObject *self, PyObject *cmd, PyObject *globals, PyObject *locals) { - PyObject *cmd, *result, *tmp = NULL; - PyObject *globals = Py_None, *locals = Py_None; + PyObject *result, *tmp = NULL; char *str; PyCompilerFlags cf; - if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals)) - return NULL; + if (globals == NULL) + globals = Py_None; + if (locals == NULL) + locals = Py_None; if (locals != Py_None && !PyMapping_Check(locals)) { PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); return NULL; @@ -631,13 +613,9 @@ static PyObject * -builtin_getattr(PyObject *self, PyObject *args) +builtin_getattr(PyObject *self, PyObject *v, PyObject *name, PyObject *dflt) { - PyObject *v, *result, *dflt = NULL; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "getattr", 2, 3, &v, &name, &dflt)) - return NULL; + PyObject *result; #ifdef Py_USING_UNICODE if (PyUnicode_Check(name)) { name = _PyUnicode_AsDefaultEncodedString(name, NULL); @@ -902,14 +880,8 @@ static PyObject * -builtin_setattr(PyObject *self, PyObject *args) +builtin_setattr(PyObject *self, PyObject *v, PyObject *name, PyObject *value) { - PyObject *v; - PyObject *name; - PyObject *value; - - if (!PyArg_UnpackTuple(args, "setattr", 3, 3, &v, &name, &value)) - return NULL; if (PyObject_SetAttr(v, name, value) != 0) return NULL; Py_INCREF(Py_None); @@ -924,13 +896,8 @@ static PyObject * -builtin_delattr(PyObject *self, PyObject *args) +builtin_delattr(PyObject *self, PyObject *v, PyObject *name) { - PyObject *v; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "delattr", 2, 2, &v, &name)) - return NULL; if (PyObject_SetAttr(v, name, (PyObject *)NULL) != 0) return NULL; Py_INCREF(Py_None); @@ -1055,12 +1022,8 @@ static PyObject * -builtin_iter(PyObject *self, PyObject *args) +builtin_iter(PyObject *self, PyObject *v, PyObject *w) { - PyObject *v, *w = NULL; - - if (!PyArg_UnpackTuple(args, "iter", 1, 2, &v, &w)) - return NULL; if (w == NULL) return PyObject_GetIter(v); if (!PyCallable_Check(v)) { @@ -1295,12 +1258,10 @@ static PyObject * -builtin_pow(PyObject *self, PyObject *args) +builtin_pow(PyObject *self, PyObject *v, PyObject *w, PyObject *z) { - PyObject *v, *w, *z = Py_None; - - if (!PyArg_UnpackTuple(args, "pow", 2, 3, &v, &w, &z)) - return NULL; + if (z == NULL) + z = Py_None; return PyNumber_Power(v, w, z); } @@ -1388,7 +1349,6 @@ int cmp_result; PyObject *zero = PyLong_FromLong(0); - if (zero == NULL) return NULL; @@ -1605,15 +1565,11 @@ static PyObject * -builtin_raw_input(PyObject *self, PyObject *args) +builtin_raw_input(PyObject *self, PyObject *v) { - PyObject *v = NULL; PyObject *fin = PySys_GetObject("stdin"); PyObject *fout = PySys_GetObject("stdout"); - if (!PyArg_UnpackTuple(args, "[raw_]input", 0, 1, &v)) - return NULL; - if (fin == NULL) { PyErr_SetString(PyExc_RuntimeError, "[raw_]input: lost sys.stdin"); return NULL; @@ -1689,14 +1645,11 @@ static PyObject * -builtin_reduce(PyObject *self, PyObject *args) +builtin_reduce(PyObject *self, PyObject *func, PyObject *seq, PyObject *result) { - PyObject *seq, *func, *result = NULL, *it; + PyObject *it, *args; - if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result)) - return NULL; - if (result != NULL) - Py_INCREF(result); + Py_XINCREF(result); it = PyObject_GetIter(seq); if (it == NULL) { @@ -1868,13 +1821,10 @@ "sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"); static PyObject * -builtin_vars(PyObject *self, PyObject *args) +builtin_vars(PyObject *self, PyObject *v) { - PyObject *v = NULL; PyObject *d; - if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v)) - return NULL; if (v == NULL) { d = PyEval_GetLocals(); if (d == NULL) { @@ -1904,15 +1854,10 @@ static PyObject* -builtin_sum(PyObject *self, PyObject *args) +builtin_sum(PyObject *self, PyObject *seq, PyObject *result) { - PyObject *seq; - PyObject *result = NULL; PyObject *temp, *item, *iter; - if (!PyArg_UnpackTuple(args, "sum", 1, 2, &seq, &result)) - return NULL; - iter = PyObject_GetIter(seq); if (iter == NULL) return NULL; @@ -1963,16 +1908,9 @@ static PyObject * -builtin_isinstance(PyObject *self, PyObject *args) +builtin_isinstance(PyObject *self, PyObject *inst, PyObject *cls) { - PyObject *inst; - PyObject *cls; - int retval; - - if (!PyArg_UnpackTuple(args, "isinstance", 2, 2, &inst, &cls)) - return NULL; - - retval = PyObject_IsInstance(inst, cls); + int retval = PyObject_IsInstance(inst, cls); if (retval < 0) return NULL; return PyBool_FromLong(retval); @@ -1988,16 +1926,9 @@ static PyObject * -builtin_issubclass(PyObject *self, PyObject *args) +builtin_issubclass(PyObject *self, PyObject *derived, PyObject *cls) { - PyObject *derived; - PyObject *cls; - int retval; - - if (!PyArg_UnpackTuple(args, "issubclass", 2, 2, &derived, &cls)) - return NULL; - - retval = PyObject_IsSubclass(derived, cls); + int retval = PyObject_IsSubclass(derived, cls); if (retval < 0) return NULL; return PyBool_FromLong(retval); @@ -2124,51 +2055,51 @@ static PyMethodDef builtin_methods[] = { {"__import__", builtin___import__, METH_VARARGS, import_doc}, - {"abs", builtin_abs, METH_O, abs_doc}, + {"abs", builtin_abs, METH_ARGS, abs_doc, 1, 1}, {"apply", builtin_apply, METH_VARARGS, apply_doc}, - {"callable", builtin_callable, METH_O, callable_doc}, - {"chr", builtin_chr, METH_VARARGS, chr_doc}, - {"cmp", builtin_cmp, METH_VARARGS, cmp_doc}, - {"coerce", builtin_coerce, METH_VARARGS, coerce_doc}, + {"callable", builtin_callable, METH_ARGS, callable_doc, 1, 1}, + {"chr", builtin_chr, METH_ARGS, chr_doc, 1, 1}, + {"cmp", builtin_cmp, METH_ARGS, cmp_doc, 2, 2}, + {"coerce", builtin_coerce, METH_ARGS, coerce_doc, 2, 2}, {"compile", builtin_compile, METH_VARARGS, compile_doc}, - {"delattr", builtin_delattr, METH_VARARGS, delattr_doc}, - {"dir", builtin_dir, METH_VARARGS, dir_doc}, - {"divmod", builtin_divmod, METH_VARARGS, divmod_doc}, - {"eval", builtin_eval, METH_VARARGS, eval_doc}, + {"delattr", builtin_delattr, METH_ARGS, delattr_doc, 2, 2}, + {"dir", builtin_dir, METH_ARGS, dir_doc, 0, 1}, + {"divmod", builtin_divmod, METH_ARGS, divmod_doc, 2, 2}, + {"eval", builtin_eval, METH_ARGS, eval_doc, 1, 3}, {"execfile", builtin_execfile, METH_VARARGS, execfile_doc}, - {"filter", builtin_filter, METH_VARARGS, filter_doc}, - {"getattr", builtin_getattr, METH_VARARGS, getattr_doc}, - {"globals", (PyCFunction)builtin_globals, METH_NOARGS, globals_doc}, + {"filter", builtin_filter, METH_ARGS, filter_doc, 2, 2}, + {"getattr", builtin_getattr, METH_ARGS, getattr_doc, 2, 3}, + {"globals", (PyCFunction)builtin_globals, METH_ARGS, globals_doc, 0, 0}, {"hasattr", builtin_hasattr, METH_VARARGS, hasattr_doc}, - {"hash", builtin_hash, METH_O, hash_doc}, - {"hex", builtin_hex, METH_O, hex_doc}, - {"id", builtin_id, METH_O, id_doc}, - {"input", builtin_input, METH_VARARGS, input_doc}, + {"hash", builtin_hash, METH_ARGS, hash_doc, 1, 1}, + {"hex", builtin_hex, METH_ARGS, hex_doc, 1, 1}, + {"id", builtin_id, METH_ARGS, id_doc, 1, 1}, + {"input", builtin_input, METH_ARGS, input_doc, 0, 1}, {"intern", builtin_intern, METH_VARARGS, intern_doc}, - {"isinstance", builtin_isinstance, METH_VARARGS, isinstance_doc}, - {"issubclass", builtin_issubclass, METH_VARARGS, issubclass_doc}, - {"iter", builtin_iter, METH_VARARGS, iter_doc}, - {"len", builtin_len, METH_O, len_doc}, - {"locals", (PyCFunction)builtin_locals, METH_NOARGS, locals_doc}, + {"isinstance", builtin_isinstance, METH_ARGS, isinstance_doc, 2, 2}, + {"issubclass", builtin_issubclass, METH_ARGS, issubclass_doc, 2, 2}, + {"iter", builtin_iter, METH_ARGS, iter_doc, 1, 2}, + {"len", builtin_len, METH_ARGS, len_doc, 1, 1}, + {"locals", (PyCFunction)builtin_locals, METH_ARGS, locals_doc, 0, 0}, {"map", builtin_map, METH_VARARGS, map_doc}, {"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc}, {"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc}, - {"oct", builtin_oct, METH_O, oct_doc}, - {"ord", builtin_ord, METH_O, ord_doc}, - {"pow", builtin_pow, METH_VARARGS, pow_doc}, + {"oct", builtin_oct, METH_ARGS, oct_doc, 1, 1}, + {"ord", builtin_ord, METH_ARGS, ord_doc, 1, 1}, + {"pow", builtin_pow, METH_ARGS, pow_doc, 2, 3}, {"range", builtin_range, METH_VARARGS, range_doc}, - {"raw_input", builtin_raw_input, METH_VARARGS, raw_input_doc}, - {"reduce", builtin_reduce, METH_VARARGS, reduce_doc}, - {"reload", builtin_reload, METH_O, reload_doc}, - {"repr", builtin_repr, METH_O, repr_doc}, + {"raw_input", builtin_raw_input, METH_ARGS, raw_input_doc, 0, 1}, + {"reduce", builtin_reduce, METH_ARGS, reduce_doc, 2, 3}, + {"reload", builtin_reload, METH_ARGS, reload_doc, 1, 1}, + {"repr", builtin_repr, METH_ARGS, repr_doc, 1, 1}, {"round", builtin_round, METH_VARARGS, round_doc}, - {"setattr", builtin_setattr, METH_VARARGS, setattr_doc}, + {"setattr", builtin_setattr, METH_ARGS, setattr_doc, 3, 3}, {"sorted", (PyCFunction)builtin_sorted, METH_VARARGS | METH_KEYWORDS, sorted_doc}, - {"sum", builtin_sum, METH_VARARGS, sum_doc}, + {"sum", builtin_sum, METH_ARGS, sum_doc, 1, 2}, #ifdef Py_USING_UNICODE - {"unichr", builtin_unichr, METH_VARARGS, unichr_doc}, + {"unichr", builtin_unichr, METH_ARGS, unichr_doc, 1, 1}, #endif - {"vars", builtin_vars, METH_VARARGS, vars_doc}, + {"vars", builtin_vars, METH_ARGS, vars_doc, 0, 1}, {"zip", builtin_zip, METH_VARARGS, zip_doc}, {NULL, NULL}, }; Index: Python/ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.421 diff -w -u -r2.421 ceval.c --- Python/ceval.c 18 Jan 2005 15:56:11 -0000 2.421 +++ Python/ceval.c 24 Jan 2005 23:27:43 -0000 @@ -3471,6 +3471,13 @@ "%.200s() takes no arguments (%d given)", ((PyCFunctionObject *)func)->m_ml->ml_name, nargs); + else if (flags & METH_ARGS) + PyErr_Format(PyExc_TypeError, + "%.200s() takes %d-%d arguments (%d given)", + ((PyCFunctionObject *)func)->m_ml->ml_name, + ((PyCFunctionObject *)func)->m_ml->ml_min_args, + ((PyCFunctionObject *)func)->m_ml->ml_max_args, + nargs); else PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%d given)", @@ -3506,6 +3513,9 @@ } static PyObject * +new_fast_function(PyObject *meth, int na, PyObject **pp_stack); + +static PyObject * call_function(PyObject ***pp_stack, int oparg #ifdef WITH_TSC , uint64* pintr0, uint64* pintr1 @@ -3527,7 +3537,12 @@ PyThreadState *tstate = PyThreadState_GET(); PCALL(PCALL_CFUNCTION); - if (flags & (METH_NOARGS | METH_O)) { + if (flags & METH_ARGS && + (na >= PyCFunction_GET_MIN_ARGS(func) && + na <= PyCFunction_GET_MAX_ARGS(func))) { + x = new_fast_function(func, na, *pp_stack); + } + else if (flags & (METH_NOARGS | METH_O)) { PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); if (flags & METH_NOARGS && na == 0) { @@ -3584,6 +3599,89 @@ return x; } +typedef PyObject *(*PyCVarArgFunction)(PyObject*, ...); + +/* XXX: if we passed pp_stack as PyObject ***, it is faster + it looks like we have less work to do unwinding stack in + above. However, the following tests fail if it is *** + + test_array,test_bsddb,test_class,test_descr,test_gc, + test_iter,test_socket,test_sys,test_weakref +*/ + +/* XXX: does not support METH_KEYWORDS */ +static PyObject* +new_fast_function(PyObject *func, int na, PyObject **pp_stack) { + PyObject *x; + /* XXX: we only need to init arg[na] .. arg[max_args] */ + PyObject *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, + *arg4 = NULL, *arg5 = NULL, *arg6 = NULL, + *arg7 = NULL, *arg8 = NULL, *arg9 = NULL; + PyThreadState *tstate = PyThreadState_GET(); + PyCVarArgFunction meth = + (PyCVarArgFunction) PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + + /* XXX: need to determine best # of args to support */ + + /* XXX: If we know that na == max_args, this can be optimized + by having a single switch, which should be a moderage win + */ + + /* handle varargs, note that if na > 0 each case falls through */ + switch (na) { + case 0: break; + case 9: arg9 = EXT_POP(pp_stack); + case 8: arg8 = EXT_POP(pp_stack); + case 7: arg7 = EXT_POP(pp_stack); + case 6: arg6 = EXT_POP(pp_stack); + case 5: arg5 = EXT_POP(pp_stack); + case 4: arg4 = EXT_POP(pp_stack); + case 3: arg3 = EXT_POP(pp_stack); + case 2: arg2 = EXT_POP(pp_stack); + case 1: arg1 = EXT_POP(pp_stack); + break; + + default: + fprintf(stderr, "FIXME: busted METH_ARGS, na=%d\n", na); + // Should raise SystemError + return NULL; + } + + // FIXME: it would be nice to handle the DECREFs here + // so they are unwound and we don't need a loop (in the caller) + switch (PyCFunction_GET_MAX_ARGS(func)) { + case 0: C_TRACE(x = (*meth)(self)); + break; + case 1: C_TRACE(x = (*meth)(self, arg1)); + break; + case 2: C_TRACE(x = (*meth)(self, arg1, arg2)); + break; + case 3: C_TRACE(x = (*meth)(self, arg1, arg2, arg3)); + break; + case 4: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4)); + break; + case 5: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4, arg5)); + break; + case 6: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6)); + break; + case 7: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + break; + case 8: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + break; + case 9: C_TRACE(x = (*meth)(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + break; + + default: + // Should raise SystemError + fprintf(stderr, "FIXME: busted METH_ARGS, max args=%d\n", + PyCFunction_GET_MAX_ARGS(func)); + return NULL; + } + + return x; +} + /* The fast_function() function optimize calls for which no argument tuple is necessary; the objects are passed directly from the stack. For the simplest case -- a function that takes only positional Index: Python/codecs.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/codecs.c,v retrieving revision 2.24 diff -w -u -r2.24 codecs.c --- Python/codecs.c 8 Jul 2004 01:55:58 -0000 2.24 +++ Python/codecs.c 24 Jan 2005 23:27:43 -0000 @@ -763,7 +763,7 @@ { "strict_errors", strict_errors, - METH_O + METH_ARGS, NULL, 1, 1 } }, #ifdef Py_USING_UNICODE @@ -772,7 +772,7 @@ { "ignore_errors", ignore_errors, - METH_O + METH_ARGS, NULL, 1, 1 } }, { @@ -780,7 +780,7 @@ { "replace_errors", replace_errors, - METH_O + METH_ARGS, NULL, 1, 1 } }, { @@ -788,7 +788,7 @@ { "xmlcharrefreplace_errors", xmlcharrefreplace_errors, - METH_O + METH_ARGS, NULL, 1, 1 } }, { @@ -796,7 +796,7 @@ { "backslashreplace_errors", backslashreplace_errors, - METH_O + METH_ARGS, NULL, 1, 1 } } #endif Index: Python/exceptions.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/exceptions.c,v retrieving revision 1.49 diff -w -u -r1.49 exceptions.c --- Python/exceptions.c 25 Aug 2004 02:14:08 -0000 1.49 +++ Python/exceptions.c 24 Jan 2005 23:27:43 -0000 @@ -216,7 +216,7 @@ { PyObject *self = PyTuple_GetItem(args, 0); if (!self) { - /* Watch out for being called to early in the bootstrapping process */ + /* Watch out for being called too early in the bootstrapping process */ if (PyExc_TypeError) { PyErr_SetString(PyExc_TypeError, "unbound method must be called with instance as first argument"); @@ -311,15 +311,11 @@ static PyObject * -Exception__getitem__(PyObject *self, PyObject *args) +Exception__getitem__(PyObject *self, PyObject *self2, PyObject *index) { PyObject *out; - PyObject *index; - if (!PyArg_ParseTuple(args, "OO:__getitem__", &self, &index)) - return NULL; - - args = PyObject_GetAttrString(self, "args"); + PyObject *args = PyObject_GetAttrString(self2, "args"); if (!args) return NULL; @@ -332,7 +328,7 @@ static PyMethodDef Exception_methods[] = { /* methods for the Exception class */ - { "__getitem__", Exception__getitem__, METH_VARARGS}, + { "__getitem__", Exception__getitem__, METH_ARGS, NULL, 2, 2}, { "__str__", Exception__str__, METH_VARARGS}, { "__init__", Exception__init__, METH_VARARGS}, { NULL, NULL } @@ -1287,7 +1283,7 @@ static PyMethodDef UnicodeEncodeError_methods[] = { {"__init__", UnicodeEncodeError__init__, METH_VARARGS}, - {"__str__", UnicodeEncodeError__str__, METH_O}, + {"__str__", UnicodeEncodeError__str__, METH_ARGS, NULL, 1, 1}, {NULL, NULL} }; @@ -1364,7 +1360,7 @@ static PyMethodDef UnicodeDecodeError_methods[] = { {"__init__", UnicodeDecodeError__init__, METH_VARARGS}, - {"__str__", UnicodeDecodeError__str__, METH_O}, + {"__str__", UnicodeDecodeError__str__, METH_ARGS, NULL, 1, 1}, {NULL, NULL} }; @@ -1479,7 +1475,7 @@ static PyMethodDef UnicodeTranslateError_methods[] = { {"__init__", UnicodeTranslateError__init__, METH_VARARGS}, - {"__str__", UnicodeTranslateError__str__, METH_O}, + {"__str__", UnicodeTranslateError__str__, METH_ARGS, NULL, 1, 1}, {NULL, NULL} }; Index: Python/import.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/import.c,v retrieving revision 2.240 diff -w -u -r2.240 import.c --- Python/import.c 7 Oct 2004 06:46:25 -0000 2.240 +++ Python/import.c 24 Jan 2005 23:27:44 -0000 @@ -2764,13 +2764,13 @@ static PyMethodDef imp_methods[] = { {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, - {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, - {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, + {"get_magic", imp_get_magic, METH_ARGS, doc_get_magic, 0, 0}, + {"get_suffixes", imp_get_suffixes, METH_ARGS, doc_get_suffixes, 0, 0}, {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, {"new_module", imp_new_module, METH_VARARGS, doc_new_module}, - {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, - {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, - {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, + {"lock_held", imp_lock_held, METH_ARGS, doc_lock_held, 0, 0}, + {"acquire_lock", imp_acquire_lock, METH_ARGS, doc_acquire_lock, 0, 0}, + {"release_lock", imp_release_lock, METH_ARGS, doc_release_lock, 0, 0}, /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"init_builtin", imp_init_builtin, METH_VARARGS}, Index: Python/sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.127 diff -w -u -r2.127 sysmodule.c --- Python/sysmodule.c 23 Jan 2005 09:41:49 -0000 2.127 +++ Python/sysmodule.c 24 Jan 2005 23:27:44 -0000 @@ -713,44 +713,44 @@ static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ - {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, - callstats_doc}, - {"displayhook", sys_displayhook, METH_O, displayhook_doc}, - {"exc_info", sys_exc_info, METH_NOARGS, exc_info_doc}, - {"exc_clear", sys_exc_clear, METH_NOARGS, exc_clear_doc}, + {"callstats", (PyCFunction)PyEval_GetCallStats, METH_ARGS, + callstats_doc, 0, 0}, + {"displayhook", sys_displayhook, METH_ARGS, displayhook_doc, 1, 1}, + {"exc_info", sys_exc_info, METH_ARGS, exc_info_doc, 0, 0}, + {"exc_clear", sys_exc_clear, METH_ARGS, exc_clear_doc, 0, 0}, {"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc}, {"exit", sys_exit, METH_VARARGS, exit_doc}, #ifdef Py_USING_UNICODE {"getdefaultencoding", (PyCFunction)sys_getdefaultencoding, - METH_NOARGS, getdefaultencoding_doc}, + METH_ARGS, getdefaultencoding_doc, 0, 0}, #endif #ifdef HAVE_DLOPEN - {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS, - getdlopenflags_doc}, + {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_ARGS, + getdlopenflags_doc, 0, 0}, #endif #ifdef COUNT_ALLOCS - {"getcounts", (PyCFunction)sys_getcounts, METH_NOARGS}, + {"getcounts", (PyCFunction)sys_getcounts, METH_ARGS, NULL, 0, 0}, #endif #ifdef DYNAMIC_EXECUTION_PROFILE {"getdxp", _Py_GetDXProfile, METH_VARARGS}, #endif #ifdef Py_USING_UNICODE {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, - METH_NOARGS, getfilesystemencoding_doc}, + METH_ARGS, getfilesystemencoding_doc, 0, 0}, #endif #ifdef Py_TRACE_REFS {"getobjects", _Py_GetObjects, METH_VARARGS}, #endif #ifdef Py_REF_DEBUG - {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS}, + {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_ARGS, NULL, 0, 0}, #endif - {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, - {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, - getrecursionlimit_doc}, + {"getrefcount", (PyCFunction)sys_getrefcount, METH_ARGS, getrefcount_doc, 1, 1}, + {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_ARGS, + getrecursionlimit_doc, 0, 0}, {"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, #ifdef MS_WINDOWS - {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, - getwindowsversion_doc}, + {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_ARGS, + getwindowsversion_doc, 0, 0}, #endif /* MS_WINDOWS */ #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, @@ -761,19 +761,19 @@ #endif {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, setcheckinterval_doc}, - {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, - getcheckinterval_doc}, + {"getcheckinterval", sys_getcheckinterval, METH_ARGS, + getcheckinterval_doc, 0, 0}, #ifdef HAVE_DLOPEN {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, setdlopenflags_doc}, #endif - {"setprofile", sys_setprofile, METH_O, setprofile_doc}, + {"setprofile", sys_setprofile, METH_ARGS, setprofile_doc, 1, 1}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, #ifdef WITH_TSC {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc}, #endif - {"settrace", sys_settrace, METH_O, settrace_doc}, + {"settrace", sys_settrace, METH_ARGS, settrace_doc, 1, 1}, {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, {NULL, NULL} /* sentinel */ };