Improve argument checking speed.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 545dba6..6403103 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3320,6 +3320,22 @@
}
}
+static int
+check_num_args(PyObject *ob, int n)
+{
+ if (!PyTuple_CheckExact(ob)) {
+ PyErr_SetString(PyExc_SystemError,
+ "PyArg_UnpackTuple() argument list is not a tuple");
+ return 0;
+ }
+ if (n == PyTuple_GET_SIZE(ob))
+ return 1;
+ PyErr_Format(
+ PyExc_TypeError,
+ "expected %d arguments, got %d", n, PyTuple_GET_SIZE(ob));
+ return 0;
+}
+
/* Generic wrappers for overloadable 'operators' such as __getitem__ */
/* There's a wrapper *function* for each distinct function typedef used
@@ -3334,7 +3350,7 @@
inquiry func = (inquiry)wrapped;
int res;
- if (!PyArg_UnpackTuple(args, "", 0, 0))
+ if (!check_num_args(args, 0))
return NULL;
res = (*func)(self);
if (res == -1 && PyErr_Occurred())
@@ -3348,7 +3364,7 @@
inquiry func = (inquiry)wrapped;
int res;
- if (!PyArg_UnpackTuple(args, "", 0, 0))
+ if (!check_num_args(args, 0))
return NULL;
res = (*func)(self);
if (res == -1 && PyErr_Occurred())
@@ -3362,8 +3378,9 @@
binaryfunc func = (binaryfunc)wrapped;
PyObject *other;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
return (*func)(self, other);
}
@@ -3373,8 +3390,9 @@
binaryfunc func = (binaryfunc)wrapped;
PyObject *other;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
!PyType_IsSubtype(other->ob_type, self->ob_type)) {
Py_INCREF(Py_NotImplemented);
@@ -3389,8 +3407,9 @@
binaryfunc func = (binaryfunc)wrapped;
PyObject *other;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
!PyType_IsSubtype(other->ob_type, self->ob_type)) {
Py_INCREF(Py_NotImplemented);
@@ -3406,8 +3425,9 @@
PyObject *other, *res;
int ok;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
ok = func(&self, &other);
if (ok < 0)
return NULL;
@@ -3459,7 +3479,7 @@
{
unaryfunc func = (unaryfunc)wrapped;
- if (!PyArg_UnpackTuple(args, "", 0, 0))
+ if (!check_num_args(args, 0))
return NULL;
return (*func)(self);
}
@@ -3509,7 +3529,7 @@
return NULL;
return (*func)(self, i);
}
- PyArg_UnpackTuple(args, "", 1, 1, &arg);
+ check_num_args(args, 1);
assert(PyErr_Occurred());
return NULL;
}
@@ -3551,8 +3571,9 @@
int i, res;
PyObject *arg;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &arg))
+ if (!check_num_args(args, 1))
return NULL;
+ arg = PyTuple_GET_ITEM(args, 0);
i = getindex(self, arg);
if (i == -1 && PyErr_Occurred())
return NULL;
@@ -3602,8 +3623,9 @@
int res;
PyObject *value;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &value))
+ if (!check_num_args(args, 1))
return NULL;
+ value = PyTuple_GET_ITEM(args, 0);
res = (*func)(self, value);
if (res == -1 && PyErr_Occurred())
return NULL;
@@ -3634,8 +3656,9 @@
int res;
PyObject *key;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &key))
+ if (!check_num_args(args, 1))
return NULL;
+ key = PyTuple_GET_ITEM(args, 0);
res = (*func)(self, key, NULL);
if (res == -1 && PyErr_Occurred())
return NULL;
@@ -3650,8 +3673,9 @@
int res;
PyObject *other;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
if (other->ob_type->tp_compare != func &&
!PyType_IsSubtype(other->ob_type, self->ob_type)) {
PyErr_Format(
@@ -3711,8 +3735,9 @@
int res;
PyObject *name;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &name))
+ if (!check_num_args(args, 1))
return NULL;
+ name = PyTuple_GET_ITEM(args, 0);
if (!hackcheck(self, func, "__delattr__"))
return NULL;
res = (*func)(self, name, NULL);
@@ -3728,7 +3753,7 @@
hashfunc func = (hashfunc)wrapped;
long res;
- if (!PyArg_UnpackTuple(args, "", 0, 0))
+ if (!check_num_args(args, 0))
return NULL;
res = (*func)(self);
if (res == -1 && PyErr_Occurred())
@@ -3750,8 +3775,9 @@
richcmpfunc func = (richcmpfunc)wrapped;
PyObject *other;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &other))
+ if (!check_num_args(args, 1))
return NULL;
+ other = PyTuple_GET_ITEM(args, 0);
return (*func)(self, other, op);
}
@@ -3776,7 +3802,7 @@
unaryfunc func = (unaryfunc)wrapped;
PyObject *res;
- if (!PyArg_UnpackTuple(args, "", 0, 0))
+ if (!check_num_args(args, 0))
return NULL;
res = (*func)(self);
if (res == NULL && !PyErr_Occurred())
@@ -3828,8 +3854,9 @@
PyObject *obj;
int ret;
- if (!PyArg_UnpackTuple(args, "", 1, 1, &obj))
+ if (!check_num_args(args, 1))
return NULL;
+ obj = PyTuple_GET_ITEM(args, 0);
ret = (*func)(self, obj, NULL);
if (ret < 0)
return NULL;