* Added a new method flag, METH_COEXIST.

* Used the flag to optimize set.__contains__(), dict.__contains__(),
  dict.__getitem__(), and list.__getitem__().
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 0cf71b5..013f5f2 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -498,6 +498,31 @@
 	return (mp->ma_lookup)(mp, key, hash)->me_value;
 }
 
+static PyObject *
+dict_getitem(PyObject *op, PyObject *key)
+{
+	long hash;
+	dictobject *mp = (dictobject *)op;
+	PyObject *v;
+
+	if (!PyDict_Check(op)) {
+		return NULL;
+	}
+	if (!PyString_CheckExact(key) ||
+	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
+	{
+		hash = PyObject_Hash(key);
+		if (hash == -1)
+			return NULL;
+	}
+	v = (mp->ma_lookup)(mp, key, hash) -> me_value;
+	if (v == NULL)
+		PyErr_SetObject(PyExc_KeyError, key);
+	else
+		Py_INCREF(v);
+	return v;
+}
+
 /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
  * dictionary if it is merely replacing the value for an existing key.
  * This is means that it's safe to loop over a dictionary with
@@ -1735,6 +1760,11 @@
 PyDoc_STRVAR(has_key__doc__,
 "D.has_key(k) -> True if D has a key k, else False");
 
+PyDoc_STRVAR(contains__doc__,
+"D.__contains__(k) -> True if D has a key k, else False");
+
+PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
+
 PyDoc_STRVAR(get__doc__,
 "D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.");
 
@@ -1781,6 +1811,10 @@
 "D.iteritems() -> an iterator over the (key, value) items of D");
 
 static PyMethodDef mapp_methods[] = {
+	{"__contains__",(PyCFunction)dict_has_key,      METH_O | METH_COEXIST,
+	 contains__doc__},
+	{"__getitem__", (PyCFunction)dict_getitem,	METH_O | METH_COEXIST,
+	 getitem__doc__},
 	{"has_key",	(PyCFunction)dict_has_key,      METH_O,
 	 has_key__doc__},
 	{"get",         (PyCFunction)dict_get,          METH_VARARGS,
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 7d5c8b4..3915cc9 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2371,6 +2371,8 @@
 static PyObject *list_iter(PyObject *seq);
 static PyObject *list_reversed(PyListObject* seq, PyObject* unused);
 
+PyDoc_STRVAR(getitem_doc,
+"x.__getitem__(y) <==> x[y]");
 PyDoc_STRVAR(reversed_doc,
 "L.__reversed__() -- return a reverse iterator over the list");
 PyDoc_STRVAR(append_doc,
@@ -2396,7 +2398,10 @@
 "list.sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list;\n\
 cmp(x, y) -> -1, 0, 1");
 
+static PyObject *list_subscript(PyListObject*, PyObject*);
+
 static PyMethodDef list_methods[] = {
+	{"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, getitem_doc},
 	{"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc},
 	{"append",	(PyCFunction)listappend,  METH_O, append_doc},
 	{"insert",	(PyCFunction)listinsert,  METH_VARARGS, insert_doc},
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 3a92fa4..5818616 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -67,7 +67,7 @@
 	PyObject *self = PyCFunction_GET_SELF(func);
 	int size;
 
-	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC)) {
+	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
 	case METH_VARARGS:
 		if (kw == NULL || PyDict_Size(kw) == 0)
 			return (*meth)(self, arg);
diff --git a/Objects/setobject.c b/Objects/setobject.c
index c060077..8e70546 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -156,6 +156,28 @@
 }
 
 static PyObject *
+set_direct_contains(PySetObject *so, PyObject *key)
+{
+	PyObject *tmp;
+	long result;
+
+	result = PyDict_Contains(so->data, key);
+	if (result == -1 && PyAnySet_Check(key)) {
+		PyErr_Clear();
+		tmp = frozenset_dict_wrapper(((PySetObject *)(key))->data);
+		if (tmp == NULL)
+			return NULL;
+		result = PyDict_Contains(so->data, tmp);
+		Py_DECREF(tmp);
+	}
+	if (result == -1)
+		return NULL;
+	return PyBool_FromLong(result);
+}
+
+PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x.");
+
+static PyObject *
 set_copy(PySetObject *so)
 {
 	return make_new_set(so->ob_type, (PyObject *)so);
@@ -968,6 +990,8 @@
 	 add_doc},
 	{"clear",	(PyCFunction)set_clear,		METH_NOARGS,
 	 clear_doc},
+	{"__contains__",	(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST,
+	 contains_doc},
 	{"copy",	(PyCFunction)set_copy,		METH_NOARGS,
 	 copy_doc},
 	{"__copy__",	(PyCFunction)set_copy,		METH_NOARGS,
@@ -1094,6 +1118,8 @@
 
 
 static PyMethodDef frozenset_methods[] = {
+	{"__contains__",	(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST,
+	 contains_doc},
 	{"copy",	(PyCFunction)frozenset_copy,	METH_NOARGS,
 	 copy_doc},
 	{"__copy__",	(PyCFunction)frozenset_copy,	METH_NOARGS,
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index e4eadb8..545dba6 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2792,8 +2792,9 @@
 
 	for (; meth->ml_name != NULL; meth++) {
 		PyObject *descr;
-		if (PyDict_GetItemString(dict, meth->ml_name))
-			continue;
+		if (PyDict_GetItemString(dict, meth->ml_name) &&
+			!(meth->ml_flags & METH_COEXIST))
+				continue;
 		if (meth->ml_flags & METH_CLASS) {
 			if (meth->ml_flags & METH_STATIC) {
 				PyErr_SetString(PyExc_ValueError,