mirror of
https://github.com/python/cpython.git
synced 2025-10-12 18:02:39 +00:00
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().
This commit is contained in:
parent
f7507dd3e8
commit
3f1057a4b6
4 changed files with 55 additions and 40 deletions
|
@ -309,6 +309,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
Py_ssize_t nargs,
|
Py_ssize_t nargs,
|
||||||
Py_ssize_t nkwargs);
|
Py_ssize_t nkwargs);
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(PyObject *func,
|
||||||
|
PyObject *obj, PyObject *args,
|
||||||
|
PyObject *kwargs);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func,
|
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func,
|
||||||
PyObject *result,
|
PyObject *result,
|
||||||
const char *where);
|
const char *where);
|
||||||
|
|
|
@ -2388,6 +2388,45 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Positional arguments are obj followed args. */
|
||||||
|
PyObject *
|
||||||
|
_PyObject_Call_Prepend(PyObject *func,
|
||||||
|
PyObject *obj, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *small_stack[8];
|
||||||
|
PyObject **stack;
|
||||||
|
Py_ssize_t argcount;
|
||||||
|
PyObject *result;
|
||||||
|
|
||||||
|
assert(PyTuple_Check(args));
|
||||||
|
|
||||||
|
argcount = PyTuple_GET_SIZE(args);
|
||||||
|
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
|
||||||
|
stack = small_stack;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *));
|
||||||
|
if (stack == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use borrowed references */
|
||||||
|
stack[0] = obj;
|
||||||
|
Py_MEMCPY(&stack[1],
|
||||||
|
&PyTuple_GET_ITEM(args, 0),
|
||||||
|
argcount * sizeof(PyObject *));
|
||||||
|
|
||||||
|
result = _PyObject_FastCallDict(func,
|
||||||
|
stack, argcount + 1,
|
||||||
|
kwargs);
|
||||||
|
if (stack != small_stack) {
|
||||||
|
PyMem_Free(stack);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
call_function_tail(PyObject *callable, PyObject *args)
|
call_function_tail(PyObject *callable, PyObject *args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -302,34 +302,19 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
method_call(PyObject *func, PyObject *arg, PyObject *kw)
|
method_call(PyObject *method, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *self = PyMethod_GET_SELF(func);
|
PyObject *self, *func;
|
||||||
PyObject *result;
|
|
||||||
|
|
||||||
func = PyMethod_GET_FUNCTION(func);
|
self = PyMethod_GET_SELF(method);
|
||||||
if (self == NULL) {
|
if (self == NULL) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Py_ssize_t argcount = PyTuple_Size(arg);
|
func = PyMethod_GET_FUNCTION(method);
|
||||||
PyObject *newarg = PyTuple_New(argcount + 1);
|
|
||||||
int i;
|
return _PyObject_Call_Prepend(func, self, args, kwargs);
|
||||||
if (newarg == NULL)
|
|
||||||
return NULL;
|
|
||||||
Py_INCREF(self);
|
|
||||||
PyTuple_SET_ITEM(newarg, 0, self);
|
|
||||||
for (i = 0; i < argcount; i++) {
|
|
||||||
PyObject *v = PyTuple_GET_ITEM(arg, i);
|
|
||||||
Py_XINCREF(v);
|
|
||||||
PyTuple_SET_ITEM(newarg, i+1, v);
|
|
||||||
}
|
|
||||||
arg = newarg;
|
|
||||||
}
|
|
||||||
result = PyObject_Call((PyObject *)func, arg, kw);
|
|
||||||
Py_DECREF(arg);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
|
@ -6356,29 +6356,16 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyObject *func;
|
PyObject *func, *result;
|
||||||
PyObject *newargs, *x;
|
|
||||||
Py_ssize_t i, n;
|
|
||||||
|
|
||||||
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
|
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
|
||||||
if (func == NULL)
|
if (func == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
assert(PyTuple_Check(args));
|
|
||||||
n = PyTuple_GET_SIZE(args);
|
|
||||||
newargs = PyTuple_New(n+1);
|
|
||||||
if (newargs == NULL)
|
|
||||||
return NULL;
|
|
||||||
Py_INCREF(type);
|
|
||||||
PyTuple_SET_ITEM(newargs, 0, (PyObject *)type);
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
x = PyTuple_GET_ITEM(args, i);
|
|
||||||
Py_INCREF(x);
|
|
||||||
PyTuple_SET_ITEM(newargs, i+1, x);
|
|
||||||
}
|
}
|
||||||
x = PyObject_Call(func, newargs, kwds);
|
|
||||||
Py_DECREF(newargs);
|
result = _PyObject_Call_Prepend(func, (PyObject *)type, args, kwds);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
return x;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue