Skip to content

Commit 800b8a8

Browse files
committed
bpo-36974: further cleanup and fixes
1 parent 54e4e69 commit 800b8a8

File tree

5 files changed

+130
-154
lines changed

5 files changed

+130
-154
lines changed

Lib/test/test_call.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,8 @@ def __call__(self, *args):
586586
return super().__call__(*args)
587587

588588
calls += [
589+
(dict.update, ({},), {"key":True}, None),
590+
({}.update, ({},), {"key":True}, None),
589591
(MethodDescriptorHeap(), (0,), {}, True),
590592
(MethodDescriptorOverridden(), (0,), {}, 'new'),
591593
(MethodDescriptorSuper(), (0,), {}, True),

Objects/call.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
216216
PyObject *result = func(callable, args,
217217
nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames);
218218
_PyStack_UnpackDict_Free(args, nargs, kwnames);
219-
return result;
219+
return _Py_CheckFunctionResult(callable, result, NULL);
220220
}
221221

222222

Objects/descrobject.c

Lines changed: 68 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -231,29 +231,25 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
231231
*
232232
* First, common helpers
233233
*/
234-
static inline const char *
234+
static const char *
235235
get_name(PyObject *func) {
236+
assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
236237
return ((PyMethodDescrObject *)func)->d_method->ml_name;
237238
}
238239

239240
typedef void (*funcptr)(void);
240241

241-
static inline funcptr
242-
get_meth(PyObject *func) {
243-
PyMethodDef *method = ((PyMethodDescrObject *)func)->d_method;
244-
return (funcptr)method->ml_meth;
245-
}
246-
247242
static inline int
248-
vectorcall_check(PyObject *func, size_t nargs, PyObject *const *args) {
243+
method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
244+
{
249245
assert(!PyErr_Occurred());
250246
assert(PyObject_TypeCheck(func, &PyMethodDescr_Type));
251247
if (nargs < 1) {
252248
PyErr_Format(PyExc_TypeError,
253249
"descriptor '%.200s' of '%.100s' "
254250
"object needs an argument",
255251
get_name(func), PyDescr_TYPE(func)->tp_name);
256-
return 0;
252+
return -1;
257253
}
258254
PyObject *self = args[0];
259255
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
@@ -264,66 +260,55 @@ vectorcall_check(PyObject *func, size_t nargs, PyObject *const *args) {
264260
"doesn't apply to a '%.100s' object",
265261
get_name(func), PyDescr_TYPE(func)->tp_name,
266262
Py_TYPE(self)->tp_name);
267-
return 0;
263+
return -1;
268264
}
269-
return 1;
270-
}
271-
272-
static inline int
273-
check_no_kwargs(PyObject *func, PyObject *kwnames) {
274-
if (kwnames && PyTuple_GET_SIZE(kwnames) > 0) {
265+
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
275266
PyErr_Format(PyExc_TypeError,
276267
"%.200s() takes no keyword arguments", get_name(func));
277-
return 0;
268+
return -1;
278269
}
279-
return 1;
270+
return 0;
280271
}
281272

282-
static inline int
283-
vectorcall_begin() {
273+
static inline funcptr
274+
method_enter_call(PyObject *func)
275+
{
284276
if (Py_EnterRecursiveCall(" while calling a Python object")) {
285-
return 0;
277+
return NULL;
286278
}
287-
return 1;
288-
}
289-
290-
static inline PyObject *
291-
vectorcall_end(PyObject *func, PyObject *result) {
292-
Py_LeaveRecursiveCall();
293-
return _Py_CheckFunctionResult(func, result, NULL);
279+
return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
294280
}
295281

296282
/* Now the actual vectorcall functions */
297283
static PyObject *
298-
_PyMethodDescr_Vectorcall_VARARGS(
284+
method_vectorcall_VARARGS(
299285
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
300286
{
301287
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
302-
if (!vectorcall_check(func, nargs, args)) {
303-
return NULL;
304-
}
305-
if (!check_no_kwargs(func, kwnames)) {
288+
if (method_check_args(func, args, nargs, kwnames)) {
306289
return NULL;
307290
}
308291
PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
309292
if (argstuple == NULL) {
310293
return NULL;
311294
}
312-
if (!vectorcall_begin()) {
295+
PyCFunction meth = (PyCFunction)method_enter_call(func);
296+
if (meth == NULL) {
297+
Py_DECREF(argstuple);
313298
return NULL;
314299
}
315-
PyCFunction meth = (PyCFunction)get_meth(func);
316300
PyObject *result = meth(args[0], argstuple);
317301
Py_DECREF(argstuple);
318-
return vectorcall_end(func, result);
302+
Py_LeaveRecursiveCall();
303+
return result;
319304
}
320305

321306
static PyObject *
322-
_PyMethodDescr_Vectorcall_VARARGS_KEYWORDS(
307+
method_vectorcall_VARARGS_KEYWORDS(
323308
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
324309
{
325310
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
326-
if (!vectorcall_check(func, nargs, args)) {
311+
if (method_check_args(func, args, nargs, NULL)) {
327312
return NULL;
328313
}
329314
PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
@@ -332,93 +317,90 @@ _PyMethodDescr_Vectorcall_VARARGS_KEYWORDS(
332317
}
333318
PyObject *result = NULL;
334319
/* Create a temporary dict for keyword arguments */
335-
PyObject *kwdict;
336-
if (kwnames == NULL || PyTuple_GET_SIZE(kwnames) == 0) {
337-
kwdict = NULL;
338-
}
339-
else {
340-
kwdict = _PyStack_AsDict(args+1 + nargs, kwnames);
320+
PyObject *kwdict = NULL;
321+
if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
322+
kwdict = _PyStack_AsDict(args + nargs, kwnames);
341323
if (kwdict == NULL) {
342-
Py_DECREF(argstuple);
343-
return NULL;
324+
goto exit;
344325
}
345326
}
346-
if (!vectorcall_begin()) {
347-
return NULL;
327+
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
328+
method_enter_call(func);
329+
if (meth == NULL) {
330+
goto exit;
348331
}
349-
PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)get_meth(func);
350332
result = meth(args[0], argstuple, kwdict);
333+
Py_LeaveRecursiveCall();
334+
exit:
351335
Py_DECREF(argstuple);
352336
Py_XDECREF(kwdict);
353-
return vectorcall_end(func, result);
337+
return result;
354338
}
355339

356340
static PyObject *
357-
_PyMethodDescr_Vectorcall_FASTCALL(
341+
method_vectorcall_FASTCALL(
358342
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
359343
{
360344
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
361-
if (!vectorcall_check(func, nargs, args)) {
345+
if (method_check_args(func, args, nargs, kwnames)) {
362346
return NULL;
363347
}
364-
if (!check_no_kwargs(func, kwnames)) {
348+
_PyCFunctionFast meth = (_PyCFunctionFast)
349+
method_enter_call(func);
350+
if (meth == NULL) {
365351
return NULL;
366352
}
367-
if (!vectorcall_begin()) {
368-
return NULL;
369-
}
370-
_PyCFunctionFast meth = (_PyCFunctionFast)get_meth(func);
371353
PyObject *result = meth(args[0], args+1, nargs-1);
372-
return vectorcall_end(func, result);
354+
Py_LeaveRecursiveCall();
355+
return result;
373356
}
374357

375358
static PyObject *
376-
_PyMethodDescr_Vectorcall_FASTCALL_KEYWORDS(
359+
method_vectorcall_FASTCALL_KEYWORDS(
377360
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
378361
{
379362
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
380-
if (!vectorcall_check(func, nargs, args)) {
363+
if (method_check_args(func, args, nargs, NULL)) {
364+
return NULL;
365+
}
366+
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
367+
method_enter_call(func);
368+
if (meth == NULL) {
381369
return NULL;
382370
}
383-
vectorcall_begin();
384-
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)get_meth(func);
385371
PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
386-
return vectorcall_end(func, result);
372+
Py_LeaveRecursiveCall();
373+
return result;
387374
}
388375

389376
static PyObject *
390-
_PyMethodDescr_Vectorcall_NOARGS(
377+
method_vectorcall_NOARGS(
391378
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
392379
{
393380
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
394-
if (!vectorcall_check(func, nargs, args)) {
395-
return NULL;
396-
}
397-
if (!check_no_kwargs(func, kwnames)) {
381+
if (method_check_args(func, args, nargs, kwnames)) {
398382
return NULL;
399383
}
400384
if (nargs != 1) {
401385
PyErr_Format(PyExc_TypeError,
402386
"%.200s() takes no arguments (%zd given)", get_name(func), nargs-1);
403387
return NULL;
404388
}
405-
if (!vectorcall_begin()) {
389+
PyCFunction meth = (PyCFunction)method_enter_call(func);
390+
if (meth == NULL) {
406391
return NULL;
407392
}
408-
PyCFunction meth = (PyCFunction)get_meth(func);
409393
PyObject *result = meth(args[0], NULL);
410-
return vectorcall_end(func, result);
394+
Py_LeaveRecursiveCall();
395+
return result;
411396
}
412397

413398
static PyObject *
414-
_PyMethodDescr_Vectorcall_O(
399+
method_vectorcall_O(
415400
PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
416401
{
417402
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
418-
if (!vectorcall_check(func, nargs, args)) {
419-
return NULL;
420-
}
421-
if (!check_no_kwargs(func, kwnames)) {
403+
if (method_check_args(func, args, nargs, kwnames)) {
422404
return NULL;
423405
}
424406
if (nargs != 2) {
@@ -427,12 +409,13 @@ _PyMethodDescr_Vectorcall_O(
427409
get_name(func), nargs-1);
428410
return NULL;
429411
}
430-
if (!vectorcall_begin()) {
412+
PyCFunction meth = (PyCFunction)method_enter_call(func);
413+
if (meth == NULL) {
431414
return NULL;
432415
}
433-
PyCFunction meth = (PyCFunction)get_meth(func);
434416
PyObject *result = meth(args[0], args[1]);
435-
return vectorcall_end(func, result);
417+
Py_LeaveRecursiveCall();
418+
return result;
436419
}
437420

438421

@@ -879,22 +862,22 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
879862
switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS))
880863
{
881864
case METH_VARARGS:
882-
vectorcall = _PyMethodDescr_Vectorcall_VARARGS;
865+
vectorcall = method_vectorcall_VARARGS;
883866
break;
884867
case METH_VARARGS | METH_KEYWORDS:
885-
vectorcall = _PyMethodDescr_Vectorcall_VARARGS_KEYWORDS;
868+
vectorcall = method_vectorcall_VARARGS_KEYWORDS;
886869
break;
887870
case METH_FASTCALL:
888-
vectorcall = _PyMethodDescr_Vectorcall_FASTCALL;
871+
vectorcall = method_vectorcall_FASTCALL;
889872
break;
890873
case METH_FASTCALL | METH_KEYWORDS:
891-
vectorcall = _PyMethodDescr_Vectorcall_FASTCALL_KEYWORDS;
874+
vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
892875
break;
893876
case METH_NOARGS:
894-
vectorcall = _PyMethodDescr_Vectorcall_NOARGS;
877+
vectorcall = method_vectorcall_NOARGS;
895878
break;
896879
case METH_O:
897-
vectorcall = _PyMethodDescr_Vectorcall_O;
880+
vectorcall = method_vectorcall_O;
898881
break;
899882
default:
900883
PyErr_SetString(PyExc_SystemError, "bad call flags");

0 commit comments

Comments
 (0)