diff -r 9be7289dca60 Objects/longobject.c --- a/Objects/longobject.c Thu Sep 20 17:25:18 2012 -0400 +++ b/Objects/longobject.c Sat Sep 22 02:05:31 2012 +0200 @@ -23,12 +23,22 @@ #define ABS(x) ((x) < 0 ? -(x) : (x)) #if NSMALLNEGINTS + NSMALLPOSINTS > 0 +typedef struct { + PyLongObject base; + /* cache result of long_to_decimal_string */ + PyObject *str; +} _PySmallIntObject; + /* 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]; +static _PySmallIntObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS]; + +#define IS_SMALL_INT(ob) (&small_ints[0] <= (_PySmallIntObject*)(ob) \ + && (_PySmallIntObject*)(ob) < &small_ints[NSMALLNEGINTS + NSMALLPOSINTS]) + #ifdef COUNT_ALLOCS Py_ssize_t quick_int_allocs, quick_neg_int_allocs; #endif @@ -1701,18 +1711,40 @@ long_to_decimal_string_internal(PyObject } else { assert(_PyUnicode_CheckConsistency(str, 1)); - *p_output = (PyObject *)str; + *p_output = str; } return 0; } static PyObject * -long_to_decimal_string(PyObject *aa) +long_to_decimal_string(PyObject *ob) { - PyObject *v; - if (long_to_decimal_string_internal(aa, &v, NULL) == -1) - return NULL; - return v; + PyObject *str; + + if (!IS_SMALL_INT(ob)) { + if (long_to_decimal_string_internal(ob, &str, NULL) == -1) + return NULL; + } + else { + _PySmallIntObject *small = (_PySmallIntObject *)ob; + if (small->str == NULL) { + int ival = (int)(small - small_ints) - NSMALLNEGINTS; + if (0 <= ival && ival <= 9) { + /* call PyUnicode_FromOrdinal() to get Unicode singletons */ + str = PyUnicode_FromOrdinal('0' + ival); + } + else { + if (long_to_decimal_string_internal(ob, &str, NULL) == -1) + return NULL; + } + small->str = str; + } + else { + str = small->str; + } + Py_INCREF(str); + } + return str; } /* Convert a long int object to a string, using a given conversion base, @@ -4982,10 +5014,12 @@ int { #if NSMALLNEGINTS + NSMALLPOSINTS > 0 int ival, size; - PyLongObject *v = small_ints; - - for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, v++) { + _PySmallIntObject *small = small_ints; + PyLongObject *v; + + for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, small++) { size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); + v = &small->base; if (Py_TYPE(v) == &PyLong_Type) { /* The element is already initialized, most likely * the Python interpreter was initialized before. @@ -5007,6 +5041,7 @@ int } Py_SIZE(v) = size; v->ob_digit[0] = abs(ival); + ((_PySmallIntObject *)v)->str = NULL; } #endif /* initialize int_info */ @@ -5024,7 +5059,7 @@ PyLong_Fini(void) reinitializations will fail. */ #if NSMALLNEGINTS + NSMALLPOSINTS > 0 int i; - PyLongObject *v = small_ints; + _PySmallIntObject *v = small_ints; for (i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++, v++) { _Py_DEC_REFTOTAL; _Py_ForgetReference((PyObject*)v); diff -r 9be7289dca60 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Thu Sep 20 17:25:18 2012 -0400 +++ b/Objects/unicodeobject.c Sat Sep 22 02:05:31 2012 +0200 @@ -13289,11 +13289,7 @@ formatlong(PyObject *val, int flags, int switch (type) { case 'd': case 'u': - /* Special-case boolean: we want 0/1 */ - if (PyBool_Check(val)) - result = PyNumber_ToBase(val, 10); - else - result = Py_TYPE(val)->tp_str(val); + result = PyNumber_ToBase(val, 10); break; case 'o': numnondigits = 2;