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 23 Jan 2005 18:10:22 -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 23 Jan 2005 18:10:22 -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,66 @@ 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: + 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: + 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: 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 23 Jan 2005 18:10:23 -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}, + {"filter", builtin_filter, METH_ARGS, filter_doc, 2, 2}, + {"getattr", builtin_getattr, METH_ARGS, getattr_doc, 2, 3}, {"globals", (PyCFunction)builtin_globals, METH_NOARGS, globals_doc}, {"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}, + {"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_NOARGS, locals_doc}, {"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 23 Jan 2005 18:10:24 -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 @@ -3543,6 +3553,16 @@ x = NULL; } } + else if (flags & METH_ARGS) { + if (na >= PyCFunction_GET_MIN_ARGS(func) && + na <= PyCFunction_GET_MAX_ARGS(func)) { + x = new_fast_function(func, na, *pp_stack); + } + else { + err_args(func, flags, na); + x = NULL; + } + } else { PyObject *callargs; callargs = load_args(pp_stack, na); @@ -3584,6 +3604,77 @@ return x; } +typedef PyObject *(*PyCVarArgFunction)(PyObject*, ...); + +static PyObject* +new_fast_function(PyObject *func, int na, PyObject **pp_stack) { + PyObject *x; + 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 save me 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); + 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: 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: + 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