Skip to content

Commit

Permalink
bpo-37337: Add _PyObject_CallMethodNoArgs() (pythonGH-14267)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdemeyer authored and methane committed Jul 8, 2019
1 parent 38f44b4 commit 762f93f
Show file tree
Hide file tree
Showing 37 changed files with 154 additions and 132 deletions.
11 changes: 11 additions & 0 deletions Doc/c-api/object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,17 @@ Object Protocol
*NULL* on failure.
.. c:function:: PyObject* _PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)
Call a method of the Python object *obj* without arguments,
where the name of the method is given as a Python string object in *name*.
Return the result of the call on success, or raise an exception and return
*NULL* on failure.
.. versionadded:: 3.9
.. c:function:: PyObject* _PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Call a callable Python object *callable*, using
Expand Down
14 changes: 14 additions & 0 deletions Include/cpython/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ PyAPI_FUNC(PyObject *) _PyObject_VectorcallMethod(
PyObject *name, PyObject *const *args,
size_t nargsf, PyObject *kwnames);

static inline PyObject *
_PyObject_CallMethodNoArgs(PyObject *self, PyObject *name)
{
return _PyObject_VectorcallMethod(name, &self,
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
as the method name. */
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
Expand Down Expand Up @@ -184,6 +191,13 @@ _PyObject_VectorcallMethodId(
return _PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
}

static inline PyObject *
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
{
return _PyObject_VectorcallMethodId(name, &self,
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o);

/* Guess the size of object 'o' using len(o) or o.__length_hint__().
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Add :c:func:`_PyObject_VectorcallMethod` for fast calling of methods.
Add fast functions for calling methods: :c:func:`_PyObject_VectorcallMethod`
and :c:func:`_PyObject_CallMethodNoArgs`
16 changes: 7 additions & 9 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ get_event_loop(void)
return NULL;
}

loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Py_DECREF(policy);
return loop;
}
Expand Down Expand Up @@ -493,7 +493,7 @@ future_init(FutureObj *fut, PyObject *loop)
}
fut->fut_loop = loop;

res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
if (res == NULL) {
return -1;
}
Expand Down Expand Up @@ -1295,9 +1295,8 @@ FutureObj_repr(FutureObj *fut)

ENSURE_FUTURE_ALIVE(fut)

PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
&PyId__repr_info,
NULL);
PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
&PyId__repr_info);
if (rinfo == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2197,8 +2196,7 @@ _asyncio_Task_cancel_impl(TaskObj *self)
PyObject *res;
int is_true;

res = _PyObject_CallMethodId(
self->task_fut_waiter, &PyId_cancel, NULL);
res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
if (res == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2735,7 +2733,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (task->task_must_cancel) {
PyObject *r;
int is_true;
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
if (r == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2826,7 +2824,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (task->task_must_cancel) {
PyObject *r;
int is_true;
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
if (r == NULL) {
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,7 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
args = PyTuple_Pack(1, dd->default_factory);
if (args == NULL)
return NULL;
items = _PyObject_CallMethodId((PyObject *)dd, &PyId_items, NULL);
items = _PyObject_CallMethodIdNoArgs((PyObject *)dd, &PyId_items);
if (items == NULL) {
Py_DECREF(args);
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3974,7 +3974,7 @@ _build_result(PyObject *result, PyObject *callargs,
_Py_IDENTIFIER(__ctypes_from_outparam__);

v = PyTuple_GET_ITEM(callargs, i);
v = _PyObject_CallMethodId(v, &PyId___ctypes_from_outparam__, NULL);
v = _PyObject_CallMethodIdNoArgs(v, &PyId___ctypes_from_outparam__);
if (v == NULL || numretvals == 1) {
Py_DECREF(callargs);
return v;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2906,7 +2906,7 @@ _curses_getwin(PyObject *module, PyObject *file)
if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
goto error;

data = _PyObject_CallMethodId(file, &PyId_read, NULL);
data = _PyObject_CallMethodIdNoArgs(file, &PyId_read);
if (data == NULL)
goto error;
if (!PyBytes_Check(data)) {
Expand Down
10 changes: 5 additions & 5 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ time_time(void)
if (time != NULL) {
_Py_IDENTIFIER(time);

result = _PyObject_CallMethodId(time, &PyId_time, NULL);
result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
Py_DECREF(time);
}
return result;
Expand Down Expand Up @@ -1918,7 +1918,7 @@ get_float_as_integer_ratio(PyObject *floatobj)
PyObject *ratio;

assert(floatobj && PyFloat_Check(floatobj));
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio);
if (ratio == NULL) {
return NULL;
}
Expand Down Expand Up @@ -3162,7 +3162,7 @@ date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
static PyObject *
date_str(PyDateTime_Date *self)
{
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
}


Expand All @@ -3188,7 +3188,7 @@ date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
&format))
return NULL;

tuple = _PyObject_CallMethodId((PyObject *)self, &PyId_timetuple, NULL);
tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple);
if (tuple == NULL)
return NULL;
result = wrap_strftime((PyObject *)self, format, tuple,
Expand Down Expand Up @@ -4175,7 +4175,7 @@ time_repr(PyDateTime_Time *self)
static PyObject *
time_str(PyDateTime_Time *self)
{
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
}

static PyObject *
Expand Down
2 changes: 1 addition & 1 deletion Modules/_dbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static PyObject *
dbm__exit__(PyObject *self, PyObject *args)
{
_Py_IDENTIFIER(close);
return _PyObject_CallMethodId(self, &PyId_close, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
}


Expand Down
2 changes: 1 addition & 1 deletion Modules/_gdbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ static PyObject *
dbm__exit__(PyObject *self, PyObject *args)
{
_Py_IDENTIFIER(close);
return _PyObject_CallMethodId(self, &PyId_close, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
}

static PyMethodDef dbm_methods[] = {
Expand Down
4 changes: 2 additions & 2 deletions Modules/_io/_iomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,

/* buffering */
if (buffering < 0) {
PyObject *res = _PyObject_CallMethodId(raw, &PyId_isatty, NULL);
PyObject *res = _PyObject_CallMethodIdNoArgs(raw, &PyId_isatty);
if (res == NULL)
goto error;
isatty = PyLong_AsLong(res);
Expand Down Expand Up @@ -494,7 +494,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
if (result != NULL) {
PyObject *exc, *val, *tb, *close_result;
PyErr_Fetch(&exc, &val, &tb);
close_result = _PyObject_CallMethodId(result, &PyId_close, NULL);
close_result = _PyObject_CallMethodIdNoArgs(result, &PyId_close);
_PyErr_ChainExceptions(exc, val, tb);
Py_XDECREF(close_result);
Py_DECREF(result);
Expand Down
26 changes: 13 additions & 13 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ static PyObject *
buffered_simple_flush(buffered *self, PyObject *args)
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_flush);
}

static int
Expand Down Expand Up @@ -513,15 +513,15 @@ buffered_close(buffered *self, PyObject *args)
}
/* flush() will most probably re-take the lock, so drop it first */
LEAVE_BUFFERED(self)
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
if (!ENTER_BUFFERED(self))
return NULL;
if (res == NULL)
PyErr_Fetch(&exc, &val, &tb);
else
Py_DECREF(res);

res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
res = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_close);

if (self->buffer) {
PyMem_Free(self->buffer);
Expand All @@ -545,7 +545,7 @@ buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
{
PyObject *raw, *res;
CHECK_INITIALIZED(self)
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
if (res == NULL)
return NULL;
Py_DECREF(res);
Expand All @@ -562,21 +562,21 @@ static PyObject *
buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_seekable);
}

static PyObject *
buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_readable);
}

static PyObject *
buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_writable);
}

static PyObject *
Expand All @@ -599,14 +599,14 @@ static PyObject *
buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_fileno);
}

static PyObject *
buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_isatty);
}

/* Forward decls */
Expand Down Expand Up @@ -670,7 +670,7 @@ _buffered_raw_tell(buffered *self)
{
Py_off_t n;
PyObject *res;
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
res = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_tell);
if (res == NULL)
return -1;
n = PyNumber_AsOff_t(res, PyExc_ValueError);
Expand Down Expand Up @@ -1350,8 +1350,8 @@ buffered_iternext(buffered *self)
line = _buffered_readline(self, -1);
}
else {
line = PyObject_CallMethodObjArgs((PyObject *)self,
_PyIO_str_readline, NULL);
line = _PyObject_CallMethodNoArgs((PyObject *)self,
_PyIO_str_readline);
if (line && !PyBytes_Check(line)) {
PyErr_Format(PyExc_OSError,
"readline() should have returned a bytes object, "
Expand Down Expand Up @@ -1566,7 +1566,7 @@ _bufferedreader_read_all(buffered *self)
}

/* Read until EOF or until read() would block. */
data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
data = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_read);
if (data == NULL)
goto cleanup;
if (data != Py_None && !PyBytes_Check(data)) {
Expand Down
17 changes: 8 additions & 9 deletions Modules/_io/iobase.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ _io__IOBase_close_impl(PyObject *self)
Py_RETURN_NONE;
}

res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs(self, _PyIO_str_flush);

PyErr_Fetch(&exc, &val, &tb);
rc = _PyObject_SetAttrId(self, &PyId___IOBase_closed, Py_True);
Expand Down Expand Up @@ -281,8 +281,7 @@ iobase_finalize(PyObject *self)
finalization process. */
if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True))
PyErr_Clear();
res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_close);
/* Silencing I/O errors is bad, but printing spurious tracebacks is
equally as bad, and potentially more frequent (because of
shutdown issues). */
Expand Down Expand Up @@ -383,7 +382,7 @@ _io__IOBase_seekable_impl(PyObject *self)
PyObject *
_PyIOBase_check_seekable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_seekable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -416,7 +415,7 @@ _io__IOBase_readable_impl(PyObject *self)
PyObject *
_PyIOBase_check_readable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_readable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -449,7 +448,7 @@ _io__IOBase_writable_impl(PyObject *self)
PyObject *
_PyIOBase_check_writable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_writable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -478,7 +477,7 @@ iobase_enter(PyObject *self, PyObject *args)
static PyObject *
iobase_exit(PyObject *self, PyObject *args)
{
return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
return _PyObject_CallMethodNoArgs(self, _PyIO_str_close);
}

/* Lower-level APIs */
Expand Down Expand Up @@ -656,7 +655,7 @@ iobase_iter(PyObject *self)
static PyObject *
iobase_iternext(PyObject *self)
{
PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL);
PyObject *line = _PyObject_CallMethodNoArgs(self, _PyIO_str_readline);

if (line == NULL)
return NULL;
Expand Down Expand Up @@ -921,7 +920,7 @@ _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
if (n < 0) {
_Py_IDENTIFIER(readall);

return _PyObject_CallMethodId(self, &PyId_readall, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_readall);
}

/* TODO: allocate a bytes object directly instead and manually construct
Expand Down
Loading

0 comments on commit 762f93f

Please sign in to comment.