diff --git a/third_party/python/Include/abstract.h b/third_party/python/Include/abstract.h index 0f69acb95..b60b01d26 100644 --- a/third_party/python/Include/abstract.h +++ b/third_party/python/Include/abstract.h @@ -14,6 +14,9 @@ PyObject *PyObject_Call(PyObject *callable_object, PyObject *args, #ifndef Py_LIMITED_API PyObject *_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs); +PyObject *_PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, + Py_ssize_t start, Py_ssize_t end); + PyObject *_PyStack_AsDict(PyObject **values, PyObject *kwnames); PyObject ** _PyStack_UnpackDict( diff --git a/third_party/python/Objects/abstract.c b/third_party/python/Objects/abstract.c index 35beea0d5..151c695d2 100644 --- a/third_party/python/Objects/abstract.c +++ b/third_party/python/Objects/abstract.c @@ -2300,6 +2300,30 @@ _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) return args; } +PyObject* +_PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, + Py_ssize_t start, Py_ssize_t end) +{ + PyObject *args; + Py_ssize_t i; + + assert(0 <= start); + assert(end <= nargs); + assert(start <= end); + + args = PyTuple_New(end - start); + if (args == NULL) { + return NULL; + } + + for (i=start; i < end; i++) { + PyObject *item = stack[i]; + Py_INCREF(item); + PyTuple_SET_ITEM(args, i - start, item); + } + return args; +} + PyObject * _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) diff --git a/third_party/python/Python/bltinmodule.c b/third_party/python/Python/bltinmodule.c index a8df11b34..1500d4677 100644 --- a/third_party/python/Python/bltinmodule.c +++ b/third_party/python/Python/bltinmodule.c @@ -239,51 +239,45 @@ _Py_IDENTIFIER(stderr); /* AC: cannot convert yet, waiting for *args support */ static PyObject * -builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) +builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, + PyObject *kwnames) { PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns; PyObject *cls = NULL, *cell = NULL; - Py_ssize_t nargs; int isclass = 0; /* initialize to prevent gcc warning */ - assert(args != NULL); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: args is not a tuple"); - return NULL; - } - nargs = PyTuple_GET_SIZE(args); if (nargs < 2) { PyErr_SetString(PyExc_TypeError, "__build_class__: not enough arguments"); return NULL; } - func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ + func = args[0]; /* Better be callable */ if (!PyFunction_Check(func)) { PyErr_SetString(PyExc_TypeError, "__build_class__: func must be a function"); return NULL; } - name = PyTuple_GET_ITEM(args, 1); + name = args[1]; if (!PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, "__build_class__: name is not a string"); return NULL; } - bases = PyTuple_GetSlice(args, 2, nargs); + bases = _PyStack_AsTupleSlice(args, nargs, 2, nargs); if (bases == NULL) return NULL; - if (kwds == NULL) { + if (kwnames == NULL) { meta = NULL; mkw = NULL; } else { - mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ + mkw = _PyStack_AsDict(args + nargs, kwnames); if (mkw == NULL) { Py_DECREF(bases); return NULL; } + meta = _PyDict_GetItemId(mkw, &PyId_metaclass); if (meta != NULL) { Py_INCREF(meta); @@ -354,13 +348,6 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) Py_DECREF(bases); return NULL; } - if (!PyMapping_Check(ns)) { - PyErr_Format(PyExc_TypeError, - "%.200s.__prepare__() must return a mapping, not %.200s", - isclass ? ((PyTypeObject *)meta)->tp_name : "", - Py_TYPE(ns)->tp_name); - goto error; - } cell = PyEval_EvalCodeEx(PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), ns, NULL, 0, NULL, 0, NULL, 0, NULL, PyFunction_GET_CLOSURE(func)); @@ -2825,7 +2812,7 @@ PyTypeObject PyZip_Type = { static PyMethodDef builtin_methods[] = { {"__build_class__", (PyCFunction)builtin___build_class__, - METH_VARARGS | METH_KEYWORDS, build_class_doc}, + METH_FASTCALL, build_class_doc}, {"__import__", (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc}, BUILTIN_ABS_METHODDEF BUILTIN_ALL_METHODDEF