bpo-35444: Unify and optimize the helper for getting a builtin object. (GH-11047)

This speeds up pickling of some iterators.

This fixes also error handling in pickling methods when fail to
look up builtin "getattr".
This commit is contained in:
Serhiy Storchaka 2018-12-11 08:28:18 +02:00 committed by GitHub
parent 7cf3d8e251
commit bb86bf4c4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 68 additions and 72 deletions

View file

@ -2358,11 +2358,12 @@ PyDoc_STRVAR(length_hint_doc,
static PyObject *
bytearrayiter_reduce(bytesiterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_seq != NULL) {
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
} else {
return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
}

View file

@ -3089,11 +3089,12 @@ PyDoc_STRVAR(length_hint_doc,
static PyObject *
striter_reduce(striterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_seq != NULL) {
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
} else {
return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
}

View file

@ -78,8 +78,6 @@ method_reduce(PyMethodObject *im, PyObject *Py_UNUSED(ignored))
{
PyObject *self = PyMethod_GET_SELF(im);
PyObject *func = PyMethod_GET_FUNCTION(im);
PyObject *builtins;
PyObject *getattr;
PyObject *funcname;
_Py_IDENTIFIER(getattr);
@ -87,9 +85,8 @@ method_reduce(PyMethodObject *im, PyObject *Py_UNUSED(ignored))
if (funcname == NULL) {
return NULL;
}
builtins = PyEval_GetBuiltins();
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
return Py_BuildValue("O(ON)", getattr, self, funcname);
return Py_BuildValue("N(ON)", _PyEval_GetBuiltinId(&PyId_getattr),
self, funcname);
}
static PyMethodDef method_methods[] = {

View file

@ -452,14 +452,9 @@ descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
static PyObject *
descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
{
PyObject *builtins;
PyObject *getattr;
_Py_IDENTIFIER(getattr);
builtins = PyEval_GetBuiltins();
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
PyDescr_NAME(descr));
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
PyDescr_TYPE(descr), PyDescr_NAME(descr));
}
static PyMethodDef descr_methods[] = {
@ -1087,13 +1082,9 @@ wrapper_repr(wrapperobject *wp)
static PyObject *
wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
{
PyObject *builtins;
PyObject *getattr;
_Py_IDENTIFIER(getattr);
builtins = PyEval_GetBuiltins();
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
wp->self, PyDescr_NAME(wp->descr));
}
static PyMethodDef wrapper_methods[] = {

View file

@ -3810,6 +3810,7 @@ dict___reversed___impl(PyDictObject *self)
static PyObject *
dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
/* copy the iterator state */
dictiterobject tmp = *di;
Py_XINCREF(tmp.di_dict);
@ -3819,7 +3820,7 @@ dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored))
if (list == NULL) {
return NULL;
}
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
}
PyTypeObject PyDictRevIterItem_Type = {

View file

@ -104,11 +104,12 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(
static PyObject *
iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_seq != NULL)
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
else
return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
@ -243,11 +244,12 @@ calliter_iternext(calliterobject *it)
static PyObject *
calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_callable != NULL && it->it_sentinel != NULL)
return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_iter),
it->it_callable, it->it_sentinel);
else
return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
static PyMethodDef calliter_methods[] = {

View file

@ -3356,23 +3356,25 @@ listreviter_setstate(listreviterobject *it, PyObject *state)
static PyObject *
listiter_reduce_general(void *_it, int forward)
{
_Py_IDENTIFIER(iter);
_Py_IDENTIFIER(reversed);
PyObject *list;
/* the objects are not the same, index is of different types! */
if (forward) {
listiterobject *it = (listiterobject *)_it;
if (it->it_seq)
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
} else {
listreviterobject *it = (listreviterobject *)_it;
if (it->it_seq)
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("reversed"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_reversed),
it->it_seq, it->it_index);
}
/* empty iterator, create an empty list */
list = PyList_New(0);
if (list == NULL)
return NULL;
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
}

View file

@ -104,16 +104,13 @@ meth_dealloc(PyCFunctionObject *m)
static PyObject *
meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored))
{
PyObject *builtins;
PyObject *getattr;
_Py_IDENTIFIER(getattr);
if (m->m_self == NULL || PyModule_Check(m->m_self))
return PyUnicode_FromString(m->m_ml->ml_name);
builtins = PyEval_GetBuiltins();
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
return Py_BuildValue("O(Os)", getattr, m->m_self, m->m_ml->ml_name);
return Py_BuildValue("N(Os)", _PyEval_GetBuiltinId(&PyId_getattr),
m->m_self, m->m_ml->ml_name);
}
static PyMethodDef meth_methods[] = {

View file

@ -1080,23 +1080,6 @@ PyObject_SelfIter(PyObject *obj)
return obj;
}
/* Convenience function to get a builtin from its name */
PyObject *
_PyObject_GetBuiltin(const char *name)
{
PyObject *mod_name, *mod, *attr;
mod_name = _PyUnicode_FromId(&PyId_builtins); /* borrowed */
if (mod_name == NULL)
return NULL;
mod = PyImport_Import(mod_name);
if (mod == NULL)
return NULL;
attr = PyObject_GetAttrString(mod, name);
Py_DECREF(mod);
return attr;
}
/* Helper used when the __next__ method is removed from a type:
tp_iternext is never NULL and can be safely called without checking
on every iteration.

View file

@ -1806,6 +1806,7 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
static PyObject *
odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
/* copy the iterator state */
odictiterobject tmp = *di;
Py_XINCREF(tmp.di_odict);
@ -1818,7 +1819,7 @@ odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
if (list == NULL) {
return NULL;
}
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
}
static PyMethodDef odictiter_methods[] = {

View file

@ -742,6 +742,7 @@ PyDoc_STRVAR(length_hint_doc,
static PyObject *
rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
PyObject *start=NULL, *stop=NULL, *step=NULL;
PyObject *range;
@ -760,7 +761,8 @@ rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored))
if (range == NULL)
goto err;
/* return the result */
return Py_BuildValue("N(N)i", _PyObject_GetBuiltin("iter"), range, r->index);
return Py_BuildValue("N(N)i", _PyEval_GetBuiltinId(&PyId_iter),
range, r->index);
err:
Py_XDECREF(start);
Py_XDECREF(stop);
@ -898,6 +900,7 @@ longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
static PyObject *
longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
PyObject *product, *stop=NULL;
PyObject *range;
@ -921,7 +924,8 @@ longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored))
}
/* return the result */
return Py_BuildValue("N(N)O", _PyObject_GetBuiltin("iter"), range, r->index);
return Py_BuildValue("N(N)O", _PyEval_GetBuiltinId(&PyId_iter),
range, r->index);
}
static PyObject *

View file

@ -842,6 +842,7 @@ static PyObject *setiter_iternext(setiterobject *si);
static PyObject *
setiter_reduce(setiterobject *si, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
/* copy the iterator state */
setiterobject tmp = *si;
Py_XINCREF(tmp.si_set);
@ -852,7 +853,7 @@ setiter_reduce(setiterobject *si, PyObject *Py_UNUSED(ignored))
if (list == NULL) {
return NULL;
}
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), list);
}
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");

View file

@ -1024,11 +1024,12 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(
static PyObject *
tupleiter_reduce(tupleiterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_seq)
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
else
return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
static PyObject *

View file

@ -15444,14 +15444,15 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(
static PyObject *
unicodeiter_reduce(unicodeiterobject *it, PyObject *Py_UNUSED(ignored))
{
_Py_IDENTIFIER(iter);
if (it->it_seq != NULL) {
return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
it->it_seq, it->it_index);
} else {
PyObject *u = (PyObject *)_PyUnicode_New(0);
if (u == NULL)
return NULL;
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u);
return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), u);
}
}