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
1 changed files with 53 additions and 54 deletions

View File

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