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

Skip to content

Commit 3f1057a

Browse files
committed
method_call() and slot_tp_new() now uses fast call
Issue #27841: Add _PyObject_Call_Prepend() helper function to prepend an argument to existing arguments to call a function. This helper uses fast calls. Modify method_call() and slot_tp_new() to use _PyObject_Call_Prepend().
1 parent f7507dd commit 3f1057a

4 files changed

Lines changed: 55 additions & 40 deletions

File tree

Include/abstract.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
309309
Py_ssize_t nargs,
310310
Py_ssize_t nkwargs);
311311

312+
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(PyObject *func,
313+
PyObject *obj, PyObject *args,
314+
PyObject *kwargs);
315+
312316
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func,
313317
PyObject *result,
314318
const char *where);

Objects/abstract.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,45 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
23882388
return result;
23892389
}
23902390

2391+
/* Positional arguments are obj followed args. */
2392+
PyObject *
2393+
_PyObject_Call_Prepend(PyObject *func,
2394+
PyObject *obj, PyObject *args, PyObject *kwargs)
2395+
{
2396+
PyObject *small_stack[8];
2397+
PyObject **stack;
2398+
Py_ssize_t argcount;
2399+
PyObject *result;
2400+
2401+
assert(PyTuple_Check(args));
2402+
2403+
argcount = PyTuple_GET_SIZE(args);
2404+
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
2405+
stack = small_stack;
2406+
}
2407+
else {
2408+
stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *));
2409+
if (stack == NULL) {
2410+
PyErr_NoMemory();
2411+
return NULL;
2412+
}
2413+
}
2414+
2415+
/* use borrowed references */
2416+
stack[0] = obj;
2417+
Py_MEMCPY(&stack[1],
2418+
&PyTuple_GET_ITEM(args, 0),
2419+
argcount * sizeof(PyObject *));
2420+
2421+
result = _PyObject_FastCallDict(func,
2422+
stack, argcount + 1,
2423+
kwargs);
2424+
if (stack != small_stack) {
2425+
PyMem_Free(stack);
2426+
}
2427+
return result;
2428+
}
2429+
23912430
static PyObject*
23922431
call_function_tail(PyObject *callable, PyObject *args)
23932432
{

Objects/classobject.c

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -302,34 +302,19 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg)
302302
}
303303

304304
static PyObject *
305-
method_call(PyObject *func, PyObject *arg, PyObject *kw)
305+
method_call(PyObject *method, PyObject *args, PyObject *kwargs)
306306
{
307-
PyObject *self = PyMethod_GET_SELF(func);
308-
PyObject *result;
307+
PyObject *self, *func;
309308

310-
func = PyMethod_GET_FUNCTION(func);
309+
self = PyMethod_GET_SELF(method);
311310
if (self == NULL) {
312311
PyErr_BadInternalCall();
313312
return NULL;
314313
}
315-
else {
316-
Py_ssize_t argcount = PyTuple_Size(arg);
317-
PyObject *newarg = PyTuple_New(argcount + 1);
318-
int i;
319-
if (newarg == NULL)
320-
return NULL;
321-
Py_INCREF(self);
322-
PyTuple_SET_ITEM(newarg, 0, self);
323-
for (i = 0; i < argcount; i++) {
324-
PyObject *v = PyTuple_GET_ITEM(arg, i);
325-
Py_XINCREF(v);
326-
PyTuple_SET_ITEM(newarg, i+1, v);
327-
}
328-
arg = newarg;
329-
}
330-
result = PyObject_Call((PyObject *)func, arg, kw);
331-
Py_DECREF(arg);
332-
return result;
314+
315+
func = PyMethod_GET_FUNCTION(method);
316+
317+
return _PyObject_Call_Prepend(func, self, args, kwargs);
333318
}
334319

335320
static PyObject *

Objects/typeobject.c

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6356,29 +6356,16 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
63566356
static PyObject *
63576357
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
63586358
{
6359-
PyObject *func;
6360-
PyObject *newargs, *x;
6361-
Py_ssize_t i, n;
6359+
PyObject *func, *result;
63626360

63636361
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
6364-
if (func == NULL)
6365-
return NULL;
6366-
assert(PyTuple_Check(args));
6367-
n = PyTuple_GET_SIZE(args);
6368-
newargs = PyTuple_New(n+1);
6369-
if (newargs == NULL)
6362+
if (func == NULL) {
63706363
return NULL;
6371-
Py_INCREF(type);
6372-
PyTuple_SET_ITEM(newargs, 0, (PyObject *)type);
6373-
for (i = 0; i < n; i++) {
6374-
x = PyTuple_GET_ITEM(args, i);
6375-
Py_INCREF(x);
6376-
PyTuple_SET_ITEM(newargs, i+1, x);
63776364
}
6378-
x = PyObject_Call(func, newargs, kwds);
6379-
Py_DECREF(newargs);
6365+
6366+
result = _PyObject_Call_Prepend(func, (PyObject *)type, args, kwds);
63806367
Py_DECREF(func);
6381-
return x;
6368+
return result;
63826369
}
63836370

63846371
static void

0 commit comments

Comments
 (0)