summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-10-14 19:53:04 (GMT)
committerGitHub <noreply@github.com>2021-10-14 19:53:04 (GMT)
commit3cc56c828d2d8f8659ea49447234bf0d2b87cd64 (patch)
tree7f204eb39062037d3575d407fda18825e314dd7e
parent39aa98346d5dd8ac591a7cafb467af21c53f1e5d (diff)
downloadcpython-3cc56c828d2d8f8659ea49447234bf0d2b87cd64.zip
cpython-3cc56c828d2d8f8659ea49447234bf0d2b87cd64.tar.gz
cpython-3cc56c828d2d8f8659ea49447234bf0d2b87cd64.tar.bz2
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().
-rw-r--r--Include/cpython/abstract.h105
-rw-r--r--Include/internal/pycore_call.h70
-rw-r--r--Modules/_functoolsmodule.c2
-rw-r--r--Objects/call.c47
-rw-r--r--Objects/classobject.c1
-rw-r--r--Python/context.c2
6 files changed, 127 insertions, 100 deletions
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
index 0814bfa..55a742c 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 933d714..f2cfd2f 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
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 4c77ee7..1f6b852 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -269,7 +269,7 @@ partial_vectorcall(partialobject *pto, PyObject *const *args,
static void
partial_setvectorcall(partialobject *pto)
{
- if (PyVectorcall_Function(pto->fn) == NULL) {
+ if (_PyVectorcall_Function(pto->fn) == NULL) {
/* Don't use vectorcall if the underlying function doesn't support it */
pto->vectorcall = NULL;
}
diff --git a/Objects/call.c b/Objects/call.c
index cfcd422..5e55518 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -109,8 +109,7 @@ _Py_CheckSlotResult(PyObject *obj, const char *slot_name, int success)
PyObject *
PyObject_CallNoArgs(PyObject *func)
{
- PyThreadState *tstate = _PyThreadState_GET();
- return _PyObject_CallNoArgsTstate(tstate, func);
+ return _PyObject_CallNoArgs(func);
}
@@ -131,7 +130,7 @@ _PyObject_FastCallDictTstate(PyThreadState *tstate, PyObject *callable,
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
- vectorcallfunc func = PyVectorcall_Function(callable);
+ vectorcallfunc func = _PyVectorcall_Function(callable);
if (func == NULL) {
/* Use tp_call instead */
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwargs);
@@ -225,6 +224,13 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
}
+vectorcallfunc
+PyVectorcall_Function(PyObject *callable)
+{
+ return _PyVectorcall_FunctionInline(callable);
+}
+
+
static PyObject *
_PyVectorcall_Call(PyThreadState *tstate, vectorcallfunc func,
PyObject *callable, PyObject *tuple, PyObject *kwargs)
@@ -260,7 +266,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
{
PyThreadState *tstate = _PyThreadState_GET();
- /* get vectorcallfunc as in PyVectorcall_Function, but without
+ /* 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) {
@@ -285,6 +291,24 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
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);
+}
+
+
+PyObject *
+_PyObject_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ return _PyObject_FastCallTstate(tstate, func, args, nargs);
+}
+
+
+PyObject *
_PyObject_Call(PyThreadState *tstate, PyObject *callable,
PyObject *args, PyObject *kwargs)
{
@@ -298,7 +322,7 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable,
assert(PyTuple_Check(args));
assert(kwargs == NULL || PyDict_Check(kwargs));
- vectorcallfunc vector_func = PyVectorcall_Function(callable);
+ vectorcallfunc vector_func = _PyVectorcall_Function(callable);
if (vector_func != NULL) {
return _PyVectorcall_Call(tstate, vector_func, callable, args, kwargs);
}
@@ -339,6 +363,19 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
}
+PyObject *
+PyObject_CallOneArg(PyObject *func, PyObject *arg)
+{
+ assert(arg != NULL);
+ PyObject *_args[2];
+ PyObject **args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET
+ args[0] = arg;
+ PyThreadState *tstate = _PyThreadState_GET();
+ size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
+ return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL);
+}
+
+
/* --- PyFunction call functions ---------------------------------- */
PyObject *
diff --git a/Objects/classobject.c b/Objects/classobject.c
index af73be3..9d4fc99 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -1,6 +1,7 @@
/* Class object implementation (dead now except for methods) */
#include "Python.h"
+#include "pycore_call.h" // _PyObject_VectorcallTstate()
#include "pycore_object.h"
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" // _PyThreadState_GET()
diff --git a/Python/context.c b/Python/context.c
index ad47992..d78f7f9 100644
--- a/Python/context.c
+++ b/Python/context.c
@@ -1,5 +1,5 @@
#include "Python.h"
-
+#include "pycore_call.h" // _PyObject_VectorcallTstate()
#include "pycore_context.h"
#include "pycore_gc.h" // _PyObject_GC_MAY_BE_TRACKED()
#include "pycore_hamt.h"