mirror of
https://github.com/python/cpython.git
synced 2025-10-13 18:33:34 +00:00
Optimize inner loops for subscript, repeat, and concat.
This commit is contained in:
parent
f889e10c19
commit
a6366fe085
2 changed files with 59 additions and 36 deletions
|
@ -382,6 +382,7 @@ list_concat(PyListObject *a, PyObject *bb)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
int i;
|
int i;
|
||||||
|
PyObject **src, **dest;
|
||||||
PyListObject *np;
|
PyListObject *np;
|
||||||
if (!PyList_Check(bb)) {
|
if (!PyList_Check(bb)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
@ -397,15 +398,19 @@ list_concat(PyListObject *a, PyObject *bb)
|
||||||
if (np == NULL) {
|
if (np == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
src = a->ob_item;
|
||||||
|
dest = np->ob_item;
|
||||||
for (i = 0; i < a->ob_size; i++) {
|
for (i = 0; i < a->ob_size; i++) {
|
||||||
PyObject *v = a->ob_item[i];
|
PyObject *v = src[i];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
np->ob_item[i] = v;
|
dest[i] = v;
|
||||||
}
|
}
|
||||||
|
src = b->ob_item;
|
||||||
|
dest = np->ob_item + a->ob_size;
|
||||||
for (i = 0; i < b->ob_size; i++) {
|
for (i = 0; i < b->ob_size; i++) {
|
||||||
PyObject *v = b->ob_item[i];
|
PyObject *v = src[i];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
np->ob_item[i + a->ob_size] = v;
|
dest[i] = v;
|
||||||
}
|
}
|
||||||
return (PyObject *)np;
|
return (PyObject *)np;
|
||||||
#undef b
|
#undef b
|
||||||
|
@ -417,7 +422,7 @@ list_repeat(PyListObject *a, int n)
|
||||||
int i, j;
|
int i, j;
|
||||||
int size;
|
int size;
|
||||||
PyListObject *np;
|
PyListObject *np;
|
||||||
PyObject **p;
|
PyObject **p, **items;
|
||||||
PyObject *elem;
|
PyObject *elem;
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -430,18 +435,20 @@ list_repeat(PyListObject *a, int n)
|
||||||
if (np == NULL)
|
if (np == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
items = np->ob_item;
|
||||||
if (a->ob_size == 1) {
|
if (a->ob_size == 1) {
|
||||||
elem = a->ob_item[0];
|
elem = a->ob_item[0];
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
np->ob_item[i] = elem;
|
items[i] = elem;
|
||||||
Py_INCREF(elem);
|
Py_INCREF(elem);
|
||||||
}
|
}
|
||||||
return (PyObject *) np;
|
return (PyObject *) np;
|
||||||
}
|
}
|
||||||
p = np->ob_item;
|
p = np->ob_item;
|
||||||
|
items = a->ob_item;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
for (j = 0; j < a->ob_size; j++) {
|
for (j = 0; j < a->ob_size; j++) {
|
||||||
*p = a->ob_item[j];
|
*p = items[j];
|
||||||
Py_INCREF(*p);
|
Py_INCREF(*p);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
@ -590,11 +597,12 @@ list_inplace_repeat(PyListObject *self, int n)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p = size;
|
p = size;
|
||||||
|
items = self->ob_item;
|
||||||
for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */
|
for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */
|
||||||
for (j = 0; j < size; j++) {
|
for (j = 0; j < size; j++) {
|
||||||
PyObject *o = PyList_GET_ITEM(self, j);
|
PyObject *o = items[j];
|
||||||
Py_INCREF(o);
|
Py_INCREF(o);
|
||||||
PyList_SET_ITEM(self, p++, o);
|
items[p++] = o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_INCREF(self);
|
Py_INCREF(self);
|
||||||
|
@ -2404,6 +2412,7 @@ list_subscript(PyListObject* self, PyObject* item)
|
||||||
int start, stop, step, slicelength, cur, i;
|
int start, stop, step, slicelength, cur, i;
|
||||||
PyObject* result;
|
PyObject* result;
|
||||||
PyObject* it;
|
PyObject* it;
|
||||||
|
PyObject **src, **dest;
|
||||||
|
|
||||||
if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
|
if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
|
||||||
&start, &stop, &step, &slicelength) < 0) {
|
&start, &stop, &step, &slicelength) < 0) {
|
||||||
|
@ -2417,11 +2426,13 @@ list_subscript(PyListObject* self, PyObject* item)
|
||||||
result = PyList_New(slicelength);
|
result = PyList_New(slicelength);
|
||||||
if (!result) return NULL;
|
if (!result) return NULL;
|
||||||
|
|
||||||
|
src = self->ob_item;
|
||||||
|
dest = ((PyListObject *)result)->ob_item;
|
||||||
for (cur = start, i = 0; i < slicelength;
|
for (cur = start, i = 0; i < slicelength;
|
||||||
cur += step, i++) {
|
cur += step, i++) {
|
||||||
it = PyList_GET_ITEM(self, cur);
|
it = src[cur];
|
||||||
Py_INCREF(it);
|
Py_INCREF(it);
|
||||||
PyList_SET_ITEM(result, i, it);
|
dest[i] = it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -2466,7 +2477,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
/* delete slice */
|
/* delete slice */
|
||||||
PyObject **garbage;
|
PyObject **garbage;
|
||||||
int cur, i, j;
|
int cur, i;
|
||||||
|
|
||||||
if (slicelength <= 0)
|
if (slicelength <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2493,17 +2504,17 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
lim = self->ob_size - cur - 1;
|
lim = self->ob_size - cur - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < lim; j++) {
|
memmove(self->ob_item + cur - i,
|
||||||
PyList_SET_ITEM(self, cur + j - i,
|
self->ob_item + cur + 1,
|
||||||
PyList_GET_ITEM(self,
|
lim * sizeof(PyObject *));
|
||||||
cur + j + 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cur = start + slicelength*step + 1;
|
for (cur = start + slicelength*step + 1;
|
||||||
cur < self->ob_size; cur++) {
|
cur < self->ob_size; cur++) {
|
||||||
PyList_SET_ITEM(self, cur - slicelength,
|
PyList_SET_ITEM(self, cur - slicelength,
|
||||||
PyList_GET_ITEM(self, cur));
|
PyList_GET_ITEM(self, cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
self->ob_size -= slicelength;
|
self->ob_size -= slicelength;
|
||||||
list_resize(self, self->ob_size);
|
list_resize(self, self->ob_size);
|
||||||
|
|
||||||
|
@ -2516,7 +2527,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* assign slice */
|
/* assign slice */
|
||||||
PyObject **garbage, *ins, *seq;
|
PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
|
||||||
int cur, i;
|
int cur, i;
|
||||||
|
|
||||||
/* protect against a[::-1] = a */
|
/* protect against a[::-1] = a */
|
||||||
|
@ -2525,11 +2536,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
PyList_GET_SIZE(value));
|
PyList_GET_SIZE(value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char msg[256];
|
seq = PySequence_Fast(value,
|
||||||
PyOS_snprintf(msg, sizeof(msg),
|
"must assign iterable to extended slice");
|
||||||
"must assign sequence (not \"%.200s\") to extended slice",
|
|
||||||
value->ob_type->tp_name);
|
|
||||||
seq = PySequence_Fast(value, msg);
|
|
||||||
if (!seq)
|
if (!seq)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2551,13 +2559,17 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
garbage = (PyObject**)
|
garbage = (PyObject**)
|
||||||
PyMem_MALLOC(slicelength*sizeof(PyObject*));
|
PyMem_MALLOC(slicelength*sizeof(PyObject*));
|
||||||
|
|
||||||
|
selfitems = self->ob_item;
|
||||||
|
if (PyList_Check(seq))
|
||||||
|
seqitems = ((PyListObject *)seq)->ob_item;
|
||||||
|
else
|
||||||
|
seqitems = ((PyTupleObject *)seq)->ob_item;
|
||||||
for (cur = start, i = 0; i < slicelength;
|
for (cur = start, i = 0; i < slicelength;
|
||||||
cur += step, i++) {
|
cur += step, i++) {
|
||||||
garbage[i] = PyList_GET_ITEM(self, cur);
|
garbage[i] = selfitems[cur];
|
||||||
|
ins = seqitems[i];
|
||||||
ins = PySequence_Fast_GET_ITEM(seq, i);
|
|
||||||
Py_INCREF(ins);
|
Py_INCREF(ins);
|
||||||
PyList_SET_ITEM(self, cur, ins);
|
selfitems[cur] = ins;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < slicelength; i++) {
|
for (i = 0; i < slicelength; i++) {
|
||||||
|
|
|
@ -136,16 +136,18 @@ PyTuple_Pack(int n, ...)
|
||||||
int i;
|
int i;
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
PyObject **items;
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
|
|
||||||
va_start(vargs, n);
|
va_start(vargs, n);
|
||||||
result = PyTuple_New(n);
|
result = PyTuple_New(n);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
items = ((PyTupleObject *)result)->ob_item;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
o = va_arg(vargs, PyObject *);
|
o = va_arg(vargs, PyObject *);
|
||||||
Py_INCREF(o);
|
Py_INCREF(o);
|
||||||
PyTuple_SET_ITEM(result, i, o);
|
items[i] = o;
|
||||||
}
|
}
|
||||||
va_end(vargs);
|
va_end(vargs);
|
||||||
return result;
|
return result;
|
||||||
|
@ -348,6 +350,7 @@ tupleconcat(register PyTupleObject *a, register PyObject *bb)
|
||||||
{
|
{
|
||||||
register int size;
|
register int size;
|
||||||
register int i;
|
register int i;
|
||||||
|
PyObject **src, **dest;
|
||||||
PyTupleObject *np;
|
PyTupleObject *np;
|
||||||
if (!PyTuple_Check(bb)) {
|
if (!PyTuple_Check(bb)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
@ -363,15 +366,19 @@ tupleconcat(register PyTupleObject *a, register PyObject *bb)
|
||||||
if (np == NULL) {
|
if (np == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
src = a->ob_item;
|
||||||
|
dest = np->ob_item;
|
||||||
for (i = 0; i < a->ob_size; i++) {
|
for (i = 0; i < a->ob_size; i++) {
|
||||||
PyObject *v = a->ob_item[i];
|
PyObject *v = src[i];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
np->ob_item[i] = v;
|
dest[i] = v;
|
||||||
}
|
}
|
||||||
|
src = b->ob_item;
|
||||||
|
dest = np->ob_item + a->ob_size;
|
||||||
for (i = 0; i < b->ob_size; i++) {
|
for (i = 0; i < b->ob_size; i++) {
|
||||||
PyObject *v = b->ob_item[i];
|
PyObject *v = src[i];
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
np->ob_item[i + a->ob_size] = v;
|
dest[i] = v;
|
||||||
}
|
}
|
||||||
return (PyObject *)np;
|
return (PyObject *)np;
|
||||||
#undef b
|
#undef b
|
||||||
|
@ -383,7 +390,7 @@ tuplerepeat(PyTupleObject *a, int n)
|
||||||
int i, j;
|
int i, j;
|
||||||
int size;
|
int size;
|
||||||
PyTupleObject *np;
|
PyTupleObject *np;
|
||||||
PyObject **p;
|
PyObject **p, **items;
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = 0;
|
n = 0;
|
||||||
if (a->ob_size == 0 || n == 1) {
|
if (a->ob_size == 0 || n == 1) {
|
||||||
|
@ -403,9 +410,10 @@ tuplerepeat(PyTupleObject *a, int n)
|
||||||
if (np == NULL)
|
if (np == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
p = np->ob_item;
|
p = np->ob_item;
|
||||||
|
items = a->ob_item;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
for (j = 0; j < a->ob_size; j++) {
|
for (j = 0; j < a->ob_size; j++) {
|
||||||
*p = a->ob_item[j];
|
*p = items[j];
|
||||||
Py_INCREF(*p);
|
Py_INCREF(*p);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
@ -584,6 +592,7 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
|
||||||
int start, stop, step, slicelength, cur, i;
|
int start, stop, step, slicelength, cur, i;
|
||||||
PyObject* result;
|
PyObject* result;
|
||||||
PyObject* it;
|
PyObject* it;
|
||||||
|
PyObject **src, **dest;
|
||||||
|
|
||||||
if (PySlice_GetIndicesEx((PySliceObject*)item,
|
if (PySlice_GetIndicesEx((PySliceObject*)item,
|
||||||
PyTuple_GET_SIZE(self),
|
PyTuple_GET_SIZE(self),
|
||||||
|
@ -597,11 +606,13 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
|
||||||
else {
|
else {
|
||||||
result = PyTuple_New(slicelength);
|
result = PyTuple_New(slicelength);
|
||||||
|
|
||||||
|
src = self->ob_item;
|
||||||
|
dest = ((PyTupleObject *)result)->ob_item;
|
||||||
for (cur = start, i = 0; i < slicelength;
|
for (cur = start, i = 0; i < slicelength;
|
||||||
cur += step, i++) {
|
cur += step, i++) {
|
||||||
it = PyTuple_GET_ITEM(self, cur);
|
it = src[cur];
|
||||||
Py_INCREF(it);
|
Py_INCREF(it);
|
||||||
PyTuple_SET_ITEM(result, i, it);
|
dest[i] = it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue