summaryrefslogtreecommitdiff
path: root/Include
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-10-14 21:53:04 +0200
committerGitHub <noreply@github.com>2021-10-14 21:53:04 +0200
commit3cc56c828d2d8f8659ea49447234bf0d2b87cd64 (patch)
tree7f204eb39062037d3575d407fda18825e314dd7e /Include
parent39aa98346d5dd8ac591a7cafb467af21c53f1e5d (diff)
downloadcpython-git-3cc56c828d2d8f8659ea49447234bf0d2b87cd64.tar.gz
bpo-45439: Move _PyObject_VectorcallTstate() to pycore_call.h (GH-28893)
* Move _PyObject_VectorcallTstate() and _PyObject_FastCallTstate() to pycore_call.h (internal C API). * Convert PyObject_CallOneArg(), PyObject_Vectorcall(), _PyObject_FastCall() and PyVectorcall_Function() static inline functions to regular functions. * Add _PyVectorcall_FunctionInline() static inline function. * PyObject_Vectorcall(), _PyObject_FastCall(), and PyObject_CallOneArg() now call _PyThreadState_GET() rather than PyThreadState_Get().
Diffstat (limited to 'Include')
-rw-r--r--Include/cpython/abstract.h105
-rw-r--r--Include/internal/pycore_call.h70
2 files changed, 82 insertions, 93 deletions
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
index 0814bfa62e..55a742c31f 100644
--- a/Include/cpython/abstract.h
+++ b/Include/cpython/abstract.h
@@ -58,72 +58,13 @@ PyVectorcall_NARGS(size_t n)
return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
}
-static inline vectorcallfunc
-PyVectorcall_Function(PyObject *callable)
-{
- PyTypeObject *tp;
- Py_ssize_t offset;
- vectorcallfunc ptr;
-
- assert(callable != NULL);
- tp = Py_TYPE(callable);
- if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) {
- return NULL;
- }
- assert(PyCallable_Check(callable));
-
- offset = tp->tp_vectorcall_offset;
- assert(offset > 0);
- memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
- return ptr;
-}
-
-/* Call the callable object 'callable' with the "vectorcall" calling
- convention.
-
- args is a C array for positional arguments.
-
- nargsf is the number of positional arguments plus optionally the flag
- PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to
- modify args[-1].
-
- kwnames is a tuple of keyword names. The values of the keyword arguments
- are stored in "args" after the positional arguments (note that the number
- of keyword arguments does not change nargsf). kwnames can also be NULL if
- there are no keyword arguments.
+PyAPI_FUNC(vectorcallfunc) PyVectorcall_Function(PyObject *callable);
- keywords must only contain strings and all keys must be unique.
-
- Return the result on success. Raise an exception and return NULL on
- error. */
-static inline PyObject *
-_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
- PyObject *const *args, size_t nargsf,
- PyObject *kwnames)
-{
- vectorcallfunc func;
- PyObject *res;
-
- assert(kwnames == NULL || PyTuple_Check(kwnames));
- assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
-
- func = PyVectorcall_Function(callable);
- if (func == NULL) {
- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
- return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames);
- }
- res = func(callable, args, nargsf, kwnames);
- return _Py_CheckFunctionResult(tstate, callable, res, NULL);
-}
-
-static inline PyObject *
-PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
- size_t nargsf, PyObject *kwnames)
-{
- PyThreadState *tstate = PyThreadState_Get();
- return _PyObject_VectorcallTstate(tstate, callable,
- args, nargsf, kwnames);
-}
+PyAPI_FUNC(PyObject *) PyObject_Vectorcall(
+ PyObject *callable,
+ PyObject *const *args,
+ size_t nargsf,
+ PyObject *kwnames);
// Backwards compatibility aliases for API that was provisional in Python 3.8
#define _PyObject_Vectorcall PyObject_Vectorcall
@@ -146,35 +87,13 @@ PyAPI_FUNC(PyObject *) PyObject_VectorcallDict(
"tuple" and keyword arguments "dict". "dict" may also be NULL */
PyAPI_FUNC(PyObject *) PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict);
-static inline PyObject *
-_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs)
-{
- return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
-}
-
-/* Same as PyObject_Vectorcall except without keyword arguments */
-static inline PyObject *
-_PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs)
-{
- PyThreadState *tstate = PyThreadState_Get();
- return _PyObject_FastCallTstate(tstate, func, args, nargs);
-}
-
-static inline PyObject *
-PyObject_CallOneArg(PyObject *func, PyObject *arg)
-{
- PyObject *_args[2];
- PyObject **args;
- PyThreadState *tstate;
- size_t nargsf;
+// Same as PyObject_Vectorcall(), except without keyword arguments
+PyAPI_FUNC(PyObject *) _PyObject_FastCall(
+ PyObject *func,
+ PyObject *const *args,
+ Py_ssize_t nargs);
- assert(arg != NULL);
- args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET
- args[0] = arg;
- tstate = PyThreadState_Get();
- nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
- return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
-}
+PyAPI_FUNC(PyObject *) PyObject_CallOneArg(PyObject *func, PyObject *arg);
PyAPI_FUNC(PyObject *) PyObject_VectorcallMethod(
PyObject *name, PyObject *const *args,
diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h
index 933d714f13..f2cfd2fd53 100644
--- a/Include/internal/pycore_call.h
+++ b/Include/internal/pycore_call.h
@@ -30,11 +30,73 @@ PyAPI_FUNC(PyObject *) _PyObject_Call(
PyObject *args,
PyObject *kwargs);
+
+// Static inline variant of public PyVectorcall_Function().
+static inline vectorcallfunc
+_PyVectorcall_FunctionInline(PyObject *callable)
+{
+ assert(callable != NULL);
+
+ PyTypeObject *tp = Py_TYPE(callable);
+ if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) {
+ return NULL;
+ }
+ assert(PyCallable_Check(callable));
+
+ Py_ssize_t offset = tp->tp_vectorcall_offset;
+ assert(offset > 0);
+
+ vectorcallfunc ptr;
+ memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
+ return ptr;
+}
+
+
+/* Call the callable object 'callable' with the "vectorcall" calling
+ convention.
+
+ args is a C array for positional arguments.
+
+ nargsf is the number of positional arguments plus optionally the flag
+ PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to
+ modify args[-1].
+
+ kwnames is a tuple of keyword names. The values of the keyword arguments
+ are stored in "args" after the positional arguments (note that the number
+ of keyword arguments does not change nargsf). kwnames can also be NULL if
+ there are no keyword arguments.
+
+ keywords must only contain strings and all keys must be unique.
+
+ Return the result on success. Raise an exception and return NULL on
+ error. */
+static inline PyObject *
+_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
+ PyObject *const *args, size_t nargsf,
+ PyObject *kwnames)
+{
+ vectorcallfunc func;
+ PyObject *res;
+
+ assert(kwnames == NULL || PyTuple_Check(kwnames));
+ assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
+
+ func = _PyVectorcall_FunctionInline(callable);
+ if (func == NULL) {
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+ return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames);
+ }
+ res = func(callable, args, nargsf, kwnames);
+ return _Py_CheckFunctionResult(tstate, callable, res, NULL);
+}
+
+
static inline PyObject *
_PyObject_CallNoArgsTstate(PyThreadState *tstate, PyObject *func) {
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
}
+
// Private static inline function variant of public PyObject_CallNoArgs()
static inline PyObject *
_PyObject_CallNoArgs(PyObject *func) {
@@ -42,6 +104,14 @@ _PyObject_CallNoArgs(PyObject *func) {
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
}
+
+static inline PyObject *
+_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs)
+{
+ return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
+}
+
+
#ifdef __cplusplus
}
#endif