Skip to content

Commit

Permalink
bpo-37547: add _PyObject_CallMethodOneArg (pythonGH-14685)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdemeyer authored and methane committed Jul 11, 2019
1 parent 2a3d4d9 commit 59ad110
Show file tree
Hide file tree
Showing 23 changed files with 104 additions and 93 deletions.
12 changes: 12 additions & 0 deletions Doc/c-api/object.rst
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
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
@@ -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
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
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
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
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
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
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
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
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
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
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

0 comments on commit 59ad110

Please sign in to comment.