Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad14ccd

Browse files
committed
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.
1 parent 937114f commit ad14ccd

6 files changed

Lines changed: 32 additions & 15 deletions

File tree

Include/object.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,10 @@ typedef struct _Py_Identifier {
147147
#define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value)
148148
#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname)
149149

150-
/* Common identifiers */
151-
PyAPI_DATA(_Py_Identifier) _PyId_path;
150+
/* Common identifiers (ex: _PyId_path is the string "path") */
152151
PyAPI_DATA(_Py_Identifier) _PyId_argv;
152+
PyAPI_DATA(_Py_Identifier) _PyId_builtins;
153+
PyAPI_DATA(_Py_Identifier) _PyId_path;
153154
PyAPI_DATA(_Py_Identifier) _PyId_stdin;
154155
PyAPI_DATA(_Py_Identifier) _PyId_stdout;
155156
PyAPI_DATA(_Py_Identifier) _PyId_stderr;

Include/unicodeobject.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,6 +1996,11 @@ PyAPI_FUNC(int) PyUnicode_Compare(
19961996
PyObject *right /* Right string */
19971997
);
19981998

1999+
PyAPI_FUNC(int) _PyUnicode_CompareWithId(
2000+
PyObject *left, /* Left string */
2001+
_Py_Identifier *right /* Right identifier */
2002+
);
2003+
19992004
PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString(
20002005
PyObject *left,
20012006
const char *right /* ASCII-encoded string */

Objects/typeobject.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,10 @@ type_set_qualname(PyTypeObject *type, PyObject *value, void *context)
345345
static PyObject *
346346
type_module(PyTypeObject *type, void *context)
347347
{
348-
PyObject *mod;
349348
char *s;
350349

351350
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
352-
mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__);
351+
PyObject *mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__);
353352
if (!mod) {
354353
PyErr_Format(PyExc_AttributeError, "__module__");
355354
return 0;
@@ -358,11 +357,14 @@ type_module(PyTypeObject *type, void *context)
358357
return mod;
359358
}
360359
else {
360+
PyObject *name;
361361
s = strrchr(type->tp_name, '.');
362362
if (s != NULL)
363363
return PyUnicode_FromStringAndSize(
364364
type->tp_name, (Py_ssize_t)(s - type->tp_name));
365-
return PyUnicode_FromString("builtins");
365+
name = _PyUnicode_FromId(&_PyId_builtins);
366+
Py_XINCREF(name);
367+
return name;
366368
}
367369
}
368370

@@ -712,7 +714,7 @@ type_repr(PyTypeObject *type)
712714
return NULL;
713715
}
714716

715-
if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins"))
717+
if (mod != NULL && _PyUnicode_CompareWithId(mod, &_PyId_builtins))
716718
rtn = PyUnicode_FromFormat("<class '%U.%U'>", mod, name);
717719
else
718720
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
@@ -2143,7 +2145,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
21432145
if (!valid_identifier(tmp))
21442146
goto error;
21452147
assert(PyUnicode_Check(tmp));
2146-
if (PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) {
2148+
if (_PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) {
21472149
if (!may_add_dict || add_dict) {
21482150
PyErr_SetString(PyExc_TypeError,
21492151
"__dict__ slot disallowed: "
@@ -2174,7 +2176,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
21742176
for (i = j = 0; i < nslots; i++) {
21752177
tmp = PyTuple_GET_ITEM(slots, i);
21762178
if ((add_dict &&
2177-
PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) ||
2179+
_PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) ||
21782180
(add_weak &&
21792181
PyUnicode_CompareWithASCIIString(tmp, "__weakref__") == 0))
21802182
continue;
@@ -3183,7 +3185,7 @@ object_repr(PyObject *self)
31833185
Py_XDECREF(mod);
31843186
return NULL;
31853187
}
3186-
if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins"))
3188+
if (mod != NULL && _PyUnicode_CompareWithId(mod, &_PyId_builtins))
31873189
rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self);
31883190
else
31893191
rtn = PyUnicode_FromFormat("<%s object at %p>",
@@ -6336,8 +6338,8 @@ super_getattro(PyObject *self, PyObject *name)
63366338
/* We want __class__ to return the class of the super object
63376339
(i.e. super, or a subclass), not the class of su->obj. */
63386340
skip = (PyUnicode_Check(name) &&
6339-
PyUnicode_GET_LENGTH(name) == 9 &&
6340-
PyUnicode_CompareWithASCIIString(name, "__class__") == 0);
6341+
PyUnicode_GET_LENGTH(name) == 9 &&
6342+
_PyUnicode_CompareWithId(name, &PyId___class__) == 0);
63416343
}
63426344

63436345
if (!skip) {
@@ -6543,8 +6545,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
65436545
for (i = 0; i < n; i++) {
65446546
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
65456547
assert(PyUnicode_Check(name));
6546-
if (!PyUnicode_CompareWithASCIIString(name,
6547-
"__class__")) {
6548+
if (!_PyUnicode_CompareWithId(name, &PyId___class__)) {
65486549
Py_ssize_t index = co->co_nlocals +
65496550
PyTuple_GET_SIZE(co->co_cellvars) + i;
65506551
PyObject *cell = f->f_localsplus[index];

Objects/unicodeobject.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10565,6 +10565,15 @@ PyUnicode_Compare(PyObject *left, PyObject *right)
1056510565
return -1;
1056610566
}
1056710567

10568+
int
10569+
_PyUnicode_CompareWithId(PyObject *left, _Py_Identifier *right)
10570+
{
10571+
PyObject *right_str = _PyUnicode_FromId(right); /* borrowed */
10572+
if (right_str == NULL)
10573+
return -1;
10574+
return PyUnicode_Compare(left, right_str);
10575+
}
10576+
1056810577
int
1056910578
PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str)
1057010579
{

Python/errors.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ PyErr_WriteUnraisable(PyObject *obj)
878878
goto done;
879879
}
880880
else {
881-
if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) {
881+
if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0) {
882882
if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0)
883883
goto done;
884884
if (PyFile_WriteString(".", f) < 0)

Python/pythonrun.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
/* Common identifiers */
3939
_Py_Identifier _PyId_argv = _Py_static_string_init("argv");
40+
_Py_Identifier _PyId_builtins = _Py_static_string_init("builtins");
4041
_Py_Identifier _PyId_path = _Py_static_string_init("path");
4142
_Py_Identifier _PyId_stdin = _Py_static_string_init("stdin");
4243
_Py_Identifier _PyId_stdout = _Py_static_string_init("stdout");
@@ -1928,7 +1929,7 @@ print_exception(PyObject *f, PyObject *value)
19281929
err = PyFile_WriteString("<unknown>", f);
19291930
}
19301931
else {
1931-
if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0)
1932+
if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0)
19321933
{
19331934
err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW);
19341935
err += PyFile_WriteString(".", f);

0 commit comments

Comments
 (0)