From ad14ccd047022d09f486d2359a342ffc5e676e5a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 00:46:04 +0100 Subject: Issue #19512: add _PyUnicode_CompareWithId() function _PyUnicode_CompareWithId() is faster than PyUnicode_CompareWithASCIIString() when both strings are equal and interned. Add also _PyId_builtins identifier for "builtins" common string. --- Include/object.h | 5 +++-- Include/unicodeobject.h | 5 +++++ Objects/typeobject.c | 23 ++++++++++++----------- Objects/unicodeobject.c | 9 +++++++++ Python/errors.c | 2 +- Python/pythonrun.c | 3 ++- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Include/object.h b/Include/object.h index a36c5be..27f48a5 100644 --- a/Include/object.h +++ b/Include/object.h @@ -147,9 +147,10 @@ typedef struct _Py_Identifier { #define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value) #define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname) -/* Common identifiers */ -PyAPI_DATA(_Py_Identifier) _PyId_path; +/* Common identifiers (ex: _PyId_path is the string "path") */ PyAPI_DATA(_Py_Identifier) _PyId_argv; +PyAPI_DATA(_Py_Identifier) _PyId_builtins; +PyAPI_DATA(_Py_Identifier) _PyId_path; PyAPI_DATA(_Py_Identifier) _PyId_stdin; PyAPI_DATA(_Py_Identifier) _PyId_stdout; PyAPI_DATA(_Py_Identifier) _PyId_stderr; diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 6d830c0..20ce41d 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1996,6 +1996,11 @@ PyAPI_FUNC(int) PyUnicode_Compare( PyObject *right /* Right string */ ); +PyAPI_FUNC(int) _PyUnicode_CompareWithId( + PyObject *left, /* Left string */ + _Py_Identifier *right /* Right identifier */ + ); + PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString( PyObject *left, const char *right /* ASCII-encoded string */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 02ad0b7..299c611 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -345,11 +345,10 @@ type_set_qualname(PyTypeObject *type, PyObject *value, void *context) static PyObject * type_module(PyTypeObject *type, void *context) { - PyObject *mod; char *s; if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { - mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__); + PyObject *mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__); if (!mod) { PyErr_Format(PyExc_AttributeError, "__module__"); return 0; @@ -358,11 +357,14 @@ type_module(PyTypeObject *type, void *context) return mod; } else { + PyObject *name; s = strrchr(type->tp_name, '.'); if (s != NULL) return PyUnicode_FromStringAndSize( type->tp_name, (Py_ssize_t)(s - type->tp_name)); - return PyUnicode_FromString("builtins"); + name = _PyUnicode_FromId(&_PyId_builtins); + Py_XINCREF(name); + return name; } } @@ -712,7 +714,7 @@ type_repr(PyTypeObject *type) return NULL; } - if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) + if (mod != NULL && _PyUnicode_CompareWithId(mod, &_PyId_builtins)) rtn = PyUnicode_FromFormat("", mod, name); else rtn = PyUnicode_FromFormat("", type->tp_name); @@ -2143,7 +2145,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) if (!valid_identifier(tmp)) goto error; assert(PyUnicode_Check(tmp)); - if (PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) { + if (_PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) { if (!may_add_dict || add_dict) { PyErr_SetString(PyExc_TypeError, "__dict__ slot disallowed: " @@ -2174,7 +2176,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) for (i = j = 0; i < nslots; i++) { tmp = PyTuple_GET_ITEM(slots, i); if ((add_dict && - PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) || + _PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) || (add_weak && PyUnicode_CompareWithASCIIString(tmp, "__weakref__") == 0)) continue; @@ -3183,7 +3185,7 @@ object_repr(PyObject *self) Py_XDECREF(mod); return NULL; } - if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) + if (mod != NULL && _PyUnicode_CompareWithId(mod, &_PyId_builtins)) rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self); else rtn = PyUnicode_FromFormat("<%s object at %p>", @@ -6336,8 +6338,8 @@ super_getattro(PyObject *self, PyObject *name) /* We want __class__ to return the class of the super object (i.e. super, or a subclass), not the class of su->obj. */ skip = (PyUnicode_Check(name) && - PyUnicode_GET_LENGTH(name) == 9 && - PyUnicode_CompareWithASCIIString(name, "__class__") == 0); + PyUnicode_GET_LENGTH(name) == 9 && + _PyUnicode_CompareWithId(name, &PyId___class__) == 0); } if (!skip) { @@ -6543,8 +6545,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds) for (i = 0; i < n; i++) { PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); assert(PyUnicode_Check(name)); - if (!PyUnicode_CompareWithASCIIString(name, - "__class__")) { + if (!_PyUnicode_CompareWithId(name, &PyId___class__)) { Py_ssize_t index = co->co_nlocals + PyTuple_GET_SIZE(co->co_cellvars) + i; PyObject *cell = f->f_localsplus[index]; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 574b57a..4ae7377 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -10566,6 +10566,15 @@ PyUnicode_Compare(PyObject *left, PyObject *right) } int +_PyUnicode_CompareWithId(PyObject *left, _Py_Identifier *right) +{ + PyObject *right_str = _PyUnicode_FromId(right); /* borrowed */ + if (right_str == NULL) + return -1; + return PyUnicode_Compare(left, right_str); +} + +int PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str) { Py_ssize_t i; diff --git a/Python/errors.c b/Python/errors.c index b92911a..93e4724 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -878,7 +878,7 @@ PyErr_WriteUnraisable(PyObject *obj) goto done; } else { - if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) { + if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0) { if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0) goto done; if (PyFile_WriteString(".", f) < 0) diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e0c8638..be41de6 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -37,6 +37,7 @@ /* Common identifiers */ _Py_Identifier _PyId_argv = _Py_static_string_init("argv"); +_Py_Identifier _PyId_builtins = _Py_static_string_init("builtins"); _Py_Identifier _PyId_path = _Py_static_string_init("path"); _Py_Identifier _PyId_stdin = _Py_static_string_init("stdin"); _Py_Identifier _PyId_stdout = _Py_static_string_init("stdout"); @@ -1928,7 +1929,7 @@ print_exception(PyObject *f, PyObject *value) err = PyFile_WriteString("", f); } else { - if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) + if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0) { err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); -- cgit v0.12