This speeds up pickling of some iterators.
This fixes also error handling in pickling methods when fail to
look up builtin "getattr".
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
+#ifndef Py_LIMITED_API
+/* Helper to look up a builtin object */
+PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *);
/* Look at the current frame's (if any) code's co_flags, and turn on
the corresponding compiler flags in cf->cf_flags. Return 1 if any
flag was set, else return 0. */
-#ifndef Py_LIMITED_API
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
#endif
_PyObject_GenericSetAttrWithDict(PyObject *, PyObject *,
PyObject *, PyObject *);
-/* Helper to look up a builtin object */
-PyAPI_FUNC(PyObject *) _PyObject_GetBuiltin(const char *name);
-
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
static inline void _Py_Dealloc_inline(PyObject *op)
--- /dev/null
+Fixed error handling in pickling methods when fail to look up builtin
+"getattr". Sped up pickling iterators.
static int
_Pickle_InitState(PickleState *st)
{
- PyObject *builtins;
PyObject *copyreg = NULL;
PyObject *compat_pickle = NULL;
PyObject *codecs = NULL;
PyObject *functools = NULL;
+ _Py_IDENTIFIER(getattr);
- builtins = PyEval_GetBuiltins();
- if (builtins == NULL)
- goto error;
- st->getattr = PyDict_GetItemString(builtins, "getattr");
+ st->getattr = _PyEval_GetBuiltinId(&PyId_getattr);
if (st->getattr == NULL)
goto error;
- Py_INCREF(st->getattr);
copyreg = PyImport_ImportModule("copyreg");
if (!copyreg)
array_arrayiterator___reduce___impl(arrayiterobject *self)
/*[clinic end generated code: output=7898a52e8e66e016 input=a062ea1e9951417a]*/
{
- PyObject *func = _PyObject_GetBuiltin("iter");
+ _Py_IDENTIFIER(iter);
+ PyObject *func = _PyEval_GetBuiltinId(&PyId_iter);
if (self->ao == NULL) {
return Py_BuildValue("N(())", func);
}
static PyObject *
_grouper_reduce(_grouperobject *lz, PyObject *Py_UNUSED(ignored))
{
+ _Py_IDENTIFIER(iter);
if (((groupbyobject *)lz->parent)->currgrouper != lz) {
- return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
+ return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
}
return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->parent, lz->tgtkey);
}
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));
}
}
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));
}
}
{
PyObject *self = PyMethod_GET_SELF(im);
PyObject *func = PyMethod_GET_FUNCTION(im);
- PyObject *builtins;
- PyObject *getattr;
PyObject *funcname;
_Py_IDENTIFIER(getattr);
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[] = {
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[] = {
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[] = {
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);
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 = {
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.");
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[] = {
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);
}
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[] = {
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.
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);
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[] = {
static PyObject *
rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored))
{
+ _Py_IDENTIFIER(iter);
PyObject *start=NULL, *stop=NULL, *step=NULL;
PyObject *range;
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);
static PyObject *
longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored))
{
+ _Py_IDENTIFIER(iter);
PyObject *product, *stop=NULL;
PyObject *range;
}
/* 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 *
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);
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.");
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 *
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);
}
}
return current_frame->f_builtins;
}
+/* Convenience function to get a builtin from its name */
+PyObject *
+_PyEval_GetBuiltinId(_Py_Identifier *name)
+{
+ PyObject *attr = _PyDict_GetItemIdWithError(PyEval_GetBuiltins(), name);
+ if (attr) {
+ Py_INCREF(attr);
+ }
+ else if (!PyErr_Occurred()) {
+ PyErr_SetObject(PyExc_AttributeError, _PyUnicode_FromId(name));
+ }
+ return attr;
+}
+
PyObject *
PyEval_GetLocals(void)
{