Issue #19646: repr(dict) now uses _PyUnicodeWriter API for better performances

This commit is contained in:
Victor Stinner 2013-11-19 13:07:38 +01:00
parent 88a9cd9b57
commit f91929b1d8

View File

@ -1397,9 +1397,9 @@ static PyObject *
dict_repr(PyDictObject *mp) dict_repr(PyDictObject *mp)
{ {
Py_ssize_t i; Py_ssize_t i;
PyObject *s, *temp, *colon = NULL; PyObject *key = NULL, *value = NULL;
PyObject *pieces = NULL, *result = NULL; _PyUnicodeWriter writer;
PyObject *key, *value; int first;
i = Py_ReprEnter((PyObject *)mp); i = Py_ReprEnter((PyObject *)mp);
if (i != 0) { if (i != 0) {
@ -1407,74 +1407,73 @@ dict_repr(PyDictObject *mp)
} }
if (mp->ma_used == 0) { if (mp->ma_used == 0) {
result = PyUnicode_FromString("{}"); Py_ReprLeave((PyObject *)mp);
goto Done; return PyUnicode_FromString("{}");
} }
pieces = PyList_New(0); _PyUnicodeWriter_Init(&writer);
if (pieces == NULL) writer.overallocate = 1;
goto Done; /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */
writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1;
colon = PyUnicode_FromString(": "); if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0)
if (colon == NULL) goto error;
goto Done;
/* Do repr() on each key+value pair, and insert ": " between them. /* Do repr() on each key+value pair, and insert ": " between them.
Note that repr may mutate the dict. */ Note that repr may mutate the dict. */
i = 0; i = 0;
first = 1;
while (PyDict_Next((PyObject *)mp, &i, &key, &value)) { while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
int status; PyObject *s;
int res;
/* Prevent repr from deleting key or value during key format. */ /* Prevent repr from deleting key or value during key format. */
Py_INCREF(key); Py_INCREF(key);
Py_INCREF(value); Py_INCREF(value);
s = PyObject_Repr(key);
PyUnicode_Append(&s, colon);
if (s == NULL)
goto Done;
PyUnicode_AppendAndDel(&s, PyObject_Repr(value)); if (!first) {
Py_DECREF(key); if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
Py_DECREF(value); goto error;
}
first = 0;
s = PyObject_Repr(key);
if (s == NULL) if (s == NULL)
goto Done; goto error;
status = PyList_Append(pieces, s); res = _PyUnicodeWriter_WriteStr(&writer, s);
Py_DECREF(s); /* append created a new ref */ Py_DECREF(s);
if (status < 0) if (res < 0)
goto Done; goto error;
if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0)
goto error;
s = PyObject_Repr(value);
if (s == NULL)
goto error;
res = _PyUnicodeWriter_WriteStr(&writer, s);
Py_DECREF(s);
if (res < 0)
goto error;
Py_CLEAR(key);
Py_CLEAR(value);
} }
/* Add "{}" decorations to the first and last items. */ writer.overallocate = 0;
assert(PyList_GET_SIZE(pieces) > 0); if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0)
s = PyUnicode_FromString("{"); goto error;
if (s == NULL)
goto Done;
temp = PyList_GET_ITEM(pieces, 0);
PyUnicode_AppendAndDel(&s, temp);
PyList_SET_ITEM(pieces, 0, s);
if (s == NULL)
goto Done;
s = PyUnicode_FromString("}");
if (s == NULL)
goto Done;
temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
PyUnicode_AppendAndDel(&temp, s);
PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
if (temp == NULL)
goto Done;
/* Paste them all together with ", " between. */
s = PyUnicode_FromString(", ");
if (s == NULL)
goto Done;
result = PyUnicode_Join(s, pieces);
Py_DECREF(s);
Done:
Py_XDECREF(pieces);
Py_XDECREF(colon);
Py_ReprLeave((PyObject *)mp); Py_ReprLeave((PyObject *)mp);
return result;
return _PyUnicodeWriter_Finish(&writer);
error:
Py_ReprLeave((PyObject *)mp);
_PyUnicodeWriter_Dealloc(&writer);
Py_XDECREF(key);
Py_XDECREF(value);
return NULL;
} }
static Py_ssize_t static Py_ssize_t