diff -r b5a953ffb2be Objects/typeobject.c --- a/Objects/typeobject.c Sun Feb 08 14:07:35 2015 -0800 +++ b/Objects/typeobject.c Mon Feb 09 12:48:37 2015 +0200 @@ -3680,8 +3680,9 @@ static PyGetSetDef object_getsets[] = { */ static PyObject * -import_copyreg(void) -{ +import_from_copyreg(_Py_Identifier *id) +{ + PyObject *res; PyObject *copyreg_str; PyObject *copyreg_module; PyInterpreterState *interp = PyThreadState_GET()->interp; @@ -3699,19 +3700,24 @@ import_copyreg(void) copyreg_module = PyDict_GetItemWithError(interp->modules, copyreg_str); if (copyreg_module != NULL) { Py_INCREF(copyreg_module); - return copyreg_module; - } - if (PyErr_Occurred()) { - return NULL; - } - return PyImport_Import(copyreg_str); + } + else { + if (PyErr_Occurred()) + return NULL; + copyreg_module = PyImport_Import(copyreg_str); + if (copyreg_module == NULL) + return NULL; + } + res = _PyObject_GetAttrId(copyreg_module, id); + Py_DECREF(copyreg_module); + return res; } Py_LOCAL(PyObject *) _PyType_GetSlotNames(PyTypeObject *cls) { - PyObject *copyreg; PyObject *slotnames; + PyObject *getslotnames; _Py_IDENTIFIER(__slotnames__); _Py_IDENTIFIER(_slotnames); @@ -3737,16 +3743,14 @@ Py_LOCAL(PyObject *) /* The class does not have the slot names cached yet. */ } - copyreg = import_copyreg(); - if (copyreg == NULL) - return NULL; - /* Use _slotnames function from the copyreg module to find the slots by this class and its bases. This function will cache the result in __slotnames__. */ - slotnames = _PyObject_CallMethodIdObjArgs(copyreg, &PyId__slotnames, - cls, NULL); - Py_DECREF(copyreg); + getslotnames = import_from_copyreg(&PyId__slotnames); + if (getslotnames == NULL) + return NULL; + slotnames = PyObject_CallFunctionObjArgs(getslotnames, cls, NULL); + Py_DECREF(getslotnames); if (slotnames == NULL) return NULL; @@ -4023,7 +4027,6 @@ static PyObject * reduce_newobj(PyObject *obj, int proto) { PyObject *args = NULL, *kwargs = NULL; - PyObject *copyreg; PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *result; @@ -4037,46 +4040,46 @@ reduce_newobj(PyObject *obj, int proto) return NULL; } } - copyreg = import_copyreg(); - if (copyreg == NULL) { - Py_DECREF(args); + if (kwargs == NULL || PyDict_Size(kwargs) == 0) { Py_XDECREF(kwargs); - return NULL; - } - if (kwargs == NULL || PyDict_Size(kwargs) == 0) { - _Py_IDENTIFIER(__newobj__); - PyObject *cls; - Py_ssize_t i, n; - - Py_XDECREF(kwargs); - newobj = _PyObject_GetAttrId(copyreg, &PyId___newobj__); - Py_DECREF(copyreg); - if (newobj == NULL) { + if (Py_TYPE(obj)->tp_init == PyBaseObject_Type.tp_init) { + newobj = (PyObject *) Py_TYPE(obj); + Py_INCREF(newobj); + newargs = args; + Py_INCREF(newargs); + } + else { + _Py_IDENTIFIER(__newobj__); + PyObject *cls; + Py_ssize_t i, n; + + newobj = import_from_copyreg(&PyId___newobj__); + if (newobj == NULL) { + Py_DECREF(args); + return NULL; + } + n = PyTuple_GET_SIZE(args); + newargs = PyTuple_New(n+1); + if (newargs == NULL) { + Py_DECREF(args); + Py_DECREF(newobj); + return NULL; + } + cls = (PyObject *) Py_TYPE(obj); + Py_INCREF(cls); + PyTuple_SET_ITEM(newargs, 0, cls); + for (i = 0; i < n; i++) { + PyObject *v = PyTuple_GET_ITEM(args, i); + Py_INCREF(v); + PyTuple_SET_ITEM(newargs, i+1, v); + } Py_DECREF(args); - return NULL; } - n = PyTuple_GET_SIZE(args); - newargs = PyTuple_New(n+1); - if (newargs == NULL) { - Py_DECREF(args); - Py_DECREF(newobj); - return NULL; - } - cls = (PyObject *) Py_TYPE(obj); - Py_INCREF(cls); - PyTuple_SET_ITEM(newargs, 0, cls); - for (i = 0; i < n; i++) { - PyObject *v = PyTuple_GET_ITEM(args, i); - Py_INCREF(v); - PyTuple_SET_ITEM(newargs, i+1, v); - } - Py_DECREF(args); } else if (proto >= 4) { _Py_IDENTIFIER(__newobj_ex__); - newobj = _PyObject_GetAttrId(copyreg, &PyId___newobj_ex__); - Py_DECREF(copyreg); + newobj = import_from_copyreg(&PyId___newobj_ex__); if (newobj == NULL) { Py_DECREF(args); Py_DECREF(kwargs); @@ -4097,7 +4100,6 @@ reduce_newobj(PyObject *obj, int proto) "keyword arguments."); Py_DECREF(args); Py_DECREF(kwargs); - Py_DECREF(copyreg); return NULL; } @@ -4141,17 +4143,18 @@ reduce_newobj(PyObject *obj, int proto) static PyObject * _common_reduce(PyObject *self, int proto) { - PyObject *copyreg, *res; + _Py_IDENTIFIER(_reduce_ex); + PyObject *reduce_ex, *res; if (proto >= 2) return reduce_newobj(self, proto); - copyreg = import_copyreg(); - if (!copyreg) + reduce_ex = import_from_copyreg(&PyId__reduce_ex); + if (!reduce_ex) return NULL; - res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto); - Py_DECREF(copyreg); + res = PyEval_CallFunction(reduce_ex, "(Oi)", self, proto); + Py_DECREF(reduce_ex); return res; }