diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/tools/python3/src/Objects/call.c | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Objects/call.c')
-rw-r--r-- | contrib/tools/python3/src/Objects/call.c | 920 |
1 files changed, 460 insertions, 460 deletions
diff --git a/contrib/tools/python3/src/Objects/call.c b/contrib/tools/python3/src/Objects/call.c index 87dc0dbbdb..84400176dd 100644 --- a/contrib/tools/python3/src/Objects/call.c +++ b/contrib/tools/python3/src/Objects/call.c @@ -1,75 +1,75 @@ #include "Python.h" -#include "pycore_call.h" -#include "pycore_ceval.h" // _PyEval_EvalFrame() -#include "pycore_object.h" -#include "pycore_pyerrors.h" -#include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_tupleobject.h" +#include "pycore_call.h" +#include "pycore_ceval.h" // _PyEval_EvalFrame() +#include "pycore_object.h" +#include "pycore_pyerrors.h" +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_tupleobject.h" #include "frameobject.h" -static PyObject *const * -_PyStack_UnpackDict(PyThreadState *tstate, - PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject **p_kwnames); - -static void -_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, - PyObject *kwnames); +static PyObject *const * +_PyStack_UnpackDict(PyThreadState *tstate, + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject **p_kwnames); +static void +_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, + PyObject *kwnames); + static PyObject * -null_error(PyThreadState *tstate) +null_error(PyThreadState *tstate) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetString(tstate, PyExc_SystemError, - "null argument to internal routine"); - } + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetString(tstate, PyExc_SystemError, + "null argument to internal routine"); + } return NULL; } PyObject* -_Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable, - PyObject *result, const char *where) +_Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable, + PyObject *result, const char *where) { assert((callable != NULL) ^ (where != NULL)); if (result == NULL) { - if (!_PyErr_Occurred(tstate)) { + if (!_PyErr_Occurred(tstate)) { if (callable) - _PyErr_Format(tstate, PyExc_SystemError, - "%R returned NULL without setting an error", - callable); + _PyErr_Format(tstate, PyExc_SystemError, + "%R returned NULL without setting an error", + callable); else - _PyErr_Format(tstate, PyExc_SystemError, - "%s returned NULL without setting an error", - where); + _PyErr_Format(tstate, PyExc_SystemError, + "%s returned NULL without setting an error", + where); #ifdef Py_DEBUG - /* Ensure that the bug is caught in debug mode. - Py_FatalError() logs the SystemError exception raised above. */ + /* Ensure that the bug is caught in debug mode. + Py_FatalError() logs the SystemError exception raised above. */ Py_FatalError("a function returned NULL without setting an error"); #endif return NULL; } } else { - if (_PyErr_Occurred(tstate)) { + if (_PyErr_Occurred(tstate)) { Py_DECREF(result); if (callable) { - _PyErr_FormatFromCauseTstate( - tstate, PyExc_SystemError, - "%R returned a result with an error set", callable); + _PyErr_FormatFromCauseTstate( + tstate, PyExc_SystemError, + "%R returned a result with an error set", callable); } else { - _PyErr_FormatFromCauseTstate( - tstate, PyExc_SystemError, - "%s returned a result with an error set", where); + _PyErr_FormatFromCauseTstate( + tstate, PyExc_SystemError, + "%s returned a result with an error set", where); } #ifdef Py_DEBUG - /* Ensure that the bug is caught in debug mode. - Py_FatalError() logs the SystemError exception raised above. */ + /* Ensure that the bug is caught in debug mode. + Py_FatalError() logs the SystemError exception raised above. */ Py_FatalError("a function returned a result with an error set"); #endif return NULL; @@ -81,176 +81,176 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable, /* --- Core PyObject call functions ------------------------------- */ -/* Call a callable Python object without any arguments */ -PyObject * -PyObject_CallNoArgs(PyObject *func) -{ - PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_CallNoArgTstate(tstate, func); -} - - +/* Call a callable Python object without any arguments */ PyObject * -_PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable, - PyObject *const *args, size_t nargsf, - PyObject *kwargs) +PyObject_CallNoArgs(PyObject *func) { - assert(callable != NULL); - - /* PyObject_VectorcallDict() must not be called with an exception set, + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_CallNoArgTstate(tstate, func); +} + + +PyObject * +_PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable, + PyObject *const *args, size_t nargsf, + PyObject *kwargs) +{ + assert(callable != NULL); + + /* PyObject_VectorcallDict() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ - assert(!_PyErr_Occurred(tstate)); + assert(!_PyErr_Occurred(tstate)); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); assert(nargs == 0 || args != NULL); assert(kwargs == NULL || PyDict_Check(kwargs)); - vectorcallfunc func = PyVectorcall_Function(callable); - if (func == NULL) { - /* Use tp_call instead */ - return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs); + vectorcallfunc func = PyVectorcall_Function(callable); + if (func == NULL) { + /* Use tp_call instead */ + return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs); } - - PyObject *res; - if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { - res = func(callable, args, nargsf, NULL); + + PyObject *res; + if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { + res = func(callable, args, nargsf, NULL); } else { - PyObject *kwnames; - PyObject *const *newargs; - newargs = _PyStack_UnpackDict(tstate, - args, nargs, - kwargs, &kwnames); - if (newargs == NULL) { + PyObject *kwnames; + PyObject *const *newargs; + newargs = _PyStack_UnpackDict(tstate, + args, nargs, + kwargs, &kwnames); + if (newargs == NULL) { return NULL; } - res = func(callable, newargs, - nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); - _PyStack_UnpackDict_Free(newargs, nargs, kwnames); + res = func(callable, newargs, + nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); + _PyStack_UnpackDict_Free(newargs, nargs, kwnames); } - return _Py_CheckFunctionResult(tstate, callable, res, NULL); -} - - -PyObject * -PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, - size_t nargsf, PyObject *kwargs) -{ - PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_FastCallDictTstate(tstate, callable, args, nargsf, kwargs); + return _Py_CheckFunctionResult(tstate, callable, res, NULL); } PyObject * -_PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable, - PyObject *const *args, Py_ssize_t nargs, - PyObject *keywords) +PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, + size_t nargsf, PyObject *kwargs) { - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - assert(keywords == NULL || PyTuple_Check(keywords) || PyDict_Check(keywords)); - - /* Slow path: build a temporary tuple for positional arguments and a - * temporary dictionary for keyword arguments (if any) */ - ternaryfunc call = Py_TYPE(callable)->tp_call; - if (call == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not callable", - Py_TYPE(callable)->tp_name); - return NULL; - } - - PyObject *argstuple = _PyTuple_FromArray(args, nargs); - if (argstuple == NULL) { - return NULL; - } - - PyObject *kwdict; - if (keywords == NULL || PyDict_Check(keywords)) { - kwdict = keywords; + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_FastCallDictTstate(tstate, callable, args, nargsf, kwargs); +} + + +PyObject * +_PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable, + PyObject *const *args, Py_ssize_t nargs, + PyObject *keywords) +{ + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + assert(keywords == NULL || PyTuple_Check(keywords) || PyDict_Check(keywords)); + + /* Slow path: build a temporary tuple for positional arguments and a + * temporary dictionary for keyword arguments (if any) */ + ternaryfunc call = Py_TYPE(callable)->tp_call; + if (call == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object is not callable", + Py_TYPE(callable)->tp_name); + return NULL; + } + + PyObject *argstuple = _PyTuple_FromArray(args, nargs); + if (argstuple == NULL) { + return NULL; + } + + PyObject *kwdict; + if (keywords == NULL || PyDict_Check(keywords)) { + kwdict = keywords; } else { - if (PyTuple_GET_SIZE(keywords)) { - assert(args != NULL); - kwdict = _PyStack_AsDict(args + nargs, keywords); + if (PyTuple_GET_SIZE(keywords)) { + assert(args != NULL); + kwdict = _PyStack_AsDict(args + nargs, keywords); if (kwdict == NULL) { Py_DECREF(argstuple); return NULL; } } else { - keywords = kwdict = NULL; + keywords = kwdict = NULL; } - } - - PyObject *result = NULL; - if (_Py_EnterRecursiveCall(tstate, " while calling a Python object") == 0) - { - result = call(callable, argstuple, kwdict); - _Py_LeaveRecursiveCall(tstate); - } - - Py_DECREF(argstuple); - if (kwdict != keywords) { - Py_DECREF(kwdict); - } - - return _Py_CheckFunctionResult(tstate, callable, result, NULL); + } + + PyObject *result = NULL; + if (_Py_EnterRecursiveCall(tstate, " while calling a Python object") == 0) + { + result = call(callable, argstuple, kwdict); + _Py_LeaveRecursiveCall(tstate); + } + + Py_DECREF(argstuple); + if (kwdict != keywords) { + Py_DECREF(kwdict); + } + + return _Py_CheckFunctionResult(tstate, callable, result, NULL); +} + + +PyObject * +PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) +{ + PyThreadState *tstate = _PyThreadState_GET(); + vectorcallfunc func; + + /* get vectorcallfunc as in PyVectorcall_Function, but without + * the Py_TPFLAGS_HAVE_VECTORCALL check */ + Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; + if (offset <= 0) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support vectorcall", + Py_TYPE(callable)->tp_name); + return NULL; + } + memcpy(&func, (char *) callable + offset, sizeof(func)); + if (func == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support vectorcall", + Py_TYPE(callable)->tp_name); + return NULL; + } + + Py_ssize_t nargs = PyTuple_GET_SIZE(tuple); + + /* Fast path for no keywords */ + if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { + return func(callable, _PyTuple_ITEMS(tuple), nargs, NULL); + } + + /* Convert arguments & call */ + PyObject *const *args; + PyObject *kwnames; + args = _PyStack_UnpackDict(tstate, + _PyTuple_ITEMS(tuple), nargs, + kwargs, &kwnames); + if (args == NULL) { + return NULL; + } + PyObject *result = func(callable, args, + nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); + _PyStack_UnpackDict_Free(args, nargs, kwnames); + + return _Py_CheckFunctionResult(tstate, callable, result, NULL); } PyObject * -PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) -{ - PyThreadState *tstate = _PyThreadState_GET(); - vectorcallfunc func; - - /* get vectorcallfunc as in PyVectorcall_Function, but without - * the Py_TPFLAGS_HAVE_VECTORCALL check */ - Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; - if (offset <= 0) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support vectorcall", - Py_TYPE(callable)->tp_name); - return NULL; - } - memcpy(&func, (char *) callable + offset, sizeof(func)); - if (func == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support vectorcall", - Py_TYPE(callable)->tp_name); - return NULL; - } - - Py_ssize_t nargs = PyTuple_GET_SIZE(tuple); - - /* Fast path for no keywords */ - if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { - return func(callable, _PyTuple_ITEMS(tuple), nargs, NULL); - } - - /* Convert arguments & call */ - PyObject *const *args; - PyObject *kwnames; - args = _PyStack_UnpackDict(tstate, - _PyTuple_ITEMS(tuple), nargs, - kwargs, &kwnames); - if (args == NULL) { - return NULL; - } - PyObject *result = func(callable, args, - nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); - _PyStack_UnpackDict_Free(args, nargs, kwnames); - - return _Py_CheckFunctionResult(tstate, callable, result, NULL); -} - - -PyObject * -_PyObject_Call(PyThreadState *tstate, PyObject *callable, - PyObject *args, PyObject *kwargs) +_PyObject_Call(PyThreadState *tstate, PyObject *callable, + PyObject *args, PyObject *kwargs) { ternaryfunc call; PyObject *result; @@ -258,76 +258,76 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable, /* PyObject_Call() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ - assert(!_PyErr_Occurred(tstate)); + assert(!_PyErr_Occurred(tstate)); assert(PyTuple_Check(args)); assert(kwargs == NULL || PyDict_Check(kwargs)); - if (PyVectorcall_Function(callable) != NULL) { - return PyVectorcall_Call(callable, args, kwargs); + if (PyVectorcall_Function(callable) != NULL) { + return PyVectorcall_Call(callable, args, kwargs); } else { - call = Py_TYPE(callable)->tp_call; + call = Py_TYPE(callable)->tp_call; if (call == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object is not callable", - Py_TYPE(callable)->tp_name); + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object is not callable", + Py_TYPE(callable)->tp_name); return NULL; } - if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { + if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { return NULL; - } + } result = (*call)(callable, args, kwargs); - _Py_LeaveRecursiveCall(tstate); + _Py_LeaveRecursiveCall(tstate); - return _Py_CheckFunctionResult(tstate, callable, result, NULL); + return _Py_CheckFunctionResult(tstate, callable, result, NULL); } } -PyObject * -PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) -{ - PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_Call(tstate, callable, args, kwargs); -} - - -PyObject * -PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) -{ - PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_Call(tstate, callable, args, kwargs); -} - - +PyObject * +PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) +{ + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_Call(tstate, callable, args, kwargs); +} + + +PyObject * +PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) +{ + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_Call(tstate, callable, args, kwargs); +} + + /* --- PyFunction call functions ---------------------------------- */ static PyObject* _Py_HOT_FUNCTION -function_code_fastcall(PyThreadState *tstate, PyCodeObject *co, - PyObject *const *args, Py_ssize_t nargs, +function_code_fastcall(PyThreadState *tstate, PyCodeObject *co, + PyObject *const *args, Py_ssize_t nargs, PyObject *globals) { - assert(tstate != NULL); - assert(globals != NULL); + assert(tstate != NULL); + assert(globals != NULL); /* XXX Perhaps we should create a specialized _PyFrame_New_NoTrack() that doesn't take locals, but does take builtins without sanity checking them. */ - PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, globals, NULL); + PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, globals, NULL); if (f == NULL) { return NULL; } - PyObject **fastlocals = f->f_localsplus; + PyObject **fastlocals = f->f_localsplus; - for (Py_ssize_t i = 0; i < nargs; i++) { + for (Py_ssize_t i = 0; i < nargs; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } - PyObject *result = _PyEval_EvalFrame(tstate, f, 0); + PyObject *result = _PyEval_EvalFrame(tstate, f, 0); if (Py_REFCNT(f) > 1) { Py_DECREF(f); @@ -343,19 +343,19 @@ function_code_fastcall(PyThreadState *tstate, PyCodeObject *co, PyObject * -_PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, - size_t nargsf, PyObject *kwnames) +_PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, + size_t nargsf, PyObject *kwnames) { - assert(PyFunction_Check(func)); - assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); + assert(PyFunction_Check(func)); + assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); - Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); - assert((nargs == 0 && nkwargs == 0) || stack != NULL); - /* kwnames must only contain strings and all keys must be unique */ + Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); + assert((nargs == 0 && nkwargs == 0) || stack != NULL); + /* kwnames must only contain strings and all keys must be unique */ - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); @@ -364,43 +364,43 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { if (argdefs == NULL && co->co_argcount == nargs) { - return function_code_fastcall(tstate, co, stack, nargs, globals); + return function_code_fastcall(tstate, co, stack, nargs, globals); } else if (nargs == 0 && argdefs != NULL && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ - stack = _PyTuple_ITEMS(argdefs); - return function_code_fastcall(tstate, co, - stack, PyTuple_GET_SIZE(argdefs), + stack = _PyTuple_ITEMS(argdefs); + return function_code_fastcall(tstate, co, + stack, PyTuple_GET_SIZE(argdefs), globals); } } - PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); - PyObject *closure = PyFunction_GET_CLOSURE(func); - PyObject *name = ((PyFunctionObject *)func) -> func_name; - PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname; + PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); + PyObject *closure = PyFunction_GET_CLOSURE(func); + PyObject *name = ((PyFunctionObject *)func) -> func_name; + PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname; - PyObject **d; - Py_ssize_t nd; + PyObject **d; + Py_ssize_t nd; if (argdefs != NULL) { - d = _PyTuple_ITEMS(argdefs); + d = _PyTuple_ITEMS(argdefs); nd = PyTuple_GET_SIZE(argdefs); - assert(nd <= INT_MAX); + assert(nd <= INT_MAX); } else { d = NULL; nd = 0; } - return _PyEval_EvalCode(tstate, - (PyObject*)co, globals, (PyObject *)NULL, - stack, nargs, - nkwargs ? _PyTuple_ITEMS(kwnames) : NULL, - stack + nargs, - nkwargs, 1, - d, (int)nd, kwdefs, - closure, name, qualname); + return _PyEval_EvalCode(tstate, + (PyObject*)co, globals, (PyObject *)NULL, + stack, nargs, + nkwargs ? _PyTuple_ITEMS(kwnames) : NULL, + stack + nargs, + nkwargs, 1, + d, (int)nd, kwdefs, + closure, name, qualname); } @@ -412,31 +412,31 @@ PyObject * PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); #ifdef Py_DEBUG /* PyEval_CallObjectWithKeywords() must not be called with an exception set. It raises a new exception if parameters are invalid or if PyTuple_New() fails, and so the original exception is lost. */ - assert(!_PyErr_Occurred(tstate)); + assert(!_PyErr_Occurred(tstate)); #endif if (args != NULL && !PyTuple_Check(args)) { - _PyErr_SetString(tstate, PyExc_TypeError, - "argument list must be a tuple"); + _PyErr_SetString(tstate, PyExc_TypeError, + "argument list must be a tuple"); return NULL; } if (kwargs != NULL && !PyDict_Check(kwargs)) { - _PyErr_SetString(tstate, PyExc_TypeError, - "keyword list must be a dictionary"); + _PyErr_SetString(tstate, PyExc_TypeError, + "keyword list must be a dictionary"); return NULL; } if (args == NULL) { - return _PyObject_FastCallDictTstate(tstate, callable, NULL, 0, kwargs); + return _PyObject_FastCallDictTstate(tstate, callable, NULL, 0, kwargs); } else { - return _PyObject_Call(tstate, callable, args, kwargs); + return _PyObject_Call(tstate, callable, args, kwargs); } } @@ -444,31 +444,31 @@ PyEval_CallObjectWithKeywords(PyObject *callable, PyObject * PyObject_CallObject(PyObject *callable, PyObject *args) { - PyThreadState *tstate = _PyThreadState_GET(); - assert(!_PyErr_Occurred(tstate)); - if (args == NULL) { - return _PyObject_CallNoArgTstate(tstate, callable); + PyThreadState *tstate = _PyThreadState_GET(); + assert(!_PyErr_Occurred(tstate)); + if (args == NULL) { + return _PyObject_CallNoArgTstate(tstate, callable); } - if (!PyTuple_Check(args)) { - _PyErr_SetString(tstate, PyExc_TypeError, - "argument list must be a tuple"); - return NULL; + if (!PyTuple_Check(args)) { + _PyErr_SetString(tstate, PyExc_TypeError, + "argument list must be a tuple"); + return NULL; } - return _PyObject_Call(tstate, callable, args, NULL); + return _PyObject_Call(tstate, callable, args, NULL); } /* Call callable(obj, *args, **kwargs). */ PyObject * -_PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable, +_PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable, PyObject *obj, PyObject *args, PyObject *kwargs) { - assert(PyTuple_Check(args)); - + assert(PyTuple_Check(args)); + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; - Py_ssize_t argcount = PyTuple_GET_SIZE(args); + Py_ssize_t argcount = PyTuple_GET_SIZE(args); if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { stack = small_stack; } @@ -483,12 +483,12 @@ _PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable, /* use borrowed references */ stack[0] = obj; memcpy(&stack[1], - _PyTuple_ITEMS(args), - argcount * sizeof(PyObject *)); + _PyTuple_ITEMS(args), + argcount * sizeof(PyObject *)); - PyObject *result = _PyObject_FastCallDictTstate(tstate, callable, - stack, argcount + 1, - kwargs); + PyObject *result = _PyObject_FastCallDictTstate(tstate, callable, + stack, argcount + 1, + kwargs); if (stack != small_stack) { PyMem_Free(stack); } @@ -499,8 +499,8 @@ _PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable, /* --- Call with a format string ---------------------------------- */ static PyObject * -_PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable, - const char *format, va_list va, int is_size_t) +_PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable, + const char *format, va_list va, int is_size_t) { PyObject* small_stack[_PY_FASTCALL_SMALL_STACK]; const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack); @@ -509,11 +509,11 @@ _PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable, PyObject *result; if (callable == NULL) { - return null_error(tstate); + return null_error(tstate); } if (!format || !*format) { - return _PyObject_CallNoArgTstate(tstate, callable); + return _PyObject_CallNoArgTstate(tstate, callable); } if (is_size_t) { @@ -534,14 +534,14 @@ _PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable, - PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */ PyObject *args = stack[0]; - result = _PyObject_VectorcallTstate(tstate, callable, - _PyTuple_ITEMS(args), - PyTuple_GET_SIZE(args), - NULL); + result = _PyObject_VectorcallTstate(tstate, callable, + _PyTuple_ITEMS(args), + PyTuple_GET_SIZE(args), + NULL); } else { - result = _PyObject_VectorcallTstate(tstate, callable, - stack, nargs, NULL); + result = _PyObject_VectorcallTstate(tstate, callable, + stack, nargs, NULL); } for (i = 0; i < nargs; ++i) { @@ -559,10 +559,10 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...) { va_list va; PyObject *result; - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); va_start(va, format); - result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0); + result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0); va_end(va); return result; @@ -577,10 +577,10 @@ PyEval_CallFunction(PyObject *callable, const char *format, ...) { va_list va; PyObject *result; - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); va_start(va, format); - result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0); + result = _PyObject_CallFunctionVa(tstate, callable, format, va, 0); va_end(va); return result; @@ -590,11 +590,11 @@ PyEval_CallFunction(PyObject *callable, const char *format, ...) PyObject * _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); - + PyThreadState *tstate = _PyThreadState_GET(); + va_list va; va_start(va, format); - PyObject *result = _PyObject_CallFunctionVa(tstate, callable, format, va, 1); + PyObject *result = _PyObject_CallFunctionVa(tstate, callable, format, va, 1); va_end(va); return result; @@ -602,37 +602,37 @@ _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) static PyObject* -callmethod(PyThreadState *tstate, PyObject* callable, const char *format, va_list va, int is_size_t) +callmethod(PyThreadState *tstate, PyObject* callable, const char *format, va_list va, int is_size_t) { assert(callable != NULL); if (!PyCallable_Check(callable)) { - _PyErr_Format(tstate, PyExc_TypeError, - "attribute of type '%.200s' is not callable", - Py_TYPE(callable)->tp_name); + _PyErr_Format(tstate, PyExc_TypeError, + "attribute of type '%.200s' is not callable", + Py_TYPE(callable)->tp_name); return NULL; } - return _PyObject_CallFunctionVa(tstate, callable, format, va, is_size_t); + return _PyObject_CallFunctionVa(tstate, callable, format, va, is_size_t); } PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *callable = PyObject_GetAttrString(obj, name); - if (callable == NULL) { + PyObject *callable = PyObject_GetAttrString(obj, name); + if (callable == NULL) { return NULL; - } + } - va_list va; + va_list va; va_start(va, format); - PyObject *retval = callmethod(tstate, callable, format, va, 0); + PyObject *retval = callmethod(tstate, callable, format, va, 0); va_end(va); Py_DECREF(callable); @@ -646,19 +646,19 @@ PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) PyObject * PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *callable = PyObject_GetAttrString(obj, name); - if (callable == NULL) { + PyObject *callable = PyObject_GetAttrString(obj, name); + if (callable == NULL) { return NULL; - } + } - va_list va; + va_list va; va_start(va, format); - PyObject *retval = callmethod(tstate, callable, format, va, 0); + PyObject *retval = callmethod(tstate, callable, format, va, 0); va_end(va); Py_DECREF(callable); @@ -670,19 +670,19 @@ PyObject * _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *callable = _PyObject_GetAttrId(obj, name); - if (callable == NULL) { + PyObject *callable = _PyObject_GetAttrId(obj, name); + if (callable == NULL) { return NULL; - } + } - va_list va; + va_list va; va_start(va, format); - PyObject *retval = callmethod(tstate, callable, format, va, 0); + PyObject *retval = callmethod(tstate, callable, format, va, 0); va_end(va); Py_DECREF(callable); @@ -694,19 +694,19 @@ PyObject * _PyObject_CallMethod_SizeT(PyObject *obj, const char *name, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *callable = PyObject_GetAttrString(obj, name); - if (callable == NULL) { + PyObject *callable = PyObject_GetAttrString(obj, name); + if (callable == NULL) { return NULL; - } + } - va_list va; + va_list va; va_start(va, format); - PyObject *retval = callmethod(tstate, callable, format, va, 1); + PyObject *retval = callmethod(tstate, callable, format, va, 1); va_end(va); Py_DECREF(callable); @@ -718,19 +718,19 @@ PyObject * _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, const char *format, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *callable = _PyObject_GetAttrId(obj, name); + PyObject *callable = _PyObject_GetAttrId(obj, name); if (callable == NULL) { return NULL; } - va_list va; + va_list va; va_start(va, format); - PyObject *retval = callmethod(tstate, callable, format, va, 1); + PyObject *retval = callmethod(tstate, callable, format, va, 1); va_end(va); Py_DECREF(callable); @@ -741,8 +741,8 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, /* --- Call with "..." arguments ---------------------------------- */ static PyObject * -object_vacall(PyThreadState *tstate, PyObject *base, - PyObject *callable, va_list vargs) +object_vacall(PyThreadState *tstate, PyObject *base, + PyObject *callable, va_list vargs) { PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; @@ -752,12 +752,12 @@ object_vacall(PyThreadState *tstate, PyObject *base, va_list countva; if (callable == NULL) { - return null_error(tstate); + return null_error(tstate); } /* Count the number of arguments */ va_copy(countva, vargs); - nargs = base ? 1 : 0; + nargs = base ? 1 : 0; while (1) { PyObject *arg = va_arg(countva, PyObject *); if (arg == NULL) { @@ -779,17 +779,17 @@ object_vacall(PyThreadState *tstate, PyObject *base, } } - i = 0; - if (base) { - stack[i++] = base; - } - - for (; i < nargs; ++i) { + i = 0; + if (base) { + stack[i++] = base; + } + + for (; i < nargs; ++i) { stack[i] = va_arg(vargs, PyObject *); } /* Call the function */ - result = _PyObject_VectorcallTstate(tstate, callable, stack, nargs, NULL); + result = _PyObject_VectorcallTstate(tstate, callable, stack, nargs, NULL); if (stack != small_stack) { PyMem_Free(stack); @@ -798,58 +798,58 @@ object_vacall(PyThreadState *tstate, PyObject *base, } +PyObject * +PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, + size_t nargsf, PyObject *kwnames) +{ + assert(name != NULL); + assert(args != NULL); + assert(PyVectorcall_NARGS(nargsf) >= 1); + + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *callable = NULL; + /* Use args[0] as "self" argument */ + int unbound = _PyObject_GetMethod(args[0], name, &callable); + if (callable == NULL) { + return NULL; + } + + if (unbound) { + /* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since + * that would be interpreted as allowing to change args[-1] */ + nargsf &= ~PY_VECTORCALL_ARGUMENTS_OFFSET; + } + else { + /* Skip "self". We can keep PY_VECTORCALL_ARGUMENTS_OFFSET since + * args[-1] in the onward call is args[0] here. */ + args++; + nargsf--; + } + PyObject *result = _PyObject_VectorcallTstate(tstate, callable, + args, nargsf, kwnames); + Py_DECREF(callable); + return result; +} + + PyObject * -PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, - size_t nargsf, PyObject *kwnames) -{ - assert(name != NULL); - assert(args != NULL); - assert(PyVectorcall_NARGS(nargsf) >= 1); - - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *callable = NULL; - /* Use args[0] as "self" argument */ - int unbound = _PyObject_GetMethod(args[0], name, &callable); - if (callable == NULL) { - return NULL; - } - - if (unbound) { - /* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since - * that would be interpreted as allowing to change args[-1] */ - nargsf &= ~PY_VECTORCALL_ARGUMENTS_OFFSET; - } - else { - /* Skip "self". We can keep PY_VECTORCALL_ARGUMENTS_OFFSET since - * args[-1] in the onward call is args[0] here. */ - args++; - nargsf--; - } - PyObject *result = _PyObject_VectorcallTstate(tstate, callable, - args, nargsf, kwnames); - Py_DECREF(callable); - return result; -} - - -PyObject * -PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...) +PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...) { - PyThreadState *tstate = _PyThreadState_GET(); - if (obj == NULL || name == NULL) { - return null_error(tstate); + PyThreadState *tstate = _PyThreadState_GET(); + if (obj == NULL || name == NULL) { + return null_error(tstate); } - PyObject *callable = NULL; - int is_method = _PyObject_GetMethod(obj, name, &callable); + PyObject *callable = NULL; + int is_method = _PyObject_GetMethod(obj, name, &callable); if (callable == NULL) { return NULL; } - obj = is_method ? obj : NULL; + obj = is_method ? obj : NULL; - va_list vargs; + va_list vargs; va_start(vargs, name); - PyObject *result = object_vacall(tstate, obj, callable, vargs); + PyObject *result = object_vacall(tstate, obj, callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -861,26 +861,26 @@ PyObject * _PyObject_CallMethodIdObjArgs(PyObject *obj, struct _Py_Identifier *name, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); if (obj == NULL || name == NULL) { - return null_error(tstate); + return null_error(tstate); } - PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ - if (!oname) { - return NULL; - } - - PyObject *callable = NULL; - int is_method = _PyObject_GetMethod(obj, oname, &callable); + PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ + if (!oname) { + return NULL; + } + + PyObject *callable = NULL; + int is_method = _PyObject_GetMethod(obj, oname, &callable); if (callable == NULL) { return NULL; } - obj = is_method ? obj : NULL; + obj = is_method ? obj : NULL; - va_list vargs; + va_list vargs; va_start(vargs, name); - PyObject *result = object_vacall(tstate, obj, callable, vargs); + PyObject *result = object_vacall(tstate, obj, callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -891,12 +891,12 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj, PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...) { - PyThreadState *tstate = _PyThreadState_GET(); + PyThreadState *tstate = _PyThreadState_GET(); va_list vargs; PyObject *result; va_start(vargs, callable); - result = object_vacall(tstate, NULL, callable, vargs); + result = object_vacall(tstate, NULL, callable, vargs); va_end(vargs); return result; @@ -932,98 +932,98 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames) } -/* Convert (args, nargs, kwargs: dict) into a (stack, nargs, kwnames: tuple). - - Allocate a new argument vector and keyword names tuple. Return the argument - vector; return NULL with exception set on error. Return the keyword names - tuple in *p_kwnames. - - This also checks that all keyword names are strings. If not, a TypeError is - raised. - - The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET. - - When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */ -static PyObject *const * -_PyStack_UnpackDict(PyThreadState *tstate, - PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject **p_kwnames) +/* Convert (args, nargs, kwargs: dict) into a (stack, nargs, kwnames: tuple). + + Allocate a new argument vector and keyword names tuple. Return the argument + vector; return NULL with exception set on error. Return the keyword names + tuple in *p_kwnames. + + This also checks that all keyword names are strings. If not, a TypeError is + raised. + + The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET. + + When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */ +static PyObject *const * +_PyStack_UnpackDict(PyThreadState *tstate, + PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject **p_kwnames) { assert(nargs >= 0); - assert(kwargs != NULL); - assert(PyDict_Check(kwargs)); - - Py_ssize_t nkwargs = PyDict_GET_SIZE(kwargs); - /* Check for overflow in the PyMem_Malloc() call below. The subtraction - * in this check cannot overflow: both maxnargs and nkwargs are - * non-negative signed integers, so their difference fits in the type. */ - Py_ssize_t maxnargs = PY_SSIZE_T_MAX / sizeof(args[0]) - 1; - if (nargs > maxnargs - nkwargs) { - _PyErr_NoMemory(tstate); - return NULL; + assert(kwargs != NULL); + assert(PyDict_Check(kwargs)); + + Py_ssize_t nkwargs = PyDict_GET_SIZE(kwargs); + /* Check for overflow in the PyMem_Malloc() call below. The subtraction + * in this check cannot overflow: both maxnargs and nkwargs are + * non-negative signed integers, so their difference fits in the type. */ + Py_ssize_t maxnargs = PY_SSIZE_T_MAX / sizeof(args[0]) - 1; + if (nargs > maxnargs - nkwargs) { + _PyErr_NoMemory(tstate); + return NULL; } - /* Add 1 to support PY_VECTORCALL_ARGUMENTS_OFFSET */ - PyObject **stack = PyMem_Malloc((1 + nargs + nkwargs) * sizeof(args[0])); + /* Add 1 to support PY_VECTORCALL_ARGUMENTS_OFFSET */ + PyObject **stack = PyMem_Malloc((1 + nargs + nkwargs) * sizeof(args[0])); if (stack == NULL) { - _PyErr_NoMemory(tstate); - return NULL; + _PyErr_NoMemory(tstate); + return NULL; } - PyObject *kwnames = PyTuple_New(nkwargs); + PyObject *kwnames = PyTuple_New(nkwargs); if (kwnames == NULL) { PyMem_Free(stack); - return NULL; + return NULL; } - stack++; /* For PY_VECTORCALL_ARGUMENTS_OFFSET */ + stack++; /* For PY_VECTORCALL_ARGUMENTS_OFFSET */ + + /* Copy positional arguments */ + for (Py_ssize_t i = 0; i < nargs; i++) { + Py_INCREF(args[i]); + stack[i] = args[i]; + } - /* Copy positional arguments */ - for (Py_ssize_t i = 0; i < nargs; i++) { - Py_INCREF(args[i]); - stack[i] = args[i]; - } - - PyObject **kwstack = stack + nargs; + PyObject **kwstack = stack + nargs; /* This loop doesn't support lookup function mutating the dictionary to change its size. It's a deliberate choice for speed, this function is called in the performance critical hot code. */ - Py_ssize_t pos = 0, i = 0; - PyObject *key, *value; - unsigned long keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; + Py_ssize_t pos = 0, i = 0; + PyObject *key, *value; + unsigned long keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; while (PyDict_Next(kwargs, &pos, &key, &value)) { - keys_are_strings &= Py_TYPE(key)->tp_flags; + keys_are_strings &= Py_TYPE(key)->tp_flags; Py_INCREF(key); - Py_INCREF(value); + Py_INCREF(value); PyTuple_SET_ITEM(kwnames, i, key); kwstack[i] = value; i++; } - /* keys_are_strings has the value Py_TPFLAGS_UNICODE_SUBCLASS if that - * flag is set for all keys. Otherwise, keys_are_strings equals 0. - * We do this check once at the end instead of inside the loop above - * because it simplifies the deallocation in the failing case. - * It happens to also make the loop above slightly more efficient. */ - if (!keys_are_strings) { - _PyErr_SetString(tstate, PyExc_TypeError, - "keywords must be strings"); - _PyStack_UnpackDict_Free(stack, nargs, kwnames); - return NULL; - } - + /* keys_are_strings has the value Py_TPFLAGS_UNICODE_SUBCLASS if that + * flag is set for all keys. Otherwise, keys_are_strings equals 0. + * We do this check once at the end instead of inside the loop above + * because it simplifies the deallocation in the failing case. + * It happens to also make the loop above slightly more efficient. */ + if (!keys_are_strings) { + _PyErr_SetString(tstate, PyExc_TypeError, + "keywords must be strings"); + _PyStack_UnpackDict_Free(stack, nargs, kwnames); + return NULL; + } + *p_kwnames = kwnames; - return stack; -} - -static void -_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, - PyObject *kwnames) -{ - Py_ssize_t n = PyTuple_GET_SIZE(kwnames) + nargs; - for (Py_ssize_t i = 0; i < n; i++) { - Py_DECREF(stack[i]); - } - PyMem_Free((PyObject **)stack - 1); - Py_DECREF(kwnames); + return stack; } + +static void +_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, + PyObject *kwnames) +{ + Py_ssize_t n = PyTuple_GET_SIZE(kwnames) + nargs; + for (Py_ssize_t i = 0; i < n; i++) { + Py_DECREF(stack[i]); + } + PyMem_Free((PyObject **)stack - 1); + Py_DECREF(kwnames); +} |