Make identifiers str (not str8) objects throughout.
This affects the parser, various object implementations,
and all places that put identifiers into C string literals.

In testing, a number of crashes occurred as code would
fail when the recursion limit was reached (such as the
Unicode interning dictionary having key/value pairs where
key is not value). To solve these, I added an overflowed
flag, which allows for 50 more recursions after the
limit was reached and the exception was raised, and
a recursion_critical flag, which indicates that recursion
absolutely must be allowed, i.e. that a certain call
must not cause a stack overflow exception.

There are still some places where both str and str8 are
accepted as identifiers; these should eventually be
removed.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 84b3384..6e63852 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -207,7 +207,7 @@
 		null_error();
 		return -1;
 	}
-	okey = PyString_FromString(key);
+	okey = PyUnicode_FromString(key);
 	if (okey == NULL)
 		return -1;
 	ret = PyObject_DelItem(o, okey);
@@ -1598,7 +1598,7 @@
 	if (key == NULL)
 		return null_error();
 
-	okey = PyString_FromString(key);
+	okey = PyUnicode_FromString(key);
 	if (okey == NULL)
 		return NULL;
 	r = PyObject_GetItem(o, okey);
@@ -1617,7 +1617,7 @@
 		return -1;
 	}
 
-	okey = PyString_FromString(key);
+	okey = PyUnicode_FromString(key);
 	if (okey == NULL)
 		return -1;
 	r = PyObject_SetItem(o, okey, value);
@@ -1989,11 +1989,13 @@
 	PyObject *bases;
 
 	if (__bases__ == NULL) {
-		__bases__ = PyString_FromString("__bases__");
+		__bases__ = PyUnicode_FromString("__bases__");
 		if (__bases__ == NULL)
 			return NULL;
 	}
+	Py_ALLOW_RECURSION
 	bases = PyObject_GetAttr(cls, __bases__);
+	Py_END_ALLOW_RECURSION
 	if (bases == NULL) {
 		if (PyErr_ExceptionMatches(PyExc_AttributeError))
 			PyErr_Clear();
@@ -2067,7 +2069,7 @@
 	int retval = 0;
 
 	if (__class__ == NULL) {
-		__class__ = PyString_FromString("__class__");
+		__class__ = PyUnicode_FromString("__class__");
 		if (__class__ == NULL)
 			return -1;
 	}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 2a1dbcb..532e637 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1078,7 +1078,7 @@
     else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len))
         return NULL;
 
-    _adjust_indices(&start, &end, PyString_GET_SIZE(self));
+    _adjust_indices(&start, &end, PyBytes_GET_SIZE(self));
 
     return PyInt_FromSsize_t(
         stringlib_count(str + start, end - start, sub, sub_len)
diff --git a/Objects/classobject.c b/Objects/classobject.c
index b7711d5..3cf64de 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -100,7 +100,7 @@
 {
 	static PyObject *docstr;
 	if (docstr == NULL) {
-		docstr= PyString_InternFromString("__doc__");
+		docstr= PyUnicode_InternFromString("__doc__");
 		if (docstr == NULL)
 			return NULL;
 	}
@@ -235,12 +235,12 @@
 			return NULL;
 		PyErr_Clear();
 	}
-	else if (!PyString_Check(funcname)) {
+	else if (!PyUnicode_Check(funcname)) {
 		Py_DECREF(funcname);
 		funcname = NULL;
 	}
 	else
-		sfuncname = PyString_AS_STRING(funcname);
+		sfuncname = PyUnicode_AsString(funcname);
 	if (klass == NULL)
 		klassname = NULL;
 	else {
@@ -250,12 +250,12 @@
 				return NULL;
 			PyErr_Clear();
 		}
-		else if (!PyString_Check(klassname)) {
+		else if (!PyUnicode_Check(klassname)) {
 			Py_DECREF(klassname);
 			klassname = NULL;
 		}
 		else
-			sklassname = PyString_AS_STRING(klassname);
+			sklassname = PyUnicode_AsString(klassname);
 	}
 	if (self == NULL)
 		result = PyUnicode_FromFormat("<unbound method %s.%s>",
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 6763950..c735193 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -32,10 +32,10 @@
 
 	for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
 		PyObject *v = PyTuple_GET_ITEM(tuple, i);
-		if (v == NULL || !PyString_CheckExact(v)) {
+		if (v == NULL || !PyUnicode_CheckExact(v)) {
 			Py_FatalError("non-string found in code slot");
 		}
-		PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
+		PyUnicode_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
 	}
 }
 
@@ -58,7 +58,7 @@
 	    varnames == NULL || !PyTuple_Check(varnames) ||
 	    freevars == NULL || !PyTuple_Check(freevars) ||
 	    cellvars == NULL || !PyTuple_Check(cellvars) ||
-	    name == NULL || !PyString_Check(name) ||
+	    name == NULL || (!PyString_Check(name) && !PyUnicode_Check(name)) ||
 	    filename == NULL || !PyString_Check(filename) ||
 	    lnotab == NULL || !PyString_Check(lnotab) ||
 	    !PyObject_CheckReadBuffer(code)) {
@@ -148,10 +148,10 @@
 
 	for (i = 0; i < len; i++) {
 		item = PyTuple_GET_ITEM(tup, i);
-		if (PyString_CheckExact(item)) {
+		if (PyUnicode_CheckExact(item)) {
 			Py_INCREF(item);
 		}
-		else if (!PyString_Check(item)) {
+		else if (!PyUnicode_Check(item)) {
 			PyErr_Format(
 				PyExc_TypeError,
 				"name tuples must contain only "
@@ -161,9 +161,9 @@
 			return NULL;
 		}
 		else {
-			item = PyString_FromStringAndSize(
-				PyString_AS_STRING(item),
-				PyString_GET_SIZE(item));
+			item = PyUnicode_FromUnicode(
+				PyUnicode_AS_UNICODE(item),
+				PyUnicode_GET_SIZE(item));
 			if (item == NULL) {
 				Py_DECREF(newtuple);
 				return NULL;
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index ed2e475..4580ef2 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -269,7 +269,7 @@
         {
 		PyObject *complexfunc;
 		if (!complex_str) {
-			if (!(complex_str = PyString_FromString("__complex__")))
+			if (!(complex_str = PyUnicode_FromString("__complex__")))
 				return cv;
 		}
 		complexfunc = _PyType_Lookup(op->ob_type, complex_str);
@@ -900,7 +900,7 @@
 
 	/* XXX Hack to support classes with __complex__ method */
 	if (complexstr == NULL) {
-		complexstr = PyString_InternFromString("__complex__");
+		complexstr = PyUnicode_InternFromString("__complex__");
 		if (complexstr == NULL)
 			return NULL;
 	}
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index e9ccefa..acd2400 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -15,7 +15,10 @@
 static char *
 descr_name(PyDescrObject *descr)
 {
-	if (descr->d_name != NULL && PyString_Check(descr->d_name))
+	if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
+		return PyUnicode_AsString(descr->d_name);
+	else if (descr->d_name != NULL && PyString_Check(descr->d_name))
+		/* XXX this should not happen */
 		return PyString_AS_STRING(descr->d_name);
 	else
 		return "?";
@@ -581,7 +584,7 @@
 	if (descr != NULL) {
 		Py_XINCREF(type);
 		descr->d_type = type;
-		descr->d_name = PyString_InternFromString(name);
+		descr->d_name = PyUnicode_InternFromString(name);
 		if (descr->d_name == NULL) {
 			Py_DECREF(descr);
 			descr = NULL;
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index b45a664..639c3c5 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1040,7 +1040,7 @@
 			static PyObject *missing_str = NULL;
 			if (missing_str == NULL)
 				missing_str =
-				  PyString_InternFromString("__missing__");
+				  PyUnicode_InternFromString("__missing__");
 			missing = _PyType_Lookup(mp->ob_type, missing_str);
 			if (missing != NULL)
 				return PyObject_CallFunctionObjArgs(missing,
@@ -2073,7 +2073,7 @@
 PyDict_GetItemString(PyObject *v, const char *key)
 {
 	PyObject *kv, *rv;
-	kv = PyString_FromString(key);
+	kv = PyUnicode_FromString(key);
 	if (kv == NULL)
 		return NULL;
 	rv = PyDict_GetItem(v, kv);
@@ -2086,10 +2086,10 @@
 {
 	PyObject *kv;
 	int err;
-	kv = PyString_FromString(key);
+	kv = PyUnicode_FromString(key);
 	if (kv == NULL)
 		return -1;
-	PyString_InternInPlace(&kv); /* XXX Should we really? */
+	PyUnicode_InternInPlace(&kv); /* XXX Should we really? */
 	err = PyDict_SetItem(v, kv, item);
 	Py_DECREF(kv);
 	return err;
@@ -2100,7 +2100,7 @@
 {
 	PyObject *kv;
 	int err;
-	kv = PyString_FromString(key);
+	kv = PyUnicode_FromString(key);
 	if (kv == NULL)
 		return -1;
 	err = PyDict_DelItem(v, kv);
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index f780b3a..bb27f1c 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -542,7 +542,7 @@
 
 int _PyFrame_Init()
 {
-	builtin_object = PyString_InternFromString("__builtins__");
+	builtin_object = PyUnicode_InternFromString("__builtins__");
 	return (builtin_object != NULL);
 }
 
@@ -722,7 +722,7 @@
 	for (j = nmap; --j >= 0; ) {
 		PyObject *key = PyTuple_GET_ITEM(map, j);
 		PyObject *value = values[j];
-		assert(PyString_Check(key));
+		assert(PyString_Check(key)/*XXX this should go*/ || PyUnicode_Check(key));
 		if (deref) {
 			assert(PyCell_Check(value));
 			value = PyCell_GET(value);
@@ -770,7 +770,7 @@
 	for (j = nmap; --j >= 0; ) {
 		PyObject *key = PyTuple_GET_ITEM(map, j);
 		PyObject *value = PyObject_GetItem(dict, key);
-		assert(PyString_Check(key));
+		assert(PyUnicode_Check(key));
 		/* We only care about NULLs if clear is true. */
 		if (value == NULL) {
 			PyErr_Clear();
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 6f17e7a..ff1b4c8 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -322,7 +322,7 @@
 
 	/* Not legal to del f.func_name or to set it to anything
 	 * other than a string object. */
-	if (value == NULL || !PyString_Check(value)) {
+	if (value == NULL || (!PyString_Check(value) && !PyUnicode_Check(value))) {
 		PyErr_SetString(PyExc_TypeError,
 				"__name__ must be set to a string object");
 		return -1;
@@ -516,7 +516,7 @@
 	if (nfree != nclosure)
 		return PyErr_Format(PyExc_ValueError,
 				    "%s requires closure of length %zd, not %zd",
-				    PyString_AS_STRING(code->co_name),
+				    PyUnicode_AsString(code->co_name),
 				    nfree, nclosure);
 	if (nclosure) {
 		Py_ssize_t i;
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 6199805..2d1c688 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -143,7 +143,7 @@
 static PyObject *
 meth_get__name__(PyCFunctionObject *m, void *closure)
 {
-	return PyString_FromString(m->m_ml->ml_name);
+	return PyUnicode_FromString(m->m_ml->ml_name);
 }
 
 static int
@@ -297,7 +297,7 @@
 	i = 0;
 	for (c = chain; c != NULL; c = c->link) {
 		for (ml = c->methods; ml->ml_name != NULL; ml++) {
-			PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
+			PyList_SetItem(v, i, PyUnicode_FromString(ml->ml_name));
 			i++;
 		}
 	}
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index daf24eb..7c5e47f 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -22,7 +22,7 @@
 	m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
 	if (m == NULL)
 		return NULL;
-	nameobj = PyString_FromString(name);
+	nameobj = PyUnicode_FromString(name);
 	m->md_dict = PyDict_New();
 	if (m->md_dict == NULL || nameobj == NULL)
 		goto fail;
diff --git a/Objects/object.c b/Objects/object.c
index be7d501..c701af0 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -465,7 +465,7 @@
 	   check this before trying the __unicode__
 	   method. */
 	if (unicodestr == NULL) {
-		unicodestr= PyString_InternFromString("__unicode__");
+		unicodestr= PyUnicode_InternFromString("__unicode__");
 		if (unicodestr == NULL)
 			return NULL;
 	}
@@ -852,7 +852,7 @@
 
 	if (v->ob_type->tp_getattr != NULL)
 		return (*v->ob_type->tp_getattr)(v, (char*)name);
-	w = PyString_InternFromString(name);
+	w = PyUnicode_InternFromString(name);
 	if (w == NULL)
 		return NULL;
 	res = PyObject_GetAttr(v, w);
@@ -880,7 +880,7 @@
 
 	if (v->ob_type->tp_setattr != NULL)
 		return (*v->ob_type->tp_setattr)(v, (char*)name, w);
-	s = PyString_InternFromString(name);
+	s = PyUnicode_InternFromString(name);
 	if (s == NULL)
 		return -1;
 	res = PyObject_SetAttr(v, s, w);
@@ -893,30 +893,19 @@
 {
 	PyTypeObject *tp = v->ob_type;
 
-	if (!PyString_Check(name)) {
-		/* The Unicode to string conversion is done here because the
-		   existing tp_getattro slots expect a string object as name
-		   and we wouldn't want to break those. */
-		if (PyUnicode_Check(name)) {
-			name = _PyUnicode_AsDefaultEncodedString(name, NULL);
-			if (name == NULL)
-				return NULL;
-		}
-		else
-		{
-			PyErr_Format(PyExc_TypeError,
-				     "attribute name must be string, not '%.200s'",
-				     name->ob_type->tp_name);
-			return NULL;
-		}
+	if (!PyUnicode_Check(name)) {
+		PyErr_Format(PyExc_TypeError,
+			     "attribute name must be string, not '%.200s'",
+			     name->ob_type->tp_name);
+		return NULL;
 	}
 	if (tp->tp_getattro != NULL)
 		return (*tp->tp_getattro)(v, name);
 	if (tp->tp_getattr != NULL)
-		return (*tp->tp_getattr)(v, PyString_AS_STRING(name));
+		return (*tp->tp_getattr)(v, PyUnicode_AsString(name));
 	PyErr_Format(PyExc_AttributeError,
 		     "'%.50s' object has no attribute '%.400s'",
-		     tp->tp_name, PyString_AS_STRING(name));
+		     tp->tp_name, PyUnicode_AsString(name));
 	return NULL;
 }
 
@@ -938,33 +927,22 @@
 	PyTypeObject *tp = v->ob_type;
 	int err;
 
-	if (!PyString_Check(name)) {
-		/* The Unicode to string conversion is done here because the
-		   existing tp_setattro slots expect a string object as name
-		   and we wouldn't want to break those. */
-		if (PyUnicode_Check(name)) {
-			name = _PyUnicode_AsDefaultEncodedString(name, NULL);
-			if (name == NULL)
-				return -1;
-		}
-		else
-		{
-			PyErr_Format(PyExc_TypeError,
-				     "attribute name must be string, not '%.200s'",
-				     name->ob_type->tp_name);
-			return -1;
-		}
+	if (!PyUnicode_Check(name)) {
+		PyErr_Format(PyExc_TypeError,
+			     "attribute name must be string, not '%.200s'",
+			     name->ob_type->tp_name);
+		return -1;
 	}
 	Py_INCREF(name);
 
-	PyString_InternInPlace(&name);
+	PyUnicode_InternInPlace(&name);
 	if (tp->tp_setattro != NULL) {
 		err = (*tp->tp_setattro)(v, name, value);
 		Py_DECREF(name);
 		return err;
 	}
 	if (tp->tp_setattr != NULL) {
-		err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);
+		err = (*tp->tp_setattr)(v, PyUnicode_AsString(name), value);
 		Py_DECREF(name);
 		return err;
 	}
@@ -976,14 +954,14 @@
 			     "(%s .%.100s)",
 			     tp->tp_name,
 			     value==NULL ? "del" : "assign to",
-			     PyString_AS_STRING(name));
+			     PyUnicode_AsString(name));
 	else
 		PyErr_Format(PyExc_TypeError,
 			     "'%.100s' object has only read-only attributes "
 			     "(%s .%.100s)",
 			     tp->tp_name,
 			     value==NULL ? "del" : "assign to",
-			     PyString_AS_STRING(name));
+			     PyUnicode_AsString(name));
 	return -1;
 }
 
@@ -1033,22 +1011,11 @@
 	Py_ssize_t dictoffset;
 	PyObject **dictptr;
 
-	if (!PyString_Check(name)){
-		/* The Unicode to string conversion is done here because the
-		   existing tp_setattro slots expect a string object as name
-		   and we wouldn't want to break those. */
-		if (PyUnicode_Check(name)) {
-			name = PyUnicode_AsEncodedString(name, NULL, NULL);
-			if (name == NULL)
-				return NULL;
-		}
-		else
-		{
-			PyErr_Format(PyExc_TypeError,
-				     "attribute name must be string, not '%.200s'",
-				     name->ob_type->tp_name);
-			return NULL;
-		}
+	if (!PyUnicode_Check(name)){
+		PyErr_Format(PyExc_TypeError,
+			     "attribute name must be string, not '%.200s'",
+			     name->ob_type->tp_name);
+		return NULL;
 	}
 	else
 		Py_INCREF(name);
@@ -1134,7 +1101,7 @@
 
 	PyErr_Format(PyExc_AttributeError,
 		     "'%.50s' object has no attribute '%.400s'",
-		     tp->tp_name, PyString_AS_STRING(name));
+		     tp->tp_name, PyUnicode_AsString(name));
   done:
 	Py_DECREF(name);
 	return res;
@@ -1149,22 +1116,11 @@
 	PyObject **dictptr;
 	int res = -1;
 
-	if (!PyString_Check(name)){
-		/* The Unicode to string conversion is done here because the
-		   existing tp_setattro slots expect a string object as name
-		   and we wouldn't want to break those. */
-		if (PyUnicode_Check(name)) {
-			name = PyUnicode_AsEncodedString(name, NULL, NULL);
-			if (name == NULL)
-				return -1;
-		}
-		else
-		{
-			PyErr_Format(PyExc_TypeError,
-				     "attribute name must be string, not '%.200s'",
-				     name->ob_type->tp_name);
-			return -1;
-		}
+	if (!PyUnicode_Check(name)){
+		PyErr_Format(PyExc_TypeError,
+			     "attribute name must be string, not '%.200s'",
+			     name->ob_type->tp_name);
+		return -1;
 	}
 	else
 		Py_INCREF(name);
@@ -1212,13 +1168,13 @@
 	if (descr == NULL) {
 		PyErr_Format(PyExc_AttributeError,
 			     "'%.100s' object has no attribute '%.200s'",
-			     tp->tp_name, PyString_AS_STRING(name));
+			     tp->tp_name, PyUnicode_AsString(name));
 		goto done;
 	}
 
 	PyErr_Format(PyExc_AttributeError,
 		     "'%.50s' object attribute '%.400s' is read-only",
-		     tp->tp_name, PyString_AS_STRING(name));
+		     tp->tp_name, PyUnicode_AsString(name));
   done:
 	Py_DECREF(name);
 	return res;
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 60e6129..92bc95b 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -686,6 +686,11 @@
 Py_ssize_t
 PyString_Size(register PyObject *op)
 {
+	if (PyUnicode_Check(op)) {
+		op = _PyUnicode_AsDefaultEncodedString(op, NULL);
+		if (!op)
+			return -1;
+	}
 	if (!PyString_Check(op))
 		return string_getsize(op);
 	return ((PyStringObject *)op) -> ob_size;
@@ -694,6 +699,11 @@
 /*const*/ char *
 PyString_AsString(register PyObject *op)
 {
+	if (PyUnicode_Check(op)) {
+		op = _PyUnicode_AsDefaultEncodedString(op, NULL);
+		if (!op)
+			return NULL;
+	}
 	if (!PyString_Check(op))
 		return string_getbuffer(op);
 	return ((PyStringObject *)op) -> ob_sval;
@@ -824,7 +834,7 @@
 {
 	static const char *hexdigits = "0123456789abcdef";
 	register PyStringObject* op = (PyStringObject*) obj;
-	Py_ssize_t length = PyUnicode_GET_SIZE(op);
+	Py_ssize_t length = PyString_GET_SIZE(op);
 	size_t newsize = 2 + 4 * op->ob_size;
 	PyObject *v;
 	if (newsize > PY_SSIZE_T_MAX || newsize / 4 != op->ob_size) {
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 5983011..ab86f54 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -35,7 +35,7 @@
 			s = type->tp_name;
 		else
 			s++;
-		return PyString_FromString(s);
+		return PyUnicode_FromString(s);
 	}
 }
 
@@ -97,9 +97,9 @@
 	else {
 		s = strrchr(type->tp_name, '.');
 		if (s != NULL)
-			return PyString_FromStringAndSize(
+			return PyUnicode_FromStringAndSize(
 			    type->tp_name, (Py_ssize_t)(s - type->tp_name));
-		return PyString_FromString("__builtin__");
+		return PyUnicode_FromString("__builtin__");
 	}
 }
 
@@ -371,7 +371,7 @@
 	mod = type_module(type, NULL);
 	if (mod == NULL)
 		PyErr_Clear();
-	else if (!PyString_Check(mod)) {
+	else if (!PyUnicode_Check(mod)) {
 		Py_DECREF(mod);
 		mod = NULL;
 	}
@@ -384,11 +384,11 @@
 	else
 		kind = "type";
 
-	if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) {
+	if (mod != NULL && strcmp(PyUnicode_AsString(mod), "__builtin__")) {
 		rtn = PyUnicode_FromFormat("<%s '%s.%s'>",
 					  kind,
-					  PyString_AS_STRING(mod),
-					  PyString_AS_STRING(name));
+					  PyUnicode_AsString(mod),
+					  PyUnicode_AsString(name));
 	}
 	else
 		rtn = PyUnicode_FromFormat("<%s '%s'>", kind, type->tp_name);
@@ -859,7 +859,7 @@
 	PyObject *res;
 
 	if (*attrobj == NULL) {
-		*attrobj = PyString_InternFromString(attrstr);
+		*attrobj = PyUnicode_InternFromString(attrstr);
 		if (*attrobj == NULL)
 			return NULL;
 	}
@@ -1415,7 +1415,7 @@
 	PyObject *descr;
 
 	if (dict_str == NULL) {
-		dict_str = PyString_InternFromString("__dict__");
+		dict_str = PyUnicode_InternFromString("__dict__");
 		if (dict_str == NULL)
 			return NULL;
 	}
@@ -1564,14 +1564,14 @@
 	unsigned char *p;
 	Py_ssize_t i, n;
 
-	if (!PyString_Check(s)) {
+	if (!PyUnicode_Check(s)) {
 		PyErr_Format(PyExc_TypeError,
 			     "__slots__ items must be strings, not '%.200s'",
 			     s->ob_type->tp_name);
 		return 0;
 	}
-	p = (unsigned char *) PyString_AS_STRING(s);
-	n = PyString_GET_SIZE(s);
+	p = (unsigned char *) PyUnicode_AsString(s);
+	n = strlen((char*)p)/*XXX PyString_GET_SIZE(s)*/;
 	/* We must reject an empty name.  As a hack, we bump the
 	   length to 1 so that the loop will balk on the trailing \0. */
 	if (n == 0)
@@ -1792,22 +1792,13 @@
 			return NULL;
 		}
 
-		tmp = _unicode_to_string(slots, nslots);
-		if (tmp == NULL)
-			goto bad_slots;
-		if (tmp != slots) {
-			Py_DECREF(slots);
-			slots = tmp;
-		}
 		/* Check for valid slot names and two special cases */
 		for (i = 0; i < nslots; i++) {
 			PyObject *tmp = PyTuple_GET_ITEM(slots, i);
-			char *s;
 			if (!valid_identifier(tmp))
 				goto bad_slots;
-			assert(PyString_Check(tmp));
-			s = PyString_AS_STRING(tmp);
-			if (strcmp(s, "__dict__") == 0) {
+			assert(PyUnicode_Check(tmp));
+			if (PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) {
 				if (!may_add_dict || add_dict) {
 					PyErr_SetString(PyExc_TypeError,
 						"__dict__ slot disallowed: "
@@ -1816,7 +1807,7 @@
 				}
 				add_dict++;
 			}
-			if (strcmp(s, "__weakref__") == 0) {
+			if (PyUnicode_CompareWithASCIIString(tmp, "__weakref__") == 0) {
 				if (!may_add_weak || add_weak) {
 					PyErr_SetString(PyExc_TypeError,
 						"__weakref__ slot disallowed: "
@@ -1836,11 +1827,11 @@
 		if (newslots == NULL)
 			goto bad_slots;
 		for (i = j = 0; i < nslots; i++) {
-			char *s;
 			tmp = PyTuple_GET_ITEM(slots, i);
-			s = PyString_AS_STRING(tmp);
-			if ((add_dict && strcmp(s, "__dict__") == 0) ||
-			    (add_weak && strcmp(s, "__weakref__") == 0))
+			if ((add_dict && 
+			     PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) ||
+			    (add_weak && 
+			     PyUnicode_CompareWithASCIIString(tmp, "__weakref__") == 0))
 				continue;
 			tmp =_Py_Mangle(name, tmp);
 			if (!tmp)
@@ -1917,7 +1908,15 @@
 	type->tp_as_sequence = &et->as_sequence;
 	type->tp_as_mapping = &et->as_mapping;
 	type->tp_as_buffer = &et->as_buffer;
-	type->tp_name = PyString_AS_STRING(name);
+	if (PyString_Check(name))
+		type->tp_name = PyString_AsString(name);
+	else {
+		type->tp_name = PyUnicode_AsString(name);
+		if (!type->tp_name) {
+			Py_DECREF(type);
+			return NULL;
+		}
+	}
 
 	/* Set tp_base and tp_bases */
 	type->tp_bases = bases;
@@ -1980,7 +1979,7 @@
 	slotoffset = base->tp_basicsize;
 	if (slots != NULL) {
 		for (i = 0; i < nslots; i++, mp++) {
-			mp->name = PyString_AS_STRING(
+			mp->name = PyUnicode_AsString(
 				PyTuple_GET_ITEM(slots, i));
 			mp->type = T_OBJECT_EX;
 			mp->offset = slotoffset;
@@ -2157,7 +2156,7 @@
 	/* Give up */
 	PyErr_Format(PyExc_AttributeError,
 			 "type object '%.50s' has no attribute '%.400s'",
-			 type->tp_name, PyString_AS_STRING(name));
+			 type->tp_name, PyUnicode_AsString(name));
 	return NULL;
 }
 
@@ -2473,7 +2472,7 @@
 	mod = type_module(type, NULL);
 	if (mod == NULL)
 		PyErr_Clear();
-	else if (!PyString_Check(mod)) {
+	else if (!PyUnicode_Check(mod)) {
 		Py_DECREF(mod);
 		mod = NULL;
 	}
@@ -2482,8 +2481,8 @@
 		return NULL;
 	if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__"))
 		rtn = PyUnicode_FromFormat("<%s.%s object at %p>",
-					  PyString_AS_STRING(mod),
-					  PyString_AS_STRING(name),
+					  PyUnicode_AsString(mod),
+					  PyUnicode_AsString(name),
 					  self);
 	else
 		rtn = PyUnicode_FromFormat("<%s object at %p>",
@@ -2686,7 +2685,7 @@
 	static PyObject *copy_reg_str;
 
 	if (!copy_reg_str) {
-		copy_reg_str = PyString_InternFromString("copy_reg");
+		copy_reg_str = PyUnicode_InternFromString("copy_reg");
 		if (copy_reg_str == NULL)
 			return NULL;
 	}
@@ -4330,7 +4329,7 @@
 	descrgetfunc f;
 
 	if (getitem_str == NULL) {
-		getitem_str = PyString_InternFromString("__getitem__");
+		getitem_str = PyUnicode_InternFromString("__getitem__");
 		if (getitem_str == NULL)
 			return NULL;
 	}
@@ -4760,13 +4759,13 @@
 	static PyObject *getattr_str = NULL;
 
 	if (getattr_str == NULL) {
-		getattr_str = PyString_InternFromString("__getattr__");
+		getattr_str = PyUnicode_InternFromString("__getattr__");
 		if (getattr_str == NULL)
 			return NULL;
 	}
 	if (getattribute_str == NULL) {
 		getattribute_str =
-			PyString_InternFromString("__getattribute__");
+			PyUnicode_InternFromString("__getattribute__");
 		if (getattribute_str == NULL)
 			return NULL;
 	}
@@ -4898,7 +4897,7 @@
 	static PyObject *get_str = NULL;
 
 	if (get_str == NULL) {
-		get_str = PyString_InternFromString("__get__");
+		get_str = PyUnicode_InternFromString("__get__");
 		if (get_str == NULL)
 			return NULL;
 	}
@@ -4968,7 +4967,7 @@
 	Py_ssize_t i, n;
 
 	if (new_str == NULL) {
-		new_str = PyString_InternFromString("__new__");
+		new_str = PyUnicode_InternFromString("__new__");
 		if (new_str == NULL)
 			return NULL;
 	}
@@ -5490,7 +5489,7 @@
 	if (initialized)
 		return;
 	for (p = slotdefs; p->name; p++) {
-		p->name_strobj = PyString_InternFromString(p->name);
+		p->name_strobj = PyUnicode_InternFromString(p->name);
 		if (!p->name_strobj)
 			Py_FatalError("Out of memory interning slotdef names");
 	}
@@ -5717,9 +5716,9 @@
 	if (!skip) {
 		/* We want __class__ to return the class of the super object
 		   (i.e. super, or a subclass), not the class of su->obj. */
-		skip = (PyString_Check(name) &&
-			PyString_GET_SIZE(name) == 9 &&
-			strcmp(PyString_AS_STRING(name), "__class__") == 0);
+		skip = (PyUnicode_Check(name) &&
+			PyUnicode_GET_SIZE(name) == 9 &&
+			PyUnicode_CompareWithASCIIString(name, "__class__") == 0);
 	}
 
 	if (!skip) {
@@ -5809,7 +5808,7 @@
 		PyObject *class_attr;
 
 		if (class_str == NULL) {
-			class_str = PyString_FromString("__class__");
+			class_str = PyUnicode_FromString("__class__");
 			if (class_str == NULL)
 				return NULL;
 		}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index e793418..87c5c99 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -458,8 +458,10 @@
     /* Copy the Unicode data into the new object */
     if (u != NULL) {
         Py_UNICODE *p = unicode->str;
-        while ((*p++ = *u++))
-            ;
+        while (size--)
+            *p++ = *u++;
+        /* Don't need to write trailing 0 because
+           that's already done by _PyUnicode_New */
     }
 
     return (PyObject *)unicode;
@@ -1184,6 +1186,16 @@
     return v;
 }
 
+char*
+PyUnicode_AsString(PyObject *unicode)
+{
+    assert(PyUnicode_Check(unicode));
+    unicode = _PyUnicode_AsDefaultEncodedString(unicode, NULL);
+    if (!unicode)
+        return NULL;
+    return PyString_AsString(unicode);
+}
+
 Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode)
 {
     if (!PyUnicode_Check(unicode)) {
@@ -3247,7 +3259,7 @@
 		goto onError;
 	}
     }
-    if (p - PyUnicode_AS_UNICODE(v) < PyString_GET_SIZE(v))
+    if (p - PyUnicode_AS_UNICODE(v) < PyUnicode_GET_SIZE(v))
 	if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
 	    goto onError;
     Py_XDECREF(errorHandler);
@@ -5861,6 +5873,24 @@
     return -1;
 }
 
+int
+PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str)
+{
+    int i;
+    Py_UNICODE *id;
+    assert(PyUnicode_Check(uni));
+    id = PyUnicode_AS_UNICODE(uni);
+    /* Compare Unicode string and source character set string */
+    for (i = 0; id[i] && str[i]; i++)
+	if (id[i] != str[i])
+	    return ((int)id[i] < (int)str[i]) ? -1 : 1;
+    if (id[i])
+	return 1; /* uni is longer */
+    if (str[i])
+	return -1; /* str is longer */
+    return 0;
+}
+
 PyObject *PyUnicode_RichCompare(PyObject *left,
                                 PyObject *right,
                                 int op)
@@ -8671,7 +8701,13 @@
 			return;
 		}
 	}
+	/* It might be that the GetItem call fails even
+	   though the key is present in the dictionary,
+	   namely when this happens during a stack overflow. */
+	Py_ALLOW_RECURSION
 	t = PyDict_GetItem(interned, (PyObject *)s);
+	Py_END_ALLOW_RECURSION
+
 	if (t) {
 		Py_INCREF(t);
 		Py_DECREF(*p);
@@ -8679,10 +8715,13 @@
 		return;
 	}
 
+	PyThreadState_GET()->recursion_critical = 1;
 	if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) {
 		PyErr_Clear();
+		PyThreadState_GET()->recursion_critical = 0;
 		return;
 	}
+	PyThreadState_GET()->recursion_critical = 0;
 	/* The two references in interned are not counted by refcnt.
 	   The deallocator will take care of this */
 	s->ob_refcnt -= 2;
@@ -8879,6 +8918,58 @@
 	return (PyObject *)it;
 }
 
+size_t
+Py_UNICODE_strlen(const Py_UNICODE *u)
+{
+    int res = 0;
+    while(*u++)
+        res++;
+    return res;
+}
+
+Py_UNICODE*
+Py_UNICODE_strcpy(Py_UNICODE *s1, const Py_UNICODE *s2)
+{
+    Py_UNICODE *u = s1;
+    while ((*u++ = *s2++));
+    return s1;
+}
+
+Py_UNICODE*
+Py_UNICODE_strncpy(Py_UNICODE *s1, const Py_UNICODE *s2, size_t n)
+{
+    Py_UNICODE *u = s1;
+    while ((*u++ = *s2++))
+        if (n-- == 0)
+            break;
+    return s1;
+}
+
+int
+Py_UNICODE_strcmp(const Py_UNICODE *s1, const Py_UNICODE *s2)
+{
+    while (*s1 && *s2 && *s1 == *s2)
+        s1++, s2++;
+    if (*s1 && *s2)
+        return (*s1 < *s2) ? -1 : +1;
+    if (*s1)
+        return 1;
+    if (*s2)
+        return -1;
+    return 0;
+}
+
+Py_UNICODE*
+Py_UNICODE_strchr(const Py_UNICODE *s, Py_UNICODE c)
+{
+    const Py_UNICODE *p;
+    for (p = s; *p; p++)
+        if (*p == c)
+            return (Py_UNICODE*)p;
+    return NULL;
+}
+
+
 #ifdef __cplusplus
 }
 #endif