Skip to content

Commit 84caa33

Browse files
authored
gh-106084: Remove _PyObject_CallMethod() function (#106159)
Remove the following private functions from the public C API: * _Py_CheckFunctionResult() * _PyObject_CallMethod() * _PyObject_CallMethodId() * _PyObject_CallMethodIdNoArgs() * _PyObject_CallMethodIdObjArgs() * _PyObject_CallMethodIdOneArg() * _PyObject_MakeTpCall() * _PyObject_VectorcallMethodId() * _PyStack_AsDict() Move these functions to the internal C API (pycore_call.h). No longer export the following functions: * _PyObject_Call() * _PyObject_CallMethod() * _PyObject_CallMethodId() * _PyObject_CallMethodIdObjArgs() * _PyObject_Call_Prepend() * _PyObject_FastCallDictTstate() * _PyStack_AsDict() The following functions are still exported for stdlib shared extensions: * _Py_CheckFunctionResult() * _PyObject_MakeTpCall() Mark the following internal functions as extern: * _PyStack_UnpackDict() * _PyStack_UnpackDict_Free() * _PyStack_UnpackDict_FreeNoDecRef()
1 parent 6b5166f commit 84caa33

File tree

9 files changed

+111
-85
lines changed

9 files changed

+111
-85
lines changed

Include/cpython/abstract.h

+1-73
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,6 @@
44

55
/* === Object Protocol ================================================== */
66

7-
/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple)
8-
format to a Python dictionary ("kwargs" dict).
9-
10-
The type of kwnames keys is not checked. The final function getting
11-
arguments is responsible to check if all keys are strings, for example using
12-
PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments().
13-
14-
Duplicate keys are merged using the last value. If duplicate keys must raise
15-
an exception, the caller is responsible to implement an explicit keys on
16-
kwnames. */
17-
PyAPI_FUNC(PyObject *) _PyStack_AsDict(
18-
PyObject *const *values,
19-
PyObject *kwnames);
20-
217
/* Suggested size (number of positional arguments) for arrays of PyObject*
228
allocated on a C stack to avoid allocating memory on the heap memory. Such
239
array is used to pass positional arguments to call functions of the
@@ -29,32 +15,17 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
2915
40 bytes on the stack. */
3016
#define _PY_FASTCALL_SMALL_STACK 5
3117

32-
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(
33-
PyThreadState *tstate,
34-
PyObject *callable,
35-
PyObject *result,
36-
const char *where);
37-
3818
/* === Vectorcall protocol (PEP 590) ============================= */
3919

40-
/* Call callable using tp_call. Arguments are like PyObject_Vectorcall()
41-
or PyObject_FastCallDict() (both forms are supported),
42-
except that nargs is plainly the number of arguments without flags. */
43-
PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall(
44-
PyThreadState *tstate,
45-
PyObject *callable,
46-
PyObject *const *args, Py_ssize_t nargs,
47-
PyObject *keywords);
48-
4920
// PyVectorcall_NARGS() is exported as a function for the stable ABI.
5021
// Here (when we are not using the stable ABI), the name is overridden to
5122
// call a static inline function for best performance.
52-
#define PyVectorcall_NARGS(n) _PyVectorcall_NARGS(n)
5323
static inline Py_ssize_t
5424
_PyVectorcall_NARGS(size_t n)
5525
{
5626
return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
5727
}
28+
#define PyVectorcall_NARGS(n) _PyVectorcall_NARGS(n)
5829

5930
PyAPI_FUNC(vectorcallfunc) PyVectorcall_Function(PyObject *callable);
6031

@@ -90,49 +61,6 @@ PyObject_CallMethodOneArg(PyObject *self, PyObject *name, PyObject *arg)
9061
return PyObject_VectorcallMethod(name, args, nargsf, _Py_NULL);
9162
}
9263

93-
PyAPI_FUNC(PyObject *) _PyObject_CallMethod(PyObject *obj,
94-
PyObject *name,
95-
const char *format, ...);
96-
97-
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
98-
as the method name. */
99-
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
100-
_Py_Identifier *name,
101-
const char *format, ...);
102-
103-
PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs(
104-
PyObject *obj,
105-
_Py_Identifier *name,
106-
...);
107-
108-
static inline PyObject *
109-
_PyObject_VectorcallMethodId(
110-
_Py_Identifier *name, PyObject *const *args,
111-
size_t nargsf, PyObject *kwnames)
112-
{
113-
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
114-
if (!oname) {
115-
return _Py_NULL;
116-
}
117-
return PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
118-
}
119-
120-
static inline PyObject *
121-
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
122-
{
123-
size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
124-
return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL);
125-
}
126-
127-
static inline PyObject *
128-
_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
129-
{
130-
PyObject *args[2] = {self, arg};
131-
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
132-
assert(arg != NULL);
133-
return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL);
134-
}
135-
13664
/* Guess the size of object 'o' using len(o) or o.__length_hint__().
13765
If neither of those return a non-negative value, then return the default
13866
value. If one of the calls fails, this function returns -1. */

Include/internal/pycore_call.h

+96-9
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,112 @@ extern "C" {
1010

1111
#include "pycore_pystate.h" // _PyThreadState_GET()
1212

13-
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
13+
// Export for shared stdlib extensions like the math extension,
14+
// function used via inlined _PyObject_VectorcallTstate() function.
15+
PyAPI_FUNC(PyObject*) _Py_CheckFunctionResult(
16+
PyThreadState *tstate,
17+
PyObject *callable,
18+
PyObject *result,
19+
const char *where);
20+
21+
/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple)
22+
format to a Python dictionary ("kwargs" dict).
23+
24+
The type of kwnames keys is not checked. The final function getting
25+
arguments is responsible to check if all keys are strings, for example using
26+
PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments().
27+
28+
Duplicate keys are merged using the last value. If duplicate keys must raise
29+
an exception, the caller is responsible to implement an explicit keys on
30+
kwnames. */
31+
extern PyObject* _PyStack_AsDict(PyObject *const *values, PyObject *kwnames);
32+
33+
extern PyObject* _PyObject_Call_Prepend(
1434
PyThreadState *tstate,
1535
PyObject *callable,
1636
PyObject *obj,
1737
PyObject *args,
1838
PyObject *kwargs);
1939

20-
PyAPI_FUNC(PyObject *) _PyObject_FastCallDictTstate(
40+
extern PyObject* _PyObject_FastCallDictTstate(
2141
PyThreadState *tstate,
2242
PyObject *callable,
2343
PyObject *const *args,
2444
size_t nargsf,
2545
PyObject *kwargs);
2646

27-
PyAPI_FUNC(PyObject *) _PyObject_Call(
47+
extern PyObject* _PyObject_Call(
2848
PyThreadState *tstate,
2949
PyObject *callable,
3050
PyObject *args,
3151
PyObject *kwargs);
3252

3353
extern PyObject * _PyObject_CallMethodFormat(
34-
PyThreadState *tstate, PyObject *callable, const char *format, ...);
54+
PyThreadState *tstate,
55+
PyObject *callable,
56+
const char *format,
57+
...);
3558

59+
// Export for shared stdlib extensions like the array extension
60+
PyAPI_FUNC(PyObject*) _PyObject_CallMethod(
61+
PyObject *obj,
62+
PyObject *name,
63+
const char *format, ...);
64+
65+
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
66+
as the method name. */
67+
extern PyObject* _PyObject_CallMethodId(
68+
PyObject *obj,
69+
_Py_Identifier *name,
70+
const char *format, ...);
71+
72+
extern PyObject* _PyObject_CallMethodIdObjArgs(
73+
PyObject *obj,
74+
_Py_Identifier *name,
75+
...);
76+
77+
static inline PyObject *
78+
_PyObject_VectorcallMethodId(
79+
_Py_Identifier *name, PyObject *const *args,
80+
size_t nargsf, PyObject *kwnames)
81+
{
82+
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
83+
if (!oname) {
84+
return _Py_NULL;
85+
}
86+
return PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
87+
}
88+
89+
static inline PyObject *
90+
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
91+
{
92+
size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
93+
return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL);
94+
}
95+
96+
static inline PyObject *
97+
_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
98+
{
99+
PyObject *args[2] = {self, arg};
100+
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
101+
assert(arg != NULL);
102+
return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL);
103+
}
104+
105+
106+
/* === Vectorcall protocol (PEP 590) ============================= */
107+
108+
// Call callable using tp_call. Arguments are like PyObject_Vectorcall()
109+
// or PyObject_FastCallDict() (both forms are supported),
110+
// except that nargs is plainly the number of arguments without flags.
111+
//
112+
// Export for shared stdlib extensions like the math extension,
113+
// function used via inlined _PyObject_VectorcallTstate() function.
114+
PyAPI_FUNC(PyObject*) _PyObject_MakeTpCall(
115+
PyThreadState *tstate,
116+
PyObject *callable,
117+
PyObject *const *args, Py_ssize_t nargs,
118+
PyObject *keywords);
36119

37120
// Static inline variant of public PyVectorcall_Function().
38121
static inline vectorcallfunc
@@ -110,22 +193,26 @@ _PyObject_CallNoArgs(PyObject *func) {
110193

111194

112195
static inline PyObject *
113-
_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs)
196+
_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func,
197+
PyObject *const *args, Py_ssize_t nargs)
114198
{
115199
EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func);
116200
return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
117201
}
118202

119-
PyObject *const *
203+
extern PyObject *const *
120204
_PyStack_UnpackDict(PyThreadState *tstate,
121205
PyObject *const *args, Py_ssize_t nargs,
122206
PyObject *kwargs, PyObject **p_kwnames);
123207

124-
void
125-
_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
208+
extern void _PyStack_UnpackDict_Free(
209+
PyObject *const *stack,
210+
Py_ssize_t nargs,
126211
PyObject *kwnames);
127212

128-
void _PyStack_UnpackDict_FreeNoDecRef(PyObject *const *stack, PyObject *kwnames);
213+
extern void _PyStack_UnpackDict_FreeNoDecRef(
214+
PyObject *const *stack,
215+
PyObject *kwnames);
129216

130217
#ifdef __cplusplus
131218
}

Modules/_bisectmodule.c

+5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
44
*/
55

6+
#ifndef Py_BUILD_CORE_BUILTIN
7+
# define Py_BUILD_CORE_MODULE 1
8+
#endif
9+
610
#define PY_SSIZE_T_CLEAN
711
#include "Python.h"
12+
#include "pycore_call.h" // _PyObject_CallMethod()
813

914
/*[clinic input]
1015
module _bisect

Modules/_io/iobase.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
#define PY_SSIZE_T_CLEAN
1212
#include "Python.h"
13+
#include "pycore_call.h" // _PyObject_CallMethod()
1314
#include "pycore_long.h" // _PyLong_GetOne()
14-
#include "pycore_object.h"
15+
#include "pycore_object.h" // _PyType_HasFeature()
1516
#include <stddef.h> // offsetof()
1617
#include "_iomodule.h"
1718

Modules/_io/textio.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
#define PY_SSIZE_T_CLEAN
1010
#include "Python.h"
11+
#include "pycore_call.h" // _PyObject_CallMethod()
1112
#include "pycore_interp.h" // PyInterpreterState.fs_codec
1213
#include "pycore_long.h" // _PyLong_GetZero()
1314
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
14-
#include "pycore_object.h"
15+
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
1516
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1617
#include "structmember.h" // PyMemberDef
1718
#include "_iomodule.h"

Modules/arraymodule.c

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#define PY_SSIZE_T_CLEAN
1111
#include "Python.h"
12+
#include "pycore_call.h" // _PyObject_CallMethod()
1213
#include "pycore_moduleobject.h" // _PyModule_GetState()
1314
#include "pycore_bytesobject.h" // _PyBytes_Repeat
1415
#include "structmember.h" // PyMemberDef

Objects/descrobject.c

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Python.h"
44
#include "pycore_abstract.h" // _PyObject_RealIsSubclass()
5+
#include "pycore_call.h" // _PyStack_AsDict()
56
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
67
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
78
#include "pycore_pystate.h" // _PyThreadState_GET()

Objects/methodobject.c

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Method object implementation */
33

44
#include "Python.h"
5+
#include "pycore_call.h" // _Py_CheckFunctionResult()
56
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
67
#include "pycore_object.h"
78
#include "pycore_pyerrors.h"

Python/pylifecycle.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
#include "Python.h"
44

5+
#include "pycore_call.h" // _PyObject_CallMethod()
56
#include "pycore_ceval.h" // _PyEval_FiniGIL()
67
#include "pycore_context.h" // _PyContext_Init()
7-
#include "pycore_exceptions.h" // _PyExc_InitTypes()
88
#include "pycore_dict.h" // _PyDict_Fini()
9+
#include "pycore_exceptions.h" // _PyExc_InitTypes()
910
#include "pycore_fileutils.h" // _Py_ResetForceASCII()
1011
#include "pycore_floatobject.h" // _PyFloat_InitTypes()
1112
#include "pycore_genobject.h" // _PyAsyncGen_Fini()

0 commit comments

Comments
 (0)