Merged the int/long unification branch, by very crude means (sorry Thomas!).
I banged on the code (beyond what's in that branch) to make fewer tests fail;
the only tests that fail now are:
  test_descr -- can't pickle ints?!
  test_pickletools -- ???
  test_socket -- See python.org/sf/1619659
  test_sqlite -- ???
I'll deal with those later.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index a341eb4..e99acf9 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -219,7 +219,7 @@
 	if (src == NULL)
 		*target = dflt;
 	else {
-		if (!PyInt_Check(src)) {
+		if (!PyInt_CheckExact(src)) {
 			PyErr_Format(PyExc_TypeError, 
 				     "\"%s\" must be an integer", name);
 			return -1;
@@ -1410,7 +1410,7 @@
 	if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
 		return NULL;
 	if (new_limit != NULL) {
-		if (!PyInt_Check(new_limit)) {
+		if (!PyInt_CheckExact(new_limit)) {
 			PyErr_Format(PyExc_TypeError, 
 				     "limit must be an integer");
 			return NULL;
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index dc7feeb..319d15e 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -991,7 +991,7 @@
 		return NULL;
 
 	proto = PyDict_GetItemString(typedict, "_length_"); /* Borrowed ref */
-	if (!proto || !PyInt_Check(proto)) {
+	if (!proto || !PyInt_CheckExact(proto)) {
 		PyErr_SetString(PyExc_AttributeError,
 				"class must define a '_length_' attribute, "
 				"which must be a positive integer");
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 18e1991..572a9fc 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -496,12 +496,6 @@
 		return 0;
 	}
 
-	if (PyInt_Check(obj)) {
-		pa->ffi_type = &ffi_type_sint;
-		pa->value.i = PyInt_AS_LONG(obj);
-		return 0;
-	}
-
 	if (PyLong_Check(obj)) {
 		pa->ffi_type = &ffi_type_sint;
 		pa->value.i = (long)PyLong_AsUnsignedLong(obj);
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index aeb1ef5..19c3b26 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -193,7 +193,7 @@
 static int 
 PyCurses_ConvertToChtype(PyObject *obj, chtype *ch)
 {
-  if (PyInt_Check(obj)) {
+  if (PyInt_CheckExact(obj)) {
     *ch = (chtype) PyInt_AsLong(obj);
   } else if(PyString_Check(obj) 
 	    && (PyString_Size(obj) == 1)) {
@@ -2364,7 +2364,7 @@
 
   if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL;
 
-  if (PyInt_Check(temp))
+  if (PyInt_CheckExact(temp))
     ch = (chtype) PyInt_AsLong(temp);
   else if (PyString_Check(temp))
     ch = (chtype) *PyString_AsString(temp);
@@ -2386,7 +2386,7 @@
 
   if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL;
 
-  if (PyInt_Check(temp))
+  if (PyInt_CheckExact(temp))
     ch = (int) PyInt_AsLong(temp);
   else if (PyString_Check(temp))
     ch = (int) *PyString_AsString(temp);
diff --git a/Modules/_sre.c b/Modules/_sre.c
index a24f286..d402965 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -2688,8 +2688,7 @@
 
     for (i = 0; i < n; i++) {
         PyObject *o = PyList_GET_ITEM(code, i);
-        unsigned long value = PyInt_Check(o) ? (unsigned long)PyInt_AsLong(o)
-                                              : PyLong_AsUnsignedLong(o);
+        unsigned long value = PyLong_AsUnsignedLong(o);
         self->code[i] = (SRE_CODE) value;
         if ((unsigned long) self->code[i] != value) {
             PyErr_SetString(PyExc_OverflowError,
@@ -2763,6 +2762,10 @@
 {
     Py_ssize_t i;
 
+    if (index == NULL)
+	/* Default value */
+	return 0;
+
     if (PyInt_Check(index))
         return PyInt_AsSsize_t(index);
 
@@ -2913,7 +2916,7 @@
 {
     Py_ssize_t index;
 
-    PyObject* index_ = Py_False; /* zero */
+    PyObject* index_ = NULL;
     if (!PyArg_UnpackTuple(args, "start", 0, 1, &index_))
         return NULL;
 
@@ -2936,7 +2939,7 @@
 {
     Py_ssize_t index;
 
-    PyObject* index_ = Py_False; /* zero */
+    PyObject* index_ = NULL;
     if (!PyArg_UnpackTuple(args, "end", 0, 1, &index_))
         return NULL;
 
@@ -2986,7 +2989,7 @@
 {
     Py_ssize_t index;
 
-    PyObject* index_ = Py_False; /* zero */
+    PyObject* index_ = NULL;
     if (!PyArg_UnpackTuple(args, "span", 0, 1, &index_))
         return NULL;
 
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 8d0a3bc..518a57e 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -118,8 +118,6 @@
 	PyNumberMethods *m;
 
 	assert(v != NULL);
-	if (PyInt_Check(v))
-		return PyLong_FromLong(PyInt_AS_LONG(v));
 	if (PyLong_Check(v)) {
 		Py_INCREF(v);
 		return v;
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index b11f0ae..09bb4ff 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -718,6 +718,119 @@
 	Py_RETURN_NONE;
 }
 
+#ifdef HAVE_GETTIMEOFDAY
+/* Profiling of integer performance */
+void print_delta(int test, struct timeval *s, struct timeval *e)
+{
+	e->tv_sec -= s->tv_sec;
+	e->tv_usec -= s->tv_usec;
+	if (e->tv_usec < 0) {
+		e->tv_sec -=1;
+		e->tv_usec += 1000000;
+	}
+	printf("Test %d: %d.%06ds\n", test, (int)e->tv_sec, e->tv_usec);
+}
+
+static PyObject *
+profile_int(PyObject *self, PyObject* args)
+{
+	int i, k;
+	struct timeval start, stop;
+	PyObject *single, **multiple, *op1, *result;
+
+	/* Test 1: Allocate and immediately deallocate
+	   many small integers */
+	gettimeofday(&start, NULL);
+	for(k=0; k < 20000; k++)
+		for(i=0; i < 1000; i++) {
+			single = PyInt_FromLong(i);
+			Py_DECREF(single);
+		}
+	gettimeofday(&stop, NULL);
+	print_delta(1, &start, &stop);
+
+	/* Test 2: Allocate and immediately deallocate
+	   many large integers */
+	gettimeofday(&start, NULL);
+	for(k=0; k < 20000; k++)
+		for(i=0; i < 1000; i++) {
+			single = PyInt_FromLong(i+1000000);
+			Py_DECREF(single);
+		}
+	gettimeofday(&stop, NULL);
+	print_delta(2, &start, &stop);
+
+	/* Test 3: Allocate a few integers, then release
+	   them all simultaneously. */
+	multiple = malloc(sizeof(PyObject*) * 1000);
+	gettimeofday(&start, NULL);
+	for(k=0; k < 20000; k++) {
+		for(i=0; i < 1000; i++) {
+			multiple[i] = PyInt_FromLong(i+1000000);
+		}
+		for(i=0; i < 1000; i++) {
+			Py_DECREF(multiple[i]);
+		}
+	}
+	gettimeofday(&stop, NULL);
+	print_delta(3, &start, &stop);
+
+	/* Test 4: Allocate many integers, then release
+	   them all simultaneously. */
+	multiple = malloc(sizeof(PyObject*) * 1000000);
+	gettimeofday(&start, NULL);
+	for(k=0; k < 20; k++) {
+		for(i=0; i < 1000000; i++) {
+			multiple[i] = PyInt_FromLong(i+1000000);
+		}
+		for(i=0; i < 1000000; i++) {
+			Py_DECREF(multiple[i]);
+		}
+	}
+	gettimeofday(&stop, NULL);
+	print_delta(4, &start, &stop);
+
+	/* Test 5: Allocate many integers < 32000 */
+	multiple = malloc(sizeof(PyObject*) * 1000000);
+	gettimeofday(&start, NULL);
+	for(k=0; k < 10; k++) {
+		for(i=0; i < 1000000; i++) {
+			multiple[i] = PyInt_FromLong(i+1000);
+		}
+		for(i=0; i < 1000000; i++) {
+			Py_DECREF(multiple[i]);
+		}
+	}
+	gettimeofday(&stop, NULL);
+	print_delta(5, &start, &stop);
+
+	/* Test 6: Perform small int addition */
+	op1 = PyInt_FromLong(1);
+	gettimeofday(&start, NULL);
+	for(i=0; i < 10000000; i++) {
+		result = PyNumber_Add(op1, op1);
+		Py_DECREF(result);
+	}
+	gettimeofday(&stop, NULL);
+	Py_DECREF(op1);
+	print_delta(6, &start, &stop);
+
+	/* Test 7: Perform medium int addition */
+	op1 = PyInt_FromLong(1000);
+	gettimeofday(&start, NULL);
+	for(i=0; i < 10000000; i++) {
+		result = PyNumber_Add(op1, op1);
+		Py_DECREF(result);
+	}
+	gettimeofday(&stop, NULL);
+	Py_DECREF(op1);
+	print_delta(7, &start, &stop);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+#endif
+
 static PyMethodDef TestMethods[] = {
 	{"raise_exception",	raise_exception,		 METH_VARARGS},
 	{"test_config",		(PyCFunction)test_config,	 METH_NOARGS},
@@ -756,6 +869,9 @@
 #ifdef WITH_THREAD
 	{"_test_thread_state",  test_thread_state, 		 METH_VARARGS},
 #endif
+#ifdef HAVE_GETTIMEOFDAY
+	{"profile_int",		profile_int,			METH_NOARGS},
+#endif
 	{NULL, NULL} /* sentinel */
 };
 
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 4347383..7be7002 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -913,7 +913,7 @@
 					PyString_GET_SIZE(value));
 	else if (PyBool_Check(value))
 		return Tcl_NewBooleanObj(PyObject_IsTrue(value));
-	else if (PyInt_Check(value))
+	else if (PyInt_CheckExact(value))
 		return Tcl_NewLongObj(PyInt_AS_LONG(value));
 	else if (PyFloat_Check(value))
 		return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index f3178ab..4c55428 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -711,7 +711,9 @@
 		PyErr_SetString(PicklingError, "no int where int expected in memo");
 		return -1;
 	}
-	c_value = PyInt_AS_LONG((PyIntObject*)value);
+	c_value = PyInt_AsLong(value);
+	if (c_value == -1 && PyErr_Occurred())
+		return -1;
 
 	if (!self->bin) {
 		s[0] = GET;
@@ -958,7 +960,7 @@
 {
 	static const char *buf[2] = {FALSE, TRUE};
 	static char len[2] = {sizeof(FALSE)-1, sizeof(TRUE)-1};
-	long l = PyInt_AS_LONG((PyIntObject *)args);
+	long l = args == Py_True;
 
 	if (self->proto >= 2) {
 		char opcode = l ? NEWTRUE : NEWFALSE;
@@ -971,10 +973,9 @@
 }
 
 static int
-save_int(Picklerobject *self, PyObject *args)
+save_int(Picklerobject *self, long l)
 {
 	char c_str[32];
-	long l = PyInt_AS_LONG((PyIntObject *)args);
 	int len = 0;
 
 	if (!self->bin
@@ -1027,9 +1028,16 @@
 	Py_ssize_t size;
 	int res = -1;
 	PyObject *repr = NULL;
-
+	int val = PyInt_AsLong(args);
 	static char l = LONG;
 
+	if (val == -1 && PyErr_Occurred()) {
+		/* out of range for int pickling */
+		PyErr_Clear();
+	}
+	else
+		return save_int(self, val);
+
 	if (self->proto >= 2) {
 		/* Linear-time pickling. */
 		size_t nbits;
@@ -2183,13 +2191,6 @@
 			goto finally;
 		}
 		break;
-        case 'i':
-		if (type == &PyInt_Type) {
-			res = save_int(self, args);
-			goto finally;
-		}
-		break;
-
         case 'l':
 		if (type == &PyLong_Type) {
 			res = save_long(self, args);
@@ -2486,7 +2487,9 @@
 			rsize += PyString_GET_SIZE(k);
 
 		else if (PyInt_Check(k)) { /* put */
-			ik = PyInt_AS_LONG((PyIntObject*)k);
+			ik = PyInt_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik >= lm || ik == 0) {
 				PyErr_SetString(PicklingError,
 						"Invalid get data");
@@ -2506,7 +2509,9 @@
 		}
 
 		else { /* put */
-			ik = PyInt_AS_LONG((PyIntObject *)k);
+			ik = PyInt_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik >= lm || ik == 0) {
 				PyErr_SetString(PicklingError,
 						"Invalid get data");
@@ -2535,8 +2540,9 @@
 		}
 
 		else if (PyTuple_Check(k)) { /* get */
-			ik = PyInt_AS_LONG((PyIntObject *)
-					    PyTuple_GET_ITEM(k, 0));
+			ik = PyLong_AsLong(PyTuple_GET_ITEM(k, 0));
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik < 256) {
 				*s++ = BINGET;
 				*s++ = (int)(ik & 0xff);
@@ -2551,7 +2557,9 @@
 		}
 
 		else { /* put */
-			ik = PyInt_AS_LONG((PyIntObject*)k);
+			ik = PyLong_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 
 			if (have_get[ik]) { /* with matching get */
 				if (ik < 256) {
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 7c6b989..42178ff 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -1314,6 +1314,9 @@
 		return NULL;
 	}
 
+	if (size == -1 && PyErr_Occurred())
+		return NULL;
+
 	return mbstreamreader_iread(self, "read", size);
 }
 
@@ -1335,6 +1338,9 @@
 		return NULL;
 	}
 
+	if (size == -1 && PyErr_Occurred())
+		return NULL;
+
 	return mbstreamreader_iread(self, "readline", size);
 }
 
@@ -1356,6 +1362,9 @@
 		return NULL;
 	}
 
+	if (sizehint == -1 && PyErr_Occurred())
+		return NULL;
+
 	r = mbstreamreader_iread(self, "read", sizehint);
 	if (r == NULL)
 		return NULL;
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 7ffa316..3757513 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -1844,10 +1844,7 @@
 		 * lose a little info.
 		 */
 		assert(PyInt_Check(factor) || PyLong_Check(factor));
-		if (PyInt_Check(factor))
-			dnum = (double)PyInt_AsLong(factor);
-		else
-			dnum = PyLong_AsDouble(factor);
+		dnum = PyLong_AsDouble(factor);
 
 		dnum *= fracpart;
 		fracpart = modf(dnum, &intpart);
@@ -3800,7 +3797,7 @@
 					Py_DECREF(obj);
 					return NULL;
 				}
-				if (PyInt_Check(p))
+				if (PyInt_CheckExact(p))
 					ia[i] = PyInt_AsLong(p);
 				else
 					good_timetuple = 0;
diff --git a/Modules/dlmodule.c b/Modules/dlmodule.c
index 5622ed9..4af7e30 100644
--- a/Modules/dlmodule.c
+++ b/Modules/dlmodule.c
@@ -107,9 +107,11 @@
 	}
 	for (i = 1; i < n; i++) {
 		PyObject *v = PyTuple_GetItem(args, i);
-		if (PyInt_Check(v))
+		if (PyInt_Check(v)) {
 			alist[i-1] = PyInt_AsLong(v);
-		else if (PyString_Check(v))
+			if (alist[i-1] == -1 && PyErr_Occurred())
+				return NULL;
+		} else if (PyString_Check(v))
 			alist[i-1] = (long)PyString_AsString(v);
 		else if (v == Py_None)
 			alist[i-1] = (long) ((char *)NULL);
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3260c3d..f8df0c4 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -5437,32 +5437,21 @@
 		elem = PySequence_GetItem(groups, i);
 		if (!elem)
 			return NULL;
-		if (!PyInt_Check(elem)) {
-			if (!PyLong_Check(elem)) {
-				PyErr_SetString(PyExc_TypeError,
-						"groups must be integers");
+		if (!PyLong_Check(elem)) {
+			PyErr_SetString(PyExc_TypeError,
+					"groups must be integers");
+			Py_DECREF(elem);
+			return NULL;
+		} else {
+			unsigned long x = PyLong_AsUnsignedLong(elem);
+			if (PyErr_Occurred()) {
+				PyErr_SetString(PyExc_TypeError, 
+						"group id too big");
 				Py_DECREF(elem);
 				return NULL;
-			} else {
-				unsigned long x = PyLong_AsUnsignedLong(elem);
-				if (PyErr_Occurred()) {
-					PyErr_SetString(PyExc_TypeError, 
-							"group id too big");
-					Py_DECREF(elem);
-					return NULL;
-				}
-				grouplist[i] = x;
-				/* read back the value to see if it fitted in gid_t */
-				if (grouplist[i] != x) {
-					PyErr_SetString(PyExc_TypeError,
-							"group id too big");
-					Py_DECREF(elem);
-					return NULL;
-				}
 			}
-		} else {
-			long x  = PyInt_AsLong(elem);
 			grouplist[i] = x;
+			/* read back the value to see if it fitted in gid_t */
 			if (grouplist[i] != x) {
 				PyErr_SetString(PyExc_TypeError,
 						"group id too big");
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 8ec0ed7..31efa0a 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -3483,12 +3483,7 @@
 {
 	unsigned long x;
 
-	if (PyInt_Check(arg)) {
-		x = PyInt_AS_LONG(arg);
-		if (x == (unsigned long) -1 && PyErr_Occurred())
-			return NULL;
-	}
-	else if (PyLong_Check(arg)) {
+	if (PyLong_Check(arg)) {
 		x = PyLong_AsUnsignedLong(arg);
 		if (x == (unsigned long) -1 && PyErr_Occurred())
 			return NULL;
@@ -3542,12 +3537,7 @@
 {
 	unsigned long x;
 
-	if (PyInt_Check(arg)) {
-		x = PyInt_AS_LONG(arg);
-		if (x == (unsigned long) -1 && PyErr_Occurred())
-			return NULL;
-	}
-	else if (PyLong_Check(arg)) {
+	if (PyLong_Check(arg)) {
 		x = PyLong_AsUnsignedLong(arg);
 		if (x == (unsigned long) -1 && PyErr_Occurred())
 			return NULL;
@@ -3827,7 +3817,7 @@
 				"getaddrinfo() argument 1 must be string or None");
 		return NULL;
 	}
-	if (PyInt_Check(pobj)) {
+	if (PyInt_CheckExact(pobj)) {
 		PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", PyInt_AsLong(pobj));
 		pptr = pbuf;
 	} else if (PyString_Check(pobj)) {
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 9ab2724..13c0535 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -357,7 +357,7 @@
 	if (y < 1900) {
 		PyObject *accept = PyDict_GetItemString(moddict,
 							"accept2dyear");
-		if (accept == NULL || !PyInt_Check(accept) ||
+		if (accept == NULL || !PyInt_CheckExact(accept) ||
 		    PyInt_AsLong(accept) == 0) {
 			PyErr_SetString(PyExc_ValueError,
 					"year >= 1900 required");