Skip to content

bpo-37547: add _PyObject_CallMethodOneArg #14685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Doc/c-api/object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,18 @@ Object Protocol
.. versionadded:: 3.9


.. c:function:: PyObject* _PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)

Call a method of the Python object *obj* with a single positional argument
*arg*, 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
18 changes: 18 additions & 0 deletions Include/cpython/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ _PyObject_CallMethodNoArgs(PyObject *self, PyObject *name)
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

static inline PyObject *
_PyObject_CallMethodOneArg(PyObject *self, PyObject *name, PyObject *arg)
{
assert(arg != NULL);
PyObject *args[2] = {self, arg};
return _PyObject_VectorcallMethod(name, args,
2 | 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 @@ -198,6 +207,15 @@ _PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

static inline PyObject *
_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
{
assert(arg != NULL);
PyObject *args[2] = {self, arg};
return _PyObject_VectorcallMethodId(name, args,
2 | 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,2 +1,2 @@
Add fast functions for calling methods: :c:func:`_PyObject_VectorcallMethod`
and :c:func:`_PyObject_CallMethodNoArgs`
Add fast functions for calling methods: :c:func:`_PyObject_VectorcallMethod`,
:c:func:`_PyObject_CallMethodNoArgs` and :c:func:`_PyObject_CallMethodOneArg`.
23 changes: 8 additions & 15 deletions Modules/_abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
{
PyObject *subtype, *result = NULL, *subclass = NULL;
PyObject *margs[2];
_abc_data *impl = _get_impl(self);
if (impl == NULL) {
return NULL;
Expand Down Expand Up @@ -515,16 +514,12 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
}
}
/* Fall back to the subclass check. */
margs[0] = self;
margs[1] = subclass;
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
subclass);
goto end;
}
margs[0] = self;
margs[1] = subclass;
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
subclass);
if (result == NULL) {
goto end;
}
Expand All @@ -536,10 +531,8 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
break;
case 0:
Py_DECREF(result);
margs[0] = self;
margs[1] = subtype;
result = _PyObject_VectorcallMethodId(&PyId___subclasscheck__, margs,
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
subtype);
break;
case 1: // Nothing to do.
break;
Expand Down Expand Up @@ -620,8 +613,8 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
}

/* 3. Check the subclass hook. */
ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__,
subclass, NULL);
ok = _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId___subclasshook__,
subclass);
if (ok == NULL) {
goto end;
}
Expand Down
14 changes: 6 additions & 8 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1842,8 +1842,8 @@ register_task(PyObject *task)
{
_Py_IDENTIFIER(add);

PyObject *res = _PyObject_CallMethodIdObjArgs(
all_tasks, &PyId_add, task, NULL);
PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
&PyId_add, task);
if (res == NULL) {
return -1;
}
Expand All @@ -1857,8 +1857,8 @@ unregister_task(PyObject *task)
{
_Py_IDENTIFIER(discard);

PyObject *res = _PyObject_CallMethodIdObjArgs(
all_tasks, &PyId_discard, task, NULL);
PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
&PyId_discard, task);
if (res == NULL) {
return -1;
}
Expand Down Expand Up @@ -2611,13 +2611,11 @@ task_step_impl(TaskObj *task, PyObject *exc)
result = _PyGen_Send((PyGenObject*)coro, Py_None);
}
else {
result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
Py_None, NULL);
result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
}
}
else {
result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
exc, NULL);
result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
if (clear_exc) {
/* We created 'exc' during this call */
Py_DECREF(exc);
Expand Down
2 changes: 1 addition & 1 deletion Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1699,7 +1699,7 @@ unpickle(PyObject *self, PyObject *args)

if (!PyArg_ParseTuple(args, "OO!", &typ, &PyTuple_Type, &state))
return NULL;
obj = _PyObject_CallMethodIdObjArgs(typ, &PyId___new__, typ, NULL);
obj = _PyObject_CallMethodIdOneArg(typ, &PyId___new__, typ);
if (obj == NULL)
return NULL;

Expand Down
15 changes: 6 additions & 9 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1237,8 +1237,7 @@ call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
if (tzinfo == Py_None)
Py_RETURN_NONE;

result = _PyObject_CallMethodIdObjArgs(tzinfo, &PyId_tzname,
tzinfoarg, NULL);
result = _PyObject_CallMethodIdOneArg(tzinfo, &PyId_tzname, tzinfoarg);

if (result == NULL || result == Py_None)
return result;
Expand Down Expand Up @@ -1693,8 +1692,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
return NULL;
}

result = _PyObject_CallMethodIdObjArgs(time, &PyId_struct_time,
args, NULL);
result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
Py_DECREF(time);
Py_DECREF(args);
return result;
Expand Down Expand Up @@ -2894,8 +2892,7 @@ date_today(PyObject *cls, PyObject *dummy)
* time.time() delivers; if someone were gonzo about optimization,
* date.today() could get away with plain C time().
*/
result = _PyObject_CallMethodIdObjArgs(cls, &PyId_fromtimestamp,
time, NULL);
result = _PyObject_CallMethodIdOneArg(cls, &PyId_fromtimestamp, time);
Py_DECREF(time);
return result;
}
Expand Down Expand Up @@ -3209,8 +3206,8 @@ date_format(PyDateTime_Date *self, PyObject *args)
if (PyUnicode_GetLength(format) == 0)
return PyObject_Str((PyObject *)self);

return _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId_strftime,
format, NULL);
return _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId_strftime,
format);
}

/* ISO methods. */
Expand Down Expand Up @@ -5960,7 +5957,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)

temp = (PyObject *)result;
result = (PyDateTime_DateTime *)
_PyObject_CallMethodIdObjArgs(tzinfo, &PyId_fromutc, temp, NULL);
_PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp);
Py_DECREF(temp);

return result;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2679,7 +2679,7 @@ treebuilder_add_subelement(PyObject *element, PyObject *child)
}
else {
PyObject *res;
res = _PyObject_CallMethodIdObjArgs(element, &PyId_append, child, NULL);
res = _PyObject_CallMethodIdOneArg(element, &PyId_append, child);
if (res == NULL)
return -1;
Py_DECREF(res);
Expand Down
10 changes: 5 additions & 5 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,8 @@ buffered_dealloc_warn(buffered *self, PyObject *source)
{
if (self->ok && self->raw) {
PyObject *r;
r = _PyObject_CallMethodIdObjArgs(self->raw, &PyId__dealloc_warn,
source, NULL);
r = _PyObject_CallMethodIdOneArg(self->raw, &PyId__dealloc_warn,
source);
if (r)
Py_DECREF(r);
else
Expand Down Expand Up @@ -1323,7 +1323,7 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
goto end;
Py_CLEAR(res);
}
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
if (res == NULL)
goto end;
/* Reset cached position */
Expand Down Expand Up @@ -1467,7 +1467,7 @@ _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
raised (see issue #10956).
*/
do {
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_readinto, memobj);
} while (res == NULL && _PyIO_trap_eintr());
Py_DECREF(memobj);
if (res == NULL)
Expand Down Expand Up @@ -1815,7 +1815,7 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
*/
do {
errno = 0;
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
res = _PyObject_CallMethodOneArg(self->raw, _PyIO_str_write, memobj);
errnum = errno;
} while (res == NULL && _PyIO_trap_eintr());
Py_DECREF(memobj);
Expand Down
4 changes: 2 additions & 2 deletions Modules/_io/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ _io_FileIO_close_impl(fileio *self)
PyObject *exc, *val, *tb;
int rc;
_Py_IDENTIFIER(close);
res = _PyObject_CallMethodIdObjArgs((PyObject*)&PyRawIOBase_Type,
&PyId_close, self, NULL);
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
&PyId_close, (PyObject *)self);
if (!self->closefd) {
self->fd = -1;
return res;
Expand Down
37 changes: 17 additions & 20 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,8 @@ _textiowrapper_fix_encoder_state(textio *self)

if (cmp == 0) {
self->encoding_start_of_stream = 0;
PyObject *res = PyObject_CallMethodObjArgs(
self->encoder, _PyIO_str_setstate, _PyLong_Zero, NULL);
PyObject *res = _PyObject_CallMethodOneArg(
self->encoder, _PyIO_str_setstate, _PyLong_Zero);
if (res == NULL) {
return -1;
}
Expand Down Expand Up @@ -1155,8 +1155,8 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
PyObject *locale_module = _PyIO_get_locale_module(state);
if (locale_module == NULL)
goto catch_ImportError;
self->encoding = _PyObject_CallMethodIdObjArgs(
locale_module, &PyId_getpreferredencoding, Py_False, NULL);
self->encoding = _PyObject_CallMethodIdOneArg(
locale_module, &PyId_getpreferredencoding, Py_False);
Py_DECREF(locale_module);
if (self->encoding == NULL) {
catch_ImportError:
Expand Down Expand Up @@ -1597,8 +1597,7 @@ _textiowrapper_writeflush(textio *self)

PyObject *ret;
do {
ret = PyObject_CallMethodObjArgs(self->buffer,
_PyIO_str_write, b, NULL);
ret = _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_write, b);
} while (ret == NULL && _PyIO_trap_eintr());
Py_DECREF(b);
if (ret == NULL)
Expand Down Expand Up @@ -1668,8 +1667,7 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
self->encoding_start_of_stream = 0;
}
else
b = PyObject_CallMethodObjArgs(self->encoder,
_PyIO_str_encode, text, NULL);
b = _PyObject_CallMethodOneArg(self->encoder, _PyIO_str_encode, text);

Py_DECREF(text);
if (b == NULL)
Expand Down Expand Up @@ -1851,9 +1849,9 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint)
if (chunk_size == NULL)
goto fail;

input_chunk = PyObject_CallMethodObjArgs(self->buffer,
input_chunk = _PyObject_CallMethodOneArg(self->buffer,
(self->has_read1 ? _PyIO_str_read1: _PyIO_str_read),
chunk_size, NULL);
chunk_size);
Py_DECREF(chunk_size);
if (input_chunk == NULL)
goto fail;
Expand Down Expand Up @@ -2414,8 +2412,8 @@ _textiowrapper_encoder_reset(textio *self, int start_of_stream)
self->encoding_start_of_stream = 1;
}
else {
res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
_PyLong_Zero, NULL);
res = _PyObject_CallMethodOneArg(self->encoder, _PyIO_str_setstate,
_PyLong_Zero);
self->encoding_start_of_stream = 0;
}
if (res == NULL)
Expand Down Expand Up @@ -2554,8 +2552,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence)
posobj = PyLong_FromOff_t(cookie.start_pos);
if (posobj == NULL)
goto fail;
res = PyObject_CallMethodObjArgs(self->buffer,
_PyIO_str_seek, posobj, NULL);
res = _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_seek, posobj);
Py_DECREF(posobj);
if (res == NULL)
goto fail;
Expand Down Expand Up @@ -2837,7 +2834,7 @@ _io_TextIOWrapper_tell_impl(textio *self)
}

finally:
res = _PyObject_CallMethodIdObjArgs(self->decoder, &PyId_setstate, saved_state, NULL);
res = _PyObject_CallMethodIdOneArg(self->decoder, &PyId_setstate, saved_state);
Py_DECREF(saved_state);
if (res == NULL)
return NULL;
Expand All @@ -2851,7 +2848,7 @@ _io_TextIOWrapper_tell_impl(textio *self)
if (saved_state) {
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
res = _PyObject_CallMethodIdObjArgs(self->decoder, &PyId_setstate, saved_state, NULL);
res = _PyObject_CallMethodIdOneArg(self->decoder, &PyId_setstate, saved_state);
_PyErr_ChainExceptions(type, value, traceback);
Py_DECREF(saved_state);
Py_XDECREF(res);
Expand All @@ -2878,7 +2875,7 @@ _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos)
return NULL;
Py_DECREF(res);

return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);
return _PyObject_CallMethodOneArg(self->buffer, _PyIO_str_truncate, pos);
}

static PyObject *
Expand Down Expand Up @@ -3055,9 +3052,9 @@ _io_TextIOWrapper_close_impl(textio *self)
else {
PyObject *exc = NULL, *val, *tb;
if (self->finalizing) {
res = _PyObject_CallMethodIdObjArgs(self->buffer,
&PyId__dealloc_warn,
self, NULL);
res = _PyObject_CallMethodIdOneArg(self->buffer,
&PyId__dealloc_warn,
(PyObject *)self);
if (res)
Py_DECREF(res);
else
Expand Down
4 changes: 2 additions & 2 deletions Modules/_io/winconsoleio.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ _io__WindowsConsoleIO_close_impl(winconsoleio *self)
PyObject *exc, *val, *tb;
int rc;
_Py_IDENTIFIER(close);
res = _PyObject_CallMethodIdObjArgs((PyObject*)&PyRawIOBase_Type,
&PyId_close, self, NULL);
res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type,
&PyId_close, self);
if (!self->closehandle) {
self->handle = INVALID_HANDLE_VALUE;
return res;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -5773,7 +5773,7 @@ instantiate(PyObject *cls, PyObject *args)
return NULL;
}
if (func == NULL) {
return _PyObject_CallMethodIdObjArgs(cls, &PyId___new__, cls, NULL);
return _PyObject_CallMethodIdOneArg(cls, &PyId___new__, cls);
}
Py_DECREF(func);
}
Expand Down
Loading