diff -r 8bac00eadfda Lib/test/test_sys.py --- a/Lib/test/test_sys.py Wed May 06 14:19:22 2015 +0300 +++ b/Lib/test/test_sys.py Wed May 06 08:58:35 2015 -0700 @@ -986,7 +986,7 @@ # PyCapsule # XXX # rangeiterator - check(iter(range(1)), size('4l')) + check(iter(range(1)), size('4l2P')) # reverse check(reversed(''), size('nP')) # range diff -r 8bac00eadfda Objects/rangeobject.c --- a/Objects/rangeobject.c Wed May 06 14:19:22 2015 +0300 +++ b/Objects/rangeobject.c Wed May 06 08:58:35 2015 -0700 @@ -2,6 +2,7 @@ #include "Python.h" #include "structmember.h" +#include "longintrepr.h" /* Support objects whose length is > PY_SSIZE_T_MAX. @@ -750,21 +751,56 @@ typedef struct { PyObject_HEAD + PyLongObject *older; + PyLongObject *old; long index; long start; long step; long len; } rangeiterobject; +#ifndef NSMALLPOSINTS +#define NSMALLPOSINTS 257 +#endif + static PyObject * rangeiter_next(rangeiterobject *r) { - if (r->index < r->len) - /* cast to unsigned to avoid possible signed overflow - in intermediate calculations. */ - return PyLong_FromLong((long)(r->start + - (unsigned long)(r->index++) * r->step)); - return NULL; + PyObject *o; + long value; + + if (r->index >= r->len) + return NULL; + + /* cast to unsigned to avoid possible signed overflow + in intermediate calculations. */ + value = (long)(r->start + (unsigned long)(r->index++) * r->step); + + if (r->older) { + int r_older_is_suitable = (Py_REFCNT(r->older) == 1) && (Py_SIZE(r->older) == 1); + int value_fits = (value >= NSMALLPOSINTS) && (value < PyLong_BASE); + + if (r_older_is_suitable && value_fits) { + r->older->ob_digit[0] = value; + o = (PyObject *)r->older; + r->older = r->old; + r->old = (PyLongObject *)o; + Py_INCREF(o); + return o; + } + + Py_DECREF(r->older); + r->older = NULL; + } + + o = PyLong_FromLong(value); + if (Py_SIZE(o) == 1) { + assert(r->older == NULL); + r->older = r->old; + r->old = (PyLongObject *)o; + Py_INCREF(o); + } + return o; } static PyObject * @@ -817,6 +853,8 @@ else if (index > r->len) index = r->len; /* exhausted iterator */ r->index = index; + Py_CLEAR(r->older); + Py_CLEAR(r->old); Py_RETURN_NONE; } @@ -835,13 +873,21 @@ static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); +static void +rangeiter_dealloc(rangeiterobject *r) +{ + Py_CLEAR(r->older); + Py_CLEAR(r->old); + PyObject_Del(r); +} + PyTypeObject PyRangeIter_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "range_iterator", /* tp_name */ sizeof(rangeiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)PyObject_Del, /* tp_dealloc */ + (destructor)rangeiter_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -917,6 +963,7 @@ return NULL; it->start = start; it->step = step; + it->older = it->old = NULL; ulen = get_len_of_range(start, stop, step); if (ulen > (unsigned long)LONG_MAX) { Py_DECREF(it);