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

Skip to content

Commit 5b4d477

Browse files
committed
Intern 1-character strings as soon as they're created. As-is, they aren't
interned when created, so the cached versions generally aren't ever interned. With the patch, the Py_INCREF(t); *p = t; Py_DECREF(s); return; indirection block in PyString_InternInPlace() is never executed during a full run of the test suite, but was executed very many times before. So I'm trading more work when creating one-character strings for doing less work later. Note that the "more work" here can happen at most 256 times per program run, so it's trivial. The same reasoning accounts for the patch's simplification of string_item (the new version can call PyString_FromStringAndSize() no more than 256 times per run, so there's no point to inlining that stuff -- if we were serious about saving time here, we'd pre-initialize the characters vector so that no runtime testing at all was needed!).
1 parent 61dff2b commit 5b4d477

1 file changed

Lines changed: 12 additions & 15 deletions

File tree

Objects/stringobject.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static PyStringObject *nullstring;
3636
PyObject *
3737
PyString_FromStringAndSize(const char *str, int size)
3838
{
39-
register PyStringObject *op;
39+
PyStringObject *op;
4040
#ifndef DONT_SHARE_SHORT_STRINGS
4141
if (size == 0 && (op = nullstring) != NULL) {
4242
#ifdef COUNT_ALLOCS
@@ -73,9 +73,11 @@ PyString_FromStringAndSize(const char *str, int size)
7373
op->ob_sval[size] = '\0';
7474
#ifndef DONT_SHARE_SHORT_STRINGS
7575
if (size == 0) {
76+
PyString_InternInPlace(&(PyObject *)op);
7677
nullstring = op;
7778
Py_INCREF(op);
7879
} else if (size == 1 && str != NULL) {
80+
PyString_InternInPlace(&(PyObject *)op);
7981
characters[*str & UCHAR_MAX] = op;
8082
Py_INCREF(op);
8183
}
@@ -87,7 +89,7 @@ PyObject *
8789
PyString_FromString(const char *str)
8890
{
8991
register size_t size = strlen(str);
90-
register PyStringObject *op;
92+
PyStringObject *op;
9193
if (size > INT_MAX) {
9294
PyErr_SetString(PyExc_OverflowError,
9395
"string is too long for a Python string");
@@ -125,9 +127,11 @@ PyString_FromString(const char *str)
125127
strcpy(op->ob_sval, str);
126128
#ifndef DONT_SHARE_SHORT_STRINGS
127129
if (size == 0) {
130+
PyString_InternInPlace(&(PyObject *)op);
128131
nullstring = op;
129132
Py_INCREF(op);
130133
} else if (size == 1) {
134+
PyString_InternInPlace(&(PyObject *)op);
131135
characters[*str & UCHAR_MAX] = op;
132136
Py_INCREF(op);
133137
}
@@ -551,24 +555,17 @@ string_item(PyStringObject *a, register int i)
551555
{
552556
int c;
553557
PyObject *v;
558+
char *pchar;
554559
if (i < 0 || i >= a->ob_size) {
555560
PyErr_SetString(PyExc_IndexError, "string index out of range");
556561
return NULL;
557562
}
558-
c = a->ob_sval[i] & UCHAR_MAX;
563+
pchar = a->ob_sval + i;
564+
c = *pchar & UCHAR_MAX;
559565
v = (PyObject *) characters[c];
560-
#ifdef COUNT_ALLOCS
561-
if (v != NULL)
562-
one_strings++;
563-
#endif
564-
if (v == NULL) {
565-
v = PyString_FromStringAndSize((char *)NULL, 1);
566-
if (v == NULL)
567-
return NULL;
568-
characters[c] = (PyStringObject *) v;
569-
((PyStringObject *)v)->ob_sval[0] = c;
570-
}
571-
Py_INCREF(v);
566+
if (v == NULL)
567+
v = PyString_FromStringAndSize(pchar, 1);
568+
Py_XINCREF(v);
572569
return v;
573570
}
574571

0 commit comments

Comments
 (0)