@@ -229,145 +229,210 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
229
229
230
230
/* Vectorcall functions for each of the PyMethodDescr calling conventions.
231
231
*
232
- * First two macros to define common boilerplate
232
+ * First, common helpers
233
233
*/
234
- #define PyMethodDescr_VECTORCALL_BEGIN (ALLOW_KWARGS ) \
235
- assert(!PyErr_Occurred()); \
236
- assert(PyObject_TypeCheck(func, &PyMethodDescr_Type)); \
237
- PyMethodDescrObject *f = (PyMethodDescrObject *)func; \
238
- Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); \
239
- PyMethodDef *method = f->d_method; \
240
- const char *name = method->ml_name; \
241
- void(*meth)(void) = (void(*)(void))method->ml_meth; \
242
- PyObject *result = NULL; \
243
- \
244
- /* self is the first positional argument */ \
245
- if (nargs < 1 ) { \
246
- PyErr_Format (PyExc_TypeError , \
247
- "descriptor '%.200s' of '%.100s' " \
248
- "object needs an argument" , \
249
- name , PyDescr_TYPE (func )-> tp_name ); \
250
- return NULL ; \
251
- } \
252
- PyObject * self = args [0 ]; \
253
- args ++ ; \
254
- nargs -- ; \
255
- if (!_PyObject_RealIsSubclass ((PyObject * )Py_TYPE (self ), \
256
- (PyObject * )PyDescr_TYPE (func ))) \
257
- { \
258
- PyErr_Format (PyExc_TypeError , \
259
- "descriptor '%.200s' for '%.100s' objects " \
260
- "doesn't apply to a '%.100s' object" , \
261
- name , PyDescr_TYPE (func )-> tp_name , \
262
- Py_TYPE (self )-> tp_name ); \
263
- return NULL ; \
264
- } \
265
- \
266
- if (!ALLOW_KWARGS && kwnames && PyTuple_GET_SIZE (kwnames ) > 0 ) { \
267
- PyErr_Format (PyExc_TypeError , \
268
- "%.200s() takes no keyword arguments" , name ); \
269
- return NULL ; \
270
- } \
271
- if (Py_EnterRecursiveCall (" while calling a Python object" )) { \
272
- return NULL ; \
273
- }
274
-
275
- #define PyMethodDescr_VECTORCALL_END \
276
- Py_LeaveRecursiveCall(); \
234
+ static inline const char *
235
+ get_name (PyObject * func ) {
236
+ return ((PyMethodDescrObject * )func )-> d_method -> ml_name ;
237
+ }
238
+
239
+ typedef void (* funcptr )(void );
240
+
241
+ static inline funcptr
242
+ get_meth (PyObject * func ) {
243
+ PyMethodDef * method = ((PyMethodDescrObject * )func )-> d_method ;
244
+ return (funcptr )method -> ml_meth ;
245
+ }
246
+
247
+ static inline int
248
+ vectorcall_check (PyObject * func , size_t nargs , PyObject * const * args ) {
249
+ assert (!PyErr_Occurred ());
250
+ assert (PyObject_TypeCheck (func , & PyMethodDescr_Type ));
251
+ if (nargs < 1 ) {
252
+ PyErr_Format (PyExc_TypeError ,
253
+ "descriptor '%.200s' of '%.100s' "
254
+ "object needs an argument" ,
255
+ get_name (func ), PyDescr_TYPE (func )-> tp_name );
256
+ return 0 ;
257
+ }
258
+ PyObject * self = args [0 ];
259
+ if (!_PyObject_RealIsSubclass ((PyObject * )Py_TYPE (self ),
260
+ (PyObject * )PyDescr_TYPE (func )))
261
+ {
262
+ PyErr_Format (PyExc_TypeError ,
263
+ "descriptor '%.200s' for '%.100s' objects "
264
+ "doesn't apply to a '%.100s' object" ,
265
+ get_name (func ), PyDescr_TYPE (func )-> tp_name ,
266
+ Py_TYPE (self )-> tp_name );
267
+ return 0 ;
268
+ }
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 ) {
275
+ PyErr_Format (PyExc_TypeError ,
276
+ "%.200s() takes no keyword arguments" , get_name (func ));
277
+ return 0 ;
278
+ }
279
+ return 1 ;
280
+ }
281
+
282
+ static inline int
283
+ vectorcall_begin () {
284
+ if (Py_EnterRecursiveCall (" while calling a Python object" )) {
285
+ return 0 ;
286
+ }
287
+ return 1 ;
288
+ }
289
+
290
+ static inline PyObject *
291
+ vectorcall_end (PyObject * func , PyObject * result ) {
292
+ Py_LeaveRecursiveCall ();
277
293
return _Py_CheckFunctionResult (func , result , NULL );
294
+ }
278
295
279
296
/* Now the actual vectorcall functions */
280
297
static PyObject *
281
298
_PyMethodDescr_Vectorcall_VARARGS (
282
299
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
283
300
{
284
- PyMethodDescr_VECTORCALL_BEGIN (0 )
285
- /* Create a temporary tuple for positional arguments */
286
- PyObject * argstuple = _PyTuple_FromArray (args , nargs );
301
+ 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 )) {
306
+ return NULL ;
307
+ }
308
+ PyObject * argstuple = _PyTuple_FromArray (args + 1 , nargs - 1 );
287
309
if (argstuple == NULL ) {
288
- goto exit ;
310
+ return NULL ;
311
+ }
312
+ if (!vectorcall_begin ()) {
313
+ return NULL ;
289
314
}
290
- result = ((PyCFunction )meth )(self , argstuple );
315
+ PyCFunction meth = (PyCFunction )get_meth (func );
316
+ PyObject * result = meth (args [0 ], argstuple );
291
317
Py_DECREF (argstuple );
292
- exit :
293
- PyMethodDescr_VECTORCALL_END
318
+ return vectorcall_end (func , result );
294
319
}
295
320
296
321
static PyObject *
297
322
_PyMethodDescr_Vectorcall_VARARGS_KEYWORDS (
298
323
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
299
324
{
300
- PyMethodDescr_VECTORCALL_BEGIN (1 )
301
- /* Create a temporary tuple for positional arguments */
302
- PyObject * argstuple = _PyTuple_FromArray (args , nargs );
325
+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
326
+ if (!vectorcall_check (func , nargs , args )) {
327
+ return NULL ;
328
+ }
329
+ PyObject * argstuple = _PyTuple_FromArray (args + 1 , nargs - 1 );
303
330
if (argstuple == NULL ) {
304
- goto exit ;
331
+ return NULL ;
305
332
}
333
+ PyObject * result = NULL ;
306
334
/* Create a temporary dict for keyword arguments */
307
335
PyObject * kwdict ;
308
336
if (kwnames == NULL || PyTuple_GET_SIZE (kwnames ) == 0 ) {
309
337
kwdict = NULL ;
310
338
}
311
339
else {
312
- kwdict = _PyStack_AsDict (args + nargs , kwnames );
340
+ kwdict = _PyStack_AsDict (args + 1 + nargs , kwnames );
313
341
if (kwdict == NULL ) {
314
342
Py_DECREF (argstuple );
315
- goto exit ;
343
+ return NULL ;
316
344
}
317
345
}
318
- result = ((PyCFunctionWithKeywords )meth )(self , argstuple , kwdict );
346
+ if (!vectorcall_begin ()) {
347
+ return NULL ;
348
+ }
349
+ PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords )get_meth (func );
350
+ result = meth (args [0 ], argstuple , kwdict );
319
351
Py_DECREF (argstuple );
320
352
Py_XDECREF (kwdict );
321
- exit :
322
- PyMethodDescr_VECTORCALL_END
353
+ return vectorcall_end (func , result );
323
354
}
324
355
325
356
static PyObject *
326
357
_PyMethodDescr_Vectorcall_FASTCALL (
327
358
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
328
359
{
329
- PyMethodDescr_VECTORCALL_BEGIN (0 )
330
- result = ((_PyCFunctionFast )meth )(self , args , nargs );
331
- PyMethodDescr_VECTORCALL_END
360
+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
361
+ if (!vectorcall_check (func , nargs , args )) {
362
+ return NULL ;
363
+ }
364
+ if (!check_no_kwargs (func , kwnames )) {
365
+ return NULL ;
366
+ }
367
+ if (!vectorcall_begin ()) {
368
+ return NULL ;
369
+ }
370
+ _PyCFunctionFast meth = (_PyCFunctionFast )get_meth (func );
371
+ PyObject * result = meth (args [0 ], args + 1 , nargs - 1 );
372
+ return vectorcall_end (func , result );
332
373
}
333
374
334
375
static PyObject *
335
376
_PyMethodDescr_Vectorcall_FASTCALL_KEYWORDS (
336
377
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
337
378
{
338
- PyMethodDescr_VECTORCALL_BEGIN (1 )
339
- result = ((_PyCFunctionFastWithKeywords )meth )(self , args , nargs , kwnames );
340
- PyMethodDescr_VECTORCALL_END
379
+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
380
+ if (!vectorcall_check (func , nargs , args )) {
381
+ return NULL ;
382
+ }
383
+ vectorcall_begin ();
384
+ _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords )get_meth (func );
385
+ PyObject * result = meth (args [0 ], args + 1 , nargs - 1 , kwnames );
386
+ return vectorcall_end (func , result );
341
387
}
342
388
343
389
static PyObject *
344
390
_PyMethodDescr_Vectorcall_NOARGS (
345
391
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
346
392
{
347
- PyMethodDescr_VECTORCALL_BEGIN (0 )
348
- if (nargs != 0 ) {
393
+ 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 )) {
398
+ return NULL ;
399
+ }
400
+ if (nargs != 1 ) {
349
401
PyErr_Format (PyExc_TypeError ,
350
- "%.200s() takes no arguments (%zd given)" , name , nargs );
402
+ "%.200s() takes no arguments (%zd given)" , get_name (func ), nargs - 1 );
403
+ return NULL ;
351
404
}
352
- else {
353
- result = (( PyCFunction ) meth )( self , NULL ) ;
405
+ if (! vectorcall_begin ()) {
406
+ return NULL ;
354
407
}
355
- PyMethodDescr_VECTORCALL_END
408
+ PyCFunction meth = (PyCFunction )get_meth (func );
409
+ PyObject * result = meth (args [0 ], NULL );
410
+ return vectorcall_end (func , result );
356
411
}
357
412
358
413
static PyObject *
359
414
_PyMethodDescr_Vectorcall_O (
360
415
PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
361
416
{
362
- PyMethodDescr_VECTORCALL_BEGIN (0 )
363
- if (nargs != 1 ) {
417
+ 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 )) {
422
+ return NULL ;
423
+ }
424
+ if (nargs != 2 ) {
364
425
PyErr_Format (PyExc_TypeError ,
365
- "%.200s() takes exactly one argument (%zd given)" , name , nargs );
426
+ "%.200s() takes exactly one argument (%zd given)" ,
427
+ get_name (func ), nargs - 1 );
428
+ return NULL ;
366
429
}
367
- else {
368
- result = (( PyCFunction ) meth )( self , args [ 0 ]) ;
430
+ if (! vectorcall_begin ()) {
431
+ return NULL ;
369
432
}
370
- PyMethodDescr_VECTORCALL_END
433
+ PyCFunction meth = (PyCFunction )get_meth (func );
434
+ PyObject * result = meth (args [0 ], args [1 ]);
435
+ return vectorcall_end (func , result );
371
436
}
372
437
373
438
0 commit comments