diff -r 49909603ca72 Objects/longobject.c --- a/Objects/longobject.c Tue Feb 12 21:03:09 2008 +0100 +++ b/Objects/longobject.c Tue Feb 12 23:18:13 2008 +0100 @@ -15,6 +15,15 @@ #ifndef NSMALLNEGINTS #define NSMALLNEGINTS 5 #endif + +/* free list for long objects with abs(size) == 1 + * The free list (ab)uses the ob_type field to chain free long objects in a + * single linked, NULL terminated list. + */ +static PyLongObject *free_list = NULL; +static unsigned int numfree = 0; +#define PyLong_MAXFREELIST 4096 + #if NSMALLNEGINTS + NSMALLPOSINTS > 0 /* Small integers are preallocated in this array so that they can be shared. @@ -39,6 +48,7 @@ get_small_int(int ival) #endif return v; } + #define CHECK_SMALL_INT(ival) \ do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \ return get_small_int(ival); \ @@ -46,7 +56,7 @@ get_small_int(int ival) #else #define CHECK_SMALL_INT(ival) -#endif +#endif /* NSMALLNEGINTS + NSMALLPOSINTS > 0 */ #define MEDIUM_VALUE(x) (Py_SIZE(x) < 0 ? -(x)->ob_digit[0] : (Py_SIZE(x) == 0 ? 0 : (x)->ob_digit[0])) /* If a freshly-allocated long is already shared, it must @@ -113,6 +123,14 @@ _PyLong_New(Py_ssize_t size) _PyLong_New(Py_ssize_t size) { PyLongObject *result; + assert(size >= 0); + + /* Use a free list of longs with size +1 (or -1) */ + if (free_list && size == 1) { + result = free_list; + free_list = (PyLongObject *)Py_TYPE(result); + numfree--; + } /* Can't use sizeof(PyLongObject) here, since the compiler takes padding at the end into account. As the consequence, this would waste 2 bytes on @@ -120,8 +138,10 @@ _PyLong_New(Py_ssize_t size) This computation would be incorrect on systems which have padding before the digits; with 16-bit digits this should not happen. */ - result = PyObject_MALLOC(sizeof(PyVarObject) + - size*sizeof(digit)); + else { + result = PyObject_MALLOC(sizeof(PyVarObject) + + size*sizeof(digit)); + } if (!result) { PyErr_NoMemory(); return NULL; @@ -2127,7 +2147,17 @@ static void static void long_dealloc(PyObject *v) { - Py_TYPE(v)->tp_free(v); + if (PyLong_CheckExact(v) && numfree < PyLong_MAXFREELIST) { + Py_ssize_t size = Py_SIZE(v); + size = size < 0 ? -size : size; + if (size == 1) { + Py_TYPE(v) = (PyTypeObject *)free_list; + free_list = (PyLongObject*)v; + numfree++; + return; + } + } + Py_TYPE(v)->tp_free(v); } static PyObject * @@ -3750,4 +3780,11 @@ PyLong_Fini(void) _Py_ForgetReference((PyObject*)v); } #endif + while (free_list) { + PyObject *v = (PyObject *)free_list; + free_list = (PyLongObject *)Py_TYPE(v); + PyLong_Type.tp_free(v); + numfree--; + } + assert(numfree == 0); }