sandbox/fastcall: 2dc558e01e66 Python/pystack.c (original) (raw)
Victor Stinner victor.stinner@gmail.com
date
Thu, 26 May 2016 00:31:39 +0200
parents
children
line wrap: on
line source
#include "Python.h" PyObject** _PyStack_FromBorrowedTuple(PyObject *args, Py_ssize_t start, int p_nargs) { Py_ssize_t len; assert(start >= 0); if (args != NULL) { assert(PyTuple_Check(args)); len = PyTuple_GET_SIZE(args); if (len <= start) { *p_nargs = 0; return NULL; } len -= start; assert(len <= INT_MAX); *p_nargs = (int)len; return &((PyTupleObject *)args)->ob_item[start]; } else { p_nargs = 0; return NULL; } } PyObject _PyStack_Copy(PyObject **small_stack, Py_ssize_t small_stack_len, PyObject **stack, int nargs) { PyObject **stack2; int i; stack2 = _PyStack_Alloc(small_stack, small_stack_len, nargs); if (stack2 == NULL) { return NULL; } for (i=0; i < nargs; i++) { PyObject *obj = stack[i]; Py_INCREF(obj); stack2[i] = obj; } return stack2; } PyObject** _PyStack_FromVa(PyObject **small_stack, Py_ssize_t small_stack_len, va_list va, int *p_na) { va_list countva; PyObject **stack; Py_ssize_t nargs; Py_VA_COPY(countva, va); nargs = 0; while (1) { PyObject *obj = (PyObject *)va_arg(countva, PyObject *); if (obj == NULL) break; nargs++; } if (nargs > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "too many arguments"); return NULL; } stack = _PyStack_Alloc(small_stack, small_stack_len, nargs); if (stack == NULL) { return NULL; } for (Py_ssize_t i = 0; i < nargs; ++i) { PyObject *obj = (PyObject *)va_arg(va, PyObject *); /* FIXME: does it matter to keep a strong reference? */ Py_INCREF(obj); stack[i] = obj; } /* check for overflow above */ *p_na = (int)nargs; return stack; } PyObject** _PyStack_PrependArg(PyObject **stack, int nargs, PyObject **small_stack, Py_ssize_t small_stack_len, PyObject *arg) { PyObject **stack2; stack2 = _PyStack_Alloc(small_stack, small_stack_len, 1 + nargs); if (stack2 == NULL) { return NULL; } Py_INCREF(arg); stack2[0] = arg; for (Py_ssize_t i = 0; i < nargs; i++) { PyObject *obj = stack[i]; Py_INCREF(obj); stack2[i+1] = obj; } return stack2; } PyObject** _PyStack_FromTuple(PyObject **small_stack, Py_ssize_t small_stack_len, PyObject *tuple, int *p_na) { PyObject **stack; Py_ssize_t nargs, i; assert(PyTuple_Check(tuple)); nargs = PyTuple_GET_SIZE(tuple); if (nargs > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "too many arguments"); *p_na = 0; return NULL; } stack = _PyStack_Alloc(small_stack, small_stack_len, nargs); if (stack == NULL) { *p_na = 0; return NULL; } for (i = 0; i < nargs; ++i) { PyObject *item = PyTuple_GET_ITEM(tuple, i); Py_INCREF(item); stack[i] = item; } /* downcas is safe, checked for integer overflow above */ *p_na = (int)nargs; return stack; } PyObject** _PyStack_Alloc(PyObject **small_stack, Py_ssize_t small_stack_len, Py_ssize_t nargs) { PyObject **stack; if (nargs <= small_stack_len) { return small_stack; } if (nargs > PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(PyObject *)) { PyErr_NoMemory(); return NULL; } stack = PyMem_Malloc(nargs * sizeof(PyObject *)); if (stack == NULL) { PyErr_NoMemory(); return NULL; } return stack; } void _PyStack_Free(PyObject **stack, PyObject **small_stack, Py_ssize_t nargs) { for (Py_ssize_t i = 0; i < nargs; i++) { Py_DECREF(stack[i]); } if (stack != small_stack) { PyMem_Free(stack); } } PyObject* _PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs, Py_ssize_t start, Py_ssize_t end) { PyObject *args; Py_ssize_t src, dst, len; assert(start >= 0); assert(end <= nargs); len = end - start; args = PyTuple_New(len); if (args == NULL) { return NULL; } for (src=start, dst=0; src < end; src++, dst++) { PyObject *item = stack[src]; Py_INCREF(item); PyTuple_SET_ITEM(args, dst, item); } return args; } PyObject* _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) { return _PyStack_AsTupleSlice(stack, nargs, 0, nargs); } int pystack_chekargs(PyObject **stack, Py_ssize_t nargs, Py_ssize_t nk, const char *func_name, Py_ssize_t min_na, Py_ssize_t max_na) { if (nargs < min_na) { PyErr_Format(PyExc_TypeError, "%s() takes at least %d argument%s (%zd given)", func_name, min_na, (min_na == 1) ? "" : "s", nargs + nk); return -1; } if (nargs > max_na) { PyErr_Format(PyExc_TypeError, "%s() takes at most %d argument%s (%zd given)", func_name, max_na, (max_na == 1) ? "" : "s", nargs + nk); return -1; } return 0; } int _PyStack_CheckArgs(PyObject **stack, Py_ssize_t nargs, PyObject *kwargs, const char *func_name, Py_ssize_t min_na, Py_ssize_t max_na) { Py_ssize_t nk; if (kwargs != NULL) { assert(PyDict_Check(kwargs)); nk = PyDict_Size(kwargs); } else { nk = 0; } if (pystack_chekargs(stack, nargs, nk, func_name, min_na, max_na) < 0) { return -1; } if (nk != 0) { PyErr_Format(PyExc_TypeError, "%s() does not take keyword arguments", func_name); return -1; } return 0; } int _PyStack_CheckArgsKeywords(PyObject **stack, Py_ssize_t nargs, PyObject *kwargs, const char *func_name, Py_ssize_t min_na, Py_ssize_t max_na) { Py_ssize_t nk; if (kwargs != NULL) { assert(PyDict_Check(kwargs)); nk = PyDict_Size(kwargs); } else { nk = 0; } return pystack_chekargs(stack, nargs, nk, func_name, min_na, max_na); }