[Python-checkins] r51509 - python/branches/int_unification/Objects/longobject.c

martin.v.loewis python-checkins at python.org
Wed Aug 23 18:24:46 CEST 2006


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;
 


More information about the Python-checkins mailing list