r51509 - python/branches/int_unification/Objects/longobject.c
Author: martin.v.loewis Date: Wed Aug 23 18:24:45 2006 New Revision: 51509 Modified: python/branches/int_unification/Objects/longobject.c Log: Bring back cache for small objects. Modified: python/branches/int_unification/Objects/longobject.c ============================================================================== --- python/branches/int_unification/Objects/longobject.c (original) +++ python/branches/int_unification/Objects/longobject.c Wed Aug 23 18:24:45 2006 @@ -9,6 +9,44 @@ #include <ctype.h> +#ifndef NSMALLPOSINTS +#define NSMALLPOSINTS 257 +#endif +#ifndef NSMALLNEGINTS +#define NSMALLNEGINTS 5 +#endif +#if NSMALLNEGINTS + NSMALLPOSINTS > 0 +/* Small integers are preallocated in this array so that they + can be shared. + The integers that are preallocated are those in the range + -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive). +*/ +static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS]; +#ifdef COUNT_ALLOCS +int quick_int_allocs, quick_neg_int_allocs; +#endif + +static inline PyObject * +get_small_int(int ival) +{ + PyObject *v = small_ints + ival + NSMALLNEGINTS; + Py_INCREF(v); +#ifdef COUNT_ALLOCS + if (ival >= 0) + quick_int_allocs++; + else + quick_neg_int_allocs++; +#endif + return (PyObject *) v; +} +#define CHECK_SMALL_INT(ival) \ + do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \ + return get_small_int(ival); \ + } while(0) + +#else +#define CHECK_SMALL_INT(ival) +#endif /* For long multiplication, use the O(N**2) school algorithm unless * both operands contain more than KARATSUBA_CUTOFF digits (this * being an internal Python long digit, in base BASE). @@ -83,6 +121,12 @@ i = src->ob_size; if (i < 0) i = -(i); + if (i < 2) { + int ival = src->ob_digit[0]; + if (src->ob_size < 0) + ival = -ival; + CHECK_SMALL_INT(ival); + } result = _PyLong_New(i); if (result != NULL) { result->ob_size = src->ob_size; @@ -102,6 +146,7 @@ int ndigits = 0; int negative = 0; + CHECK_SMALL_INT(ival); if (ival < 0) { ival = -ival; negative = 1; @@ -138,6 +183,7 @@ unsigned long t; int ndigits = 0; + CHECK_SMALL_INT(ival); /* Count the number of Python digits. */ t = (unsigned long)ival; while (t) { @@ -174,6 +220,7 @@ neg = 1; dval = -dval; } + CHECK_SMALL_INT((int)dval); frac = frexp(dval, &expo); /* dval = frac*2**expo; 0.0 <= frac < 1.0 */ if (expo <= 0) return PyLong_FromLong(0L); @@ -801,6 +848,9 @@ #if SIZEOF_LONG_LONG < SIZEOF_VOID_P # error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)" #endif + /* special-case null pointer */ + if (!p) + return PyInt_FromLong(0); return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)p); } @@ -861,6 +911,7 @@ int ndigits = 0; int negative = 0; + CHECK_SMALL_INT(ival); if (ival < 0) { ival = -ival; negative = 1; @@ -897,6 +948,7 @@ unsigned PY_LONG_LONG t; int ndigits = 0; + CHECK_SMALL_INT(ival); /* Count the number of Python digits. */ t = (unsigned PY_LONG_LONG)ival; while (t) { @@ -922,6 +974,7 @@ { Py_ssize_t bytes = ival; int one = 1; + CHECK_SMALL_INT(ival); return _PyLong_FromByteArray( (unsigned char *)&bytes, SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1); @@ -934,6 +987,7 @@ { size_t bytes = ival; int one = 1; + CHECK_SMALL_INT(ival); return _PyLong_FromByteArray( (unsigned char *)&bytes, SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0); @@ -3402,29 +3456,30 @@ int _PyLong_Init(void) { - int ival; -#if 0 #if NSMALLNEGINTS + NSMALLPOSINTS > 0 - for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) { - if (!free_list && (free_list = fill_free_list()) == NULL) - return 0; - /* PyObject_New is inlined */ - v = free_list; - free_list = (PyIntObject *)v->ob_type; - PyObject_INIT(v, &PyInt_Type); - v->ob_ival = ival; - small_ints[ival + NSMALLNEGINTS] = v; + int ival; + PyLongObject *v = small_ints; + for (ival = -NSMALLNEGINTS; ival < 0; ival++, v++) { + PyObject_INIT(v, &PyLong_Type); + v->ob_size = -1; + v->ob_digit[0] = -ival; + } + for (; ival < NSMALLPOSINTS; ival++, v++) { + PyObject_INIT(v, &PyLong_Type); + v->ob_size = ival ? 1 : 0; + v->ob_digit[0] = ival; } #endif -#endif return 1; } void PyLong_Fini(void) { - int i; #if 0 + int i; + /* This is currently not needed; the small integers + are statically allocated */ #if NSMALLNEGINTS + NSMALLPOSINTS > 0 PyIntObject **q;
participants (1)
-
martin.v.loewis