Skip to main content

Include/internal/pycore_call.h

Source:

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_call.h

pycore_call.h provides low-overhead call helpers for sites inside the CPython interpreter that call Python callables from C. The public API (PyObject_Call, PyObject_CallOneArg) routes through the vectorcall protocol; these internal helpers add further shortcuts for zero- and one-argument calls and for cases where the argument tuple is already built.

Map

LinesSymbolRole
1-40_PyObject_CallNoArgsInline; calls with empty args and NULL kwargs
41-80_PyObject_Call1ArgInline; calls with a single positional argument
81-120_PyObject_FastCallDictCall with C array of args plus optional dict of kwargs

Reading

_PyObject_CallNoArgs

// Include/internal/pycore_call.h:1 _PyObject_CallNoArgs
static inline PyObject *
_PyObject_CallNoArgs(PyObject *func) {
return _PyObject_FastCallDict(func, NULL, 0, NULL);
}

This is a two-level shortcut. Most call sites that pass no arguments previously called PyObject_CallObject(func, NULL), which allocated an empty tuple. _PyObject_CallNoArgs avoids that allocation entirely by routing through the vectorcall fast path.

_PyObject_Call1Arg

// Include/internal/pycore_call.h:41 _PyObject_Call1Arg
static inline PyObject *
_PyObject_Call1Arg(PyObject *func, PyObject *arg) {
return _PyObject_FastCallDict(func, &arg, 1, NULL);
}

Passing &arg as the args array avoids building an argument tuple for the common case of a single argument. This pattern is used throughout typeobject.c for slot calls like tp_hash, tp_repr, and tp_richcompare.

_PyObject_FastCallDict

_PyObject_FastCallDict is the workhorse. It checks whether func supports the vectorcall protocol (PY_VECTORCALL_ARGUMENTS_OFFSET), and if so calls vectorcallfunc directly. Otherwise it falls back to building a tuple and dict and calling tp_call.

// Include/internal/pycore_call.h:81 _PyObject_FastCallDict
PyObject *_PyObject_FastCallDict(
PyObject *callable,
PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs);

gopy notes

Not yet ported. gopy's equivalent call path goes through vm.CallObject in vm/eval_call.go. The no-args and one-arg shortcuts map naturally to separate Go branches that avoid allocating a []py.Object slice for trivial call sites.