Commit dd8d4870 authored by Raymond Hettinger's avatar Raymond Hettinger

Optimize slice assignments.

* Replace sprintf message with a constant message string -- this error
  message ran on every invocation except straight deletions but it was
  only needed when the rhs was not iterable.  The message was also
  out-of-date and did not reflect that iterable arguments were allowed.

* For inner loops that do not make ref count adjustments, use memmove()
  for fast copying and better readability.

* For inner loops that do make ref count adjustments, speed them up by
  factoring out the constant structure reference and using vitem[] instead.
parent 9b24233d
...@@ -460,6 +460,7 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -460,6 +460,7 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
list. :-( */ list. :-( */
PyObject **recycle, **p; PyObject **recycle, **p;
PyObject **item; PyObject **item;
PyObject **vitem = NULL;
PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */ PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */
int n; /* Size of replacement list */ int n; /* Size of replacement list */
int d; /* Change in size */ int d; /* Change in size */
...@@ -469,7 +470,6 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -469,7 +470,6 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
if (v == NULL) if (v == NULL)
n = 0; n = 0;
else { else {
char msg[256];
if (a == b) { if (a == b) {
/* Special case "a[i:j] = a" -- copy b first */ /* Special case "a[i:j] = a" -- copy b first */
int ret; int ret;
...@@ -480,15 +480,16 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -480,15 +480,16 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
Py_DECREF(v); Py_DECREF(v);
return ret; return ret;
} }
v_as_SF = PySequence_Fast(v, "can only assign an iterable");
PyOS_snprintf(msg, sizeof(msg),
"must assign sequence"
" (not \"%.200s\") to slice",
v->ob_type->tp_name);
v_as_SF = PySequence_Fast(v, msg);
if(v_as_SF == NULL) if(v_as_SF == NULL)
return -1; return -1;
n = PySequence_Fast_GET_SIZE(v_as_SF); n = PySequence_Fast_GET_SIZE(v_as_SF);
if (PyList_Check(v_as_SF))
vitem = ((PyListObject *)v_as_SF)->ob_item;
else {
assert (PyTuple_Check(v_as_SF));
vitem = ((PyTupleObject *)v_as_SF)->ob_item;
}
} }
if (ilow < 0) if (ilow < 0)
ilow = 0; ilow = 0;
...@@ -510,11 +511,11 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -510,11 +511,11 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
else else
p = recycle = NULL; p = recycle = NULL;
if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */ if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */
for (k = ilow; k < ihigh; k++) memmove(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *));
*p++ = item[k]; p += ihigh - ilow;
if (d < 0) { if (d < 0) {
for (/*k = ihigh*/; k < a->ob_size; k++) memmove(&item[ihigh+d], &item[ihigh],
item[k+d] = item[k]; (a->ob_size - ihigh)*sizeof(PyObject *));
list_resize(a, a->ob_size + d); list_resize(a, a->ob_size + d);
item = a->ob_item; item = a->ob_item;
} }
...@@ -527,13 +528,13 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -527,13 +528,13 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
return -1; return -1;
} }
item = a->ob_item; item = a->ob_item;
for (k = s; --k >= ihigh; ) memmove(&item[ihigh+d], &item[ihigh],
item[k+d] = item[k]; (s - ihigh)*sizeof(PyObject *));
for (/*k = ihigh-1*/; k >= ilow; --k) memmove(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *));
*p++ = item[k]; p += ihigh - ilow;
} }
for (k = 0; k < n; k++, ilow++) { for (k = 0; k < n; k++, ilow++) {
PyObject *w = PySequence_Fast_GET_ITEM(v_as_SF, k); PyObject *w = vitem[k];
Py_XINCREF(w); Py_XINCREF(w);
item[ilow] = w; item[ilow] = w;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment