Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5e02c78

Browse files
bpo-31410: Optimized calling wrapper and classmethod descriptors. (#3481)
1 parent b3a7796 commit 5e02c78

2 files changed

Lines changed: 34 additions & 29 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optimized calling wrapper and classmethod descriptors.

Objects/descrobject.c

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
296296
PyObject *kwds)
297297
{
298298
Py_ssize_t argc;
299-
PyObject *self, *func, *result, **stack;
299+
PyObject *self, *result;
300300

301301
/* Make sure that the first argument is acceptable as 'self' */
302302
assert(PyTuple_Check(args));
@@ -330,20 +330,38 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
330330
return NULL;
331331
}
332332

333-
func = PyCFunction_NewEx(descr->d_method, self, NULL);
334-
if (func == NULL)
335-
return NULL;
336-
stack = &PyTuple_GET_ITEM(args, 1);
337-
result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
338-
Py_DECREF(func);
333+
result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
334+
&PyTuple_GET_ITEM(args, 1), argc - 1,
335+
kwds);
336+
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
339337
return result;
340338
}
341339

340+
Py_LOCAL_INLINE(PyObject *)
341+
wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
342+
PyObject *args, PyObject *kwds)
343+
{
344+
wrapperfunc wrapper = descr->d_base->wrapper;
345+
346+
if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
347+
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
348+
return (*wk)(self, args, descr->d_wrapped, kwds);
349+
}
350+
351+
if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
352+
PyErr_Format(PyExc_TypeError,
353+
"wrapper %s() takes no keyword arguments",
354+
descr->d_base->name);
355+
return NULL;
356+
}
357+
return (*wrapper)(self, args, descr->d_wrapped);
358+
}
359+
342360
static PyObject *
343361
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
344362
{
345363
Py_ssize_t argc;
346-
PyObject *self, *func, *result, **stack;
364+
PyObject *self, *result;
347365

348366
/* Make sure that the first argument is acceptable as 'self' */
349367
assert(PyTuple_Check(args));
@@ -369,16 +387,16 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
369387
return NULL;
370388
}
371389

372-
func = PyWrapper_New((PyObject *)descr, self);
373-
if (func == NULL)
390+
args = PyTuple_GetSlice(args, 1, argc);
391+
if (args == NULL) {
374392
return NULL;
375-
376-
stack = &PyTuple_GET_ITEM(args, 1);
377-
result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
378-
Py_DECREF(func);
393+
}
394+
result = wrapperdescr_raw_call(descr, self, args, kwds);
395+
Py_DECREF(args);
379396
return result;
380397
}
381398

399+
382400
static PyObject *
383401
method_get_doc(PyMethodDescrObject *descr, void *closure)
384402
{
@@ -1167,21 +1185,7 @@ static PyGetSetDef wrapper_getsets[] = {
11671185
static PyObject *
11681186
wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
11691187
{
1170-
wrapperfunc wrapper = wp->descr->d_base->wrapper;
1171-
PyObject *self = wp->self;
1172-
1173-
if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
1174-
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
1175-
return (*wk)(self, args, wp->descr->d_wrapped, kwds);
1176-
}
1177-
1178-
if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
1179-
PyErr_Format(PyExc_TypeError,
1180-
"wrapper %s() takes no keyword arguments",
1181-
wp->descr->d_base->name);
1182-
return NULL;
1183-
}
1184-
return (*wrapper)(self, args, wp->descr->d_wrapped);
1188+
return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
11851189
}
11861190

11871191
static int

0 commit comments

Comments
 (0)