Index: Include/object.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/object.h,v
retrieving revision 2.78
diff -u -u -r2.78 object.h
--- Include/object.h	2001/04/20 19:13:01	2.78
+++ Include/object.h	2001/04/22 16:27:18
@@ -253,6 +253,9 @@
 	/* Iterators */
 	getiterfunc tp_iter;
 
+	/* type ordinal */
+	int tp_ord;
+
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	int tp_alloc;
@@ -366,6 +369,17 @@
 
 #define PyType_HasFeature(t,f)  (((t)->tp_flags & (f)) != 0)
 
+
+#define PyType_UNKNOWN 0
+#define PyType_NONE 1
+#define PyType_INT 2
+#define PyType_FLOAT 3
+#define PyType_STRING 4
+#define PyType_LIST 5
+#define PyType_TUPLE 6
+
+#define PyType_Ord(t) ((t)->tp_ord)
+#define PyObject_TypeOrd(o) PyType_Ord((o)->ob_type)
 
 /*
 The macros Py_INCREF(op) and Py_DECREF(op) are used to increment or decrement
Index: Objects/dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.79
diff -u -u -r2.79 dictobject.c
--- Objects/dictobject.c	2001/04/20 19:13:02	2.79
+++ Objects/dictobject.c	2001/04/22 16:27:40
@@ -150,6 +150,83 @@
 	return (PyObject *)mp;
 }
 
+int
+int_cmp_eq(PyObject *v, PyObject *w)
+{
+	if (PyInt_Check(w)) {
+            long a = PyInt_AS_LONG(v);
+            long b = PyInt_AS_LONG(w);
+	    return a == b;
+	}
+	else
+		return PyObject_RichCompareBool(v, w, Py_EQ);
+}
+
+int
+string_cmp_eq(PyObject *v, PyObject *w)
+{
+	if (PyString_Check(w)) {
+		PyStringObject *a = (PyStringObject *)v;
+		PyStringObject *b = (PyStringObject *)w;
+                if (a == b) {
+                    return 1;
+                }
+                else {
+                    if (a->ob_size != b->ob_size)
+                        return 0;
+                    else
+                        return 0 == memcmp(a->ob_sval, b->ob_sval, a->ob_size);
+                }
+	}
+	else
+		return PyObject_RichCompareBool(v, w, Py_EQ);
+}
+
+int
+tuple_cmp_eq(PyObject *v, PyObject *w)
+{
+	if (PyTuple_Check(v)) {
+		int i;
+		PyTupleObject *vt, *wt;
+		vt = (PyTupleObject *)v;
+		wt = (PyTupleObject *)w;
+
+		if (vt->ob_size != wt->ob_size)
+			return 0;
+
+		/* Search for the first index where items are different */
+		for (i = 0; i < vt->ob_size && i < wt->ob_size; i++) {
+			int k = PyObject_RichCompareBool(vt->ob_item[i],
+							 wt->ob_item[i], Py_EQ);
+			if (k != 1)
+				return k;
+		}
+		return 1;
+	}
+	else
+		return PyObject_RichCompareBool(v, w, Py_EQ);
+
+}
+
+
+int cmp_eq(PyObject *v, PyObject *w)
+{
+	return PyObject_RichCompareBool(v, w, Py_EQ);
+}
+
+objobjproc cmp_bool[] =  {
+	cmp_eq,			/* PyType_UNKNOWN */
+	cmp_eq, 		/* PyType_NONE */
+	int_cmp_eq, 		/* PyType_INT */
+	cmp_eq,			/* PyType_FLOAT */
+	string_cmp_eq,		/* PyType_STRING */
+	cmp_eq,			/* PyType_LIST */
+	tuple_cmp_eq,		/* PyType_TUPLE */
+};
+
+#define CmpEq(v, w) (cmp_bool[PyObject_TypeOrd(v)](v, w))
+//#define CmpEq(v, w) PyObject_RichCompareBool(v, w, Py_EQ)
+
 /*
 The basic lookup function used by all operations.
 This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
@@ -207,7 +284,7 @@
 				restore_error = 1;
 				PyErr_Fetch(&err_type, &err_value, &err_tb);
 			}
-			cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
+			cmp = CmpEq(ep->me_key, key);
 			if (cmp > 0) {
 				if (restore_error)
 					PyErr_Restore(err_type, err_value,
@@ -252,7 +329,7 @@
 						    &err_tb);
 				}
 			}
-			cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
+			cmp = CmpEq(ep->me_key, key);
 			if (cmp > 0) {
 				if (restore_error)
 					PyErr_Restore(err_type, err_value,
@@ -289,7 +366,6 @@
 	register unsigned int mask = mp->ma_size-1;
 	dictentry *ep0 = mp->ma_table;
 	register dictentry *ep;
-	cmpfunc compare = PyString_Type.tp_compare;
 
 	/* make sure this function doesn't have to handle non-string keys */
 	if (!PyString_Check(key)) {
@@ -312,7 +388,7 @@
 		freeslot = ep;
 	else {
 		if (ep->me_hash == hash
-		    && compare(ep->me_key, key) == 0) {
+		    && string_cmp_eq(ep->me_key, key)) {
 			return ep;
 		}
 		freeslot = NULL;
@@ -336,7 +412,7 @@
 		}
 		else if (ep->me_key == key
 			 || (ep->me_hash == hash
-			     && compare(ep->me_key, key) == 0)) {
+			     && string_cmp_eq(ep->me_key, key))) {
 			return ep;
 		}
 		/* Cycle through GF(2^n)-{0} */
@@ -1006,7 +1082,7 @@
 			if (bval == NULL)
 				cmp = 0;
 			else {
-			    cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
+			    cmp = CmpEq(aval, bval);
 			    if (cmp < 0)
 				return NULL;
 			}
Index: Objects/floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.81
diff -u -u -r2.81 floatobject.c
--- Objects/floatobject.c	2001/03/11 08:37:29	2.81
+++ Objects/floatobject.c	2001/04/22 16:27:44
@@ -682,7 +682,14 @@
 	0,			/*tp_getattro*/
 	0,			/*tp_setattro*/
 	0,			/*tp_as_buffer*/
-	Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
+	Py_TPFLAGS_CHECKTYPES,	/*tp_flags*/
+	0,		/*tp_doc*/
+	0,		/*tp_traverse*/
+	0,		/*tp_clear*/
+	0,		/*tp_richcompare*/
+	0,		/*tp_weaklistoffset*/
+	0,		/*tp_iter*/
+	PyType_FLOAT,	/*tp_ord*/
 };
 
 void
Index: Objects/intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.56
diff -u -u -r2.56 intobject.c
--- Objects/intobject.c	2001/03/06 12:12:02	2.56
+++ Objects/intobject.c	2001/04/22 16:27:47
@@ -808,7 +808,15 @@
 	0,			/*tp_getattro*/
 	0,			/*tp_setattro*/
 	0,			/*tp_as_buffer*/
-	Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
+	Py_TPFLAGS_CHECKTYPES,	/*tp_flags*/
+	0,		/*tp_doc*/
+	0,		/*tp_traverse*/
+	0,		/*tp_clear*/
+	0,		/*tp_richcompare*/
+	0,		/*tp_weaklistoffset*/
+	0,		/*tp_iter*/
+	PyType_INT,	/*tp_ord*/
+
 };
 
 void
Index: Objects/listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92
diff -u -u -r2.92 listobject.c
--- Objects/listobject.c	2001/02/12 22:06:02	2.92
+++ Objects/listobject.c	2001/04/22 16:27:55
@@ -1567,6 +1567,9 @@
  	(traverseproc)list_traverse,		/* tp_traverse */
  	(inquiry)list_clear,			/* tp_clear */
 	list_richcompare,			/* tp_richcompare */
+	0,					/*tp_weaklistoffset*/
+	0,					/*tp_iter*/
+	PyType_LIST,				/*tp_ord*/
 };
 
 
Index: Objects/object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.124
diff -u -u -r2.124 object.c
--- Objects/object.c	2001/03/25 19:16:13	2.124
+++ Objects/object.c	2001/04/22 16:28:01
@@ -1271,6 +1271,19 @@
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
 	0,		/*tp_hash */
+        0,		/*tp_call*/
+        0,		/*tp_str*/
+	0,		/*tp_getattro*/
+	0,		/*tp_setattro*/
+	0,		/*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,		/*tp_doc*/
+	0,		/*tp_traverse*/
+	0,		/*tp_clear*/
+	0,		/*tp_richcompare*/
+	0,		/*tp_weaklistoffset*/
+	0,		/*tp_iter*/
+	PyType_NONE,	/*tp_ord*/
 };
 
 PyObject _Py_NoneStruct = {
Index: Objects/stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.103
diff -u -u -r2.103 stringobject.c
--- Objects/stringobject.c	2001/04/20 19:13:02	2.103
+++ Objects/stringobject.c	2001/04/22 16:28:14
@@ -2380,6 +2380,12 @@
 	&string_as_buffer,	/*tp_as_buffer*/
 	Py_TPFLAGS_DEFAULT,	/*tp_flags*/
 	0,		/*tp_doc*/
+	0,		/*tp_traverse*/
+	0,		/*tp_clear*/
+	0,		/*tp_richcompare*/
+	0,		/*tp_weaklistoffset*/
+	0,		/*tp_iter*/
+	PyType_STRING,	/*tp_ord*/
 };
 
 void
Index: Objects/tupleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.48
diff -u -u -r2.48 tupleobject.c
--- Objects/tupleobject.c	2001/01/18 00:00:53	2.48
+++ Objects/tupleobject.c	2001/04/22 16:28:15
@@ -480,6 +480,9 @@
  	(traverseproc)tupletraverse,		/* tp_traverse */
 	0,					/* tp_clear */
 	tuplerichcompare,			/* tp_richcompare */
+	0,					/*tp_weaklistoffset*/
+	0,					/*tp_iter*/
+	PyType_TUPLE,				/*tp_ord*/
 };
 
 /* The following function breaks the notion that tuples are immutable:
Index: Python/ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.240
diff -u -u -r2.240 ceval.c
--- Python/ceval.c	2001/04/21 02:46:11	2.240
+++ Python/ceval.c	2001/04/22 16:28:30
@@ -67,7 +67,6 @@
 static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
 static int assign_slice(PyObject *, PyObject *,
 			PyObject *, PyObject *);
-static PyObject *cmp_outcome(int, PyObject *, PyObject *);
 static PyObject *import_from(PyObject *, PyObject *);
 static int import_all_from(PyObject *, PyObject *);
 static PyObject *build_class(PyObject *, PyObject *, PyObject *);
@@ -347,6 +346,461 @@
 }
 
 
+static PyObject *
+slow_cmp(PyObject *v, PyObject *w, int op)
+{
+    register int res = 0;
+    switch (op) {
+    case IS:
+    case IS_NOT:
+            res = (v == w);
+            if (op == (int) IS_NOT)
+                    res = !res;
+            break;
+    case IN:
+    case NOT_IN:
+            res = PySequence_Contains(w, v);
+            if (res < 0)
+                    return NULL;
+            if (op == (int) NOT_IN)
+                    res = !res;
+            break;
+    case EXC_MATCH:
+            res = PyErr_GivenExceptionMatches(v, w);
+            break;
+    default:
+            return PyObject_RichCompare(v, w, op);
+    }
+    v = res ? Py_True : Py_False;
+    Py_INCREF(v);
+    return v;
+}
+
+#define slow_add PyNumber_Add
+#define slow_sub PyNumber_Subtract
+#define slow_iadd PyNumber_InPlaceAdd
+#define slow_isub PyNumber_InPlaceSubtract
+#define slow_getitem PyObject_GetItem
+
+static PyObject *
+int_add(PyObject *v, PyObject *w)
+{
+    register long a, b, i;
+    switch (PyObject_TypeOrd(w)) {
+        case PyType_INT:
+            a = PyInt_AS_LONG(v);
+            b = PyInt_AS_LONG(w);
+            i = a + b;
+            if ((i^a) < 0 && (i^b) < 0) {
+                PyErr_SetString(PyExc_OverflowError, "integer addition");
+                return NULL;
+            }
+            else
+                return PyInt_FromLong(i);
+            break;
+        case PyType_FLOAT:
+            return w->ob_type->tp_as_number->nb_add(v, w);
+    }
+    return slow_add(v, w);
+}
+#define int_iadd int_add
+
+static PyObject *
+int_sub(PyObject *v, PyObject *w)
+{
+    register long a, b, i;
+    switch (PyObject_TypeOrd(w)) {
+        case PyType_INT:
+            a = PyInt_AS_LONG(v);
+            b = PyInt_AS_LONG(w);
+            i = a - b;
+            if ((i^a) < 0 && (i^~b) < 0) {
+                PyErr_SetString(PyExc_OverflowError, "integer subtraction");
+                return NULL;
+            }
+            else
+                return PyInt_FromLong(i);
+        case PyType_FLOAT:
+            return w->ob_type->tp_as_number->nb_subtract(v, w);
+    }
+    return slow_sub(v, w);
+}
+#define int_isub int_sub
+
+static PyObject *
+int_cmp(PyObject *v, PyObject *w, int op)
+{
+    register long a, b;
+    register int res = 0;
+    switch (PyObject_TypeOrd(w)) {
+        case PyType_INT:
+            a = PyInt_AS_LONG(v);
+            b = PyInt_AS_LONG(w);
+            switch (op) {
+                case LT: res = a <  b; break;
+                case LE: res = a <= b; break;
+                case EQ: res = a == b; break;
+                case NE: res = a != b; break;
+                case GT: res = a >  b; break;
+                case GE: res = a >= b; break;
+                case IS: res = v == w; break;
+                case IS_NOT: res = v != w; break;
+                default: goto slow;
+            }
+            break;
+        case PyType_NONE:
+            switch (op) {
+                case EQ:
+                case IS:
+                case GT:
+                case GE:
+                    res = 0;
+                    break;
+                case NE:
+                case IS_NOT:
+                case LT:
+                case LE:
+                    res = 1;
+                    break;
+                default: goto slow;
+            }
+            break;
+        default:
+            goto slow;
+    }
+    v = res ? Py_True : Py_False;
+    Py_INCREF(v);
+    return v;
+slow:
+    return slow_cmp(v, w, op);
+}
+
+static PyObject *
+float_add(PyObject *v, PyObject *w)
+{
+    switch (PyObject_TypeOrd(w)) {
+        case PyType_INT:
+            return v->ob_type->tp_as_number->nb_add(v, w);
+        case PyType_FLOAT:
+            return v->ob_type->tp_as_number->nb_add(v, w);
+    }
+    return slow_add(v, w);
+}
+#define float_iadd float_add
+
+static PyObject *
+float_sub(PyObject *v, PyObject *w)
+{
+    switch (PyObject_TypeOrd(w)) {
+        case PyType_INT:
+            return v->ob_type->tp_as_number->nb_subtract(v, w);
+        case PyType_FLOAT:
+            return v->ob_type->tp_as_number->nb_subtract(v, w);
+    }
+    return slow_sub(v, w);
+}
+#define float_isub float_sub
+
+
+static PyObject *
+none_cmp(PyObject *v, PyObject *w, int op)
+{
+    int res = 0;
+    if (w == Py_None) {
+        switch (op) {
+            case EQ:
+            case IS:
+            case LE:
+            case GE:
+                res = 1;
+                break;
+            case NE:
+            case IS_NOT:
+            case LT:
+            case GT:
+                res = 0;
+                break;
+            default:
+                return slow_cmp(v, w, op);
+        }
+    } else {
+        switch (op) {
+            case EQ:
+            case IS:
+            case GT:
+            case GE:
+                res = 0;
+                break;
+            case NE:
+            case IS_NOT:
+            case LT:
+            case LE:
+                res = 1;
+                break;
+            default:
+                return slow_cmp(v, w, op);
+        }
+    }
+    v = res ? Py_True : Py_False;
+    Py_INCREF(v);
+    return v;
+}
+
+static PyObject *
+list_getitem(PyObject *v, PyObject *w)
+{
+    if (PyInt_Check(w)) {
+        long i = PyInt_AsLong(w);
+        if (i < 0)
+            i += PyList_GET_SIZE(v);
+        if (i < 0 ||
+                i >= PyList_GET_SIZE(v)) {
+            PyErr_SetString(PyExc_IndexError,
+                    "list index out of range");
+            return NULL;
+        }
+        else {
+            v = PyList_GET_ITEM(v, i);
+            Py_INCREF(v);
+            return v;
+        }
+    }
+    else {
+        return slow_getitem(v, w);
+    }
+}
+
+static PyObject *
+string_add(PyObject *v, PyObject *w)
+{
+    if (PyString_Check(w)) {
+        unsigned int size;
+        PyStringObject *op;
+        PyStringObject *a = (PyStringObject *)v;
+        PyStringObject *b = (PyStringObject *)w;
+
+        /* Optimize cases with empty left or right operand */
+        if (a->ob_size == 0) {
+            Py_INCREF(b);
+            return (PyObject *)b;
+        }
+        if (b->ob_size == 0) {
+            Py_INCREF(a);
+            return (PyObject *)a;
+        }
+        size = a->ob_size + b->ob_size;
+        /* PyObject_NewVar is inlined */
+        op = (PyStringObject *)
+            PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
+        if (op == NULL)
+            return PyErr_NoMemory();
+        PyObject_INIT_VAR(op, &PyString_Type, size);
+#ifdef CACHE_HASH
+        op->ob_shash = -1;
+#endif
+#ifdef INTERN_STRINGS
+        op->ob_sinterned = NULL;
+#endif
+        memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
+        memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
+        op->ob_sval[size] = '\0';
+        return (PyObject *) op;
+    }
+    else {
+        return slow_add(v, w);
+    }
+}
+
+
+static PyObject *
+string_cmp(PyObject *v, PyObject *w, int op)
+{
+    if (PyString_Check(w)) {
+        int res;
+        PyStringObject *a = (PyStringObject *)v;
+        PyStringObject *b = (PyStringObject *)w;
+        /*
+#ifdef INTERN_STRINGS
+        if (a->ob_sinterned != NULL)
+            a = (PyStringObject *)a->ob_sinterned;
+        if (b->ob_sinterned != NULL)
+            b = (PyStringObject *)b->ob_sinterned;
+#endif
+        */
+        switch (op) {
+            case EQ:
+            case NE:
+                if (a == b) {
+                    res = 1;
+                }
+                else {
+                    if (a->ob_size != b->ob_size)
+                        res = 0;
+                    else
+                        res = 0 == memcmp(a->ob_sval, b->ob_sval, a->ob_size);
+                }
+        	if (op == NE) res = !res;
+                break;
+            case IS:
+                res = a == b;
+                break;
+            case IS_NOT:
+                res = a != b;
+                break;
+            default:
+                return slow_cmp(v, w, op);
+        }
+        v = res ? Py_True : Py_False;
+        Py_INCREF(v);
+        return v;
+    }
+    else {
+        return slow_cmp(v, w, op);
+    }
+
+}
+
+static PyObject *
+tuple_getitem(PyObject *v, PyObject *w)
+{
+    PyTupleObject *a = (PyTupleObject *)v;
+    if (PyInt_Check(w)) {
+        long i = PyInt_AsLong(w);
+	if (i < 0 || i >= a->ob_size) {
+		PyErr_SetString(PyExc_IndexError, "tuple index out of range");
+		return NULL;
+	}
+	Py_INCREF(a->ob_item[i]);
+	return a->ob_item[i];
+    }
+    else {
+        return slow_getitem(v, w);
+    }
+}
+
+#define slow_istrue PyObject_IsTrue
+
+int
+int_istrue(PyObject *v)
+{
+    return ((PyIntObject *)v)->ob_ival != 0;
+}
+
+int
+none_istrue(PyObject *v)
+{
+    return 0;
+}
+
+int
+list_istrue(PyObject *v)
+{
+    return ((PyListObject *)v)->ob_size > 0;
+}
+
+int
+string_istrue(PyObject *v)
+{
+    return ((PyStringObject *)v)->ob_size > 0;
+}
+
+int
+tuple_istrue(PyObject *v)
+{
+    return ((PyTupleObject *)v)->ob_size > 0;
+}
+
+struct {
+    inquiry istrue;
+    binaryfunc add;
+    binaryfunc inplace_add;
+    binaryfunc sub;
+    binaryfunc inplace_sub;
+    binaryfunc getitem;
+    richcmpfunc cmp;
+} fast_op_table [] = {
+
+    /* PyType_UNKNOWN */
+    {
+        slow_istrue,
+        slow_add,
+        slow_iadd,
+        slow_sub,
+        slow_isub,
+        slow_getitem,
+        slow_cmp,
+    },
+    
+    /* PyType_NONE */
+    {
+        none_istrue,
+        slow_add,
+        slow_iadd,
+        slow_sub,
+        slow_isub,
+        slow_getitem,
+        none_cmp,
+    },
+
+    /* PyType_INT */
+    {
+        int_istrue,
+        int_add,
+        int_iadd,
+        int_sub,
+        int_isub,
+        slow_getitem,
+        int_cmp,
+    },
+
+    /* PyType_FLOAT */
+    {
+        slow_istrue,
+        float_add,
+        float_iadd,
+        float_sub,
+        float_isub,
+        slow_getitem,
+        slow_cmp,
+    },
+
+    /* PyType_STRING */
+    {
+        string_istrue,
+        string_add,
+        slow_iadd,
+        slow_sub,
+        slow_isub,
+        slow_getitem,
+        string_cmp,
+    },
+
+    /* PyType_LIST */
+    {
+        list_istrue,
+        slow_add,
+        slow_iadd,
+        slow_sub,
+        slow_isub,
+        list_getitem,
+        slow_cmp,
+    },
+
+    /* PyType_TUPLE */
+    {
+        tuple_istrue,
+        slow_add,
+        slow_iadd,
+        slow_sub,
+        slow_isub,
+        tuple_getitem,
+        slow_cmp,
+    }
+};
+
+#define LookupOp(v) fast_op_table[PyObject_TypeOrd(v)]
+
+
 /* Interpreter main loop */
 
 static PyObject *
@@ -904,7 +1358,7 @@
 
 		case UNARY_NOT:
 			v = POP();
-			err = PyObject_IsTrue(v);
+			err = LookupOp(v).istrue(v);
 			Py_DECREF(v);
 			if (err == 0) {
 				Py_INCREF(Py_True);
@@ -978,22 +1432,7 @@
 		case BINARY_ADD:
 			w = POP();
 			v = POP();
-			if (PyInt_Check(v) && PyInt_Check(w)) {
-				/* INLINE: int + int */
-				register long a, b, i;
-				a = PyInt_AS_LONG(v);
-				b = PyInt_AS_LONG(w);
-				i = a + b;
-				if ((i^a) < 0 && (i^b) < 0) {
-					PyErr_SetString(PyExc_OverflowError,
-							"integer addition");
-					x = NULL;
-				}
-				else
-					x = PyInt_FromLong(i);
-			}
-			else
-				x = PyNumber_Add(v, w);
+                        x = LookupOp(v).add(v, w);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1003,22 +1442,7 @@
 		case BINARY_SUBTRACT:
 			w = POP();
 			v = POP();
-			if (PyInt_Check(v) && PyInt_Check(w)) {
-				/* INLINE: int - int */
-				register long a, b, i;
-				a = PyInt_AS_LONG(v);
-				b = PyInt_AS_LONG(w);
-				i = a - b;
-				if ((i^a) < 0 && (i^~b) < 0) {
-					PyErr_SetString(PyExc_OverflowError,
-							"integer subtraction");
-					x = NULL;
-				}
-				else
-					x = PyInt_FromLong(i);
-			}
-			else
-				x = PyNumber_Subtract(v, w);
+                        x = LookupOp(v).sub(v, w);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1028,24 +1452,7 @@
 		case BINARY_SUBSCR:
 			w = POP();
 			v = POP();
-			if (PyList_Check(v) && PyInt_Check(w)) {
-				/* INLINE: list[int] */
-				long i = PyInt_AsLong(w);
-				if (i < 0)
-					i += PyList_GET_SIZE(v);
-				if (i < 0 ||
-				    i >= PyList_GET_SIZE(v)) {
-					PyErr_SetString(PyExc_IndexError,
-						"list index out of range");
-					x = NULL;
-				}
-				else {
-					x = PyList_GET_ITEM(v, i);
-					Py_INCREF(x);
-				}
-			}
-			else
-				x = PyObject_GetItem(v, w);
+                        x = LookupOp(v).getitem(v, w);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1145,22 +1552,7 @@
 		case INPLACE_ADD:
 			w = POP();
 			v = POP();
-			if (PyInt_Check(v) && PyInt_Check(w)) {
-				/* INLINE: int + int */
-				register long a, b, i;
-				a = PyInt_AS_LONG(v);
-				b = PyInt_AS_LONG(w);
-				i = a + b;
-				if ((i^a) < 0 && (i^b) < 0) {
-					PyErr_SetString(PyExc_OverflowError,
-							"integer addition");
-					x = NULL;
-				}
-				else
-					x = PyInt_FromLong(i);
-			}
-			else
-				x = PyNumber_InPlaceAdd(v, w);
+                        x = LookupOp(v).inplace_add(v, w);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1170,22 +1562,7 @@
 		case INPLACE_SUBTRACT:
 			w = POP();
 			v = POP();
-			if (PyInt_Check(v) && PyInt_Check(w)) {
-				/* INLINE: int - int */
-				register long a, b, i;
-				a = PyInt_AS_LONG(v);
-				b = PyInt_AS_LONG(w);
-				i = a - b;
-				if ((i^a) < 0 && (i^~b) < 0) {
-					PyErr_SetString(PyExc_OverflowError,
-							"integer subtraction");
-					x = NULL;
-				}
-				else
-					x = PyInt_FromLong(i);
-			}
-			else
-				x = PyNumber_InPlaceSubtract(v, w);
+                        x = LookupOp(v).inplace_sub(v, w);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1773,30 +2150,7 @@
 		case COMPARE_OP:
 			w = POP();
 			v = POP();
-			if (PyInt_Check(v) && PyInt_Check(w)) {
-				/* INLINE: cmp(int, int) */
-				register long a, b;
-				register int res;
-				a = PyInt_AS_LONG(v);
-				b = PyInt_AS_LONG(w);
-				switch (oparg) {
-				case LT: res = a <  b; break;
-				case LE: res = a <= b; break;
-				case EQ: res = a == b; break;
-				case NE: res = a != b; break;
-				case GT: res = a >  b; break;
-				case GE: res = a >= b; break;
-				case IS: res = v == w; break;
-				case IS_NOT: res = v != w; break;
-				default: goto slow_compare;
-				}
-				x = res ? Py_True : Py_False;
-				Py_INCREF(x);
-			}
-			else {
-			  slow_compare:
-				x = cmp_outcome(oparg, v, w);
-			}
+                        x = LookupOp(v).cmp(v, w, oparg);
 			Py_DECREF(v);
 			Py_DECREF(w);
 			PUSH(x);
@@ -1856,7 +2210,8 @@
 			continue;
 
 		case JUMP_IF_FALSE:
-			err = PyObject_IsTrue(TOP());
+                        v = TOP();
+			err = LookupOp(v).istrue(v);
 			if (err > 0)
 				err = 0;
 			else if (err == 0)
@@ -1866,7 +2221,8 @@
 			continue;
 
 		case JUMP_IF_TRUE:
-			err = PyObject_IsTrue(TOP());
+                        v = TOP();
+			err = LookupOp(v).istrue(v);
 			if (err > 0) {
 				err = 0;
 				JUMPBY(oparg);
@@ -3323,36 +3679,6 @@
 		return PySequence_DelSlice(u, ilow, ihigh);
 	else
 		return PySequence_SetSlice(u, ilow, ihigh, x);
-}
-
-static PyObject *
-cmp_outcome(int op, register PyObject *v, register PyObject *w)
-{
-	int res = 0;
-	switch (op) {
-	case IS:
-	case IS_NOT:
-		res = (v == w);
-		if (op == (int) IS_NOT)
-			res = !res;
-		break;
-	case IN:
-	case NOT_IN:
-		res = PySequence_Contains(w, v);
-		if (res < 0)
-			return NULL;
-		if (op == (int) NOT_IN)
-			res = !res;
-		break;
-	case EXC_MATCH:
-		res = PyErr_GivenExceptionMatches(v, w);
-		break;
-	default:
-		return PyObject_RichCompare(v, w, op);
-	}
-	v = res ? Py_True : Py_False;
-	Py_INCREF(v);
-	return v;
 }
 
 static PyObject *
