Index: Python/codecs.c
===================================================================
--- Python/codecs.c	(revision 58355)
+++ Python/codecs.c	(working copy)
@@ -28,7 +28,7 @@
 
 int PyCodec_Register(PyObject *search_function)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = PyThreadState_Get()->interp;
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
 	goto onError;
     if (search_function == NULL) {
@@ -102,7 +102,7 @@
 	goto onError;
     }
 
-    interp = PyThreadState_GET()->interp;
+    interp = PyThreadState_Get()->interp;
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
 	goto onError;
 
@@ -410,7 +410,7 @@
    Return 0 on success, -1 on error */
 int PyCodec_RegisterError(const char *name, PyObject *error)
 {
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = PyThreadState_Get()->interp;
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
 	return -1;
     if (!PyCallable_Check(error)) {
@@ -428,7 +428,7 @@
 {
     PyObject *handler = NULL;
 
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = PyThreadState_Get()->interp;
     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
 	return NULL;
 
@@ -805,7 +805,7 @@
 	}
     };
 
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
+    PyInterpreterState *interp = PyThreadState_Get()->interp;
     PyObject *mod;
     unsigned i;
 
Index: Python/errors.c
===================================================================
--- Python/errors.c	(revision 58355)
+++ Python/errors.c	(working copy)
@@ -24,7 +24,7 @@
 void
 PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *oldtype, *oldvalue, *oldtraceback;
 
 	if (traceback != NULL && !PyTraceBack_Check(traceback)) {
@@ -52,6 +52,8 @@
 void
 PyErr_SetObject(PyObject *exception, PyObject *value)
 {
+	if (exception != NULL && exception->ob_type == NULL)
+		Py_FatalError("Unitialized exception type passed to PyErr_SetObject");
 	if (exception != NULL &&
 	    !PyExceptionClass_Check(exception)) {
 		PyErr_Format(PyExc_SystemError,
@@ -82,7 +84,7 @@
 PyObject *
 PyErr_Occurred(void)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 
 	return tstate->curexc_type;
 }
@@ -215,7 +217,7 @@
 			Py_DECREF(initial_tb);
 	}
 	/* normalize recursively */
-	tstate = PyThreadState_GET();
+	tstate = PyThreadState_Get();
 	if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
 	    --tstate->recursion_depth;
 	    PyErr_SetObject(PyExc_RuntimeError, PyExc_RecursionErrorInst);
@@ -225,11 +227,20 @@
 	--tstate->recursion_depth;
 }
 
+PyObject *
+PyErr_SimplifyException(PyObject *exc, PyObject *val, PyObject *tb)
+{
+    PyErr_NormalizeException(&exc, &val, &tb);
+    Py_DECREF(exc);
+    Py_XDECREF(tb);
+    return val;
+}
 
+
 void
 PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 
 	*p_type = tstate->curexc_type;
 	*p_value = tstate->curexc_value;
@@ -291,11 +302,6 @@
 #endif /* Unix/Windows */
 #endif /* PLAN 9*/
 
-#ifdef EINTR
-	if (i == EINTR && PyErr_CheckSignals())
-		return NULL;
-#endif
-
 #ifdef PLAN9
 	rerrstr(errbuf, sizeof errbuf);
 	message = PyUnicode_DecodeUTF8(errbuf, strlen(errbuf), "ignore");
Index: Python/ceval.c
===================================================================
--- Python/ceval.c	(revision 58355)
+++ Python/ceval.c	(working copy)
@@ -79,7 +79,7 @@
 
 #ifdef Py_DEBUG
 /* For debugging the interpreter: */
-#define LLTRACE  1	/* Low-level trace feature */
+//#define LLTRACE  1	/* Low-level trace feature */
 #define CHECKEXC 1	/* Double-check exception checking */
 #endif
 
@@ -87,11 +87,11 @@
 
 /* Forward declarations */
 #ifdef WITH_TSC
-static PyObject * call_function(PyObject ***, int, uint64*, uint64*);
+static PyObject * call_function(PyThreadState *, PyObject ***, int, uint64*, uint64*);
 #else
-static PyObject * call_function(PyObject ***, int);
+static PyObject * call_function(PyThreadState *, PyObject ***, int);
 #endif
-static PyObject * fast_function(PyObject *, PyObject ***, int, int, int);
+static PyObject * fast_function(PyThreadState *, PyObject *, PyObject ***, int, int, int);
 static PyObject * do_call(PyObject *, PyObject ***, int, int);
 static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int);
 static PyObject * update_keyword_args(PyObject *, int, PyObject ***,
@@ -199,222 +199,12 @@
 #endif
 
 
-#ifdef WITH_THREAD
-
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
 #include "pythread.h"
 
-static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */
-static long main_thread = 0;
 
-int
-PyEval_ThreadsInitialized(void)
-{
-	return interpreter_lock != 0;
-}
-
-void
-PyEval_InitThreads(void)
-{
-	if (interpreter_lock)
-		return;
-	interpreter_lock = PyThread_allocate_lock();
-	PyThread_acquire_lock(interpreter_lock, 1);
-	main_thread = PyThread_get_thread_ident();
-}
-
-void
-PyEval_AcquireLock(void)
-{
-	PyThread_acquire_lock(interpreter_lock, 1);
-}
-
-void
-PyEval_ReleaseLock(void)
-{
-	PyThread_release_lock(interpreter_lock);
-}
-
-void
-PyEval_AcquireThread(PyThreadState *tstate)
-{
-	if (tstate == NULL)
-		Py_FatalError("PyEval_AcquireThread: NULL new thread state");
-	/* Check someone has called PyEval_InitThreads() to create the lock */
-	assert(interpreter_lock);
-	PyThread_acquire_lock(interpreter_lock, 1);
-	if (PyThreadState_Swap(tstate) != NULL)
-		Py_FatalError(
-			"PyEval_AcquireThread: non-NULL old thread state");
-}
-
-void
-PyEval_ReleaseThread(PyThreadState *tstate)
-{
-	if (tstate == NULL)
-		Py_FatalError("PyEval_ReleaseThread: NULL thread state");
-	if (PyThreadState_Swap(NULL) != tstate)
-		Py_FatalError("PyEval_ReleaseThread: wrong thread state");
-	PyThread_release_lock(interpreter_lock);
-}
-
-/* This function is called from PyOS_AfterFork to ensure that newly
-   created child processes don't hold locks referring to threads which
-   are not running in the child process.  (This could also be done using
-   pthread_atfork mechanism, at least for the pthreads implementation.) */
-
-void
-PyEval_ReInitThreads(void)
-{
-	if (!interpreter_lock)
-		return;
-	/*XXX Can't use PyThread_free_lock here because it does too
-	  much error-checking.  Doing this cleanly would require
-	  adding a new function to each thread_*.h.  Instead, just
-	  create a new lock and waste a little bit of memory */
-	interpreter_lock = PyThread_allocate_lock();
-	PyThread_acquire_lock(interpreter_lock, 1);
-	main_thread = PyThread_get_thread_ident();
-}
-#endif
-
-/* Functions save_thread and restore_thread are always defined so
-   dynamically loaded modules needn't be compiled separately for use
-   with and without threads: */
-
-PyThreadState *
-PyEval_SaveThread(void)
-{
-	PyThreadState *tstate = PyThreadState_Swap(NULL);
-	if (tstate == NULL)
-		Py_FatalError("PyEval_SaveThread: NULL tstate");
-#ifdef WITH_THREAD
-	if (interpreter_lock)
-		PyThread_release_lock(interpreter_lock);
-#endif
-	return tstate;
-}
-
-void
-PyEval_RestoreThread(PyThreadState *tstate)
-{
-	if (tstate == NULL)
-		Py_FatalError("PyEval_RestoreThread: NULL tstate");
-#ifdef WITH_THREAD
-	if (interpreter_lock) {
-		int err = errno;
-		PyThread_acquire_lock(interpreter_lock, 1);
-		errno = err;
-	}
-#endif
-	PyThreadState_Swap(tstate);
-}
-
-
-/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
-   signal handlers or Mac I/O completion routines) can schedule calls
-   to a function to be called synchronously.
-   The synchronous function is called with one void* argument.
-   It should return 0 for success or -1 for failure -- failure should
-   be accompanied by an exception.
-
-   If registry succeeds, the registry function returns 0; if it fails
-   (e.g. due to too many pending calls) it returns -1 (without setting
-   an exception condition).
-
-   Note that because registry may occur from within signal handlers,
-   or other asynchronous events, calling malloc() is unsafe!
-
-#ifdef WITH_THREAD
-   Any thread can schedule pending calls, but only the main thread
-   will execute them.
-#endif
-
-   XXX WARNING!  ASYNCHRONOUSLY EXECUTING CODE!
-   There are two possible race conditions:
-   (1) nested asynchronous registry calls;
-   (2) registry calls made while pending calls are being processed.
-   While (1) is very unlikely, (2) is a real possibility.
-   The current code is safe against (2), but not against (1).
-   The safety against (2) is derived from the fact that only one
-   thread (the main thread) ever takes things out of the queue.
-
-   XXX Darn!  With the advent of thread state, we should have an array
-   of pending calls per thread in the thread state!  Later...
-*/
-
-#define NPENDINGCALLS 32
-static struct {
-	int (*func)(void *);
-	void *arg;
-} pendingcalls[NPENDINGCALLS];
-static volatile int pendingfirst = 0;
-static volatile int pendinglast = 0;
-static volatile int things_to_do = 0;
-
-int
-Py_AddPendingCall(int (*func)(void *), void *arg)
-{
-	static volatile int busy = 0;
-	int i, j;
-	/* XXX Begin critical section */
-	/* XXX If you want this to be safe against nested
-	   XXX asynchronous calls, you'll have to work harder! */
-	if (busy)
-		return -1;
-	busy = 1;
-	i = pendinglast;
-	j = (i + 1) % NPENDINGCALLS;
-	if (j == pendingfirst) {
-		busy = 0;
-		return -1; /* Queue full */
-	}
-	pendingcalls[i].func = func;
-	pendingcalls[i].arg = arg;
-	pendinglast = j;
-
-	_Py_Ticker = 0;
-	things_to_do = 1; /* Signal main loop */
-	busy = 0;
-	/* XXX End critical section */
-	return 0;
-}
-
-int
-Py_MakePendingCalls(void)
-{
-	static int busy = 0;
-#ifdef WITH_THREAD
-	if (main_thread && PyThread_get_thread_ident() != main_thread)
-		return 0;
-#endif
-	if (busy)
-		return 0;
-	busy = 1;
-	things_to_do = 0;
-	for (;;) {
-		int i;
-		int (*func)(void *);
-		void *arg;
-		i = pendingfirst;
-		if (i == pendinglast)
-			break; /* Queue empty */
-		func = pendingcalls[i].func;
-		arg = pendingcalls[i].arg;
-		pendingfirst = (i + 1) % NPENDINGCALLS;
-		if (func(arg) < 0) {
-			busy = 0;
-			things_to_do = 1; /* We're not done yet */
-			return -1;
-		}
-	}
-	busy = 0;
-	return 0;
-}
-
-
 /* The interpreter's recursion limit */
 
 #ifndef Py_DEFAULT_RECURSION_LIMIT
@@ -444,7 +234,7 @@
 int
 _Py_CheckRecursiveCall(char *where)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 
 #ifdef USE_STACKCHECK
 	if (PyOS_CheckStack()) {
@@ -491,8 +281,8 @@
 
 /* for manipulating the thread switch and periodic "stuff" - used to be
    per thread, now just a pair o' globals */
-int _Py_CheckInterval = 100;
-volatile int _Py_Ticker = 100;
+int _Py_CheckInterval = 10000;
+//volatile int _Py_Ticker = 100;
 
 PyObject *
 PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
@@ -528,14 +318,14 @@
 	register int oparg;	/* Current opcode argument, if any */
 	register enum why_code why; /* Reason for block stack unwind */
 	register int err;	/* Error status -- nonzero if error */
-	register PyObject *x;	/* Result object -- NULL if error */
+	PyObject *x;	/* Result object -- NULL if error */
 	register PyObject *v;	/* Temporary objects popped off stack */
 	register PyObject *w;
 	register PyObject *u;
 	register PyObject *t;
 	register PyObject **fastlocals, **freevars;
 	PyObject *retval = NULL;	/* Return value */
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyCodeObject *co;
 
 	/* when tracing we set things up so that
@@ -689,7 +479,7 @@
    variable would be pointing to already-freed memory. */
 #define SETLOCAL(i, value)	do { PyObject *tmp = GETLOCAL(i); \
 				     GETLOCAL(i) = value; \
-                                     Py_XDECREF(tmp); } while (0)
+                                     Py_XDECREFTS(tmp); } while (0)
 
 /* Start of code */
 
@@ -700,6 +490,7 @@
 	if (Py_EnterRecursiveCall(""))
 		return NULL;
 
+	//printf("%p's old %p replaced with f %p\n", tstate, tstate->frame, f);
 	tstate->frame = f;
 
 	if (tstate->use_tracing) {
@@ -801,63 +592,12 @@
 		assert(stack_pointer >= f->f_valuestack); /* else underflow */
 		assert(STACK_LEVEL() <= co->co_stacksize);  /* else overflow */
 
-		/* Do periodic things.  Doing this every time through
-		   the loop would add too much overhead, so we do it
-		   only every Nth instruction.  We also do it if
-		   ``things_to_do'' is set, i.e. when an asynchronous
-		   event needs attention (e.g. a signal handler or
-		   async I/O handler); see Py_AddPendingCall() and
-		   Py_MakePendingCalls() above. */
-
-		if (--_Py_Ticker < 0) {
-			if (*next_instr == SETUP_FINALLY) {
-				/* Make the last opcode before
-				   a try: finally: block uninterruptable. */
-				goto fast_next_opcode;
-			}
-			_Py_Ticker = _Py_CheckInterval;
-			tstate->tick_counter++;
-#ifdef WITH_TSC
-			ticked = 1;
-#endif
-			if (things_to_do) {
-				if (Py_MakePendingCalls() < 0) {
-					why = WHY_EXCEPTION;
-					goto on_error;
-				}
-				if (things_to_do)
-					/* MakePendingCalls() didn't succeed.
-					   Force early re-execution of this
-					   "periodic" code, possibly after
-					   a thread switch */
-					_Py_Ticker = 0;
-			}
-#ifdef WITH_THREAD
-			if (interpreter_lock) {
-				/* Give another thread a chance */
-
-				if (PyThreadState_Swap(NULL) != tstate)
-					Py_FatalError("ceval: tstate mix-up");
-				PyThread_release_lock(interpreter_lock);
-
-				/* Other threads may run now */
-
-				PyThread_acquire_lock(interpreter_lock, 1);
-				if (PyThreadState_Swap(tstate) != NULL)
-					Py_FatalError("ceval: orphan tstate");
-
-				/* Check for thread interrupts */
-
-				if (tstate->async_exc != NULL) {
-					x = tstate->async_exc;
-					tstate->async_exc = NULL;
-					PyErr_SetNone(x);
-					Py_DECREF(x);
-					why = WHY_EXCEPTION;
-					goto on_error;
-				}
-			}
-#endif
+		/* Check for asynchronous events, unless we're at the
+		 * last opcode before a try-finally block. */
+		if (*next_instr != SETUP_FINALLY && PyThreadState_Tick()) {
+			assert(PyErr_Occurred());
+			why = WHY_EXCEPTION;
+			goto on_error;
 		}
 
 	fast_next_opcode:
@@ -895,6 +635,7 @@
 			oparg = NEXTARG();
 	  dispatch_opcode:
 #ifdef DYNAMIC_EXECUTION_PROFILE
+#error bleh
 #ifdef DXPAIRS
 		dxpairs[lastopcode][opcode]++;
 		lastopcode = opcode;
@@ -903,6 +644,7 @@
 #endif
 
 #ifdef LLTRACE
+#error bleh lltrace
 		/* Instruction tracing */
 
 		if (lltrace) {
@@ -935,7 +677,7 @@
 		case LOAD_FAST:
 			x = GETLOCAL(oparg);
 			if (x != NULL) {
-				Py_INCREF(x);
+				Py_INCREFTS(x);
 				PUSH(x);
 				goto fast_next_opcode;
 			}
@@ -946,7 +688,7 @@
 
 		case LOAD_CONST:
 			x = GETITEM(consts, oparg);
-			Py_INCREF(x);
+			Py_INCREFTS(x);
 			PUSH(x);
 			goto fast_next_opcode;
 
@@ -959,7 +701,7 @@
 		PREDICTED(POP_TOP);
 		case POP_TOP:
 			v = POP();
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			goto fast_next_opcode;
 
 		case ROT_TWO:
@@ -991,27 +733,27 @@
 
 		case DUP_TOP:
 			v = TOP();
-			Py_INCREF(v);
+			Py_INCREFTS(v);
 			PUSH(v);
 			goto fast_next_opcode;
 
 		case DUP_TOPX:
 			if (oparg == 2) {
 				x = TOP();
-				Py_INCREF(x);
+				Py_INCREFTS(x);
 				w = SECOND();
-				Py_INCREF(w);
+				Py_INCREFTS(w);
 				STACKADJ(2);
 				SET_TOP(x);
 				SET_SECOND(w);
 				goto fast_next_opcode;
 			} else if (oparg == 3) {
 				x = TOP();
-				Py_INCREF(x);
+				Py_INCREFTS(x);
 				w = SECOND();
-				Py_INCREF(w);
+				Py_INCREFTS(w);
 				v = THIRD();
-				Py_INCREF(v);
+				Py_INCREFTS(v);
 				STACKADJ(3);
 				SET_TOP(x);
 				SET_SECOND(w);
@@ -1025,7 +767,7 @@
 		case UNARY_POSITIVE:
 			v = TOP();
 			x = PyNumber_Positive(v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1033,7 +775,7 @@
 		case UNARY_NEGATIVE:
 			v = TOP();
 			x = PyNumber_Negative(v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1041,14 +783,14 @@
 		case UNARY_NOT:
 			v = TOP();
 			err = PyObject_IsTrue(v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			if (err == 0) {
-				Py_INCREF(Py_True);
+				Py_INCREFTS(Py_True);
 				SET_TOP(Py_True);
 				continue;
 			}
 			else if (err > 0) {
-				Py_INCREF(Py_False);
+				Py_INCREFTS(Py_False);
 				SET_TOP(Py_False);
 				err = 0;
 				continue;
@@ -1059,7 +801,7 @@
 		case UNARY_INVERT:
 			v = TOP();
 			x = PyNumber_Invert(v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1068,8 +810,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Power(v, w, Py_None);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1078,8 +820,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Multiply(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1088,8 +830,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_TrueDivide(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1098,8 +840,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_FloorDivide(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1108,8 +850,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Remainder(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1137,9 +879,9 @@
 			  slow_add:
 				x = PyNumber_Add(v, w);
 			}
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 		  skip_decref_vx:
-			Py_DECREF(w);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1161,8 +903,8 @@
 			  slow_sub:
 				x = PyNumber_Subtract(v, w);
 			}
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1177,7 +919,7 @@
 					i += PyList_GET_SIZE(v);
 				if (i >= 0 && i < PyList_GET_SIZE(v)) {
 					x = PyList_GET_ITEM(v, i);
-					Py_INCREF(x);
+					Py_INCREFTS(x);
 				}
 				else
 					goto slow_get;
@@ -1185,8 +927,8 @@
 			else
 			  slow_get:
 				x = PyObject_GetItem(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1195,8 +937,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Lshift(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1205,8 +947,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Rshift(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1215,8 +957,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_And(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1225,8 +967,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Xor(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1235,8 +977,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_Or(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1245,8 +987,8 @@
 			w = POP();
 			v = POP();
 			err = PyList_Append(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			if (err == 0) {
 				PREDICT(JUMP_ABSOLUTE);
 				continue;
@@ -1257,8 +999,8 @@
 			w = POP();
 			v = POP();
 			err = PySet_Add(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			if (err == 0) {
 				PREDICT(JUMP_ABSOLUTE);
 				continue;
@@ -1269,8 +1011,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlacePower(v, w, Py_None);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1279,8 +1021,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceMultiply(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1289,8 +1031,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceTrueDivide(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1299,8 +1041,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceFloorDivide(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1309,8 +1051,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceRemainder(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1338,9 +1080,9 @@
 			  slow_iadd:
 				x = PyNumber_InPlaceAdd(v, w);
 			}
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 		  skip_decref_v:
-			Py_DECREF(w);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1362,8 +1104,8 @@
 			  slow_isub:
 				x = PyNumber_InPlaceSubtract(v, w);
 			}
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1372,8 +1114,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceLshift(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1382,8 +1124,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceRshift(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1392,8 +1134,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceAnd(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1402,8 +1144,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceXor(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1412,8 +1154,8 @@
 			w = POP();
 			v = TOP();
 			x = PyNumber_InPlaceOr(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1425,9 +1167,9 @@
 			STACKADJ(-3);
 			/* v[w] = u */
 			err = PyObject_SetItem(v, w, u);
-			Py_DECREF(u);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(u);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			if (err == 0) continue;
 			break;
 
@@ -1437,8 +1179,8 @@
 			STACKADJ(-2);
 			/* del v[w] */
 			err = PyObject_DelItem(v, w);
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			if (err == 0) continue;
 			break;
 
@@ -1458,12 +1200,12 @@
 			}
 			if (err == 0) {
 				w = PyEval_CallObject(w, x);
-				Py_XDECREF(w);
+				Py_XDECREFTS(w);
 				if (w == NULL)
 					err = -1;
 			}
-			Py_DECREF(v);
-			Py_XDECREF(x);
+			Py_DECREFTS(v);
+			Py_XDECREFTS(x);
 			break;
 
 #ifdef CASE_TOO_BIG
@@ -1490,7 +1232,7 @@
 		case STORE_LOCALS:
 			x = POP();
 			v = f->f_locals;
-			Py_XDECREF(v);
+			Py_XDECREFTS(v);
 			f->f_locals = x;
 			continue;
 
@@ -1510,7 +1252,7 @@
 				PyTryBlock *b = PyFrame_BlockPop(f);
 				while (STACK_LEVEL() > b->b_level) {
 					v = POP();
-					Py_DECREF(v);
+					Py_DECREFTS(v);
 				}
 			}
 			continue;
@@ -1536,18 +1278,19 @@
 					"'finally' pops bad exception");
 				why = WHY_EXCEPTION;
 			}
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			break;
 
 		case LOAD_BUILD_CLASS:
-			x = PyDict_GetItemString(f->f_builtins,
-						 "__build_class__");
+			if (PyDict_GetItemStringEx(f->f_builtins,
+					"__build_class__", &x) < 0)
+				break;
 			if (x == NULL) {
 				PyErr_SetString(PyExc_ImportError,
 						"__build_class__ not found");
 				break;
 			}
-			Py_INCREF(x);
+			/*Py_INCREFTS(x);*/
 			PUSH(x);
 			break;
 
@@ -1559,7 +1302,7 @@
 					err = PyDict_SetItem(x, w, v);
 				else
 					err = PyObject_SetItem(x, w, v);
-				Py_DECREF(v);
+				Py_DECREFTS(v);
 				if (err == 0) continue;
 				break;
 			}
@@ -1591,10 +1334,10 @@
 					((PyTupleObject *)v)->ob_item;
 				while (oparg--) {
 					w = items[oparg];
-					Py_INCREF(w);
+					Py_INCREFTS(w);
 					PUSH(w);
 				}
-				Py_DECREF(v);
+				Py_DECREFTS(v);
 				continue;
 			} else if (PyList_CheckExact(v) &&
 				   PyList_GET_SIZE(v) == oparg) {
@@ -1602,7 +1345,7 @@
 					((PyListObject *)v)->ob_item;
 				while (oparg--) {
 					w = items[oparg];
-					Py_INCREF(w);
+					Py_INCREFTS(w);
 					PUSH(w);
 				}
 			} else if (unpack_iterable(v, oparg, -1,
@@ -1612,7 +1355,7 @@
 				/* unpack_iterable() raised an exception */
 				why = WHY_EXCEPTION;
 			}
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			break;
 
 		case UNPACK_EX:
@@ -1626,7 +1369,7 @@
 			} else {
 				why = WHY_EXCEPTION;
 			}
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			break;
 		}
 
@@ -1636,8 +1379,8 @@
 			u = SECOND();
 			STACKADJ(-2);
 			err = PyObject_SetAttr(v, w, u); /* v.w = u */
-			Py_DECREF(v);
-			Py_DECREF(u);
+			Py_DECREFTS(v);
+			Py_DECREFTS(u);
 			if (err == 0) continue;
 			break;
 
@@ -1646,14 +1389,14 @@
 			v = POP();
 			err = PyObject_SetAttr(v, w, (PyObject *)NULL);
 							/* del v.w */
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			break;
 
 		case STORE_GLOBAL:
 			w = GETITEM(names, oparg);
 			v = POP();
 			err = PyDict_SetItem(f->f_globals, w, v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			if (err == 0) continue;
 			break;
 
@@ -1674,9 +1417,8 @@
 			}
 			if (PyDict_CheckExact(v)) {
 				x = PyDict_GetItem(v, w);
-				Py_XINCREF(x);
-			}
-			else {
+				Py_XINCREFTS(x);
+			} else {
 				x = PyObject_GetItem(v, w);
 				if (x == NULL && PyErr_Occurred()) {
 					if (!PyErr_ExceptionMatches(
@@ -1686,9 +1428,11 @@
 				}
 			}
 			if (x == NULL) {
-				x = PyDict_GetItem(f->f_globals, w);
+				if (PyDict_GetItemEx(f->f_globals, w, &x) < 0)
+					break;
 				if (x == NULL) {
-					x = PyDict_GetItem(f->f_builtins, w);
+					if (PyDict_GetItemEx(f->f_builtins, w, &x) < 0)
+						break;
 					if (x == NULL) {
 						format_exc_check_arg(
 							    PyExc_NameError,
@@ -1696,7 +1440,6 @@
 						break;
 					}
 				}
-				Py_INCREF(x);
 			}
 			PUSH(x);
 			continue;
@@ -1711,37 +1454,52 @@
 				if (hash != -1) {
 					PyDictObject *d;
 					PyDictEntry *e;
+					PyDict_LockState lockstate;
+
 					d = (PyDictObject *)(f->f_globals);
-					e = d->ma_lookup(d, w, hash);
+					_pydictlock_initstate_read(&lockstate);
+					_pydictlock_acquire(d, &lockstate);
+					e = d->ma_lookup(d, w, hash, &lockstate);
 					if (e == NULL) {
+						_pydictlock_release(d, &lockstate);
 						x = NULL;
 						break;
 					}
 					x = e->me_value;
 					if (x != NULL) {
-						Py_INCREF(x);
+						Py_INCREFTS(x);
+						_pydictlock_release(d, &lockstate);
 						PUSH(x);
 						continue;
 					}
+					_pydictlock_release(d, &lockstate);
+
 					d = (PyDictObject *)(f->f_builtins);
-					e = d->ma_lookup(d, w, hash);
+					_pydictlock_initstate_read(&lockstate);
+					_pydictlock_acquire(d, &lockstate);
+					e = d->ma_lookup(d, w, hash, &lockstate);
 					if (e == NULL) {
+						_pydictlock_release(d, &lockstate);
 						x = NULL;
 						break;
 					}
 					x = e->me_value;
 					if (x != NULL) {
-						Py_INCREF(x);
+						Py_INCREFTS(x);
+						_pydictlock_release(d, &lockstate);
 						PUSH(x);
 						continue;
 					}
+					_pydictlock_release(d, &lockstate);
 					goto load_global_error;
 				}
 			}
 			/* This is the un-inlined version of the code above */
-			x = PyDict_GetItem(f->f_globals, w);
+			if (PyDict_GetItemEx(f->f_builtins, w, &x) < 0)
+				break;
 			if (x == NULL) {
-				x = PyDict_GetItem(f->f_builtins, w);
+				if (PyDict_GetItemEx(f->f_builtins, w, &x) < 0)
+					break;
 				if (x == NULL) {
 				  load_global_error:
 					format_exc_check_arg(
@@ -1750,7 +1508,6 @@
 					break;
 				}
 			}
-			Py_INCREF(x);
 			PUSH(x);
 			continue;
 
@@ -1769,7 +1526,7 @@
 
 		case LOAD_CLOSURE:
 			x = freevars[oparg];
-			Py_INCREF(x);
+			Py_INCREFTS(x);
 			PUSH(x);
 			if (x != NULL) continue;
 			break;
@@ -1804,7 +1561,7 @@
 			w = POP();
 			x = freevars[oparg];
 			PyCell_Set(x, w);
-			Py_DECREF(w);
+			Py_DECREFTS(w);
 			continue;
 
 		case BUILD_TUPLE:
@@ -1838,10 +1595,10 @@
 					w = POP();
 					if (err == 0)
 						err = PySet_Add(x, w);
-					Py_DECREF(w);
+					Py_DECREFTS(w);
 				}
 				if (err != 0) {
-					Py_DECREF(x);
+					Py_DECREFTS(x);
 					break;
 				}
 				PUSH(x);
@@ -1863,7 +1620,7 @@
 					PyString_GET_SIZE(w));
 			else
 				x = NULL;
-			Py_DECREF(w);
+			Py_DECREFTS(w);
 			PUSH(x);
 			if (x != NULL) continue;
 			break;
@@ -1872,7 +1629,7 @@
 			w = GETITEM(names, oparg);
 			v = TOP();
 			x = PyObject_GetAttr(v, w);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -1898,14 +1655,14 @@
 				default: goto slow_compare;
 				}
 				x = res ? Py_True : Py_False;
-				Py_INCREF(x);
+				Py_INCREFTS(x);
 			}
 			else {
 			  slow_compare:
 				x = cmp_outcome(oparg, v, w);
 			}
-			Py_DECREF(v);
-			Py_DECREF(w);
+			Py_DECREFTS(v);
+			Py_DECREFTS(w);
 			SET_TOP(x);
 			if (x == NULL) break;
 			PREDICT(JUMP_IF_FALSE);
@@ -1914,7 +1671,9 @@
 
 		case IMPORT_NAME:
 			w = GETITEM(names, oparg);
-			x = PyDict_GetItemString(f->f_builtins, "__import__");
+			if (PyDict_GetItemStringEx(f->f_builtins,
+					"__import__", &x) < 0)
+				break;
 			if (x == NULL) {
 				PyErr_SetString(PyExc_ImportError,
 						"__import__ not found");
@@ -1937,19 +1696,20 @@
 					    f->f_locals == NULL ?
 						  Py_None : f->f_locals,
 					    v);
-			Py_DECREF(v);
-			Py_DECREF(u);
+			Py_DECREFTS(v);
+			Py_DECREFTS(u);
 			if (w == NULL) {
 				u = POP();
-				x = NULL;
+				Py_CLEARTS(x);
 				break;
 			}
 			READ_TIMESTAMP(intr0);
-			x = PyEval_CallObject(x, w);
+			v = PyEval_CallObject(x, w);
+			Py_CLEARTS(x);
 			READ_TIMESTAMP(intr1);
-			Py_DECREF(w);
-			SET_TOP(x);
-			if (x != NULL) continue;
+			Py_DECREFTS(w);
+			SET_TOP(v);
+			if (v != NULL) continue;
 			break;
 
 		case IMPORT_STAR:
@@ -1964,7 +1724,7 @@
 			err = import_all_from(x, v);
 			READ_TIMESTAMP(intr1);
 			PyFrame_LocalsToFast(f, 0);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			if (err == 0) continue;
 			break;
 
@@ -2033,7 +1793,7 @@
 			/* before: [obj]; after [getiter(obj)] */
 			v = TOP();
 			x = PyObject_GetIter(v);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			if (x != NULL) {
 				SET_TOP(x);
 				PREDICT(FOR_ITER);
@@ -2046,6 +1806,10 @@
 		case FOR_ITER:
 			/* before: [iter]; after: [iter, iter()] *or* [] */
 			v = TOP();
+			extern PyTypeObject PyFakeRange_Type;
+			if (v->ob_type == &PyFakeRange_Type) {
+				//printf("Moo %p %s %p %p %p %p\n", v, v->ob_type->tp_name, stack_pointer, next_instr, freevars, fastlocals);
+			}
 			x = (*v->ob_type->tp_iternext)(v);
 			if (x != NULL) {
 				PUSH(x);
@@ -2061,7 +1825,7 @@
 			}
 			/* iterator ended normally */
  			x = v = POP();
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			JUMPBY(oparg);
 			continue;
 
@@ -2126,20 +1890,20 @@
 				break; /* Go to error exit */
 			if (u != Py_None && PyObject_IsTrue(x)) {
 				/* There was an exception and a true return */
-				Py_DECREF(x);
+				Py_DECREFTS(x);
 				x = TOP(); /* Again */
 				STACKADJ(-3);
-				Py_INCREF(Py_None);
+				Py_INCREFTS(Py_None);
 				SET_TOP(Py_None);
-				Py_DECREF(x);
-				Py_DECREF(u);
-				Py_DECREF(v);
-				Py_DECREF(w);
+				Py_DECREFTS(x);
+				Py_DECREFTS(u);
+				Py_DECREFTS(v);
+				Py_DECREFTS(w);
 			} else {
 				/* Let END_FINALLY do its thing */
-				Py_DECREF(x);
+				Py_DECREFTS(x);
 				x = POP();
-				Py_DECREF(x);
+				Py_DECREFTS(x);
 			}
 			break;
 		}
@@ -2150,9 +1914,9 @@
 			PCALL(PCALL_ALL);
 			sp = stack_pointer;
 #ifdef WITH_TSC
-			x = call_function(&sp, oparg, &intr0, &intr1);
+			x = call_function(tstate, &sp, oparg, &intr0, &intr1);
 #else
-			x = call_function(&sp, oparg);
+			x = call_function(tstate, &sp, oparg);
 #endif
 			stack_pointer = sp;
 			PUSH(x);
@@ -2181,25 +1945,25 @@
 		    if (PyMethod_Check(func)
 			&& PyMethod_GET_SELF(func) != NULL) {
 			    PyObject *self = PyMethod_GET_SELF(func);
-			    Py_INCREF(self);
+			    Py_INCREFTS(self);
 			    func = PyMethod_GET_FUNCTION(func);
-			    Py_INCREF(func);
-			    Py_DECREF(*pfunc);
+			    Py_INCREFTS(func);
+			    Py_DECREFTS(*pfunc);
 			    *pfunc = self;
 			    na++;
 			    n++;
 		    } else
-			    Py_INCREF(func);
+			    Py_INCREFTS(func);
 		    sp = stack_pointer;
 		    READ_TIMESTAMP(intr0);
 		    x = ext_do_call(func, &sp, flags, na, nk);
 		    READ_TIMESTAMP(intr1);
 		    stack_pointer = sp;
-		    Py_DECREF(func);
+		    Py_DECREFTS(func);
 
 		    while (stack_pointer > pfunc) {
 			    w = POP();
-			    Py_DECREF(w);
+			    Py_DECREFTS(w);
 		    }
 		    PUSH(x);
 		    if (x != NULL)
@@ -2216,12 +1980,12 @@
 
 			v = POP(); /* code object */
 			x = PyFunction_New(v, f->f_globals);
-			Py_DECREF(v);
+			Py_DECREFTS(v);
 			
 			if (x != NULL && opcode == MAKE_CLOSURE) {
 				v = POP();
 				err = PyFunction_SetClosure(x, v);
-				Py_DECREF(v);
+				Py_DECREFTS(v);
 			}
 
 			if (x != NULL && num_annotations > 0) {
@@ -2229,7 +1993,7 @@
 				u = POP(); /* names of args with annotations */
 				v = PyDict_New();
 				if (v == NULL) {
-					Py_DECREF(x);
+					Py_DECREFTS(x);
 					x = NULL;
 					break;
 				}
@@ -2241,19 +2005,19 @@
 					w = POP();
 					/* XXX(nnorwitz): check for errors */
 					PyDict_SetItem(v, t, w);
-					Py_DECREF(w);
+					Py_DECREFTS(w);
 				}
 
 				err = PyFunction_SetAnnotations(x, v);
-				Py_DECREF(v);
-				Py_DECREF(u);
+				Py_DECREFTS(v);
+				Py_DECREFTS(u);
 			}
 
 			/* XXX Maybe this should be a separate opcode? */
 			if (x != NULL && posdefaults > 0) {
 				v = PyTuple_New(posdefaults);
 				if (v == NULL) {
-					Py_DECREF(x);
+					Py_DECREFTS(x);
 					x = NULL;
 					break;
 				}
@@ -2262,12 +2026,12 @@
 					PyTuple_SET_ITEM(v, posdefaults, w);
 				}
 				err = PyFunction_SetDefaults(x, v);
-				Py_DECREF(v);
+				Py_DECREFTS(v);
 			}
 			if (x != NULL && kwdefaults > 0) {
 				v = PyDict_New();
 				if (v == NULL) {
-					Py_DECREF(x);
+					Py_DECREFTS(x);
 					x = NULL;
 					break;
 				}
@@ -2276,11 +2040,11 @@
 					u = POP(); /* kw only arg name */
 					/* XXX(nnorwitz): check for errors */
 					PyDict_SetItem(v, u, w);
-					Py_DECREF(w);
-					Py_DECREF(u);
+					Py_DECREFTS(w);
+					Py_DECREFTS(u);
 				}
 				err = PyFunction_SetKwDefaults(x, v);
-				Py_DECREF(v);
+				Py_DECREFTS(v);
 			}
 			PUSH(x);
 			break;
@@ -2294,9 +2058,9 @@
 			v = POP();
 			u = TOP();
 			x = PySlice_New(u, v, w);
-			Py_DECREF(u);
-			Py_DECREF(v);
-			Py_XDECREF(w);
+			Py_DECREFTS(u);
+			Py_DECREFTS(v);
+			Py_XDECREFTS(w);
 			SET_TOP(x);
 			if (x != NULL) continue;
 			break;
@@ -2397,13 +2161,13 @@
 						   b->b_level);
 				why = WHY_NOT;
 				JUMPTO(PyInt_AS_LONG(retval));
-				Py_DECREF(retval);
+				Py_DECREFTS(retval);
 				break;
 			}
 
 			while (STACK_LEVEL() > b->b_level) {
 				v = POP();
-				Py_XDECREF(v);
+				Py_XDECREFTS(v);
 			}
 			if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
 				why = WHY_NOT;
@@ -2418,7 +2182,7 @@
 					PyErr_Fetch(&exc, &val, &tb);
 					if (val == NULL) {
 						val = Py_None;
-						Py_INCREF(val);
+						Py_INCREFTS(val);
 					}
 					/* Make the raw exception data
 					   available to the handler,
@@ -2432,7 +2196,7 @@
 							     exc, val, tb);
 					}
 					if (tb == NULL) {
-						Py_INCREF(Py_None);
+						Py_INCREFTS(Py_None);
 						PUSH(Py_None);
 					} else
 						PUSH(tb);
@@ -2463,7 +2227,7 @@
 	/* Pop remaining stack entries. */
 	while (!EMPTY()) {
 		v = POP();
-		Py_XDECREF(v);
+		Py_XDECREFTS(v);
 	}
 
 	if (why != WHY_RETURN)
@@ -2476,7 +2240,7 @@
 				if (call_trace(tstate->c_tracefunc,
 					       tstate->c_traceobj, f,
 					       PyTrace_RETURN, retval)) {
-					Py_XDECREF(retval);
+					Py_XDECREFTS(retval);
 					retval = NULL;
 					why = WHY_EXCEPTION;
 				}
@@ -2495,7 +2259,7 @@
 			else if (call_trace(tstate->c_profilefunc,
 					    tstate->c_profileobj, f,
 					    PyTrace_RETURN, retval)) {
-				Py_XDECREF(retval);
+				Py_XDECREFTS(retval);
 				retval = NULL;
 				why = WHY_EXCEPTION;
 			}
@@ -2512,6 +2276,7 @@
 	/* pop frame */
 exit_eval_frame:
 	Py_LeaveRecursiveCall();
+	//printf("%p's old %p replaced with f->f_back %p\n", tstate, tstate->frame, f->f_back);
 	tstate->frame = f->f_back;
 
 	return retval;
@@ -2529,7 +2294,7 @@
 	register PyFrameObject *f;
 	register PyObject *retval = NULL;
 	register PyObject **fastlocals, **freevars;
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *x, *u;
 
 	if (globals == NULL) {
@@ -2579,7 +2344,7 @@
 		}
 		for (i = 0; i < n; i++) {
 			x = args[i];
-			Py_INCREF(x);
+			Py_INCREFTS(x);
 			SETLOCAL(i, x);
 		}
 		if (co->co_flags & CO_VARARGS) {
@@ -2589,7 +2354,7 @@
 			SETLOCAL(co->co_argcount + co->co_kwonlyargcount, u);
 			for (i = n; i < argcount; i++) {
 				x = args[i];
-				Py_INCREF(x);
+				Py_INCREFTS(x);
 				PyTuple_SET_ITEM(u, i-n, x);
 			}
 		}
@@ -2640,7 +2405,7 @@
 					     keyword);
 					goto fail;
 				}
-				Py_INCREF(value);
+				Py_INCREFTS(value);
 				SETLOCAL(j, value);
 			}
 		}
@@ -2656,7 +2421,7 @@
 				if (kwdefs != NULL)
 					def = PyDict_GetItem(kwdefs, name);
 				if (def != NULL) {
-					Py_INCREF(def);
+					Py_INCREFTS(def);
 					SETLOCAL(i, def);
 					continue;
 				}
@@ -2690,7 +2455,7 @@
 			for (; i < defcount; i++) {
 				if (GETLOCAL(m+i) == NULL) {
 					PyObject *def = defs[i];
-					Py_INCREF(def);
+					Py_INCREFTS(def);
 					SETLOCAL(m+i, def);
 				}
 			}
@@ -2753,7 +2518,7 @@
 		int i;
 		for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
 			PyObject *o = PyTuple_GET_ITEM(closure, i);
-			Py_INCREF(o);
+			Py_INCREFTS(o);
 			freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
 		}
 	}
@@ -2761,7 +2526,7 @@
 	if (co->co_flags & CO_GENERATOR) {
 		/* Don't need to keep the reference to f_back, it will be set
 		 * when the generator is resumed. */
-		Py_XDECREF(f->f_back);
+		Py_XDECREFTS(f->f_back);
 		f->f_back = NULL;
 
 		PCALL(PCALL_GENERATOR);
@@ -2782,7 +2547,7 @@
 	*/
 	assert(tstate != NULL);
 	++tstate->recursion_depth;
-	Py_DECREF(f);
+	Py_DECREFTS(f);
 	--tstate->recursion_depth;
 	return retval;
 }
@@ -2866,12 +2631,12 @@
 		/* Save previous exception of this thread in this frame. */
 		if (tstate->exc_type == NULL) {
 			/* XXX Why is this set to Py_None? */
-			Py_INCREF(Py_None);
+			Py_INCREFTS(Py_None);
 			tstate->exc_type = Py_None;
 		}
-		Py_INCREF(tstate->exc_type);
-		Py_XINCREF(tstate->exc_value);
-		Py_XINCREF(tstate->exc_traceback);
+		Py_INCREFTS(tstate->exc_type);
+		Py_XINCREFTS(tstate->exc_value);
+		Py_XINCREFTS(tstate->exc_traceback);
 		frame->f_exc_type = tstate->exc_type;
 		frame->f_exc_value = tstate->exc_value;
 		frame->f_exc_traceback = tstate->exc_traceback;
@@ -2880,16 +2645,16 @@
 	tmp_type = tstate->exc_type;
 	tmp_value = tstate->exc_value;
 	tmp_tb = tstate->exc_traceback;
-	Py_INCREF(type);
-	Py_XINCREF(value);
-	Py_XINCREF(tb);
+	Py_INCREFTS(type);
+	Py_XINCREFTS(value);
+	Py_XINCREFTS(tb);
 	tstate->exc_type = type;
 	tstate->exc_value = value;
 	tstate->exc_traceback = tb;
 	PyException_SetTraceback(value, tb);
-	Py_XDECREF(tmp_type);
-	Py_XDECREF(tmp_value);
-	Py_XDECREF(tmp_tb);
+	Py_XDECREFTS(tmp_type);
+	Py_XDECREFTS(tmp_value);
+	Py_XDECREFTS(tmp_tb);
 }
 
 static void
@@ -2910,15 +2675,15 @@
 	tmp_type = tstate->exc_type;
 	tmp_value = tstate->exc_value;
 	tmp_tb = tstate->exc_traceback;
-	Py_INCREF(frame->f_exc_type);
-	Py_XINCREF(frame->f_exc_value);
-	Py_XINCREF(frame->f_exc_traceback);
+	Py_INCREFTS(frame->f_exc_type);
+	Py_XINCREFTS(frame->f_exc_value);
+	Py_XINCREFTS(frame->f_exc_traceback);
 	tstate->exc_type = frame->f_exc_type;
 	tstate->exc_value = frame->f_exc_value;
 	tstate->exc_traceback = frame->f_exc_traceback;
-	Py_XDECREF(tmp_type);
-	Py_XDECREF(tmp_value);
-	Py_XDECREF(tmp_tb);
+	Py_XDECREFTS(tmp_type);
+	Py_XDECREFTS(tmp_value);
+	Py_XDECREFTS(tmp_tb);
 
 	/* Clear the frame's exception info. */
 	tmp_type = frame->f_exc_type;
@@ -2927,9 +2692,9 @@
 	frame->f_exc_type = NULL;
 	frame->f_exc_value = NULL;
 	frame->f_exc_traceback = NULL;
-	Py_DECREF(tmp_type);
-	Py_XDECREF(tmp_value);
-	Py_XDECREF(tmp_tb);
+	Py_DECREFTS(tmp_type);
+	Py_XDECREFTS(tmp_value);
+	Py_XDECREFTS(tmp_tb);
 }
 
 /* Logic for the raise statement (too complicated for inlining).
@@ -2941,7 +2706,7 @@
 
 	if (exc == NULL) {
 		/* Reraise */
-		PyThreadState *tstate = PyThreadState_GET();
+		PyThreadState *tstate = PyThreadState_Get();
 		type = tstate->exc_type;
 		value = tstate->exc_value;
 		tb = tstate->exc_traceback;
@@ -2985,16 +2750,26 @@
 	tb = PyException_GetTraceback(value);
 	if (cause) {
 		PyObject *fixed_cause;
+		int i;
 		if (PyExceptionClass_Check(cause)) {
 			fixed_cause = PyObject_CallObject(cause, NULL);
 			if (fixed_cause == NULL)
 				goto raise_error;
 			Py_DECREF(cause);
-		}
-		else if (PyExceptionInstance_Check(cause)) {
+		} else if (PyExceptionInstance_Check(cause)) {
 			fixed_cause = cause;
-		}
-		else {
+		} else if (PyTuple_Check(cause)) {
+			for (i = 0; i < PyTuple_GET_SIZE(cause); i++) {
+				PyObject *ob = PyTuple_GET_ITEM(cause, i);
+				if (!PyExceptionInstance_Check(ob)) {
+					PyErr_SetString(PyExc_TypeError,
+						"exception causes must "
+						"derive from BaseException");
+					goto raise_error;
+				}
+			}
+			fixed_cause = cause;
+		} else {
 			PyErr_SetString(PyExc_TypeError,
 					"exception causes must derive from "
 					"BaseException");
@@ -3220,14 +2995,14 @@
 void
 PyEval_SetProfile(Py_tracefunc func, PyObject *arg)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *temp = tstate->c_profileobj;
-	Py_XINCREF(arg);
+	Py_XINCREFTS(arg);
 	tstate->c_profilefunc = NULL;
 	tstate->c_profileobj = NULL;
 	/* Must make sure that tracing is not ignored if 'temp' is freed */
 	tstate->use_tracing = tstate->c_tracefunc != NULL;
-	Py_XDECREF(temp);
+	Py_XDECREFTS(temp);
 	tstate->c_profilefunc = func;
 	tstate->c_profileobj = arg;
 	/* Flag that tracing or profiling is turned on */
@@ -3237,14 +3012,14 @@
 void
 PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *temp = tstate->c_traceobj;
-	Py_XINCREF(arg);
+	Py_XINCREFTS(arg);
 	tstate->c_tracefunc = NULL;
 	tstate->c_traceobj = NULL;
 	/* Must make sure that profiling is not ignored if 'temp' is freed */
 	tstate->use_tracing = tstate->c_profilefunc != NULL;
-	Py_XDECREF(temp);
+	Py_XDECREFTS(temp);
 	tstate->c_tracefunc = func;
 	tstate->c_traceobj = arg;
 	/* Flag that tracing or profiling is turned on */
@@ -3257,7 +3032,7 @@
 {
 	PyFrameObject *current_frame = PyEval_GetFrame();
 	if (current_frame == NULL)
-		return PyThreadState_GET()->interp->builtins;
+		return PyThreadState_Get()->interp->builtins;
 	else
 		return current_frame->f_builtins;
 }
@@ -3285,7 +3060,7 @@
 PyFrameObject *
 PyEval_GetFrame(void)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	return _PyThreadState_GetFrame(tstate);
 }
 
@@ -3431,7 +3206,7 @@
 	}
 
 static PyObject *
-call_function(PyObject ***pp_stack, int oparg
+call_function(PyThreadState *tstate, PyObject ***pp_stack, int oparg
 #ifdef WITH_TSC
 		, uint64* pintr0, uint64* pintr1
 #endif
@@ -3449,7 +3224,6 @@
 	*/
 	if (PyCFunction_Check(func) && nk == 0) {
 		int flags = PyCFunction_GET_FLAGS(func);
-		PyThreadState *tstate = PyThreadState_GET();
 
 		PCALL(PCALL_CFUNCTION);
 		if (flags & (METH_NOARGS | METH_O)) {
@@ -3461,7 +3235,7 @@
 			else if (flags & METH_O && na == 1) {
 				PyObject *arg = EXT_POP(*pp_stack);
 				C_TRACE(x, (*meth)(self,arg));
-				Py_DECREF(arg);
+				Py_DECREFTS(arg);
 			}
 			else {
 				err_args(func, flags, na);
@@ -3474,7 +3248,7 @@
 			READ_TIMESTAMP(*pintr0);
 			C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
 			READ_TIMESTAMP(*pintr1);
-			Py_XDECREF(callargs);
+			Py_XDECREFTS(callargs);
 		}
 	} else {
 		if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
@@ -3482,22 +3256,22 @@
 			PyObject *self = PyMethod_GET_SELF(func);
 			PCALL(PCALL_METHOD);
 			PCALL(PCALL_BOUND_METHOD);
-			Py_INCREF(self);
+			Py_INCREFTS(self);
 			func = PyMethod_GET_FUNCTION(func);
-			Py_INCREF(func);
-			Py_DECREF(*pfunc);
+			Py_INCREFTS(func);
+			Py_DECREFTS(*pfunc);
 			*pfunc = self;
 			na++;
 			n++;
 		} else
-			Py_INCREF(func);
+			Py_INCREFTS(func);
 		READ_TIMESTAMP(*pintr0);
 		if (PyFunction_Check(func))
-			x = fast_function(func, pp_stack, n, na, nk);
+			x = fast_function(tstate, func, pp_stack, n, na, nk);
 		else
 			x = do_call(func, pp_stack, na, nk);
 		READ_TIMESTAMP(*pintr1);
-		Py_DECREF(func);
+		Py_DECREFTS(func);
 	}
 
 	/* Clear the stack of the function object.  Also removes
@@ -3506,7 +3280,7 @@
 	 */
 	while ((*pp_stack) > pfunc) {
 		w = EXT_POP(*pp_stack);
-		Py_DECREF(w);
+		Py_DECREFTS(w);
 		PCALL(PCALL_POP);
 	}
 	return x;
@@ -3522,7 +3296,7 @@
 */
 
 static PyObject *
-fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
+fast_function(PyThreadState *tstate, PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
 {
 	PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
 	PyObject *globals = PyFunction_GET_GLOBALS(func);
@@ -3538,7 +3312,6 @@
 	    co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
 		PyFrameObject *f;
 		PyObject *retval = NULL;
-		PyThreadState *tstate = PyThreadState_GET();
 		PyObject **fastlocals, **stack;
 		int i;
 
@@ -3557,12 +3330,12 @@
 		stack = (*pp_stack) - n;
 
 		for (i = 0; i < n; i++) {
-			Py_INCREF(*stack);
+			Py_INCREFTS(*stack);
 			fastlocals[i] = *stack++;
 		}
 		retval = PyEval_EvalFrameEx(f,0);
 		++tstate->recursion_depth;
-		Py_DECREF(f);
+		Py_DECREFTS(f);
 		--tstate->recursion_depth;
 		return retval;
 	}
@@ -3966,6 +3739,7 @@
 {
 	/* This function implements 'variable += expr' when both arguments
 	   are strings. */
+	PyThreadState *tstate = PyThreadState_Get();
 	Py_ssize_t v_len = PyString_GET_SIZE(v);
 	Py_ssize_t w_len = PyString_GET_SIZE(w);
 	Py_ssize_t new_len = v_len + w_len;
@@ -3975,7 +3749,7 @@
 		return NULL;
 	}
 
-	if (v->ob_refcnt == 2) {
+	if (Py_RefcntMatches(v, 2)) {
 		/* In the common case, there are 2 references to the value
 		 * stored in 'variable' when the += is performed: one on the
 		 * value stack (in 'v') and one still stored in the
@@ -4016,7 +3790,7 @@
 		}
 	}
 
-	if (v->ob_refcnt == 1 && !PyString_CHECK_INTERNED(v)) {
+	if (Py_RefcntMatches(v, 1) && !_PyString_SnoopState((PyStringObject *)v)) {
 		/* Now we own the last reference to 'v', so we can resize it
 		 * in-place.
 		 */
Index: Python/getargs.c
===================================================================
--- Python/getargs.c	(revision 58355)
+++ Python/getargs.c	(working copy)
@@ -1846,6 +1846,90 @@
 			funcname);
 	return 0;
 }
+
+
+/* We assume args and kw were both constructed by other
+ * argument functions and neither can be modified while
+ * we iterate over them.
+ */
+int
+PyArg_RequireShareable(const char *funcname, PyObject *args, PyObject *kwargs)
+{
+	assert (args != NULL || kwargs != NULL);
+
+	if (args != NULL) {
+		Py_ssize_t i;
+		Py_ssize_t size = PyTuple_Size(args);
+		for (i = 0; i < size; i++) {
+			if (!PyObject_IsShareable(PyTuple_GetItem(args, i))) {
+				PyErr_Format(PyExc_TypeError, "%s requires "
+					"shareable arguments; positional "
+					"argument %d is not shareable",
+					funcname, i+1);
+				return 0;
+			}
+		}
+	}
+
+	if (kwargs != NULL) {
+		PyObject *key, *value;
+		Py_ssize_t pos = 0;
+		while (PyDict_Next(kwargs, &pos, &key, &value)) {
+			if (!PyObject_IsShareable(key)) {
+				char *ks = PyString_AsString(key);
+				PyErr_Format(PyExc_TypeError, "%s requires "
+					"shareable arguments; keyword "
+					"argument %s's key is not shareable",
+					funcname, ks);
+				return 0;
+			}
+			if (!PyObject_IsShareable(value)) {
+				char *ks = PyString_AsString(key);
+				PyErr_Format(PyExc_TypeError, "%s requires "
+					"shareable arguments; keyword "
+					"argument %s's value is not shareable",
+					funcname, ks);
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+/* funcname is the outer function (written in C) which wants a shareable object.
+ * innerfunc is the inner function that just returned a (hopefully) shareable object.
+ * The error context will be checked AND CHANGED to be shareable.
+ */
+int
+PyArg_RequireShareableReturn(const char *funcname, PyObject *innerfunc, PyObject *result)
+{
+	if (result != NULL) {
+		if (PyErr_Occurred())
+			Py_FatalError("Both exception and return value set");
+
+		if (PyObject_IsShareable(result))
+			return 1;
+
+		if (PyFunction_Check(innerfunc)) {
+			char *innerfuncname = PyString_AsString(
+				((PyFunctionObject *)innerfunc)->func_name);
+			PyErr_Format(PyExc_TypeError, "%s given unshareable return "
+				"value by %s()", funcname, innerfuncname);
+		} else
+			PyErr_Format(PyExc_TypeError, "%s given unshareable return "
+				"value by callable", funcname);
+
+		return 0;
+	} else {
+		if (!PyErr_Occurred())
+			Py_FatalError("Neither exception nor return value set");
+
+		/* XXX FIXME */
+		return 1;
+	}
+}
+
 #ifdef __cplusplus
 };
 #endif
Index: Python/traceback.c
===================================================================
--- Python/traceback.c	(revision 58355)
+++ Python/traceback.c	(working copy)
@@ -34,12 +34,9 @@
 static void
 tb_dealloc(PyTracebackObject *tb)
 {
-	PyObject_GC_UnTrack(tb);
-	Py_TRASHCAN_SAFE_BEGIN(tb)
 	Py_XDECREF(tb->tb_next);
 	Py_XDECREF(tb->tb_frame);
-	PyObject_GC_Del(tb);
-	Py_TRASHCAN_SAFE_END(tb)
+	PyObject_DEL(tb);
 }
 
 static int
@@ -101,7 +98,7 @@
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
+	tb = PyObject_NEW(PyTracebackObject, &PyTraceBack_Type);
 	if (tb != NULL) {
 		Py_XINCREF(next);
 		tb->tb_next = next;
@@ -110,7 +107,6 @@
 		tb->tb_lasti = frame->f_lasti;
 		tb->tb_lineno = PyCode_Addr2Line(frame->f_code, 
 						 frame->f_lasti);
-		PyObject_GC_Track(tb);
 	}
 	return tb;
 }
@@ -118,7 +114,7 @@
 int
 PyTraceBack_Here(PyFrameObject *frame)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
 	PyTracebackObject *tb = newtracebackobject(oldtb, frame);
 	if (tb == NULL)
@@ -181,7 +177,13 @@
 		}
 	}
 	PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
-	err = PyFile_WriteString(linebuf, f);
+
+	if (f == NULL) {
+		PySys_WriteStderr("%s", linebuf);
+		err = 0;
+	} else
+		err = PyFile_WriteString(linebuf, f);
+
 	if (xfp == NULL)
 		return err;
 	else if (err != 0) {
@@ -236,8 +238,6 @@
 		}
 		depth--;
 		tb = tb->tb_next;
-		if (err == 0)
-			err = PyErr_CheckSignals();
 	}
 	return err;
 }
@@ -260,7 +260,13 @@
 		if (limit <= 0)
 			return 0;
 	}
-	err = PyFile_WriteString("Traceback (most recent call last):\n", f);
+
+	if (f == NULL) {
+		PySys_WriteStderr("Traceback (most recent call last):\n");
+		err = 0;
+	} else
+		err = PyFile_WriteString("Traceback (most recent call last):\n", f);
+
 	if (!err)
 		err = tb_printinternal((PyTracebackObject *)v, f, limit);
 	return err;
Index: Python/sigcheck.c
===================================================================
--- Python/sigcheck.c	(revision 58355)
+++ Python/sigcheck.c	(working copy)
@@ -1,19 +0,0 @@
-
-/* Sigcheck is similar to intrcheck() but sets an exception when an
-   interrupt occurs.  It can't be in the intrcheck.c file since that
-   file (and the whole directory it is in) doesn't know about objects
-   or exceptions.  It can't be in errors.c because it can be
-   overridden (at link time) by a more powerful version implemented in
-   signalmodule.c. */
-
-#include "Python.h"
-
-/* ARGSUSED */
-int
-PyErr_CheckSignals(void)
-{
-	if (!PyOS_InterruptOccurred())
-		return 0;
-	PyErr_SetNone(PyExc_KeyboardInterrupt);
-	return -1;
-}
Index: Python/thread_pthread.h
===================================================================
--- Python/thread_pthread.h	(revision 58355)
+++ Python/thread_pthread.h	(working copy)
@@ -106,6 +106,7 @@
 } pthread_lock;
 
 #define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
+#define CHECK_STATUS_ABORT(name)  if (status != 0) { perror(name); abort(); }
 
 /*
  * Initialization.
@@ -144,18 +145,21 @@
  */
 
 
-long
-PyThread_start_new_thread(void (*func)(void *), void *arg)
+int
+PyThread_start_new_thread(PyThread_type_handle *handle, void (*func)(void *), void *arg)
 {
-	pthread_t th;
+	PyThread_type_handle dummy_handle;
 	int status;
 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 	pthread_attr_t attrs;
 #endif
 #if defined(THREAD_STACK_SIZE)
-	size_t	tss;
+	size_t tss;
 #endif
 
+	if (handle == NULL)
+		handle = &dummy_handle;
+
 	dprintf(("PyThread_start_new_thread called\n"));
 	if (!initialized)
 		PyThread_init_thread();
@@ -178,7 +182,7 @@
         pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
 #endif
 
-	status = pthread_create(&th, 
+	status = pthread_create(&handle->_value,
 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 				 &attrs,
 #else
@@ -194,133 +198,199 @@
 	if (status != 0)
             return -1;
 
-        pthread_detach(th);
+        pthread_detach(handle->_value);
 
-#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
-	return (long) th;
-#else
-	return (long) *(long *) &th;
-#endif
+        return 0;
 }
 
-/* XXX This implementation is considered (to quote Tim Peters) "inherently
-   hosed" because:
-     - It does not guarantee the promise that a non-zero integer is returned.
-     - The cast to long is inherently unsafe.
-     - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
-       latter return statement (for Alpha OSF/1) are any longer necessary.
-*/
-long 
-PyThread_get_thread_ident(void)
+PyThread_type_handle
+PyThread_get_handle(void)
 {
-	volatile pthread_t threadid;
-	if (!initialized)
-		PyThread_init_thread();
-	/* Jump through some hoops for Alpha OSF/1 */
-	threadid = pthread_self();
-#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
-	return (long) threadid;
-#else
-	return (long) *(long *) &threadid;
-#endif
+    PyThread_type_handle handle;
+    handle._value = pthread_self();
+    return handle;
 }
 
-static void 
-do_PyThread_exit_thread(int no_cleanup)
+void
+PyThread_send_signal(PyThread_type_handle handle, int signum)
 {
-	dprintf(("PyThread_exit_thread called\n"));
-	if (!initialized) {
-		if (no_cleanup)
-			_exit(0);
-		else
-			exit(0);
-	}
+    int status = pthread_kill(handle._value, signum);
+    if (status < 0) {
+        fprintf(stderr, "pthread_kill failed with %d\n", errno);
+        Py_FatalError("PyThread_send_signal failed calling pthread_kill");
+    }
 }
 
-void 
-PyThread_exit_thread(void)
+
+/*
+ * Lock support.
+ */
+
+PyThread_type_lock
+PyThread_lock_allocate(void)
 {
-	do_PyThread_exit_thread(0);
+	//sem_t *lock;
+	pthread_mutex_t *lock;
+	int status, error = 0;
+
+	dprintf(("PyThread_allocate_lock called\n"));
+	if (!initialized)
+		PyThread_init_thread();
+
+	//lock = (sem_t *)malloc(sizeof(sem_t));
+	lock = malloc(sizeof(pthread_mutex_t));
+
+	if (lock) {
+		//status = sem_init(lock,0,1);
+		status = pthread_mutex_init(lock, NULL);
+		CHECK_STATUS("pthread_mutex_init");
+
+		if (error) {
+			free((void *)lock);
+			lock = NULL;
+		}
+	}
+
+	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
+	return (PyThread_type_lock)lock;
 }
 
-void 
-PyThread__exit_thread(void)
+void
+PyThread_lock_free(PyThread_type_lock lock)
 {
-	do_PyThread_exit_thread(1);
+	//sem_t *thelock = (sem_t *)lock;
+	pthread_mutex_t *thelock = (pthread_mutex_t *)lock;
+	int status;
+
+	dprintf(("PyThread_free_lock(%p) called\n", lock));
+
+	if (!thelock)
+		return;
+
+	//status = sem_destroy(thelock);
+	status = pthread_mutex_destroy(thelock);
+	CHECK_STATUS_ABORT("pthread_mutex_destroy");
+
+	free((void *)thelock);
 }
 
-#ifndef NO_EXIT_PROG
-static void 
-do_PyThread_exit_prog(int status, int no_cleanup)
+#include <execinfo.h>
+
+void
+PyThread_lock_acquire(PyThread_type_lock lock)
 {
-	dprintf(("PyThread_exit_prog(%d) called\n", status));
-	if (!initialized)
-		if (no_cleanup)
-			_exit(status);
-		else
-			exit(status);
+	//sem_t *thelock = (sem_t *)lock;
+	pthread_mutex_t *thelock = (pthread_mutex_t *)lock;
+	int status;
+	static unsigned long long count;
+
+#if 0
+	count++;
+	if ((count % 10000) == 0) {
+		void *scratch[10] = {};
+		printf("PyThread_lock_acquire: %llu\n", count);
+		backtrace(scratch, 10);
+		backtrace_symbols_fd(scratch, 2, 1);
+		printf("*****\n");
+	}
+#endif
+
+	dprintf(("PyThread_acquire_lock(%p) called\n", lock));
+
+	//if (!waitflag)
+	//	abort();
+	status = pthread_mutex_lock(thelock);
+	CHECK_STATUS_ABORT("pthread_mutex_lock");
+
+	dprintf(("PyThread_acquire_lock(%p)\n", lock));
 }
 
-void 
-PyThread_exit_prog(int status)
+/* This is only temporary, until a better interface is available to those
+ * who need such functionality. */
+int
+_PyThread_lock_tryacquire(PyThread_type_lock lock)
 {
-	do_PyThread_exit_prog(status, 0);
+	int success;
+	//sem_t *thelock = (sem_t *)lock;
+	pthread_mutex_t *thelock = (pthread_mutex_t *)lock;
+	int status;
+
+	dprintf(("PyThread_tryacquire_lock(%p) called\n", lock));
+
+	//if (!waitflag)
+	//	abort();
+	status = pthread_mutex_trylock(thelock);
+	if (status != EBUSY)
+		CHECK_STATUS_ABORT("pthread_mutex_trylock");
+
+	success = (status == 0) ? 1 : 0;
+	dprintf(("PyThread_tryacquire_lock(%p) -> %d\n", lock, success));
+	return success;
 }
 
-void 
-PyThread__exit_prog(int status)
+void
+PyThread_lock_release(PyThread_type_lock lock)
 {
-	do_PyThread_exit_prog(status, 1);
+	//sem_t *thelock = (sem_t *)lock;
+	pthread_mutex_t *thelock = (pthread_mutex_t *)lock;
+	int status;
+
+	dprintf(("PyThread_release_lock(%p) called\n", lock));
+
+	//status = sem_post(thelock);
+	status = pthread_mutex_unlock(thelock);
+	CHECK_STATUS_ABORT("pthread_mutex_unlock");
 }
-#endif /* NO_EXIT_PROG */
 
-#ifdef USE_SEMAPHORES
 
 /*
- * Lock support.
+ * Semaphore support.
  */
 
-PyThread_type_lock 
-PyThread_allocate_lock(void)
+PyThread_type_sem
+PyThread_sem_allocate(int initial_value)
 {
-	sem_t *lock;
+	sem_t *sem;
 	int status, error = 0;
 
-	dprintf(("PyThread_allocate_lock called\n"));
+	dprintf(("PyThread_sem_allocate called\n"));
 	if (!initialized)
 		PyThread_init_thread();
 
-	lock = (sem_t *)malloc(sizeof(sem_t));
+	if (initial_value < 0 || initial_value > 1)
+		Py_FatalError("PyThread_sem_allocate given invalid initial_value");
 
-	if (lock) {
-		status = sem_init(lock,0,1);
+	sem = malloc(sizeof(sem_t));
+
+	if (sem) {
+		status = sem_init(sem, 0, initial_value);
 		CHECK_STATUS("sem_init");
 
 		if (error) {
-			free((void *)lock);
-			lock = NULL;
+			free((void *)sem);
+			sem = NULL;
 		}
 	}
 
-	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
-	return (PyThread_type_lock)lock;
+	dprintf(("PyThread_sem_allocate() -> %p\n", sem));
+	return (PyThread_type_sem)sem;
 }
 
-void 
-PyThread_free_lock(PyThread_type_lock lock)
+void
+PyThread_sem_free(PyThread_type_sem sem)
 {
-	sem_t *thelock = (sem_t *)lock;
-	int status, error = 0;
+	sem_t *thesem = (sem_t *)sem;
+	int status;
 
-	dprintf(("PyThread_free_lock(%p) called\n", lock));
+	dprintf(("PyThread_sem_free(%p) called\n", sem));
 
-	if (!thelock)
+	if (!thesem)
 		return;
 
-	status = sem_destroy(thelock);
-	CHECK_STATUS("sem_destroy");
+	status = sem_destroy(thesem);
+	CHECK_STATUS_ABORT("sem_destroy");
 
-	free((void *)thelock);
+	free((void *)thesem);
 }
 
 /*
@@ -330,162 +400,202 @@
  * either.
  */
 static int
-fix_status(int status)
+fix_sem_status(int status)
 {
 	return (status == -1) ? errno : status;
 }
 
-int 
-PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+void
+PyThread_sem_wait(PyThread_type_sem sem)
 {
-	int success;
-	sem_t *thelock = (sem_t *)lock;
-	int status, error = 0;
+	sem_t *thesem = (sem_t *)sem;
+	int status;
 
-	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+	dprintf(("PyThread_sem_wait(%p) called\n", sem));
 
 	do {
-		if (waitflag)
-			status = fix_status(sem_wait(thelock));
-		else
-			status = fix_status(sem_trywait(thelock));
+		status = fix_sem_status(sem_wait(thesem));
 	} while (status == EINTR); /* Retry if interrupted by a signal */
 
-	if (waitflag) {
-		CHECK_STATUS("sem_wait");
-	} else if (status != EAGAIN) {
-		CHECK_STATUS("sem_trywait");
-	}
+	if (status != EINTR)
+		CHECK_STATUS_ABORT("sem_wait");
 	
-	success = (status == 0) ? 1 : 0;
-
-	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
-	return success;
+	dprintf(("PyThread_sem_wait(%p)\n", sem));
 }
 
-void 
-PyThread_release_lock(PyThread_type_lock lock)
+void
+PyThread_sem_post(PyThread_type_sem sem)
 {
-	sem_t *thelock = (sem_t *)lock;
-	int status, error = 0;
+	sem_t *thesem = (sem_t *)sem;
+	int status;
 
-	dprintf(("PyThread_release_lock(%p) called\n", lock));
+	dprintf(("PyThread_sem_post(%p) called\n", sem));
 
-	status = sem_post(thelock);
-	CHECK_STATUS("sem_post");
+	status = sem_post(thesem);
+	CHECK_STATUS_ABORT("sem_post");
 }
 
-#else /* USE_SEMAPHORES */
 
 /*
- * Lock support.
+ * Condition support.
  */
-PyThread_type_lock 
-PyThread_allocate_lock(void)
+
+PyThread_type_cond
+PyThread_cond_allocate(void)
 {
-	pthread_lock *lock;
+	pthread_cond_t *cond;
 	int status, error = 0;
 
-	dprintf(("PyThread_allocate_lock called\n"));
+	dprintf(("PyThread_cond_allocate called\n"));
 	if (!initialized)
 		PyThread_init_thread();
 
-	lock = (pthread_lock *) malloc(sizeof(pthread_lock));
-	if (lock) {
-		memset((void *)lock, '\0', sizeof(pthread_lock));
-		lock->locked = 0;
+	cond = malloc(sizeof(pthread_cond_t));
 
-		status = pthread_mutex_init(&lock->mut,
-					    pthread_mutexattr_default);
-		CHECK_STATUS("pthread_mutex_init");
-
-		status = pthread_cond_init(&lock->lock_released,
-					   pthread_condattr_default);
+	if (cond) {
+		status = pthread_cond_init(cond, NULL);
 		CHECK_STATUS("pthread_cond_init");
 
 		if (error) {
-			free((void *)lock);
-			lock = 0;
+			free((void *)cond);
+			cond = NULL;
 		}
 	}
 
-	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
-	return (PyThread_type_lock) lock;
+	dprintf(("PyThread_cond_allocate() -> %p\n", cond));
+	return (PyThread_type_cond)cond;
 }
 
-void 
-PyThread_free_lock(PyThread_type_lock lock)
+void
+PyThread_cond_free(PyThread_type_cond cond)
 {
-	pthread_lock *thelock = (pthread_lock *)lock;
-	int status, error = 0;
+	pthread_cond_t *thecond = (pthread_cond_t *)cond;
+	int status;
 
-	dprintf(("PyThread_free_lock(%p) called\n", lock));
+	dprintf(("PyThread_cond_free(%p) called\n", cond));
 
-	status = pthread_mutex_destroy( &thelock->mut );
-	CHECK_STATUS("pthread_mutex_destroy");
+	if (!thecond)
+		return;
 
-	status = pthread_cond_destroy( &thelock->lock_released );
-	CHECK_STATUS("pthread_cond_destroy");
+	status = pthread_cond_destroy(thecond);
+	CHECK_STATUS_ABORT("pthread_cond_destroy");
 
-	free((void *)thelock);
+	free((void *)thecond);
 }
 
-int 
-PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+void
+PyThread_cond_wait(PyThread_type_cond cond, PyThread_type_lock lock)
 {
-	int success;
-	pthread_lock *thelock = (pthread_lock *)lock;
+	pthread_cond_t *thecond = (pthread_cond_t *)cond;
+	pthread_mutex_t *thelock = (pthread_mutex_t *)lock;
+	int status;
+
+	dprintf(("PyThread_cond_wait(%p, %p) called\n", cond, lock));
+
+	status = pthread_cond_wait(thecond, thelock);
+	CHECK_STATUS_ABORT("pthread_cond_wait");
+	
+	dprintf(("PyThread_cond_wait(%p, %p)\n", cond, lock));
+}
+
+void
+PyThread_cond_wakeone(PyThread_type_cond cond)
+{
+	pthread_cond_t *thecond = (pthread_cond_t *)cond;
+	int status;
+
+	dprintf(("PyThread_cond_wait(%p) called\n", cond));
+
+	status = pthread_cond_signal(thecond);
+	CHECK_STATUS_ABORT("pthread_cond_signal");
+	
+	dprintf(("PyThread_cond_wait(%p)\n", cond));
+}
+
+void
+PyThread_cond_wakeall(PyThread_type_cond cond)
+{
+	pthread_cond_t *thecond = (pthread_cond_t *)cond;
+	int status;
+
+	dprintf(("PyThread_cond_wait(%p) called\n", cond));
+
+	status = pthread_cond_broadcast(thecond);
+	CHECK_STATUS_ABORT("pthread_cond_broadcast");
+	
+	dprintf(("PyThread_cond_wait(%p)\n", cond));
+}
+
+
+/*
+ * Thread-local Storage support.
+ */
+
+#define Py_HAVE_NATIVE_TLS
+
+PyThread_type_key
+PyThread_create_key(void)
+{
+	pthread_key_t *thekey;
 	int status, error = 0;
 
-	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+	thekey = malloc(sizeof(pthread_key_t));
 
-	status = pthread_mutex_lock( &thelock->mut );
-	CHECK_STATUS("pthread_mutex_lock[1]");
-	success = thelock->locked == 0;
+	if (thekey) {
+		//status = sem_init(lock,0,1);
+		//status = pthread_mutex_init(lock, NULL);
+		status = pthread_key_create(thekey, NULL);
+		CHECK_STATUS("pthread_key_create");
 
-	if ( !success && waitflag ) {
-		/* continue trying until we get the lock */
-
-		/* mut must be locked by me -- part of the condition
-		 * protocol */
-		while ( thelock->locked ) {
-			status = pthread_cond_wait(&thelock->lock_released,
-						   &thelock->mut);
-			CHECK_STATUS("pthread_cond_wait");
+		if (error) {
+			free((void *)thekey);
+			thekey = NULL;
 		}
-		success = 1;
 	}
-	if (success) thelock->locked = 1;
-	status = pthread_mutex_unlock( &thelock->mut );
-	CHECK_STATUS("pthread_mutex_unlock[1]");
 
-	if (error) success = 0;
-	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
-	return success;
+	return (PyThread_type_key *)thekey;
 }
 
-void 
-PyThread_release_lock(PyThread_type_lock lock)
+void
+PyThread_delete_key(PyThread_type_key key)
 {
-	pthread_lock *thelock = (pthread_lock *)lock;
-	int status, error = 0;
+	pthread_key_t *thekey = (pthread_key_t *)key;
+	int status = 0;
 
-	dprintf(("PyThread_release_lock(%p) called\n", lock));
+	status = pthread_key_delete(*thekey);
+	CHECK_STATUS_ABORT("pthread_key_delete");
+}
 
-	status = pthread_mutex_lock( &thelock->mut );
-	CHECK_STATUS("pthread_mutex_lock[3]");
+/* Unlock the default implementation, I consider replacing an existing
+ * key to be an error.  I'm not going to check it. */
+void
+PyThread_set_key_value(PyThread_type_key key, void *value)
+{
+	pthread_key_t *thekey = (pthread_key_t *)key;
+	int status = 0;
 
-	thelock->locked = 0;
+	assert(thekey != NULL); /* Use PyThread_delete_key_value to delete */
+	status = pthread_setspecific(*thekey, value);
+	CHECK_STATUS_ABORT("pthread_setspecific");
+}
 
-	status = pthread_mutex_unlock( &thelock->mut );
-	CHECK_STATUS("pthread_mutex_unlock[3]");
+void *
+PyThread_get_key_value(PyThread_type_key key)
+{
+	pthread_key_t *thekey = (pthread_key_t *)key;
+	return pthread_getspecific(*thekey);
+}
 
-	/* wake up someone (anyone, if any) waiting on the lock */
-	status = pthread_cond_signal( &thelock->lock_released );
-	CHECK_STATUS("pthread_cond_signal");
+void
+PyThread_delete_key_value(PyThread_type_key key)
+{
+	pthread_key_t *thekey = (pthread_key_t *)key;
+	int status = 0;
+
+	status = pthread_setspecific(*thekey, NULL);
+	CHECK_STATUS_ABORT("pthread_setspecific");
 }
 
-#endif /* USE_SEMAPHORES */
 
 /* set the thread stack size.
  * Return 0 if size is valid, -1 if size is invalid,
Index: Python/ast.c
===================================================================
--- Python/ast.c	(revision 58355)
+++ Python/ast.c	(working copy)
@@ -1645,6 +1645,7 @@
             return NULL;
         s[0] = '-';
         strcpy(s + 1, STR(pnum));
+        //printf("Old %p '%s' -> new %p '%s'\n", STR(pnum), STR(pnum), s, s);
         PyObject_FREE(STR(pnum));
         STR(pnum) = s;
         return ast_for_atom(c, patom);
@@ -3117,6 +3118,7 @@
     char *buf;
     char *p;
     const char *end;
+    const char *orig_s = s;
     if (encoding == NULL) {
         buf = (char *)s;
         u = NULL;
@@ -3131,6 +3133,8 @@
         p = buf = PyString_AsString(u);
         end = s + len;
         while (s < end) {
+            if (*s == '\0')
+                Py_FatalError("Meh");
             if (*s == '\\') {
                 *p++ = *s++;
                 if (*s & 0x80) {
@@ -3162,9 +3166,14 @@
                 *p++ = *s++;
             }
         }
+        *p = '\0';
         len = p - buf;
         s = buf;
+//        if (s[len] == '\0')
+//            Py_FatalError("Feh");
     }
+//    if (s - orig_s > strlen(orig_s))
+//        Py_FatalError("decode_unicode went too far\n");
     if (rawmode)
         v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL);
     else
Index: Python/pystate.c
===================================================================
--- Python/pystate.c	(revision 58355)
+++ Python/pystate.c	(working copy)
@@ -2,6 +2,8 @@
 /* Thread and interpreter state structures and their interfaces */
 
 #include "Python.h"
+#include "monitorobject.h"
+#include "interruptobject.h"
 
 /* --------------------------------------------------------------------------
 CAUTION
@@ -23,55 +25,69 @@
 #endif
 
 
-#ifdef WITH_THREAD
 #include "pythread.h"
 static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
-#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
-#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
-#define HEAD_UNLOCK() PyThread_release_lock(head_mutex)
+#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_lock_allocate()))
+#define HEAD_LOCK() PyThread_lock_acquire(head_mutex)
+#define HEAD_UNLOCK() PyThread_lock_release(head_mutex)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+void _PyMonitorSpace_Push(PyMonitorSpaceFrame *frame, struct _PyMonitorSpaceObject *monitorspace);
+void _PyMonitorSpace_Pop(PyMonitorSpaceFrame *frame);
+
 /* The single PyInterpreterState used by this process'
    GILState implementation
 */
 static PyInterpreterState *autoInterpreterState = NULL;
-static int autoTLSkey = 0;
-#else
-#define HEAD_INIT() /* Nothing */
-#define HEAD_LOCK() /* Nothing */
-#define HEAD_UNLOCK() /* Nothing */
-#endif
+static PyThread_type_key autoTLSkey = 0;
 
 static PyInterpreterState *interp_head = NULL;
 
-PyThreadState *_PyThreadState_Current = NULL;
-PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
+/* This hook exists so psyco can provide it's own frame objects */
+static struct _frame *threadstate_getframe(PyThreadState *self);
+PyThreadFrameGetter _PyThreadState_GetFrame = threadstate_getframe;
 
-#ifdef WITH_THREAD
-static void _PyGILState_NoteThreadState(PyThreadState* tstate);
-#endif
+typedef struct _pending_writer {
+	struct _pending_writer *next;
+	PyThread_type_sem sem;
+} pending_writer;
 
+static PyThread_type_lock interpreter_lock = NULL; /* This is the GIL */
+static PyThread_type_cond pending_readers;
+static PyThread_type_cond active_readers;
+static Py_ssize_t pending_readers_count;
+static Py_ssize_t active_readers_count;
+static int active_writer;
+static pending_writer *pending_writers;
+static pending_writer *pending_writers_last;
 
+__thread PyThreadState *_py_local_tstate;
+
+
 PyInterpreterState *
 PyInterpreterState_New(void)
 {
-	PyInterpreterState *interp = (PyInterpreterState *)
-				     malloc(sizeof(PyInterpreterState));
+	PyInterpreterState *interp;
 
+	if (autoInterpreterState)
+		Py_FatalError("InterpreterState already exists");
+
+	interp = malloc(sizeof(PyInterpreterState));
+
 	if (interp != NULL) {
 		HEAD_INIT();
-#ifdef WITH_THREAD
 		if (head_mutex == NULL)
 			Py_FatalError("Can't initialize threads for interpreter");
-#endif
 		interp->modules = NULL;
 		interp->modules_reloading = NULL;
 		interp->sysdict = NULL;
 		interp->builtins = NULL;
 		interp->tstate_head = NULL;
+		interp->tstate_count = 0;
+		interp->entertag = 0;
 		interp->codec_search_path = NULL;
 		interp->codec_search_cache = NULL;
 		interp->codec_error_registry = NULL;
@@ -90,6 +106,8 @@
 		interp->next = interp_head;
 		interp_head = interp;
 		HEAD_UNLOCK();
+
+		autoInterpreterState = interp;
 	}
 
 	return interp;
@@ -114,23 +132,12 @@
 }
 
 
-static void
-zapthreads(PyInterpreterState *interp)
-{
-	PyThreadState *p;
-	/* No need to lock the mutex here because this should only happen
-	   when the threads are all really dead (XXX famous last words). */
-	while ((p = interp->tstate_head) != NULL) {
-		PyThreadState_Delete(p);
-	}
-}
-
-
 void
 PyInterpreterState_Delete(PyInterpreterState *interp)
 {
 	PyInterpreterState **p;
-	zapthreads(interp);
+	if (AO_load_full(&interp->tstate_count) != 0)
+		Py_FatalError("Attempting to delete PyInterpreterState with threads left");
 	HEAD_LOCK();
 	for (p = &interp_head; ; p = &(*p)->next) {
 		if (*p == NULL)
@@ -144,6 +151,7 @@
 	*p = interp->next;
 	HEAD_UNLOCK();
 	free(interp);
+	autoInterpreterState = NULL;
 }
 
 
@@ -155,71 +163,138 @@
 }
 
 PyThreadState *
-PyThreadState_New(PyInterpreterState *interp)
+_PyThreadState_New(void)
 {
-	PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
+	PyThreadState *tstate;
+	PyObject *monitorspace;
+	int i, j;
 
-	if (_PyThreadState_GetFrame == NULL)
-		_PyThreadState_GetFrame = threadstate_getframe;
+	tstate = malloc(sizeof(PyThreadState));
+	if (tstate == NULL)
+		return NULL;
 
-	if (tstate != NULL) {
-		tstate->interp = interp;
+	tstate->interp = NULL;
 
-		tstate->frame = NULL;
-		tstate->recursion_depth = 0;
-		tstate->overflowed = 0;
-		tstate->recursion_critical = 0;
-		tstate->tracing = 0;
-		tstate->use_tracing = 0;
-		tstate->tick_counter = 0;
-		tstate->gilstate_counter = 0;
-		tstate->async_exc = NULL;
-#ifdef WITH_THREAD
-		tstate->thread_id = PyThread_get_thread_ident();
-#else
-		tstate->thread_id = 0;
-#endif
+	tstate->frame = NULL;
+	tstate->recursion_depth = 0;
+	tstate->overflowed = 0;
+	tstate->recursion_critical = 0;
+	tstate->dealloc_depth = 0;
+	tstate->tracing = 0;
+	tstate->use_tracing = 0;
 
-		tstate->dict = NULL;
+	tstate->large_ticks = 0;
+	tstate->small_ticks = 0;
 
-		tstate->curexc_type = NULL;
-		tstate->curexc_value = NULL;
-		tstate->curexc_traceback = NULL;
+	tstate->inspect_count = 0;
+	tstate->inspect_queue_lock = NULL;
+	tstate->inspect_lock = NULL;
+	tstate->inspect_flag = 0;
 
-		tstate->exc_type = NULL;
-		tstate->exc_value = NULL;
-		tstate->exc_traceback = NULL;
+	tstate->suspended = 1;
 
-		tstate->c_profilefunc = NULL;
-		tstate->c_tracefunc = NULL;
-		tstate->c_profileobj = NULL;
-		tstate->c_traceobj = NULL;
+	tstate->enterframe = NULL;
 
-#ifdef WITH_THREAD
-		_PyGILState_NoteThreadState(tstate);
-#endif
+	tstate->dict = NULL;
 
-		HEAD_LOCK();
-		tstate->next = interp->tstate_head;
-		interp->tstate_head = tstate;
-		HEAD_UNLOCK();
+	tstate->curexc_type = NULL;
+	tstate->curexc_value = NULL;
+	tstate->curexc_traceback = NULL;
+
+	tstate->exc_type = NULL;
+	tstate->exc_value = NULL;
+	tstate->exc_traceback = NULL;
+
+	tstate->c_profilefunc = NULL;
+	tstate->c_tracefunc = NULL;
+	tstate->c_profileobj = NULL;
+	tstate->c_traceobj = NULL;
+
+	tstate->import_depth = 0;
+	tstate->monitorspace_frame = &tstate->_base_monitorspace_frame;
+	tstate->_base_monitorspace_frame.prevframe = NULL;
+	tstate->_base_monitorspace_frame.monitorspace = NULL;
+
+	for (i = 0; i < PYMALLOC_CACHE_SIZECLASSES; i++) {
+		for (j = 0; j < PYMALLOC_CACHE_COUNT; j++)
+			tstate->malloc_cache[i][j] = NULL;
 	}
 
+	for (i = 0; i < PYGC_CACHE_SIZECLASSES; i++) {
+		for (j = 0; j < PYGC_CACHE_COUNT; j++)
+			tstate->gc_object_cache[i][j] = NULL;
+	}
+
+	for (i = 0; i < Py_ASYNCREFCOUNT_TABLE; i ++) {
+		tstate->async_refcounts[i].obj = NULL;
+		tstate->async_refcounts[i].diff = 0;
+	}
+
+	tstate->interrupt_point = NULL;
+
+	tstate->critical_section = NULL;
+
+	tstate->active_lock = NULL;
+	tstate->lockwait_prev = NULL;
+	tstate->lockwait_next = NULL;
+	tstate->lockwait_cond = NULL;
+
+	tstate->lockwait_cond = PyThread_cond_allocate();
+	if (!tstate->lockwait_cond)
+		goto failed;
+	tstate->inspect_queue_lock = PyThread_lock_allocate();
+	if (!tstate->inspect_queue_lock)
+		goto failed;
+	tstate->inspect_lock = PyThread_lock_allocate();
+	if (!tstate->inspect_lock)
+		goto failed;
+
+	//printf("New tstate %p\n", tstate);
 	return tstate;
+
+failed:
+	if (tstate->lockwait_cond)
+		PyThread_cond_free(tstate->lockwait_cond);
+	if (tstate->inspect_queue_lock)
+		PyThread_lock_free(tstate->inspect_queue_lock);
+	if (tstate->inspect_lock)
+		PyThread_lock_free(tstate->inspect_lock);
+	free(tstate);
+	return NULL;
 }
 
+static void
+_PyThreadState_Bind(PyInterpreterState *interp, PyThreadState *tstate)
+{
+	assert(autoTLSkey);
+	if (PyThread_get_key_value(autoTLSkey) != 0)
+		Py_FatalError("Thread already has PyThreadState");
 
+	tstate->interp = interp;
+	PyThread_set_key_value(autoTLSkey, tstate);
+	_py_local_tstate = tstate;
+
+	AO_fetch_and_add1_full(&interp->tstate_count);
+
+	HEAD_LOCK();
+	tstate->next = interp->tstate_head;
+	interp->tstate_head = tstate;
+	HEAD_UNLOCK();
+}
+
 void
 PyThreadState_Clear(PyThreadState *tstate)
 {
 	if (Py_VerboseFlag && tstate->frame != NULL)
 		fprintf(stderr,
 		  "PyThreadState_Clear: warning: thread still has a frame\n");
+	if (Py_VerboseFlag && tstate->monitorspace_frame != &tstate->_base_monitorspace_frame)
+		fprintf(stderr,
+		  "PyThreadState_Clear: warning: thread still has monitorspace frame\n");
 
 	Py_CLEAR(tstate->frame);
 
 	Py_CLEAR(tstate->dict);
-	Py_CLEAR(tstate->async_exc);
 
 	Py_CLEAR(tstate->curexc_type);
 	Py_CLEAR(tstate->curexc_value);
@@ -235,18 +310,41 @@
 	Py_CLEAR(tstate->c_traceobj);
 }
 
+void
+_PyThreadState_Delete(PyThreadState *tstate)
+{
+	assert(tstate->interp == NULL);
+	assert(tstate->critical_section == NULL);
 
-/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
+	//printf("Deleting tstate %p\n", tstate);
+	//free(tstate);
+	/* XXX FIXME We need a users count and we need to delay actual
+	 * deletion until the tracing GC goes through and resets the
+	 * owner fields. */
+	/* We're also leaking locks and stuff */
+}
+
 static void
-tstate_delete_common(PyThreadState *tstate)
+_PyThreadState_Unbind(PyThreadState *tstate)
 {
 	PyInterpreterState *interp;
 	PyThreadState **p;
+
+	assert(tstate != NULL && tstate == PyThreadState_Get());
+	_PyGC_Object_Cache_Flush();
+	_PyGC_AsyncRefcount_Flush();
+	PyState_Suspend();
+
 	if (tstate == NULL)
 		Py_FatalError("PyThreadState_Delete: NULL tstate");
 	interp = tstate->interp;
 	if (interp == NULL)
 		Py_FatalError("PyThreadState_Delete: NULL interp");
+
+	assert(tstate->interrupt_point == NULL);
+	assert(tstate->active_lock == NULL);
+	PyThread_cond_free(tstate->lockwait_cond);
+
 	HEAD_LOCK();
 	for (p = &interp->tstate_head; ; p = &(*p)->next) {
 		if (*p == NULL)
@@ -257,75 +355,27 @@
 	}
 	*p = tstate->next;
 	HEAD_UNLOCK();
-	free(tstate);
-}
 
+	AO_fetch_and_sub1_full(&tstate->interp->tstate_count);
 
-void
-PyThreadState_Delete(PyThreadState *tstate)
-{
-	if (tstate == _PyThreadState_Current)
-		Py_FatalError("PyThreadState_Delete: tstate is still current");
-	tstate_delete_common(tstate);
-#ifdef WITH_THREAD
-	if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
-		PyThread_delete_key_value(autoTLSkey);
-#endif /* WITH_THREAD */
-}
+	PyThread_delete_key_value(autoTLSkey);
+	_py_local_tstate = NULL;
 
-
-#ifdef WITH_THREAD
-void
-PyThreadState_DeleteCurrent()
-{
-	PyThreadState *tstate = _PyThreadState_Current;
-	if (tstate == NULL)
-		Py_FatalError(
-			"PyThreadState_DeleteCurrent: no current tstate");
-	_PyThreadState_Current = NULL;
-	tstate_delete_common(tstate);
-	if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
-		PyThread_delete_key_value(autoTLSkey);
-	PyEval_ReleaseLock();
+	tstate->interp = NULL;
 }
-#endif /* WITH_THREAD */
 
 
 PyThreadState *
-PyThreadState_Get(void)
+_PyThreadState_Get(void)
 {
-	if (_PyThreadState_Current == NULL)
+	//PyThreadState *tstate = PyThread_get_key_value(autoTLSkey);
+	PyThreadState *tstate = _py_local_tstate;
+	if (tstate == NULL)
 		Py_FatalError("PyThreadState_Get: no current thread");
-
-	return _PyThreadState_Current;
+	return tstate;
 }
 
 
-PyThreadState *
-PyThreadState_Swap(PyThreadState *newts)
-{
-	PyThreadState *oldts = _PyThreadState_Current;
-
-	_PyThreadState_Current = newts;
-	/* It should not be possible for more than one thread state
-	   to be used for a thread.  Check this the best we can in debug
-	   builds.
-	*/
-#if defined(Py_DEBUG) && defined(WITH_THREAD)
-	if (newts) {
-		/* This can be called from PyEval_RestoreThread(). Similar
-		   to it, we need to ensure errno doesn't change.
-		*/
-		int err = errno;
-		PyThreadState *check = PyGILState_GetThisThreadState();
-		if (check && check->interp == newts->interp && check != newts)
-			Py_FatalError("Invalid thread state for this thread");
-		errno = err;
-	}
-#endif
-	return oldts;
-}
-
 /* An extension mechanism to store arbitrary additional per-thread state.
    PyThreadState_GetDict() returns a dictionary that can be used to hold such
    state; the caller should pick a unique key and store its state there.  If
@@ -335,19 +385,23 @@
 PyObject *
 PyThreadState_GetDict(void)
 {
-	if (_PyThreadState_Current == NULL)
+	//PyThreadState *tstate = PyThread_get_key_value(autoTLSkey);
+	PyThreadState *tstate = _py_local_tstate;
+	if (tstate == NULL)
 		return NULL;
 
-	if (_PyThreadState_Current->dict == NULL) {
+	if (tstate->dict == NULL) {
 		PyObject *d;
-		_PyThreadState_Current->dict = d = PyDict_New();
+		tstate->dict = d = PyDict_New();
 		if (d == NULL)
 			PyErr_Clear();
 	}
-	return _PyThreadState_Current->dict;
+	return tstate->dict;
 }
 
 
+/* XXX FIXME rebuild this as part of a much broader debugging hooks API */
+#if 0
 /* Asynchronously raise an exception in a thread.
    Requested by Just van Rossum and Alex Martelli.
    To prevent naive misuse, you must write your own extension
@@ -355,10 +409,10 @@
    Returns the number of tstates modified (normally 1, but 0 if `id` didn't
    match any known thread id).  Can be called with exc=NULL to clear an
    existing async exception.  This raises no exceptions. */
-
+/* XXX FIXME scrap and redesign */
 int
 PyThreadState_SetAsyncExc(long id, PyObject *exc) {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyInterpreterState *interp = tstate->interp;
 	PyThreadState *p;
 
@@ -389,11 +443,46 @@
 	HEAD_UNLOCK();
 	return 0;
 }
+#endif
 
+/* Do periodic things.  This is called from the main event loop, so we
+ * take care to reduce the per-call costs. */
+int
+PyThreadState_Tick(void)
+{
+	PyThreadState *tstate = PyThreadState_Get();
 
+	if (AO_load_acquire(&tstate->inspect_flag)) {
+#if 0
+		PyState_Suspend();
+		PyState_Resume();
+#else
+		PyThread_lock_release(tstate->inspect_lock);
+		PyThread_lock_acquire(tstate->inspect_queue_lock);
+		PyThread_lock_acquire(tstate->inspect_lock);
+		PyThread_lock_release(tstate->inspect_queue_lock);
+#endif
+	}
+
+	if (tstate->small_ticks > 0) {
+		tstate->small_ticks--;
+		return 0;
+	} else {
+		PyState_Suspend();
+		PyState_Resume();
+
+		tstate->large_ticks++;
+		tstate->small_ticks = _Py_CheckInterval; /* XXX use atomic access? */
+
+		return 0;
+	}
+}
+
+
 /* Routines for advanced debuggers, requested by David Beazley.
    Don't use unless you know what you are doing! */
-
+/* XXX FIXME not even slightly thread-safe!  These should be scrapped
+   and redesigned! */
 PyInterpreterState *
 PyInterpreterState_Head(void)
 {
@@ -415,6 +504,7 @@
 	return tstate->next;
 }
 
+
 /* The implementation of sys._current_frames().  This is intended to be
    called with the GIL held, as it will be when called via
    sys._current_frames().  It's possible it would work fine even without
@@ -445,7 +535,7 @@
 			struct _frame *frame = t->frame;
 			if (frame == NULL)
 				continue;
-			id = PyInt_FromLong(t->thread_id);
+			id = PyLong_FromVoidPtr(t);
 			if (id == NULL)
 				goto Fail;
 			stat = PyDict_SetItem(result, id, (PyObject *)frame);
@@ -463,172 +553,384 @@
  	return NULL;
 }
 
-/* Python "auto thread state" API. */
-#ifdef WITH_THREAD
 
-/* Keep this as a static, as it is not reliable!  It can only
-   ever be compared to the state for the *current* thread.
-   * If not equal, then it doesn't matter that the actual
-     value may change immediately after comparison, as it can't
-     possibly change to the current thread's state.
-   * If equal, then the current thread holds the lock, so the value can't
-     change until we yield the lock.
-*/
-static int
-PyThreadState_IsCurrent(PyThreadState *tstate)
+static void
+state_interrupt_callback(struct _PyInterruptQueue *queue, void *arg)
 {
-	/* Must be the tstate for this thread */
-	assert(PyGILState_GetThisThreadState()==tstate);
-	/* On Windows at least, simple reads and writes to 32 bit values
-	   are atomic.
-	*/
-	return tstate == _PyThreadState_Current;
 }
 
-/* Internal initialization/finalization functions called by
-   Py_Initialize/Py_Finalize
-*/
+PyState_EnterFrame *
+PyState_Enter(void)
+{
+	PyState_EnterFrame *enterframe;
+	PyMonitorSpaceObject *monitorspace;
+	PyMonitorSpaceFrame *monitorframe;
+
+	enterframe = _PyState_EnterPreallocated(NULL);
+	if (enterframe == NULL)
+		return NULL;
+
+#if 0
+	monitorframe = malloc(sizeof(PyMonitorSpaceFrame));
+	if (monitorframe == NULL) {
+		_PyState_ExitSimple(enterframe);
+		return NULL;
+	}
+	//*monitorframe = PyMonitorSpaceFrame_INIT;
+	monitorframe->prevframe = NULL;
+	monitorframe->monitorspace = NULL;
+
+	monitorspace = (PyMonitorSpaceObject *)PyObject_CallObject((PyObject *)&PyMonitorSpace_Type, NULL);
+	if (monitorspace == NULL) {
+		free(monitorframe);
+		_PyState_ExitSimple(enterframe);
+		return NULL;
+	}
+
+	_PyMonitorSpace_Push(monitorframe, monitorspace);
+#elif 1
+	monitorframe = malloc(sizeof(PyMonitorSpaceFrame));
+	if (monitorframe == NULL) {
+		_PyState_ExitSimple(enterframe);
+		return NULL;
+	}
+	//*monitorframe = PyMonitorSpaceFrame_INIT;
+	monitorframe->prevframe = NULL;
+	monitorframe->monitorspace = NULL;
+	_PyMonitorSpace_Push(monitorframe, NULL);
+#endif
+	return enterframe;
+}
+
+PyState_EnterFrame *
+_PyState_EnterPreallocated(PyThreadState *new_tstate)
+{
+	PyThreadState *tstate;
+	PyState_EnterFrame *frame;
+	static const PyMonitorSpaceFrame initframe = PyMonitorSpaceFrame_INIT;
+
+	assert(autoInterpreterState);
+	//tstate = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+	tstate = _py_local_tstate;
+
+	frame = malloc(sizeof(PyState_EnterFrame));
+	if (frame == NULL)
+		return NULL;
+
+	if (tstate == NULL) {
+		PyInterruptObject *point;
+		/* Create a new thread state for this thread */
+		if (new_tstate == NULL) {
+			tstate = _PyThreadState_New();
+			if (tstate == NULL) {
+				free(frame);
+				return NULL;
+			}
+		} else
+			tstate = new_tstate;
+
+		_PyThreadState_Bind(autoInterpreterState, tstate);
+		frame->prevframe = tstate->enterframe;
+		tstate->enterframe = frame;
+		frame->locked = 0;
+		frame->monitorspaceframe = initframe;
+
+		PyState_Resume();
+		point = PyInterrupt_New(state_interrupt_callback, NULL, NULL);
+		if (point == NULL) {
+			PyState_Suspend();
+			_PyThreadState_Unbind(tstate);
+			_PyThreadState_Delete(tstate);
+			free(frame);
+			return NULL;
+		}
+		PyInterrupt_Push(point);
+		PyState_Suspend();
+	} else {
+		if (new_tstate != NULL)
+			Py_FatalError("Unexpected new_tstate");
+
+		if (tstate->enterframe->locked)
+			PyState_Suspend();
+
+		frame->prevframe = tstate->enterframe;
+		tstate->enterframe = frame;
+		frame->locked = 0;
+		frame->monitorspaceframe = initframe;
+	}
+
+	PyState_Resume();
+	return frame;
+}
+
 void
-_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
+PyState_Exit(PyState_EnterFrame *enterframe)
 {
-	assert(i && t); /* must init with valid states */
-	autoTLSkey = PyThread_create_key();
-	autoInterpreterState = i;
-	assert(PyThread_get_key_value(autoTLSkey) == NULL);
-	assert(t->gilstate_counter == 0);
+#if 0
+	PyThreadState *tstate = PyThreadState_Get();
+	PyMonitorSpaceFrame *monitorframe = tstate->monitorspace_frame;
+	PyMonitorSpaceObject *monitorspace = monitorframe->monitorspace;
 
-	_PyGILState_NoteThreadState(t);
+	_PyMonitorSpace_Pop(monitorframe);
+	Py_DECREF(monitorspace);
+	free(monitorframe);
+#endif
+	_PyState_ExitSimple(enterframe);
 }
 
 void
-_PyGILState_Fini(void)
+_PyState_ExitSimple(PyState_EnterFrame *enterframe)
 {
-	PyThread_delete_key(autoTLSkey);
-	autoTLSkey = 0;
-	autoInterpreterState = NULL;
+	PyThreadState *tstate = PyThreadState_Get();
+	PyState_EnterFrame *oldframe;
+
+	oldframe = tstate->enterframe;
+	if (enterframe != oldframe)
+		Py_FatalError("PyState_Exit called with wrong frame");
+
+	if (tstate->suspended)
+		Py_FatalError("PyState_Exit called while suspended");
+
+	if (!oldframe->locked)
+		Py_FatalError("PyState_Exit called in an unlocked state");
+
+	if (oldframe->prevframe == NULL) {
+		PyInterrupt_Pop(tstate->interrupt_point);
+		Py_CLEAR(tstate->interrupt_point);
+		PyThreadState_Clear(tstate);
+		_PyThreadState_Unbind(tstate);
+		_PyThreadState_Delete(tstate);
+		free(oldframe);
+	} else {
+		PyState_Suspend();
+
+		tstate->enterframe = oldframe->prevframe;
+		free(oldframe);
+
+		if (tstate->enterframe->locked)
+			PyState_Resume();
+	}
 }
 
-/* When a thread state is created for a thread by some mechanism other than
-   PyGILState_Ensure, it's important that the GILState machinery knows about
-   it so it doesn't try to create another thread state for the thread (this is
-   a better fix for SF bug #1010677 than the first one attempted).
-*/
-static void
-_PyGILState_NoteThreadState(PyThreadState* tstate)
+
+void
+PyState_EnterImport(void)
 {
-	/* If autoTLSkey is 0, this must be the very first threadstate created
-	   in Py_Initialize().  Don't do anything for now (we'll be back here
-	   when _PyGILState_Init is called). */
-	if (!autoTLSkey)
-		return;
+	PyThreadState *tstate = PyThreadState_Get();
 
-	/* Stick the thread state for this thread in thread local storage.
+	tstate->import_depth++;
+}
 
-	   The only situation where you can legitimately have more than one
-	   thread state for an OS level thread is when there are multiple
-	   interpreters, when:
+void
+PyState_ExitImport(void)
+{
+	PyThreadState *tstate = PyThreadState_Get();
 
-	       a) You shouldn't really be using the PyGILState_ APIs anyway,
-	          and:
+	tstate->import_depth--;
+	assert(tstate->import_depth >= 0);
+}
 
-	       b) The slightly odd way PyThread_set_key_value works (see
-	          comments by its implementation) means that the first thread
-	          state created for that given OS level thread will "win",
-	          which seems reasonable behaviour.
-	*/
-	if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
-		Py_FatalError("Couldn't create autoTLSkey mapping");
 
-	/* PyGILState_Release must not try to delete this thread state. */
-	tstate->gilstate_counter = 1;
+/* Stops all other threads from accessing their PyState */
+void
+PyState_StopTheWorld(void)
+{
+	/* XXX FIXME */
+    Py_FatalError("FIXME StopTheWorld");
 }
 
-/* The public functions */
-PyThreadState *
-PyGILState_GetThisThreadState(void)
+void
+PyState_StartTheWorld(void)
 {
-	if (autoInterpreterState == NULL || autoTLSkey == 0)
-		return NULL;
-	return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+    Py_FatalError("FIXME StartTheWorld");
 }
 
-PyGILState_STATE
-PyGILState_Ensure(void)
+
+/* XXX change "active" MonitorSpace to none */
+void
+PyState_Suspend(void)
 {
-	int current;
-	PyThreadState *tcur;
-	/* Note that we do not auto-init Python here - apart from
-	   potential races with 2 threads auto-initializing, pep-311
-	   spells out other issues.  Embedders are expected to have
-	   called Py_Initialize() and usually PyEval_InitThreads().
-	*/
-	assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
-	tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
-	if (tcur == NULL) {
-		/* Create a new thread state for this thread */
-		tcur = PyThreadState_New(autoInterpreterState);
-		if (tcur == NULL)
-			Py_FatalError("Couldn't create thread-state for new thread");
-		/* This is our thread state!  We'll need to delete it in the
-		   matching call to PyGILState_Release(). */
-		tcur->gilstate_counter = 0;
-		current = 0; /* new thread state is never current */
+	int err = errno;
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(!tstate->suspended);
+	tstate->suspended = 1;
+	tstate->enterframe->locked = 0;
+	PyThread_lock_release(tstate->inspect_lock);
+
+	errno = err;
+}
+
+/* XXX Reactivate MonitorSpace */
+void
+PyState_Resume(void)
+{
+	int err = errno;
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(tstate->suspended);
+	PyThread_lock_acquire(tstate->inspect_lock);
+	tstate->suspended = 0;
+	tstate->enterframe->locked = 1;
+
+	errno = err;
+}
+
+
+PyCritical *
+PyCritical_Allocate(Py_ssize_t depth)
+{
+	PyCritical *crit = malloc(sizeof(PyCritical));
+	if (crit == NULL)
+		return NULL;
+
+	crit->lock = PyThread_lock_allocate();
+	if (!crit->lock) {
+		free(crit);
+		return NULL;
 	}
-	else
-		current = PyThreadState_IsCurrent(tcur);
-	if (current == 0)
-		PyEval_RestoreThread(tcur);
-	/* Update our counter in the thread-state - no need for locks:
-	   - tcur will remain valid as we hold the GIL.
-	   - the counter is safe as we are the only thread "allowed"
-	     to modify this value
-	*/
-	++tcur->gilstate_counter;
-	return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
+
+	crit->depth = depth;
+	crit->prev = NULL;
+
+	return crit;
 }
 
 void
-PyGILState_Release(PyGILState_STATE oldstate)
+PyCritical_Free(PyCritical *crit)
 {
-	PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
-                                                                autoTLSkey);
-	if (tcur == NULL)
-		Py_FatalError("auto-releasing thread-state, "
-		              "but no thread-state for this thread");
-	/* We must hold the GIL and have our thread state current */
-	/* XXX - remove the check - the assert should be fine,
-	   but while this is very new (April 2003), the extra check
-	   by release-only users can't hurt.
-	*/
-	if (! PyThreadState_IsCurrent(tcur))
-		Py_FatalError("This thread state must be current when releasing");
-	assert(PyThreadState_IsCurrent(tcur));
-	--tcur->gilstate_counter;
-	assert(tcur->gilstate_counter >= 0); /* illegal counter value */
+	PyThread_lock_free(crit->lock);
+	free(crit);
+}
 
-	/* If we're going to destroy this thread-state, we must
-	 * clear it while the GIL is held, as destructors may run.
-	 */
-	if (tcur->gilstate_counter == 0) {
-		/* can't have been locked when we created it */
-		assert(oldstate == PyGILState_UNLOCKED);
-		PyThreadState_Clear(tcur);
-		/* Delete the thread-state.  Note this releases the GIL too!
-		 * It's vital that the GIL be held here, to avoid shutdown
-		 * races; see bugs 225673 and 1061968 (that nasty bug has a
-		 * habit of coming back).
-		 */
-		PyThreadState_DeleteCurrent();
+void
+PyCritical_Enter(PyCritical *crit)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(!tstate->suspended);
+
+	if (tstate->critical_section != NULL &&
+			tstate->critical_section->depth <= crit->depth)
+		Py_FatalError("PyCritical_Enter called while "
+			"already in deeper critical section");
+
+	if (!_PyThread_lock_tryacquire(crit->lock)) {
+		PyState_Suspend();
+		PyThread_lock_acquire(crit->lock);
+		PyState_Resume();
 	}
-	/* Release the lock if necessary */
-	else if (oldstate == PyGILState_UNLOCKED)
-		PyEval_SaveThread();
+
+	assert(crit->prev == NULL);
+	crit->prev = tstate->critical_section;
+	tstate->critical_section = crit;
 }
 
-#ifdef __cplusplus
+void
+PyCritical_Exit(PyCritical *crit)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(!tstate->suspended);
+
+	if (tstate->critical_section != crit)
+		Py_FatalError("PyCritical_Exit called with wrong "
+			"critical section");
+
+	tstate->critical_section = crit->prev;
+	crit->prev = NULL;
+
+	PyThread_lock_release(crit->lock);
 }
-#endif
 
-#endif /* WITH_THREAD */
+/* This is just a bodge for deathqueue_wait.  It shouldn't be used in general */
+void
+_PyCritical_CondWait(PyCritical *crit, PyThread_type_cond cond)
+{
+    PyThreadState *tstate = PyThreadState_Get();
 
+    assert(!tstate->suspended);
 
+    if (tstate->critical_section != crit)
+        Py_FatalError("_PyCritical_CondWait called with wrong "
+            "critical section");
+
+    PyThread_cond_wait(cond, crit->lock);
+}
+
+
+extern PyThreadState * (*pymalloc_threadstate_hook)(void);
+
+void
+_PyState_InitThreads(void)
+{
+	if (interpreter_lock)
+		Py_FatalError("Interpreter state already initialized");
+	interpreter_lock = PyThread_lock_allocate();
+	pending_readers = PyThread_cond_allocate();
+	active_readers = PyThread_cond_allocate();
+	autoTLSkey = PyThread_create_key();
+	if (!interpreter_lock || !pending_readers || !active_readers ||
+			!autoTLSkey)
+		Py_FatalError("Allocation failed in _PyState_InitThreads");
+	pymalloc_threadstate_hook = PyThreadState_Get;
+}
+
+void
+PyState_PrepareFork(void)
+{
+	PyThread_lock_acquire(interpreter_lock);
+}
+
+void
+PyState_CleanupForkParent(void)
+{
+	PyThread_lock_release(interpreter_lock);
+}
+
+/* This function is called from PyOS_AfterFork to reset the interpreter's
+   locks so they can be used in the child process.  (This could also be
+   done using pthread_atfork mechanism, at least for the pthreads
+   implementation.)
+
+   However, this only resets a few of the locks that may be in use, so
+   doing anything non-trivial is almost certainly unsafe.
+
+   Cleaning up properly is impossible.  The users of fork should really
+   be rewritten in C so they don't need to touch python objects before
+   they exec.  For now, we bodge things.*/
+void
+PyState_CleanupForkChild(void)
+{
+	PyState_EnterTag entertag;
+
+	if (!interpreter_lock)
+		return;
+
+	interpreter_lock = PyThread_lock_allocate();
+	if (!interpreter_lock)
+		Py_FatalError("Unable to allocate lock");
+	pending_readers_count = 0;
+	active_readers_count = 0;
+	active_writer = 0;
+	pending_writers = NULL;
+	PyThread_delete_key_value(autoTLSkey);
+	entertag = PyState_Enter();
+	if (!entertag)
+		Py_FatalError("Unable to re-enter state after fork");
+}
+
+/* Internal initialization/finalization functions called by
+   Py_Initialize/Py_Finalize
+*/
+void
+_PyState_Fini(void)
+{
+	PyThread_delete_key(autoTLSkey);
+	autoTLSkey = 0;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
Index: Python/pythonrun.c
===================================================================
--- Python/pythonrun.c	(revision 58355)
+++ Python/pythonrun.c	(working copy)
@@ -17,6 +17,7 @@
 #include "ast.h"
 #include "eval.h"
 #include "marshal.h"
+#include "branchobject.h"
 
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
@@ -49,6 +50,8 @@
 extern grammar _PyParser_Grammar; /* From graminit.c */
 
 /* Forward */
+static void initfinalize(void);
+static void finifinalize(void);
 static void initmain(void);
 static void initsite(void);
 static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *,
@@ -59,16 +62,22 @@
 static void initsigs(void);
 static void call_py_exitfuncs(void);
 static void call_ll_exitfuncs(void);
+extern void _PyGC_Init(void);
+extern void _PyUnicode_PreInit(void);
 extern void _PyUnicode_Init(void);
 extern void _PyUnicode_Fini(void);
+extern void _PyUnicode_PostFini(void);
+extern void _PyString_PostFini(void);
+extern void _PyDict_PreInit(void);
 extern int _PyLong_Init(void);
 extern void PyLong_Fini(void);
 
-#ifdef WITH_THREAD
-extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
-extern void _PyGILState_Fini(void);
-#endif /* WITH_THREAD */
+extern void _PyState_InitThreads(void);
+extern void _PyState_Fini(void);
 
+extern void _Py_Refchain_Init(void);
+extern void _Py_Refchain_Fini(void);
+
 int Py_DebugFlag; /* Needed by parser.c */
 int Py_VerboseFlag; /* Needed by import.c */
 int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
@@ -83,6 +92,8 @@
 */
 static PyObject *warnings_module = NULL;
 
+static PyObject *finalize_branch = NULL;
+
 /* Returns a borrowed reference to the 'warnings' module, or NULL.
    If the module is returned, it is guaranteed to have been obtained
    without acquiring the import lock
@@ -112,6 +123,7 @@
 	return warnings_module;
 }
 
+/* 0 for uninitialized, 1 for initialized, -1 for finalized */
 static int initialized = 0;
 
 /* API to access the initialized flag -- useful for esoteric use */
@@ -119,7 +131,9 @@
 int
 Py_IsInitialized(void)
 {
-	return initialized;
+    /* Typical callers don't want to know we're finalized, so we make
+     * sure they don't have to test for it. */
+    return initialized == 1;
 }
 
 /* Global initializations.  Can be undone by Py_Finalize().  Don't
@@ -146,10 +160,10 @@
 }
 
 void
-Py_InitializeEx(int install_sigs)
+Py_InitializeEx(int handle_sigint)
 {
 	PyInterpreterState *interp;
-	PyThreadState *tstate;
+	//PyThreadState *tstate;
 	PyObject *bimod, *sysmod;
 	char *p;
 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
@@ -157,8 +171,12 @@
 #endif
 	extern void _Py_ReadyTypes(void);
 
-	if (initialized)
-		return;
+	if (initialized == 1)
+		Py_FatalError("Cannot call Py_Initialize: already initialized");
+	if (initialized == -1)
+		Py_FatalError("Cannot call Py_Initialize: already finalized");
+	if (initialized != 0)
+		Py_FatalError("Cannot call Py_Initialize: unknown initialized stated");
 	initialized = 1;
 
 #ifdef HAVE_SETLOCALE
@@ -175,28 +193,48 @@
 	if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
 		Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
 
+	_PyGC_Init();
+
+	_Py_Refchain_Init();
+
+	_PyState_InitThreads();
+
 	interp = PyInterpreterState_New();
 	if (interp == NULL)
 		Py_FatalError("Py_Initialize: can't make first interpreter");
 
-	tstate = PyThreadState_New(interp);
-	if (tstate == NULL)
-		Py_FatalError("Py_Initialize: can't make first thread");
-	(void) PyThreadState_Swap(tstate);
+	interp->entertag = PyState_Enter();
+	if (!interp->entertag)
+		Py_FatalError("Py_Initialize: PySpace_Enter failed");
+	//tstate = PyThreadState_New(interp);
+	//if (tstate == NULL)
+	//	Py_FatalError("Py_Initialize: can't make first thread");
+	//(void) PyThreadState_Swap(tstate);
+	//PyState_Resume();
 
-	_Py_ReadyTypes();
+	/* Bare minimum before other types */
+	_PyUnicode_PreInit();
+	_PyDict_PreInit();
 
 	if (!_PyFrame_Init())
 		Py_FatalError("Py_Initialize: can't init frames");
-
+	_PyMethod_Init();
 	if (!_PyLong_Init())
 		Py_FatalError("Py_Initialize: can't init longs");
-
+	_PyFloat_Init();
+	_PyTuple_Init();
+	_PyList_Init();
+	_PySet_Init();
+	_PyString_Init();
 	if (!PyBytes_Init())
 		Py_FatalError("Py_Initialize: can't init bytes");
+	_PyCFunction_Init();
 
-	_PyFloat_Init();
+	/* Init Unicode implementation; relies on the codec registry */
+	_PyUnicode_Init();
 
+	_Py_ReadyTypes();
+
 	interp->modules = PyDict_New();
 	if (interp->modules == NULL)
 		Py_FatalError("Py_Initialize: can't make modules dictionary");
@@ -204,9 +242,6 @@
 	if (interp->modules_reloading == NULL)
 		Py_FatalError("Py_Initialize: can't make modules_reloading dictionary");
 
-	/* Init Unicode implementation; relies on the codec registry */
-	_PyUnicode_Init();
-
 	bimod = _PyBuiltin_Init();
 	if (bimod == NULL)
 		Py_FatalError("Py_Initialize: can't initialize __builtin__");
@@ -215,6 +250,8 @@
 		Py_FatalError("Py_Initialize: can't initialize builtins dict");
 	Py_INCREF(interp->builtins);
 
+	_Py_ThreadTools_Init();
+
 	sysmod = _PySys_Init();
 	if (sysmod == NULL)
 		Py_FatalError("Py_Initialize: can't initialize sys");
@@ -229,26 +266,21 @@
 
 	_PyImport_Init();
 
-	/* initialize builtin exceptions */
-	_PyExc_Init();
-
 	/* phase 2 of builtins */
 	_PyImport_FixupExtension("__builtin__", "__builtin__");
 
 	_PyImportHooks_Init();
 
-	if (install_sigs)
-		initsigs(); /* Signal handling stuff, including initintr() */
+	_PySignal_Init();
 
+	initfinalize();
+
+	_PySignal_InitSigInt(handle_sigint);
+
 	initmain(); /* Module __main__ */
 	if (!Py_NoSiteFlag)
 		initsite(); /* Module site */
 
-	/* auto-thread-state API, if available */
-#ifdef WITH_THREAD
-	_PyGILState_Init(interp, tstate);
-#endif /* WITH_THREAD */
-
 	warnings_module = PyImport_ImportModule("warnings");
 	if (!warnings_module)
 		PyErr_Clear();
@@ -339,8 +371,12 @@
 	PyInterpreterState *interp;
 	PyThreadState *tstate;
 
-	if (!initialized)
-		return;
+	if (initialized == 0)
+		Py_FatalError("Cannot call Py_Finalize: not yet initialized");
+	if (initialized == -1)
+		Py_FatalError("Cannot call Py_Finalize: already finalized");
+	if (initialized != 1)
+		Py_FatalError("Cannot call Py_Finalize: unknown initialized stated");
 
 	/* The interpreter is still entirely intact at this point, and the
 	 * exit funcs may be relying on that.  In particular, if some thread
@@ -351,18 +387,25 @@
 	 * threads created thru it, so this also protects pending imports in
 	 * the threads created via Threading.
 	 */
+	/* XXX FIXME this isn't done in a thread-safe fashion.  The
+	 * initialized variable itself isn't accessed atomically, but we
+	 * also have a race before we change it after checking it. */
 	call_py_exitfuncs();
-	initialized = 0;
+	initialized = -1;
 
 	/* Flush stdout+stderr */
 	flush_std_files();
 
 	/* Get current thread state and interpreter pointer */
-	tstate = PyThreadState_GET();
+	tstate = PyThreadState_Get();
 	interp = tstate->interp;
 
+	_PySignal_FiniSigInt();
+
+	finifinalize();
+
 	/* Disable signal handling */
-	PyOS_FiniInterrupts();
+	_PySignal_Fini();
 
 	/* drop module references we saved */
 	Py_XDECREF(warnings_module);
@@ -380,20 +423,21 @@
 	 * XXX but I'm unclear on exactly how that one happens.  In any case,
 	 * XXX I haven't seen a real-life report of either of these.
 	 */
-	PyGC_Collect();
+	//PyGC_Collect();
 #ifdef COUNT_ALLOCS
 	/* With COUNT_ALLOCS, it helps to run GC multiple times:
 	   each collection might release some types from the type
 	   list, so they become garbage. */
-	while (PyGC_Collect() > 0)
-		/* nothing */;
+	//while (PyGC_Collect() > 0)
+	//	/* nothing */;
 #endif
 
 	/* Destroy all modules */
 	PyImport_Cleanup();
 
 	/* Flush stdout+stderr (again, in case more was printed) */
-	flush_std_files();
+	/* XXX io.py is long gone at this point */
+	//flush_std_files();
 
 	/* Collect final garbage.  This disposes of cycles created by
 	 * new-style class definitions, for example.
@@ -434,11 +478,6 @@
 		_Py_PrintReferences(stderr);
 #endif /* Py_TRACE_REFS */
 
-	/* Cleanup auto-thread-state */
-#ifdef WITH_THREAD
-	_PyGILState_Fini();
-#endif /* WITH_THREAD */
-
 	/* Clear interpreter state */
 	PyInterpreterState_Clear(interp);
 
@@ -450,16 +489,13 @@
 
 	_PyExc_Fini();
 
-	/* Delete current thread */
-	PyThreadState_Swap(NULL);
-	PyInterpreterState_Delete(interp);
-
 	/* Sundry finalizers */
 	PyMethod_Fini();
 	PyFrame_Fini();
 	PyCFunction_Fini();
 	PyTuple_Fini();
 	PyList_Fini();
+	PyDict_Fini();
 	PySet_Fini();
 	PyString_Fini();
 	PyBytes_Fini();
@@ -490,114 +526,21 @@
 		_PyObject_DebugMallocStats();
 #endif
 
+	_PyUnicode_PostFini();
+	_PyString_PostFini();
+
 	call_ll_exitfuncs();
-}
 
-/* Create and initialize a new interpreter and thread, and return the
-   new thread.  This requires that Py_Initialize() has been called
-   first.
-
-   Unsuccessful initialization yields a NULL pointer.  Note that *no*
-   exception information is available even in this case -- the
-   exception information is held in the thread, and there is no
-   thread.
-
-   Locking: as above.
-
-*/
-
-PyThreadState *
-Py_NewInterpreter(void)
-{
-	PyInterpreterState *interp;
-	PyThreadState *tstate, *save_tstate;
-	PyObject *bimod, *sysmod;
-
-	if (!initialized)
-		Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
-
-	interp = PyInterpreterState_New();
-	if (interp == NULL)
-		return NULL;
-
-	tstate = PyThreadState_New(interp);
-	if (tstate == NULL) {
-		PyInterpreterState_Delete(interp);
-		return NULL;
-	}
-
-	save_tstate = PyThreadState_Swap(tstate);
-
-	/* XXX The following is lax in error checking */
-
-	interp->modules = PyDict_New();
-	interp->modules_reloading = PyDict_New();
-
-	bimod = _PyImport_FindExtension("__builtin__", "__builtin__");
-	if (bimod != NULL) {
-		interp->builtins = PyModule_GetDict(bimod);
-		if (interp->builtins == NULL)
-			goto handle_error;
-		Py_INCREF(interp->builtins);
-	}
-	sysmod = _PyImport_FindExtension("sys", "sys");
-	if (bimod != NULL && sysmod != NULL) {
-		interp->sysdict = PyModule_GetDict(sysmod);
-		if (interp->sysdict == NULL)
-			goto handle_error;
-		Py_INCREF(interp->sysdict);
-		PySys_SetPath(Py_GetPath());
-		PyDict_SetItemString(interp->sysdict, "modules",
-				     interp->modules);
-		_PyImportHooks_Init();
-		initmain();
-		if (!Py_NoSiteFlag)
-			initsite();
-	}
-
-	if (!PyErr_Occurred())
-		return tstate;
-
-handle_error:
-	/* Oops, it didn't work.  Undo it all. */
-
-	PyErr_Print();
-	PyThreadState_Clear(tstate);
-	PyThreadState_Swap(save_tstate);
-	PyThreadState_Delete(tstate);
+	/* Delete current thread */
+	//PyThreadState_Swap(NULL);
+	//PyThreadState_DeleteCurrent();
+	PyState_Exit(interp->entertag);
 	PyInterpreterState_Delete(interp);
 
-	return NULL;
-}
+	/* Cleanup auto-thread-state */
+	_PyState_Fini();
 
-/* Delete an interpreter and its last thread.  This requires that the
-   given thread state is current, that the thread has no remaining
-   frames, and that it is its interpreter's only remaining thread.
-   It is a fatal error to violate these constraints.
-
-   (Py_Finalize() doesn't have these constraints -- it zaps
-   everything, regardless.)
-
-   Locking: as above.
-
-*/
-
-void
-Py_EndInterpreter(PyThreadState *tstate)
-{
-	PyInterpreterState *interp = tstate->interp;
-
-	if (tstate != PyThreadState_GET())
-		Py_FatalError("Py_EndInterpreter: thread is not current");
-	if (tstate->frame != NULL)
-		Py_FatalError("Py_EndInterpreter: thread still has a frame");
-	if (tstate != interp->tstate_head || tstate->next != NULL)
-		Py_FatalError("Py_EndInterpreter: not the last thread");
-
-	PyImport_Cleanup();
-	PyInterpreterState_Clear(interp);
-	PyThreadState_Swap(NULL);
-	PyInterpreterState_Delete(interp);
+	_Py_Refchain_Fini();
 }
 
 static char *progname = "python";
@@ -632,6 +575,87 @@
 	return home;
 }
 
+/* Create finalizer thread */
+static void
+initfinalize(void)
+{
+    PyObject *queue, *runfinalizers, *x;
+
+    queue = PyObject_CallObject((PyObject *)&_PyDeathQueue_Type, NULL);
+    if (queue == NULL)
+        Py_FatalError("Py_Initialize: can't initialize finalizequeue");
+    if (PySys_SetObject("finalizequeue", queue) != 0)
+        Py_FatalError("Py_Initialize: can't assign finalizequeue");
+
+    runfinalizers = PySys_GetObject("_runfinalizers");
+    if (runfinalizers == NULL)
+        Py_FatalError("lost sys._runfinalizers");
+    Py_INCREF(runfinalizers);  /* PySys_GetObject returns a borrowed reference */
+
+    finalize_branch = PyObject_CallObject((PyObject *)&PyBranch_Type, NULL);
+    if (finalize_branch == NULL)
+        Py_FatalError("Failed to initialize finalize_branch");
+    x = PyObject_CallMethod(finalize_branch, "__enter__", "");
+    if (x == NULL)
+        Py_FatalError("Failed to call finalize_branch.__enter__()");
+    Py_DECREF(x);
+
+    x = PyObject_CallMethod(finalize_branch, "add", "OO", runfinalizers, queue);
+    if (x == NULL)
+        Py_FatalError("Failed to spawn finalizer thread");
+    Py_DECREF(queue);
+    Py_DECREF(runfinalizers);
+    Py_DECREF(x);
+}
+
+/* Destroy the finalizer thread */
+static void
+finifinalize(void)
+{
+    PyObject *x, *dummy, *queue;
+    PyObject *e_type, *e_val, *e_tb;
+
+    dummy = PySet_New(NULL);
+    if (dummy == NULL)
+        Py_FatalError("failed to create dummy to exit finalizer thread");
+    queue = PySys_GetObject("finalizequeue");
+    if (queue == NULL)
+        Py_FatalError("lost sys.finalizequeue");
+
+    x = PyObject_CallMethod(queue, "watch", "OO", dummy, Py_None);
+    if (x == NULL)
+        Py_FatalError("failed to watch dummy to exit finalizer thread");
+    Py_DECREF(x);
+    Py_DECREF(dummy);
+    //Py_DECREF(queue);  // PySys_GetObject returns a borrowed reference
+
+    /* XXX We're dependant on the GC deleting dummy, and preferably
+     * immediately.  This SHOULD happen, but it's not a great assumption. */
+
+    /* XXX This is all a big bodge */
+    PyErr_Fetch(&e_type, &e_val, &e_tb);
+    PyErr_NormalizeException(&e_type, &e_val, &e_tb);
+    if (e_type == NULL) {
+        Py_INCREF(Py_None);
+        e_type = Py_None;
+        Py_INCREF(Py_None);
+        e_val = Py_None;
+    }
+    if (e_tb == NULL) {
+        Py_INCREF(Py_None);
+        e_tb = Py_None;
+    }
+    assert(e_type && e_val && e_tb);
+    x = PyObject_CallMethod(finalize_branch, "__exit__", "OOO", e_type, e_val, e_tb);
+    /* XXX any DECREFs needed? */
+    if (x == NULL)
+        PyErr_Print();
+        //Py_FatalError("failed to call finalize_branch.__exit__()");
+    Py_XDECREF(x);
+    Py_CLEAR(finalize_branch);
+    /* XXX reraise or whatever as required by __exit__ specs */
+}
+
 /* Create __main__ module */
 
 static void
@@ -659,8 +683,14 @@
 	PyObject *m, *f;
 	m = PyImport_ImportModule("site");
 	if (m == NULL) {
-		f = PySys_GetObject("stderr");
-		if (Py_VerboseFlag) {
+		//f = PySys_GetObject("stderr");
+		f = NULL;
+		if (f == NULL) {
+			fprintf(stderr, "'import site' failed; retrieving "
+				"sys.stderr also failed.\n");
+			PyErr_Print();
+			//PyErr_Clear();
+		} else if (Py_VerboseFlag) {
 			PyFile_WriteString(
 				"'import site' failed; traceback:\n", f);
 			PyErr_Print();
@@ -1144,11 +1174,12 @@
 	int err = 0;
 	PyObject *f = PySys_GetObject("stderr");
 	Py_INCREF(value);
-	if (f == NULL)
+
+	if (f == NULL) {
 		_PyObject_Dump(value);
-	if (f == NULL)
+		PyTraceBack_Print(tb, NULL);  /* XXX FIXME check return? */
 		fprintf(stderr, "lost sys.stderr\n");
-	else {
+	} else {
 		fflush(stdout);
 		if (tb && tb != Py_None)
 			err = PyTraceBack_Print(tb, f);
@@ -1648,22 +1679,7 @@
 	exit(sts);
 }
 
-static void
-initsigs(void)
-{
-#ifdef SIGPIPE
-	PyOS_setsig(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGXFZ
-	PyOS_setsig(SIGXFZ, SIG_IGN);
-#endif
-#ifdef SIGXFSZ
-	PyOS_setsig(SIGXFSZ, SIG_IGN);
-#endif
-	PyOS_InitInterrupts(); /* May imply initsignal() */
-}
 
-
 /*
  * The file descriptor fd is considered ``interactive'' if either
  *   a) isatty(fd) is TRUE, or
@@ -1715,63 +1731,6 @@
 #endif /* USE_STACKCHECK */
 
 
-/* Wrappers around sigaction() or signal(). */
-
-PyOS_sighandler_t
-PyOS_getsig(int sig)
-{
-#ifdef HAVE_SIGACTION
-	struct sigaction context;
-	if (sigaction(sig, NULL, &context) == -1)
-		return SIG_ERR;
-	return context.sa_handler;
-#else
-	PyOS_sighandler_t handler;
-/* Special signal handling for the secure CRT in Visual Studio 2005 */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-	switch (sig) {
-	/* Only these signals are valid */
-	case SIGINT:
-	case SIGILL:
-	case SIGFPE:
-	case SIGSEGV:
-	case SIGTERM:
-	case SIGBREAK:
-	case SIGABRT:
-		break;
-	/* Don't call signal() with other values or it will assert */
-	default:
-		return SIG_ERR;
-	}
-#endif /* _MSC_VER && _MSC_VER >= 1400 */
-	handler = signal(sig, SIG_IGN);
-	if (handler != SIG_ERR)
-		signal(sig, handler);
-	return handler;
-#endif
-}
-
-PyOS_sighandler_t
-PyOS_setsig(int sig, PyOS_sighandler_t handler)
-{
-#ifdef HAVE_SIGACTION
-	struct sigaction context, ocontext;
-	context.sa_handler = handler;
-	sigemptyset(&context.sa_mask);
-	context.sa_flags = 0;
-	if (sigaction(sig, &context, &ocontext) == -1)
-		return SIG_ERR;
-	return ocontext.sa_handler;
-#else
-	PyOS_sighandler_t oldhandler;
-	oldhandler = signal(sig, handler);
-#ifdef HAVE_SIGINTERRUPT
-	siginterrupt(sig, 1);
-#endif
-	return oldhandler;
-#endif
-}
-
 /* Deprecated C API functions still provided for binary compatiblity */
 
 #undef PyParser_SimpleParseFile
Index: Python/import.c
===================================================================
--- Python/import.c	(revision 58355)
+++ Python/import.c	(working copy)
@@ -14,6 +14,7 @@
 #include "eval.h"
 #include "osdefs.h"
 #include "importdl.h"
+#include "pystate.h"
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
@@ -242,47 +243,49 @@
 
 #include "pythread.h"
 
+#warning Import locking is all bodged and needs a rewrite
 static PyThread_type_lock import_lock = 0;
-static long import_lock_thread = -1;
+static PyThreadState *import_lock_thread = NULL;
 static int import_lock_level = 0;
 
 static void
 lock_import(void)
 {
-	long me = PyThread_get_thread_ident();
-	if (me == -1)
-		return; /* Too bad */
+	PyThreadState *tstate = PyThreadState_Get();
 	if (import_lock == NULL) {
-		import_lock = PyThread_allocate_lock();
+		import_lock = PyThread_lock_allocate();
 		if (import_lock == NULL)
 			return;  /* Nothing much we can do. */
 	}
-	if (import_lock_thread == me) {
+	if (import_lock_thread == tstate) {
 		import_lock_level++;
 		return;
 	}
-	if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0))
+	if (import_lock_thread != NULL || !_PyThread_lock_tryacquire(import_lock))
 	{
-		PyThreadState *tstate = PyEval_SaveThread();
-		PyThread_acquire_lock(import_lock, 1);
-		PyEval_RestoreThread(tstate);
+		//PyThreadState *tstate = PyEval_SaveThread();
+		PyState_Suspend();
+		PyThread_lock_acquire(import_lock);
+		/* XXX This should be replaced with a "large lock" with deadlock detection */
+		//PyEval_RestoreThread(tstate);
+		PyState_Resume();
 	}
-	import_lock_thread = me;
+	import_lock_thread = tstate;
 	import_lock_level = 1;
 }
 
 static int
 unlock_import(void)
 {
-	long me = PyThread_get_thread_ident();
-	if (me == -1 || import_lock == NULL)
+	PyThreadState *tstate = PyThreadState_Get();
+	if (import_lock == NULL)
 		return 0; /* Too bad */
-	if (import_lock_thread != me)
+	if (import_lock_thread != tstate)
 		return -1;
 	import_lock_level--;
 	if (import_lock_level == 0) {
-		import_lock_thread = -1;
-		PyThread_release_lock(import_lock);
+		import_lock_thread = NULL;
+		PyThread_lock_release(import_lock);
 	}
 	return 1;
 }
@@ -295,7 +298,7 @@
 {
 #ifdef _AIX
 	if (import_lock != NULL)
-		import_lock = PyThread_allocate_lock();
+		import_lock = PyThread_lock_allocate();
 #endif
 }
 
@@ -310,7 +313,7 @@
 imp_lock_held(PyObject *self, PyObject *noargs)
 {
 #ifdef WITH_THREAD
-	return PyBool_FromLong(import_lock_thread != -1);
+	return PyBool_FromLong(import_lock_thread != NULL);
 #else
 	return PyBool_FromLong(0);
 #endif
@@ -353,7 +356,7 @@
 PyObject *
 PyImport_GetModuleDict(void)
 {
-	PyInterpreterState *interp = PyThreadState_GET()->interp;
+	PyInterpreterState *interp = PyThreadState_Get()->interp;
 	if (interp->modules == NULL)
 		Py_FatalError("PyImport_GetModuleDict: no module dictionary!");
 	return interp->modules;
@@ -384,7 +387,7 @@
 	Py_ssize_t pos, ndone;
 	char *name;
 	PyObject *key, *value, *dict;
-	PyInterpreterState *interp = PyThreadState_GET()->interp;
+	PyInterpreterState *interp = PyThreadState_Get()->interp;
 	PyObject *modules = interp->modules;
 
 	if (modules == NULL)
@@ -452,7 +455,7 @@
 		ndone = 0;
 		pos = 0;
 		while (PyDict_Next(modules, &pos, &key, &value)) {
-			if (value->ob_refcnt != 1)
+			if (!Py_RefcntMatches(value, 1))
 				continue;
 			if (PyUnicode_Check(key) && PyModule_Check(value)) {
 				name = PyUnicode_AsString(key);
@@ -589,13 +592,19 @@
 PyObject *
 PyImport_AddModule(const char *name)
 {
+	return PyImport_AddModuleEx(name, 0);
+}
+
+PyObject *
+PyImport_AddModuleEx(const char *name, int shared)
+{
 	PyObject *modules = PyImport_GetModuleDict();
 	PyObject *m;
 
 	if ((m = PyDict_GetItemString(modules, name)) != NULL &&
 	    PyModule_Check(m))
 		return m;
-	m = PyModule_New(name);
+	m = PyModule_NewEx(name, shared);
 	if (m == NULL)
 		return NULL;
 	if (PyDict_SetItemString(modules, name, m) != 0) {
@@ -636,19 +645,31 @@
 PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
 {
 	PyObject *modules = PyImport_GetModuleDict();
-	PyObject *m, *d, *v;
+	PyObject *m, *d, *v, *tmp;
+	int shared = 0;
 
-	m = PyImport_AddModule(name);
-	if (m == NULL)
+	PyState_EnterImport(); /* XXX should probably be done earlier */
+	if (((PyCodeObject *)co)->co_flags & CO_FUTURE_SHARED_MODULE)
+		shared = 1;
+
+	m = PyImport_AddModuleEx(name, shared);
+	if (m == NULL) {
+		PyState_ExitImport();
 		return NULL;
+	}
+
 	/* If the module is being reloaded, we get the old module back
 	   and re-use its dict to exec the new code. */
 	d = PyModule_GetDict(m);
-	if (PyDict_GetItemString(d, "__builtins__") == NULL) {
+	if (PyDict_GetItemStringEx(d, "__builtins__", &tmp) < 0)
+		goto error;
+	if (tmp == NULL) {
 		if (PyDict_SetItemString(d, "__builtins__",
 					 PyEval_GetBuiltins()) != 0)
 			goto error;
-	}
+	} else
+		Py_DECREF(tmp);
+
 	/* Remember the filename as the __file__ attribute */
 	v = NULL;
 	if (pathname != NULL) {
@@ -673,15 +694,18 @@
 		PyErr_Format(PyExc_ImportError,
 			     "Loaded module %.200s not found in sys.modules",
 			     name);
+		PyState_ExitImport();
 		return NULL;
 	}
 
 	Py_INCREF(m);
 
+	PyState_ExitImport();
 	return m;
 
   error:
 	_RemoveModule(name);
+	PyState_ExitImport();
 	return NULL;
 }
 
@@ -2975,7 +2999,6 @@
 	0,                         /* tp_descr_set */
 	0,                         /* tp_dictoffset */
 	(initproc)NullImporter_init,      /* tp_init */
-	0,                         /* tp_alloc */
 	PyType_GenericNew          /* tp_new */
 };
 
Index: Python/symtable.c
===================================================================
--- Python/symtable.c	(revision 58355)
+++ Python/symtable.c	(working copy)
@@ -33,8 +33,9 @@
 	k = PyLong_FromVoidPtr(key);
 	if (k == NULL)
 		goto fail;
-	ste = (PySTEntryObject *)PyObject_New(PySTEntryObject,
-					      &PySTEntry_Type);
+	ste = PyObject_NEW(PySTEntryObject, &PySTEntry_Type);
+	if (ste == NULL)
+		Py_FatalError("Allocation failed in PySTEntry_New");
 	ste->ste_table = st;
 	ste->ste_id = k;
 	ste->ste_tmpname = 0;
@@ -102,7 +103,7 @@
 	Py_XDECREF(ste->ste_symbols);
 	Py_XDECREF(ste->ste_varnames);
 	Py_XDECREF(ste->ste_children);
-	PyObject_Del(ste);
+	PyObject_DEL(ste);
 }
 
 #define OFF(x) offsetof(PySTEntryObject, x)
@@ -155,7 +156,6 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	0,					/* tp_new */
 };
 
Index: Python/marshal.c
===================================================================
--- Python/marshal.c	(revision 58355)
+++ Python/marshal.c	(working copy)
@@ -231,7 +231,7 @@
 	}
 #endif
 	else if (PyString_Check(v)) {
-		if (p->strings && PyString_CHECK_INTERNED(v)) {
+		if (p->strings && _PyString_SnoopState((PyStringObject *)v)) {
 			PyObject *o = PyDict_GetItem(p->strings, v);
 			if (o) {
 				long w = PyInt_AsLong(o);
Index: Python/thread.c
===================================================================
--- Python/thread.c	(revision 58355)
+++ Python/thread.c	(working copy)
@@ -202,7 +202,7 @@
 While some of these functions have error-return values, none set any
 Python exception.
 
-None of the functions does memory management on behalf of the void* values.
+None of the functions do memory management on behalf of the void* values.
 You need to allocate and deallocate them yourself.  If the void* values
 happen to be PyObject*, these functions don't do refcount operations on
 them either.
@@ -265,7 +265,7 @@
 
 	if (!keymutex)
 		return NULL;
-	PyThread_acquire_lock(keymutex, 1);
+	PyThread_lock_acquire(keymutex);
 	for (p = keyhead; p != NULL; p = p->next) {
 		if (p->id == id && p->key == key)
 			goto Done;
@@ -283,7 +283,7 @@
 		keyhead = p;
 	}
  Done:
-	PyThread_release_lock(keymutex);
+	PyThread_lock_release(keymutex);
 	return p;
 }
 
@@ -298,7 +298,7 @@
 	 * threads simultaneously.
 	 */
 	if (keymutex == NULL)
-		keymutex = PyThread_allocate_lock();
+		keymutex = PyThread_lock_allocate();
 	return ++nkeys;
 }
 
@@ -308,7 +308,7 @@
 {
 	struct key *p, **q;
 
-	PyThread_acquire_lock(keymutex, 1);
+	PyThread_lock_acquire(keymutex);
 	q = &keyhead;
 	while ((p = *q) != NULL) {
 		if (p->key == key) {
@@ -319,7 +319,7 @@
 		else
 			q = &p->next;
 	}
-	PyThread_release_lock(keymutex);
+	PyThread_lock_release(keymutex);
 }
 
 /* Confusing:  If the current thread has an association for key,
@@ -362,7 +362,7 @@
 	long id = PyThread_get_thread_ident();
 	struct key *p, **q;
 
-	PyThread_acquire_lock(keymutex, 1);
+	PyThread_lock_acquire(keymutex);
 	q = &keyhead;
 	while ((p = *q) != NULL) {
 		if (p->key == key && p->id == id) {
@@ -374,7 +374,7 @@
 		else
 			q = &p->next;
 	}
-	PyThread_release_lock(keymutex);
+	PyThread_lock_release(keymutex);
 }
 
 #endif /* Py_HAVE_NATIVE_TLS */
Index: Python/future.c
===================================================================
--- Python/future.c	(revision 58355)
+++ Python/future.c	(working copy)
@@ -33,6 +33,8 @@
 			continue;
 		} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
 			continue;
+		} else if (strcmp(feature, FUTURE_SHARED_MODULE) == 0) {
+			ff->ff_features |= CO_FUTURE_SHARED_MODULE;
 		} else if (strcmp(feature, "braces") == 0) {
 			PyErr_SetString(PyExc_SyntaxError,
 					"not a chance");
Index: Python/dynload_shlib.c
===================================================================
--- Python/dynload_shlib.c	(revision 58355)
+++ Python/dynload_shlib.c	(working copy)
@@ -109,7 +109,7 @@
 	}
 
 #if !(defined(PYOS_OS2) && defined(PYCC_GCC))
-        dlopenflags = PyThreadState_GET()->interp->dlopenflags;
+        dlopenflags = PyThreadState_Get()->interp->dlopenflags;
 #endif
 
 	if (Py_VerboseFlag)
Index: Python/modsupport.c
===================================================================
--- Python/modsupport.c	(revision 58355)
+++ Python/modsupport.c	(working copy)
@@ -32,6 +32,14 @@
 Py_InitModule4(const char *name, PyMethodDef *methods, const char *doc,
 	       PyObject *passthrough, int module_api_version)
 {
+	return Py_InitModule5(name, methods, doc, passthrough,
+		module_api_version, 0);
+}
+
+PyObject *
+Py_InitModule5(const char *name, PyMethodDef *methods, const char *doc,
+	       PyObject *passthrough, int module_api_version, int shared)
+{
 	PyObject *m, *d, *v, *n;
 	PyMethodDef *ml;
 	if (!Py_IsInitialized())
@@ -61,7 +69,7 @@
 			_Py_PackageContext = NULL;
 		}
 	}
-	if ((m = PyImport_AddModule(name)) == NULL)
+	if ((m = PyImport_AddModuleEx(name, shared)) == NULL)
 		return NULL;
 	d = PyModule_GetDict(m);
 	if (methods != NULL) {
Index: Python/bltinmodule.c
===================================================================
--- Python/bltinmodule.c	(revision 58355)
+++ Python/bltinmodule.c	(working copy)
@@ -8,6 +8,9 @@
 
 #include <ctype.h>
 
+#include "monitorobject.h"
+#include "branchobject.h"
+
 /* The default encoding used by the platform file system APIs
    Can remain NULL for all platforms that don't have such a concept
 */
@@ -140,12 +143,16 @@
 	PyObject *locals = NULL;
 	PyObject *fromlist = NULL;
 	int level = -1;
+	PyObject *r;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|OOOi:__import__",
 			kwlist, &name, &globals, &locals, &fromlist, &level))
 		return NULL;
-	return PyImport_ImportModuleLevel(name, globals, locals,
+	PyState_EnterImport();
+	r = PyImport_ImportModuleLevel(name, globals, locals,
 					  fromlist, level);
+	PyState_ExitImport();
+	return r;
 }
 
 PyDoc_STRVAR(import_doc,
@@ -287,7 +294,7 @@
 
         /* Initialize cached value */
         if (format_str == NULL) {
-                /* Initialize static variable needed by _PyType_Lookup */
+                /* Initialize static variable needed by _PyType_LookupEx */
                 format_str = PyUnicode_FromString("__format__");
                 if (format_str == NULL)
                         goto done;
@@ -307,8 +314,9 @@
                 if (PyType_Ready(Py_Type(value)) < 0)
                         goto done;
 
-        /* Find the (unbound!) __format__ method (a borrowed reference) */
-        meth = _PyType_Lookup(Py_Type(value), format_str);
+        /* Find the (unbound!) __format__ method */
+        if (_PyType_LookupEx(Py_Type(value), format_str, &meth) < 0)
+                goto done;
         if (meth == NULL) {
                 PyErr_Format(PyExc_TypeError,
                              "Type %.100s doesn't define __format__",
@@ -318,6 +326,7 @@
 
         /* And call it, binding it to the value */
         result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL);
+        Py_DECREF(meth);
 
         if (result && !PyUnicode_Check(result)) {
                 PyErr_SetString(PyExc_TypeError,
@@ -1418,6 +1427,7 @@
 	int ndigits = UNDEF_NDIGITS;
 	static char *kwlist[] = {"number", "ndigits", 0};
 	PyObject *number, *round;
+	PyObject *result;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:round",
                 kwlist, &number, &ndigits))
@@ -1434,7 +1444,8 @@
 			return NULL;
 	}
 
-	round = _PyType_Lookup(Py_Type(number), round_str);
+	if (_PyType_LookupEx(Py_Type(number), round_str, &round) < 0)
+		return NULL;
 	if (round == NULL) {
 		PyErr_Format(PyExc_TypeError,
 			     "type %.100s doesn't define __round__ method",
@@ -1443,9 +1454,11 @@
 	}
 
 	if (ndigits == UNDEF_NDIGITS)
-                return PyObject_CallFunction(round, "O", number);
+		result = PyObject_CallFunction(round, "O", number);
 	else
-                return PyObject_CallFunction(round, "Oi", number, ndigits);
+                result = PyObject_CallFunction(round, "Oi", number, ndigits);
+	Py_DECREF(round);
+	return result;
 #undef UNDEF_NDIGITS
 }
 
@@ -1541,6 +1554,7 @@
 {
 	static PyObject *trunc_str = NULL;
 	PyObject *trunc;
+	PyObject *result;
 
 	if (Py_Type(number)->tp_dict == NULL) {
 		if (PyType_Ready(Py_Type(number)) < 0)
@@ -1553,14 +1567,17 @@
 			return NULL;
 	}
 
-	trunc = _PyType_Lookup(Py_Type(number), trunc_str);
+	if (_PyType_LookupEx(Py_Type(number), trunc_str, &trunc) < 0)
+		return NULL;
 	if (trunc == NULL) {
 		PyErr_Format(PyExc_TypeError,
 			     "type %.100s doesn't define __trunc__ method",
 			     Py_Type(number)->tp_name);
 		return NULL;
 	}
-	return PyObject_CallFunction(trunc, "O", number);
+	result = PyObject_CallFunction(trunc, "O", number);
+	Py_DECREF(trunc);
+	return result;
 }
 
 PyDoc_STRVAR(trunc_doc,
@@ -1700,50 +1717,50 @@
 
 static PyMethodDef builtin_methods[] = {
  	{"__build_class__", (PyCFunction)builtin___build_class__,
-         METH_VARARGS | METH_KEYWORDS, build_class_doc},
- 	{"__import__",	(PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},
- 	{"abs",		builtin_abs,        METH_O, abs_doc},
- 	{"all",		builtin_all,        METH_O, all_doc},
- 	{"any",		builtin_any,        METH_O, any_doc},
-	{"bin",		builtin_bin,	    METH_O, bin_doc},
- 	{"chr",		builtin_chr,        METH_VARARGS, chr_doc},
- 	{"cmp",		builtin_cmp,        METH_VARARGS, cmp_doc},
- 	{"compile",	(PyCFunction)builtin_compile,    METH_VARARGS | METH_KEYWORDS, compile_doc},
- 	{"delattr",	builtin_delattr,    METH_VARARGS, delattr_doc},
- 	{"dir",		builtin_dir,        METH_VARARGS, dir_doc},
- 	{"divmod",	builtin_divmod,     METH_VARARGS, divmod_doc},
- 	{"eval",	builtin_eval,       METH_VARARGS, eval_doc},
-	{"exec",        builtin_exec,       METH_VARARGS, exec_doc},
- 	{"filter",	builtin_filter,     METH_VARARGS, filter_doc},
- 	{"format",	builtin_format,     METH_VARARGS, format_doc},
- 	{"getattr",	builtin_getattr,    METH_VARARGS, getattr_doc},
- 	{"globals",	(PyCFunction)builtin_globals,    METH_NOARGS, globals_doc},
- 	{"hasattr",	builtin_hasattr,    METH_VARARGS, hasattr_doc},
- 	{"hash",	builtin_hash,       METH_O, hash_doc},
- 	{"hex",		builtin_hex,        METH_O, hex_doc},
- 	{"id",		builtin_id,         METH_O, id_doc},
- 	{"input",	builtin_input,      METH_VARARGS, input_doc},
- 	{"isinstance",  builtin_isinstance, METH_VARARGS, isinstance_doc},
- 	{"issubclass",  builtin_issubclass, METH_VARARGS, issubclass_doc},
- 	{"iter",	builtin_iter,       METH_VARARGS, iter_doc},
- 	{"len",		builtin_len,        METH_O, len_doc},
- 	{"locals",	(PyCFunction)builtin_locals,     METH_NOARGS, locals_doc},
- 	{"map",		builtin_map,        METH_VARARGS, map_doc},
- 	{"max",		(PyCFunction)builtin_max,        METH_VARARGS | METH_KEYWORDS, max_doc},
- 	{"min",		(PyCFunction)builtin_min,        METH_VARARGS | METH_KEYWORDS, min_doc},
-	{"next",	(PyCFunction)builtin_next,       METH_VARARGS, next_doc},
- 	{"oct",		builtin_oct,        METH_O, oct_doc},
- 	{"ord",		builtin_ord,        METH_O, ord_doc},
- 	{"pow",		builtin_pow,        METH_VARARGS, pow_doc},
- 	{"print",	(PyCFunction)builtin_print,      METH_VARARGS | METH_KEYWORDS, print_doc},
- 	{"repr",	builtin_repr,       METH_O, repr_doc},
- 	{"round",	(PyCFunction)builtin_round,      METH_VARARGS | METH_KEYWORDS, round_doc},
- 	{"setattr",	builtin_setattr,    METH_VARARGS, setattr_doc},
- 	{"sorted",	(PyCFunction)builtin_sorted,     METH_VARARGS | METH_KEYWORDS, sorted_doc},
- 	{"sum",		builtin_sum,        METH_VARARGS, sum_doc},
- 	{"vars",	builtin_vars,       METH_VARARGS, vars_doc},
- 	{"trunc",	builtin_trunc,      METH_O, trunc_doc},
-  	{"zip",         builtin_zip,        METH_VARARGS, zip_doc},
+         METH_SHARED | METH_VARARGS | METH_KEYWORDS, build_class_doc},
+ 	{"__import__",	(PyCFunction)builtin___import__, METH_SHARED | METH_VARARGS | METH_KEYWORDS, import_doc},
+ 	{"abs",		builtin_abs,        METH_SHARED | METH_O, abs_doc},
+ 	{"all",		builtin_all,        METH_SHARED | METH_O, all_doc},
+ 	{"any",		builtin_any,        METH_SHARED | METH_O, any_doc},
+	{"bin",		builtin_bin,	    METH_SHARED | METH_O, bin_doc},
+ 	{"chr",		builtin_chr,        METH_SHARED | METH_VARARGS, chr_doc},
+ 	{"cmp",		builtin_cmp,        METH_SHARED | METH_VARARGS, cmp_doc},
+ 	{"compile",	(PyCFunction)builtin_compile,    METH_SHARED | METH_VARARGS | METH_KEYWORDS, compile_doc},
+ 	{"delattr",	builtin_delattr,    METH_SHARED | METH_VARARGS, delattr_doc},
+ 	{"dir",		builtin_dir,        METH_SHARED | METH_VARARGS, dir_doc},
+ 	{"divmod",	builtin_divmod,     METH_SHARED | METH_VARARGS, divmod_doc},
+ 	{"eval",	builtin_eval,       METH_SHARED | METH_VARARGS, eval_doc},
+	{"exec",        builtin_exec,       METH_SHARED | METH_VARARGS, exec_doc},
+ 	{"filter",	builtin_filter,     METH_SHARED | METH_VARARGS, filter_doc},
+ 	{"format",	builtin_format,     METH_SHARED | METH_VARARGS, format_doc},
+ 	{"getattr",	builtin_getattr,    METH_SHARED | METH_VARARGS, getattr_doc},
+ 	{"globals",	(PyCFunction)builtin_globals,    METH_SHARED | METH_NOARGS, globals_doc},
+ 	{"hasattr",	builtin_hasattr,    METH_SHARED | METH_VARARGS, hasattr_doc},
+ 	{"hash",	builtin_hash,       METH_SHARED | METH_O, hash_doc},
+ 	{"hex",		builtin_hex,        METH_SHARED | METH_O, hex_doc},
+ 	{"id",		builtin_id,         METH_SHARED | METH_O, id_doc},
+ 	{"input",	builtin_input,      METH_SHARED | METH_VARARGS, input_doc},
+ 	{"isinstance",  builtin_isinstance, METH_SHARED | METH_VARARGS, isinstance_doc},
+ 	{"issubclass",  builtin_issubclass, METH_SHARED | METH_VARARGS, issubclass_doc},
+ 	{"iter",	builtin_iter,       METH_SHARED | METH_VARARGS, iter_doc},
+ 	{"len",		builtin_len,        METH_SHARED | METH_O, len_doc},
+ 	{"locals",	(PyCFunction)builtin_locals,     METH_SHARED | METH_NOARGS, locals_doc},
+ 	{"map",		builtin_map,        METH_SHARED | METH_VARARGS, map_doc},
+ 	{"max",		(PyCFunction)builtin_max,        METH_SHARED | METH_VARARGS | METH_KEYWORDS, max_doc},
+ 	{"min",		(PyCFunction)builtin_min,        METH_SHARED | METH_VARARGS | METH_KEYWORDS, min_doc},
+	{"next",	(PyCFunction)builtin_next,       METH_SHARED | METH_VARARGS, next_doc},
+ 	{"oct",		builtin_oct,        METH_SHARED | METH_O, oct_doc},
+ 	{"ord",		builtin_ord,        METH_SHARED | METH_O, ord_doc},
+ 	{"pow",		builtin_pow,        METH_SHARED | METH_VARARGS, pow_doc},
+ 	{"print",	(PyCFunction)builtin_print,      METH_SHARED | METH_VARARGS | METH_KEYWORDS, print_doc},
+ 	{"repr",	builtin_repr,       METH_SHARED | METH_O, repr_doc},
+ 	{"round",	(PyCFunction)builtin_round,      METH_SHARED | METH_VARARGS | METH_KEYWORDS, round_doc},
+ 	{"setattr",	builtin_setattr,    METH_SHARED | METH_VARARGS, setattr_doc},
+ 	{"sorted",	(PyCFunction)builtin_sorted,     METH_SHARED | METH_VARARGS | METH_KEYWORDS, sorted_doc},
+ 	{"sum",		builtin_sum,        METH_SHARED | METH_VARARGS, sum_doc},
+ 	{"vars",	builtin_vars,       METH_SHARED | METH_VARARGS, vars_doc},
+ 	{"trunc",	builtin_trunc,      METH_SHARED | METH_O, trunc_doc},
+  	{"zip",         builtin_zip,        METH_SHARED | METH_VARARGS, zip_doc},
 	{NULL,		NULL},
 };
 
@@ -1752,15 +1769,19 @@
 \n\
 Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices.");
 
+extern PyTypeObject PyFakeRange_Type;
 PyObject *
 _PyBuiltin_Init(void)
 {
 	PyObject *mod, *dict, *debug;
-	mod = Py_InitModule4("__builtin__", builtin_methods,
+
+	PyState_EnterImport();
+
+	mod = Py_InitModule5("__builtin__", builtin_methods,
 			     builtin_doc, (PyObject *)NULL,
-			     PYTHON_API_VERSION);
+			     PYTHON_API_VERSION, 1);
 	if (mod == NULL)
-		return NULL;
+		goto error;
 	dict = PyModule_GetDict(mod);
 
 #ifdef Py_TRACE_REFS
@@ -1777,7 +1798,7 @@
 
 #define SETBUILTIN(NAME, OBJECT) \
 	if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0)	\
-		return NULL;						\
+		goto error;						\
 	ADD_TO_ALL(OBJECT)
 
 	SETBUILTIN("None",		Py_None);
@@ -1795,6 +1816,7 @@
 	SETBUILTIN("complex",		&PyComplex_Type);
 #endif
 	SETBUILTIN("dict",		&PyDict_Type);
+	SETBUILTIN("shareddict",	&PySharedDict_Type);
  	SETBUILTIN("enumerate",		&PyEnum_Type);
 	SETBUILTIN("float",		&PyFloat_Type);
 	SETBUILTIN("frozenset",		&PyFrozenSet_Type);
@@ -1803,6 +1825,7 @@
 	SETBUILTIN("list",		&PyList_Type);
 	SETBUILTIN("object",		&PyBaseObject_Type);
 	SETBUILTIN("range",		&PyRange_Type);
+	SETBUILTIN("fakerange",		&PyFakeRange_Type);
 	SETBUILTIN("reversed",		&PyReversed_Type);
 	SETBUILTIN("set",		&PySet_Type);
 	SETBUILTIN("slice",		&PySlice_Type);
@@ -1815,11 +1838,57 @@
 	debug = PyBool_FromLong(Py_OptimizeFlag == 0);
 	if (PyDict_SetItemString(dict, "__debug__", debug) < 0) {
 		Py_XDECREF(debug);
-		return NULL;
+		goto error;
 	}
 	Py_XDECREF(debug);
 
+	/* initialize builtin exceptions */
+	_PyExc_Init();
+
+	PyState_ExitImport();
 	return mod;
+
+error:
+	PyState_ExitImport();
+	return NULL;
 #undef ADD_TO_ALL
 #undef SETBUILTIN
 }
+
+
+/* Doesn't really belong here, but oh well */
+PyDoc_STRVAR(module_doc,
+"This is a template module just for instruction.");
+
+PyMODINIT_FUNC
+_Py_ThreadTools_Init(void)
+{
+	PyObject *mod, *dict;
+
+	mod = Py_InitModule3("_threadtools", NULL, module_doc);
+	if (mod == NULL)
+		return;
+
+	dict = PyModule_GetDict(mod);
+
+#ifdef Py_TRACE_REFS
+#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0)
+#else
+#define ADD_TO_ALL(OBJECT) (void)0
+#endif
+
+#define SETBUILTIN(NAME, OBJECT) \
+	if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0)	\
+		goto error;						\
+	ADD_TO_ALL(OBJECT)
+
+	SETBUILTIN("MonitorMeta",	&PyMonitorMeta_Type);
+	SETBUILTIN("Monitor",		&PyMonitor_Type);
+	SETBUILTIN("MonitorSpace",	&PyMonitorSpace_Type);
+	SETBUILTIN("branch",		&PyBranch_Type);
+
+error:
+	;
+#undef ADD_TO_ALL
+#undef SETBUILTIN
+}
Index: Python/sysmodule.c
===================================================================
--- Python/sysmodule.c	(revision 58355)
+++ Python/sysmodule.c	(working copy)
@@ -48,7 +48,7 @@
 PyObject *
 PySys_GetObject(const char *name)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *sd = tstate->interp->sysdict;
 	if (sd == NULL)
 		return NULL;
@@ -58,7 +58,7 @@
 int
 PySys_SetObject(const char *name, PyObject *v)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject *sd = tstate->interp->sysdict;
 	if (v == NULL) {
 		if (PyDict_GetItemString(sd, name) == NULL)
@@ -74,10 +74,13 @@
 sys_displayhook(PyObject *self, PyObject *o)
 {
 	PyObject *outf;
-	PyInterpreterState *interp = PyThreadState_GET()->interp;
+	PyInterpreterState *interp = PyThreadState_Get()->interp;
 	PyObject *modules = interp->modules;
-	PyObject *builtins = PyDict_GetItemString(modules, "__builtin__");
+	PyObject *builtins;
 
+	if (PyDict_GetItemStringEx(modules, "__builtin__", &builtins) < 0)
+		return NULL;
+
 	if (builtins == NULL) {
 		PyErr_SetString(PyExc_RuntimeError, "lost __builtin__");
 		return NULL;
@@ -87,24 +90,32 @@
 	/* After printing, also assign to '_' */
 	/* Before, set '_' to None to avoid recursion */
 	if (o == Py_None) {
+		Py_DECREF(builtins);
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
 	if (PyObject_SetAttrString(builtins, "_", Py_None) != 0)
-		return NULL;
+		goto failed;
 	outf = PySys_GetObject("stdout");
 	if (outf == NULL) {
 		PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
-		return NULL;
+		goto failed;
 	}
 	if (PyFile_WriteObject(o, outf, 0) != 0)
-		return NULL;
+		goto failed;
 	if (PyFile_WriteString("\n", outf) != 0)
-		return NULL;
-	if (PyObject_SetAttrString(builtins, "_", o) != 0)
-		return NULL;
+		goto failed;
+	/* XXX FIXME this'll fail if o isn't shareable */
+#warning XXX FIXME displayhook
+	//if (PyObject_SetAttrString(builtins, "_", o) != 0)
+	//	goto failed;
+	Py_DECREF(builtins);
 	Py_INCREF(Py_None);
 	return Py_None;
+
+failed:
+	Py_DECREF(builtins);
+	return NULL;
 }
 
 PyDoc_STRVAR(displayhook_doc,
@@ -134,7 +145,7 @@
 sys_exc_info(PyObject *self, PyObject *noargs)
 {
 	PyThreadState *tstate;
-	tstate = PyThreadState_GET();
+	tstate = PyThreadState_Get();
 	return Py_BuildValue(
 		"(OOO)",
 		tstate->exc_type != NULL ? tstate->exc_type : Py_None,
@@ -526,7 +537,7 @@
 sys_setdlopenflags(PyObject *self, PyObject *args)
 {
 	int new_val;
-        PyThreadState *tstate = PyThreadState_GET();
+        PyThreadState *tstate = PyThreadState_Get();
 	if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val))
 		return NULL;
         if (!tstate)
@@ -549,7 +560,7 @@
 static PyObject *
 sys_getdlopenflags(PyObject *self, PyObject *args)
 {
-        PyThreadState *tstate = PyThreadState_GET();
+        PyThreadState *tstate = PyThreadState_Get();
         if (!tstate)
 		return NULL;
         return PyInt_FromLong(tstate->interp->dlopenflags);
@@ -582,7 +593,7 @@
 static PyObject *
 sys_getrefcount(PyObject *self, PyObject *arg)
 {
-	return PyInt_FromSsize_t(arg->ob_refcnt);
+	return PyInt_FromSsize_t(Py_RefcntSnoop(arg));
 }
 
 #ifdef Py_REF_DEBUG
@@ -626,7 +637,7 @@
 static PyObject *
 sys_getframe(PyObject *self, PyObject *args)
 {
-	PyFrameObject *f = PyThreadState_GET()->frame;
+	PyFrameObject *f = PyThreadState_Get()->frame;
 	int depth = -1;
 
 	if (!PyArg_ParseTuple(args, "|i:_getframe", &depth))
@@ -700,6 +711,33 @@
 10. Number of stack pops performed by call_function()"
 );
 
+static PyObject *
+sys_runfinalizers(PyObject *self, PyObject *queue)
+{
+    PyObject *core, *res;
+
+    while (1) {
+        core = PyObject_CallMethod(queue, "pop", "");
+        if (core == NULL)
+            return NULL;
+        if (core == Py_None)
+            return Py_None;  /* Just steal the reference that was core */
+        res = PyObject_CallMethod(core, "__finalize__", "");
+        Py_DECREF(core);
+        if (res == NULL)
+            return NULL;
+        Py_DECREF(res);
+    }
+}
+
+PyDoc_STRVAR(runfinalizers_doc,
+"_runfinalizers(queue)\n\
+\n\
+Run all __finalize__ methods of objects returned by queue.pop(),\n\
+blocking if none are available.  Returns if an exception is thrown or\n\
+if queue.pop() produces None."
+);
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -760,6 +798,7 @@
 #ifdef USE_MALLOPT
 	{"mdebug",	sys_mdebug, METH_VARARGS},
 #endif
+	{"_runfinalizers", sys_runfinalizers, METH_O | METH_SHARED, runfinalizers_doc},
 	{"setdefaultencoding", sys_setdefaultencoding, METH_VARARGS,
 	 setdefaultencoding_doc},
 	{"setcheckinterval",	sys_setcheckinterval, METH_VARARGS,
Index: configure
===================================================================
--- configure	(revision 58355)
+++ configure	(working copy)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 57931 .
+# From configure.in Revision: 58054 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61 for python 3.0.
 #
@@ -1346,6 +1346,7 @@
   --with(out)-tsc         enable/disable timestamp counter profile
   --with(out)-pymalloc    disable/enable specialized mallocs
   --with-wctype-functions use wctype.h functions
+  --with-freethread       enable free threading
   --with-fpectl           enable SIGFPE catching
   --with-libm=STRING      math library
   --with-libc=STRING      C library
@@ -14606,6 +14607,31 @@
 fi
 
 
+# Check for --with-freethread
+{ echo "$as_me:$LINENO: checking for --with-freethread" >&5
+echo $ECHO_N "checking for --with-freethread... $ECHO_C" >&6; }
+
+# Check whether --with-freethread was given.
+if test "${with_freethread+set}" = set; then
+  withval=$with_freethread;
+if test "$withval" != no
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_FREETHREAD 1
+_ACEOF
+
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; };
+else { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; };
+fi
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
 # -I${DLINCLDIR} is added to the compile rule for importdl.o
 
 DLINCLDIR=.
Index: LICENSE
===================================================================
--- LICENSE	(revision 58355)
+++ LICENSE	(working copy)
@@ -1,3 +1,7 @@
+The python-safethread patch is licensed under the Apache License, version 2.0.  Obviously the rest of Python is under its own license (or licenses.)
+
+~~~~~~~~~~
+
 A. HISTORY OF THE SOFTWARE
 ==========================
 
Index: Include/datetime.h
===================================================================
--- Include/datetime.h	(revision 58355)
+++ Include/datetime.h	(working copy)
@@ -76,13 +76,8 @@
 typedef struct
 {
 	_PyDateTime_TIMEHEAD
-} _PyDateTime_BaseTime;		/* hastzinfo false */
-
-typedef struct
-{
-	_PyDateTime_TIMEHEAD
 	PyObject *tzinfo;
-} PyDateTime_Time;		/* hastzinfo true */
+} PyDateTime_Time;
 
 
 /* All datetime objects are of PyDateTime_DateTimeType, but that can be
@@ -103,13 +98,8 @@
 typedef struct
 {
 	_PyDateTime_DATETIMEHEAD
-} _PyDateTime_BaseDateTime;	/* hastzinfo false */
-
-typedef struct
-{
-	_PyDateTime_DATETIMEHEAD
 	PyObject *tzinfo;
-} PyDateTime_DateTime;		/* hastzinfo true */
+} PyDateTime_DateTime;
 
 
 /* Apply for date and datetime instances. */
Index: Include/stringobject.h
===================================================================
--- Include/stringobject.h	(revision 58355)
+++ Include/stringobject.h	(working copy)
@@ -35,7 +35,7 @@
 typedef struct {
     PyObject_VAR_HEAD
     long ob_shash;
-    int ob_sstate;
+    AO_t ob_sstate;
     char ob_sval[1];
 
     /* Invariants:
@@ -76,12 +76,10 @@
 						   const char *);
 
 PyAPI_FUNC(void) PyString_InternInPlace(PyObject **);
-PyAPI_FUNC(void) PyString_InternImmortal(PyObject **);
 PyAPI_FUNC(PyObject *) PyString_InternFromString(const char *);
 PyAPI_FUNC(void) _Py_ReleaseInternedStrings(void);
 
-/* Use only if you know it's a string */
-#define PyString_CHECK_INTERNED(op) (((PyStringObject *)(op))->ob_sstate)
+PyAPI_FUNC(int) _PyString_SnoopState(PyStringObject *op);
 
 /* Macro, trading safety for speed */
 #define PyString_AS_STRING(op) (assert(PyString_Check(op)),(((PyStringObject *)(op))->ob_sval))
Index: Include/dictobject.h
===================================================================
--- Include/dictobject.h	(revision 58355)
+++ Include/dictobject.h	(working copy)
@@ -67,6 +67,7 @@
 it's two-thirds full.
 */
 typedef struct _dictobject PyDictObject;
+typedef struct _pydict_lockstate PyDict_LockState;
 struct _dictobject {
 	PyObject_HEAD
 	Py_ssize_t ma_fill;  /* # Active + # Dummy */
@@ -78,24 +79,50 @@
 	 */
 	Py_ssize_t ma_mask;
 
+	/* Counter for number of times ma_table has been reallocated and
+	 * rebuilt.  Used to detect changes during a lookup.
+	 *
+	 * It's theoretically possible for this to wrap around completely
+	 * during one lookup, causing it to not restart.  Using a 64bit
+	 * counter would be the safest defense against this, but for now
+	 * we'll just be lazy.
+	 */
+	unsigned long long ma_rebuilds;
+
 	/* ma_table points to ma_smalltable for small tables, else to
 	 * additional malloc'ed memory.  ma_table is never NULL!  This rule
 	 * saves repeated runtime null-tests in the workhorse getitem and
 	 * setitem calls.
 	 */
 	PyDictEntry *ma_table;
-	PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
+	PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key,
+		long hash, PyDict_LockState *lockstate);
 	PyDictEntry ma_smalltable[PyDict_MINSIZE];
 };
 
+typedef struct {
+    PyDictObject base;
+    AO_t readonly_mode;
+    PyCritical *crit;
+    int read_count;
+} PySharedDictObject;
+
+struct _pydict_lockstate {
+    int doing_write;  /* These two flags are mutually incompatible */
+    int skipped_lock;
+};
+
 PyAPI_DATA(PyTypeObject) PyDict_Type;
+PyAPI_DATA(PyTypeObject) PySharedDict_Type;
 
 #define PyDict_Check(op) \
                  PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_DICT_SUBCLASS)
 #define PyDict_CheckExact(op) (Py_Type(op) == &PyDict_Type)
+#define PySharedDict_Check(op) (Py_Type(op) == &PySharedDict_Type)
 
 PyAPI_FUNC(PyObject *) PyDict_New(void);
 PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key);
+PyAPI_FUNC(int) PyDict_GetItemEx(PyObject *op, PyObject *key, PyObject **value);
 PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item);
 PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key);
 PyAPI_FUNC(void) PyDict_Clear(PyObject *mp);
@@ -103,6 +130,8 @@
 	PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value);
 PyAPI_FUNC(int) _PyDict_Next(
 	PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, long *hash);
+PyAPI_FUNC(int) PyDict_NextEx(PyObject *mp, Py_ssize_t *pos,
+    PyObject **key, PyObject **value);
 PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp);
 PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp);
 PyAPI_FUNC(PyObject *) PyDict_Items(PyObject *mp);
@@ -133,8 +162,10 @@
 					   int override);
 
 PyAPI_FUNC(PyObject *) PyDict_GetItemString(PyObject *dp, const char *key);
+PyAPI_FUNC(int) PyDict_GetItemStringEx(PyObject *v, const char *key, PyObject **value);
 PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
 PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
+PyAPI_FUNC(int) PyDict_ContainsString(PyObject *d, const char *key);
 
 #ifdef __cplusplus
 }
Index: Include/code.h
===================================================================
--- Include/code.h	(revision 58355)
+++ Include/code.h	(working copy)
@@ -49,6 +49,7 @@
 #define CO_FUTURE_ABSOLUTE_IMPORT 0x4000 /* do absolute imports by default */
 #define CO_FUTURE_WITH_STATEMENT  0x8000
 #endif
+#define CO_FUTURE_SHARED_MODULE 0x0800
 
 /* This should be defined if a future statement modifies the syntax.
    For example, when a keyword is added.
Index: Include/unicodeobject.h
===================================================================
--- Include/unicodeobject.h	(revision 58355)
+++ Include/unicodeobject.h	(working copy)
@@ -404,7 +404,7 @@
     Py_ssize_t length;		/* Length of raw Unicode data in buffer */
     Py_UNICODE *str;		/* Raw Unicode buffer */
     long hash;			/* Hash value; -1 if not set */
-    int state;			/* != 0 if interned. In this case the two
+    AO_t state;			/* != 0 if interned. In this case the two
     				 * references from the dictionary to this object
     				 * are *not* counted in ob_refcnt. */
     PyObject *defenc;		/* (Default) Encoded version as Python
@@ -415,8 +415,7 @@
 PyAPI_DATA(PyTypeObject) PyUnicode_Type;
 
 #define SSTATE_NOT_INTERNED 0
-#define SSTATE_INTERNED_MORTAL 1
-#define SSTATE_INTERNED_IMMORTAL 2
+#define SSTATE_INTERNED 1
 
 #define PyUnicode_Check(op) \
                  PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_UNICODE_SUBCLASS)
@@ -551,13 +550,9 @@
 PyAPI_FUNC(PyObject *) PyUnicode_FromFormat(const char*, ...);
 
 PyAPI_FUNC(void) PyUnicode_InternInPlace(PyObject **);
-PyAPI_FUNC(void) PyUnicode_InternImmortal(PyObject **);
 PyAPI_FUNC(PyObject *) PyUnicode_InternFromString(const char *);
 PyAPI_FUNC(void) _Py_ReleaseInternedUnicodeStrings(void);
 
-/* Use only if you know it's a string */
-#define PyUnicode_CHECK_INTERNED(op) (((PyUnicodeObject *)(op))->state)
-
 /* --- wchar_t support for platforms which support it --------------------- */
 
 #ifdef HAVE_WCHAR_H
Index: Include/interruptobject.h
===================================================================
--- Include/interruptobject.h	(revision 0)
+++ Include/interruptobject.h	(revision 0)
@@ -0,0 +1,57 @@
+/* Interrupt Object */
+
+#ifndef Py_INTERRUPTOBJECT_H
+#define Py_INTERRUPTOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pythread.h"
+
+
+struct _PyInterruptQueue;
+
+typedef struct _PyInterruptObject {
+	PyObject_HEAD
+	PyThread_type_lock lock;
+	int interrupted;
+	struct _PyInterruptObject *parent;
+	struct _PyInterruptObject *child;
+
+	/* Either the C or the Python version will be set, but not both */
+	void (*notify_parent_int_c)(struct _PyInterruptQueue *, void *arg);
+	void *arg;
+	PyObject *notify_parent_int_python;
+
+	/* Used only when notify_parent_int_python is used */
+	struct _PyInterruptObject *next;
+} PyInterruptObject;
+
+typedef struct _PyInterruptQueue {
+	PyInterruptObject *head;
+	PyInterruptObject *tail;
+} PyInterruptQueue;
+
+
+PyAPI_DATA(PyTypeObject) PyInterrupt_Type;
+#define PyInterrupt_Check(op) (Py_Type(op) == &PyInterrupt_Type)
+
+PyAPI_FUNC(PyInterruptObject *) PyInterrupt_New(
+	void (*)(struct _PyInterruptQueue *, void *),
+	void *, PyObject *);
+PyAPI_FUNC(void) PyInterrupt_Push(PyInterruptObject *);
+PyAPI_FUNC(void) PyInterrupt_Pop(PyInterruptObject *);
+
+/* Init and Add will only run C functions, so they can be called while
+ * you hold a lock.  Finish calls any remaining python functions, so it
+ * should be called after you release your lock. */
+PyAPI_FUNC(void) PyInterruptQueue_Init(PyInterruptQueue *);
+PyAPI_FUNC(void) PyInterruptQueue_Add(PyInterruptQueue *, PyInterruptObject *);
+PyAPI_FUNC(void) PyInterruptQueue_AddFromParent(PyInterruptQueue *, PyInterruptObject *);
+PyAPI_FUNC(void) PyInterruptQueue_Finish(PyInterruptQueue *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERRUPTOBJECT_H */
Index: Include/ceval.h
===================================================================
--- Include/ceval.h	(revision 58355)
+++ Include/ceval.h	(working copy)
@@ -39,20 +39,17 @@
    flag was set, else return 0. */
 PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
 
-PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg);
-PyAPI_FUNC(int) Py_MakePendingCalls(void);
-
 /* Protection against deeply nested recursive calls */
 PyAPI_FUNC(void) Py_SetRecursionLimit(int);
 PyAPI_FUNC(int) Py_GetRecursionLimit(void);
 
 #define Py_EnterRecursiveCall(where)                                    \
-	    (_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) &&  \
+	    (_Py_MakeRecCheck(PyThreadState_Get()->recursion_depth) &&  \
 	     _Py_CheckRecursiveCall(where))
 #define Py_LeaveRecursiveCall()				\
-    do{ if((--PyThreadState_GET()->recursion_depth) <   \
+    do{ if((--PyThreadState_Get()->recursion_depth) <   \
 	   _Py_CheckRecursionLimit - 50);               \
-	  PyThreadState_GET()->overflowed = 0;          \
+	  PyThreadState_Get()->overflowed = 0;          \
     } while(0)
 PyAPI_FUNC(int) _Py_CheckRecursiveCall(char *where);
 PyAPI_DATA(int) _Py_CheckRecursionLimit;
@@ -63,11 +60,11 @@
 #endif
 
 #define Py_ALLOW_RECURSION \
-  do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
-    PyThreadState_GET()->recursion_critical = 1;
+  do { unsigned char _old = PyThreadState_Get()->recursion_critical;\
+    PyThreadState_Get()->recursion_critical = 1;
 
 #define Py_END_ALLOW_RECURSION \
-    PyThreadState_GET()->recursion_critical = _old; \
+    PyThreadState_Get()->recursion_critical = _old; \
   } while(0);
 
 PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *);
@@ -81,84 +78,7 @@
 PyAPI_DATA(volatile int) _Py_Ticker;
 PyAPI_DATA(int) _Py_CheckInterval;
 
-/* Interface for threads.
 
-   A module that plans to do a blocking system call (or something else
-   that lasts a long time and doesn't touch Python data) can allow other
-   threads to run as follows:
-
-	...preparations here...
-	Py_BEGIN_ALLOW_THREADS
-	...blocking system call here...
-	Py_END_ALLOW_THREADS
-	...interpret result here...
-
-   The Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS pair expands to a
-   {}-surrounded block.
-   To leave the block in the middle (e.g., with return), you must insert
-   a line containing Py_BLOCK_THREADS before the return, e.g.
-
-	if (...premature_exit...) {
-		Py_BLOCK_THREADS
-		PyErr_SetFromErrno(PyExc_IOError);
-		return NULL;
-	}
-
-   An alternative is:
-
-	Py_BLOCK_THREADS
-	if (...premature_exit...) {
-		PyErr_SetFromErrno(PyExc_IOError);
-		return NULL;
-	}
-	Py_UNBLOCK_THREADS
-
-   For convenience, that the value of 'errno' is restored across
-   Py_END_ALLOW_THREADS and Py_BLOCK_THREADS.
-
-   WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND
-   Py_END_ALLOW_THREADS!!!
-
-   The function PyEval_InitThreads() should be called only from
-   initthread() in "threadmodule.c".
-
-   Note that not yet all candidates have been converted to use this
-   mechanism!
-*/
-
-PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void);
-PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
-
-#ifdef WITH_THREAD
-
-PyAPI_FUNC(int)  PyEval_ThreadsInitialized(void);
-PyAPI_FUNC(void) PyEval_InitThreads(void);
-PyAPI_FUNC(void) PyEval_AcquireLock(void);
-PyAPI_FUNC(void) PyEval_ReleaseLock(void);
-PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);
-PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate);
-PyAPI_FUNC(void) PyEval_ReInitThreads(void);
-
-#define Py_BEGIN_ALLOW_THREADS { \
-			PyThreadState *_save; \
-			_save = PyEval_SaveThread();
-#define Py_BLOCK_THREADS	PyEval_RestoreThread(_save);
-#define Py_UNBLOCK_THREADS	_save = PyEval_SaveThread();
-#define Py_END_ALLOW_THREADS	PyEval_RestoreThread(_save); \
-		 }
-
-#else /* !WITH_THREAD */
-
-#define Py_BEGIN_ALLOW_THREADS {
-#define Py_BLOCK_THREADS
-#define Py_UNBLOCK_THREADS
-#define Py_END_ALLOW_THREADS }
-
-#endif /* !WITH_THREAD */
-
-PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
-
-
 #ifdef __cplusplus
 }
 #endif
Index: Include/objimpl.h
===================================================================
--- Include/objimpl.h	(revision 58355)
+++ Include/objimpl.h	(working copy)
@@ -6,6 +6,7 @@
 #define Py_OBJIMPL_H
 
 #include "pymem.h"
+#include "pythread.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -94,6 +95,7 @@
    the object gets initialized via PyObject_{Init, InitVar} after obtaining
    the raw memory.
 */
+#if 0
 PyAPI_FUNC(void *) PyObject_Malloc(size_t);
 PyAPI_FUNC(void *) PyObject_Realloc(void *, size_t);
 PyAPI_FUNC(void) PyObject_Free(void *);
@@ -130,6 +132,7 @@
 
 #define PyObject_Del		PyObject_Free
 #define PyObject_DEL		PyObject_FREE
+#endif
 
 /*
  * Generic object allocator interface
@@ -137,23 +140,31 @@
  */
 
 /* Functions */
-PyAPI_FUNC(PyObject *) PyObject_Init(PyObject *, PyTypeObject *);
-PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *,
-                                                 PyTypeObject *, Py_ssize_t);
 PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
-PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
+PyAPI_FUNC(PyObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
+PyAPI_FUNC(void) _PyObject_Del(PyObject *);
+PyAPI_FUNC(void) _PyObject_Revive(PyObject *);
+PyAPI_FUNC(void) _PyObject_Complete(PyObject *);
+PyAPI_FUNC(PyObject *) _PyObject_Resize(PyObject *, Py_ssize_t);
 
-#define PyObject_New(type, typeobj) \
-		( (type *) _PyObject_New(typeobj) )
-#define PyObject_NewVar(type, typeobj, n) \
-		( (type *) _PyObject_NewVar((typeobj), (n)) )
+#define PyObject_New _PyObject_New
+#define PyObject_NewVar _PyObject_NewVar
+#define PyObject_Del _PyObject_Del
+#define PyObject_Revive _PyObject_Revive
+#define PyObject_Complete _PyObject_Complete
+#define PyObject_Resize _PyObject_Resize
 
-/* Macros trading binary compatibility for speed. See also pymem.h.
-   Note that these macros expect non-NULL object pointers.*/
-#define PyObject_INIT(op, typeobj) \
-	( Py_Type(op) = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
-#define PyObject_INIT_VAR(op, typeobj, size) \
-	( Py_Size(op) = (size), PyObject_INIT((op), (typeobj)) )
+#define PyObject_NEW(type, typeobj) \
+        ((type *) _PyObject_New(typeobj))
+#define PyObject_NEWVAR(type, typeobj, n) \
+        ((type *) _PyObject_NewVar((typeobj), (n)))
+#define PyObject_DEL(op) (PyObject_Del((PyObject *)(op)))
+#define PyObject_REVIVE(op) \
+        (PyObject_Revive((PyObject *)(op)))
+#define PyObject_COMPLETE(op) \
+        (PyObject_Complete((PyObject *)(op)))
+#define PyObject_RESIZE(type, op, n) \
+        ((type *) PyObject_Resize((PyObject *)(op), (n)))
 
 #define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
 
@@ -179,15 +190,6 @@
 	  ) & ~(SIZEOF_VOID_P - 1)		\
 	)
 
-#define PyObject_NEW(type, typeobj) \
-( (type *) PyObject_Init( \
-	(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
-
-#define PyObject_NEW_VAR(type, typeobj, n) \
-( (type *) PyObject_InitVar( \
-      (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\
-      (typeobj), (n)) )
-
 /* This example code implements an object constructor with a custom
    allocator, where PyObject_New is inlined, and shows the important
    distinction between two steps (at least):
@@ -231,70 +233,34 @@
 #define PyObject_IS_GC(o) (PyType_IS_GC(Py_Type(o)) && \
 	(Py_Type(o)->tp_is_gc == NULL || Py_Type(o)->tp_is_gc(o)))
 
-PyAPI_FUNC(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, Py_ssize_t);
-#define PyObject_GC_Resize(type, op, n) \
-		( (type *) _PyObject_GC_Resize((PyVarObject *)(op), (n)) )
-
-/* for source compatibility with 2.2 */
-#define _PyObject_GC_Del PyObject_GC_Del
-
+#if 0
 /* GC information is stored BEFORE the object structure. */
 typedef union _gc_head {
 	struct {
+		Py_ssize_t gc_sizeclass;
 		union _gc_head *gc_next;
 		union _gc_head *gc_prev;
 		Py_ssize_t gc_refs;
 	} gc;
 	long double dummy;  /* force worst-case alignment */
 } PyGC_Head;
+#else
+#define PyGC_Head PyObject
+#endif
 
 extern PyGC_Head *_PyGC_generation0;
 
+#if 0
 #define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
+#endif
 
 #define _PyGC_REFS_UNTRACKED			(-2)
 #define _PyGC_REFS_REACHABLE			(-3)
 #define _PyGC_REFS_TENTATIVELY_UNREACHABLE	(-4)
 
-/* Tell the GC to track this object.  NB: While the object is tracked the
- * collector it must be safe to call the ob_traverse method. */
-#define _PyObject_GC_TRACK(o) do { \
-	PyGC_Head *g = _Py_AS_GC(o); \
-	if (g->gc.gc_refs != _PyGC_REFS_UNTRACKED) \
-		Py_FatalError("GC object already tracked"); \
-	g->gc.gc_refs = _PyGC_REFS_REACHABLE; \
-	g->gc.gc_next = _PyGC_generation0; \
-	g->gc.gc_prev = _PyGC_generation0->gc.gc_prev; \
-	g->gc.gc_prev->gc.gc_next = g; \
-	_PyGC_generation0->gc.gc_prev = g; \
-    } while (0);
+PyAPI_FUNC(void) _PyGC_Object_Cache_Flush(void);
 
-/* Tell the GC to stop tracking this object.
- * gc_next doesn't need to be set to NULL, but doing so is a good
- * way to provoke memory errors if calling code is confused.
- */
-#define _PyObject_GC_UNTRACK(o) do { \
-	PyGC_Head *g = _Py_AS_GC(o); \
-	assert(g->gc.gc_refs != _PyGC_REFS_UNTRACKED); \
-	g->gc.gc_refs = _PyGC_REFS_UNTRACKED; \
-	g->gc.gc_prev->gc.gc_next = g->gc.gc_next; \
-	g->gc.gc_next->gc.gc_prev = g->gc.gc_prev; \
-	g->gc.gc_next = NULL; \
-    } while (0);
 
-PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t);
-PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *);
-PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t);
-PyAPI_FUNC(void) PyObject_GC_Track(void *);
-PyAPI_FUNC(void) PyObject_GC_UnTrack(void *);
-PyAPI_FUNC(void) PyObject_GC_Del(void *);
-
-#define PyObject_GC_New(type, typeobj) \
-		( (type *) _PyObject_GC_New(typeobj) )
-#define PyObject_GC_NewVar(type, typeobj, n) \
-		( (type *) _PyObject_GC_NewVar((typeobj), (n)) )
-
-
 /* Utility macro to help write tp_traverse functions.
  * To use this macro, the tp_traverse function must name its arguments
  * "visit" and "arg".  This is intended to keep tp_traverse functions
@@ -322,9 +288,6 @@
 /* Test if a type supports weak references */
 #define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0)
 
-#define PyObject_GET_WEAKREFS_LISTPTR(o) \
-	((PyObject **) (((char *) (o)) + Py_Type(o)->tp_weaklistoffset))
-
 #ifdef __cplusplus
 }
 #endif
Index: Include/moduleobject.h
===================================================================
--- Include/moduleobject.h	(revision 58355)
+++ Include/moduleobject.h	(working copy)
@@ -13,6 +13,7 @@
 #define PyModule_CheckExact(op) (Py_Type(op) == &PyModule_Type)
 
 PyAPI_FUNC(PyObject *) PyModule_New(const char *);
+PyAPI_FUNC(PyObject *) PyModule_NewEx(const char *, int);
 PyAPI_FUNC(PyObject *) PyModule_GetDict(PyObject *);
 PyAPI_FUNC(const char *) PyModule_GetName(PyObject *);
 PyAPI_FUNC(const char *) PyModule_GetFilename(PyObject *);
Index: Include/monitorobject.h
===================================================================
--- Include/monitorobject.h	(revision 0)
+++ Include/monitorobject.h	(revision 0)
@@ -0,0 +1,51 @@
+/* Monitor object and Monitor Space interface */
+
+#ifndef Py_MONITOROBJECT_H
+#define Py_MONITOROBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pythread.h"
+
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *mon_monitorspace;  /* The monitorspace that contains us */
+} PyMonitorObject;
+
+typedef struct _PyMonitorSpaceObject {
+	PyObject_HEAD
+	PyThread_type_lock lock;
+	/* XXX FIXME rename struct _ts */
+	struct _ts *lock_holder;
+	struct _ts *first_waiter;
+	struct _ts *last_waiter;
+	/* XXX flag (or counter?) used by PyState_StopTheWorld */
+} PyMonitorSpaceObject;
+
+PyAPI_DATA(PyTypeObject) PyMonitorMeta_Type;
+PyAPI_DATA(PyTypeObject) PyMonitor_Type;
+PyAPI_DATA(PyTypeObject) PyMonitorSpace_Type;
+
+#define PyMonitorMeta_Check(op) PyObject_TypeCheck(op, &PyMonitorMeta_Type)
+#define PyMonitorMeta_CheckExact(op) ((op)->ob_type == &PyMonitorMeta_Type)
+
+#define PyMonitor_Check(op) \
+	PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_MONITOR_SUBCLASS)
+#define PyMonitor_CheckExact(op) ((op)->ob_type == &PyMonitor_Type)
+
+#define PyMonitorSpace_Check(op) PyObject_TypeCheck(op, &PyMonitorSpace_Type)
+#define PyMonitorSpace_CheckExact(op) ((op)->ob_type == &PyMonitorSpace_Type)
+
+#define PyMonitor_GetMonitorSpace(op) \
+	((PyMonitorSpaceObject *)(((PyMonitorObject *)op)->mon_monitorspace))
+
+PyAPI_FUNC(int) PyMonitorSpace_IsCurrent(struct _PyMonitorSpaceObject *);
+PyAPI_FUNC(PyObject *) PyMonitorSpace_GetCurrent(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_MONITOROBJECT_H */
Index: Include/Python.h
===================================================================
--- Include/Python.h	(revision 58355)
+++ Include/Python.h	(working copy)
@@ -107,7 +107,7 @@
 #include "pythonrun.h"
 #include "ceval.h"
 #include "sysmodule.h"
-#include "intrcheck.h"
+#include "pysignal.h"
 #include "import.h"
 
 #include "abstract.h"
Index: Include/branchobject.h
===================================================================
--- Include/branchobject.h	(revision 0)
+++ Include/branchobject.h	(revision 0)
@@ -0,0 +1,66 @@
+/* Branch object */
+
+#ifndef Py_BRANCHOBJECT_H
+#define Py_BRANCHOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pythread.h"
+#include "pystate.h"
+
+
+struct _PyInterruptObject; /* Avoid including interruptobject.h */
+
+struct _PyBranchObject;
+
+typedef struct _PyBranchChild {
+	PyInterpreterState *interp;
+	PyThreadState *tstate;
+	struct _PyInterruptObject *interrupt_point;
+	struct _PyBranchObject *branch;
+	PyObject *func;
+	PyObject *args;
+	PyObject *kwds;
+	int save_result;
+	PyObject *result;
+	PyObject *exception;
+	struct _PyBranchChild *prev;
+	struct _PyBranchChild *next;
+} PyBranchChild;
+
+typedef struct _PyBranchObject {
+	PyObject_HEAD
+	PyThread_type_lock col_lock;
+	int col_state;
+
+	PyObject *col_ownerthread;
+	PyObject *col_threads;
+	PyBranchChild *col_mainthread;
+	PyBranchChild *col_head;
+	PyBranchChild *col_tail;
+	Py_ssize_t col_threadcount;
+	PyThread_type_sem col_nothreads;
+
+	struct _PyInterruptObject *col_baseinterrupt;
+
+	int col_interrupting;
+	Py_ssize_t col_resultcount;
+	Py_ssize_t col_exceptioncount;
+} PyBranchObject;
+
+PyAPI_DATA(PyTypeObject) PyBranch_Type;
+
+#define PyBranch_Check(op) PyObject_TypeCheck(op, &PyBranch_Type)
+#define PyBranch_CheckExact(op) (Py_Type(op) == &PyBranch_Type)
+
+#define BRANCH_NEW	1
+#define BRANCH_ALIVE	2
+#define BRANCH_DYING	3
+#define BRANCH_DEAD	4
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_BRANCHOBJECT_H */
Index: Include/pymem.h
===================================================================
--- Include/pymem.h	(revision 58355)
+++ Include/pymem.h	(working copy)
@@ -49,6 +49,72 @@
    performed on failure (no exception is set, no warning is printed, etc).
 */
 
+#if 1
+PyAPI_FUNC(void) Py_FatalError(const char *message);
+
+/* XXX Must match up with obmalloc.c's size_classes */
+#define PYMALLOC_CACHE_SIZECLASSES 13
+
+#define PYMALLOC_CACHE_COUNT 32
+
+
+PyAPI_FUNC(void *) pymemcache_malloc(size_t);
+PyAPI_FUNC(void *) pymemcache_realloc(void *, size_t);
+PyAPI_FUNC(void) pymemcache_free(void *);
+
+
+/* pymemwrap is just a temporary bodge until the different names are
+ * properly unified. */
+PyAPI_FUNC(void *) _pymemwrap_malloc(const char *, const char *, size_t);
+PyAPI_FUNC(void *) _pymemwrap_realloc(const char *, const char *, void *, size_t);
+PyAPI_FUNC(void) _pymemwrap_free(const char *, const char *, void *);
+
+#define PyMEMWRAP_MALLOC(name, group) \
+static inline void * \
+name(size_t size) \
+{ \
+	return _pymemwrap_malloc(#name, #group, size); \
+}
+
+#define PyMEMWRAP_REALLOC(name, group) \
+static inline void * \
+name(void *oldmem, size_t size) \
+{ \
+	return _pymemwrap_realloc(#name, #group, oldmem, size); \
+}
+
+#define PyMEMWRAP_FREE(name, group) \
+static inline void \
+name(void *mem) \
+{ \
+	_pymemwrap_free(#name, #group, mem); \
+}
+
+PyMEMWRAP_MALLOC(PyMem_Malloc, PyMem_Camel)
+PyMEMWRAP_REALLOC(PyMem_Realloc, PyMem_Camel)
+PyMEMWRAP_FREE(PyMem_Free, PyMem_Camel)
+
+PyMEMWRAP_MALLOC(PyMem_MALLOC, PyMem_UPPER)
+PyMEMWRAP_REALLOC(PyMem_REALLOC, PyMem_UPPER)
+PyMEMWRAP_FREE(PyMem_FREE, PyMem_UPPER)
+
+PyMEMWRAP_MALLOC(PyObject_Malloc, PyObject_Camel)
+PyMEMWRAP_REALLOC(PyObject_Realloc, PyObject_Camel)
+PyMEMWRAP_FREE(PyObject_Free, PyObject_Camel)
+
+PyMEMWRAP_MALLOC(PyObject_MALLOC, PyObject_UPPER)
+PyMEMWRAP_REALLOC(PyObject_REALLOC, PyObject_UPPER)
+PyMEMWRAP_FREE(PyObject_FREE, PyObject_UPPER)
+
+/* PyMem_Del is only used by multibytecodec.c */
+PyMEMWRAP_FREE(PyMem_Del, PyMem_CamelDel)
+PyMEMWRAP_FREE(PyMem_DEL, PyMem_UPPERDEL)
+
+//PyMEMWRAP_FREE(hidden_PyObject_Del, PyObject_CamelDel)
+//PyAPI_FUNC(void) PyObject_Del(void *);
+//PyMEMWRAP_FREE(PyObject_DEL, PyObject_UPPERDEL)
+
+#else
 PyAPI_FUNC(void *) PyMem_Malloc(size_t);
 PyAPI_FUNC(void *) PyMem_Realloc(void *, size_t);
 PyAPI_FUNC(void) PyMem_Free(void *);
@@ -74,6 +140,7 @@
 #define PyMem_FREE		free
 
 #endif	/* PYMALLOC_DEBUG */
+#endif
 
 /*
  * Type-oriented memory interface
@@ -97,8 +164,8 @@
 /* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
  * anymore.  They're just confusing aliases for PyMem_{Free,FREE} now.
  */
-#define PyMem_Del		PyMem_Free
-#define PyMem_DEL		PyMem_FREE
+//#define PyMem_Del		PyMem_Free
+//#define PyMem_DEL		PyMem_FREE
 
 #ifdef __cplusplus
 }
Index: Include/pystate.h
===================================================================
--- Include/pystate.h	(revision 58355)
+++ Include/pystate.h	(working copy)
@@ -8,15 +8,35 @@
 extern "C" {
 #endif
 
+#include <atomic_ops.h>
+
+#include "pythread.h"
+
+
+/* XXX Must match up with gcmodule.c's gc_cache_size_classes */
+#define PYGC_CACHE_SIZECLASSES 13
+
+#define PYGC_CACHE_COUNT 32
+
+/* XXX Must be a power of 2 */
+//#define Py_ASYNCREFCOUNT_TABLE 1024
+#define Py_ASYNCREFCOUNT_TABLE 2048
+
+
 /* State shared between threads */
 
 struct _ts; /* Forward */
 struct _is; /* Forward */
+struct _PyMonitorSpaceFrame; /* Forward */
+struct _PyState_EnterFrame;
+typedef struct _PyState_EnterFrame *PyState_EnterTag;
 
 typedef struct _is {
 
     struct _is *next;
     struct _ts *tstate_head;
+    AO_t tstate_count;
+    PyState_EnterTag entertag;
 
     PyObject *modules;
     PyObject *sysdict;
@@ -40,6 +60,8 @@
 /* State unique per thread */
 
 struct _frame; /* Avoid including frameobject.h */
+struct _PyMonitorSpaceObject; /* Avoid including monitorobject.h */
+struct _PyInterruptObject; /* Avoid including interruptobject.h */
 
 /* Py_tracefunc return -1 when raising an exception, or 0 for success. */
 typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
@@ -53,6 +75,32 @@
 #define PyTrace_C_EXCEPTION 5
 #define PyTrace_C_RETURN 6
 
+typedef struct _PyMonitorSpaceFrame {
+	struct _PyMonitorSpaceFrame *prevframe;
+	struct _PyMonitorSpaceObject *monitorspace;
+} PyMonitorSpaceFrame;
+
+#define PyMonitorSpaceFrame_INIT {NULL, NULL}
+
+typedef struct _PyState_EnterFrame {
+	struct _PyState_EnterFrame *prevframe;
+	PyMonitorSpaceFrame monitorspaceframe;
+	int locked;
+} PyState_EnterFrame;
+
+typedef struct _PyCritical {
+    PyThread_type_lock lock;
+    Py_ssize_t depth;
+    struct _PyCritical *prev;
+} PyCritical;
+
+struct _object;  /* From object.h, which includes us.  Doh! */
+
+typedef struct {
+	struct _object *obj;
+	AO_t diff;
+} PyAsyncRefEntry;
+
 typedef struct _ts {
     /* See Python/ceval.c for comments explaining most fields */
 
@@ -62,9 +110,10 @@
     struct _frame *frame;
     int recursion_depth;
     char overflowed; /* The stack has overflowed. Allow 50 more calls
-		        to handle the runtime error. */
-    char recursion_critical; /* The current calls must not cause 
-				a stack overflow. */
+                        to handle the runtime error. */
+    char recursion_critical; /* The current calls must not cause
+                                a stack overflow. */
+    int dealloc_depth;
     /* 'tracing' keeps track of the execution depth when tracing/profiling.
        This is to prevent the actual trace/profile code from being recorded in
        the trace/profile. */
@@ -86,21 +135,45 @@
 
     PyObject *dict;  /* Stores per-thread state */
 
-    /* tick_counter is incremented whenever the check_interval ticker
+    /* large_ticks is incremented whenever the check_interval ticker
      * reaches zero. The purpose is to give a useful measure of the number
      * of interpreted bytecode instructions in a given thread.  This
      * extremely lightweight statistic collector may be of interest to
      * profilers (like psyco.jit()), although nothing in the core uses it.
      */
-    int tick_counter;
+    int large_ticks;
+    int small_ticks;
 
-    int gilstate_counter;
+    AO_t inspect_count;
+    PyThread_type_lock inspect_queue_lock;
+    PyThread_type_lock inspect_lock;
+    AO_t inspect_flag;
 
-    PyObject *async_exc; /* Asynchronous exception to raise */
-    long thread_id; /* Thread id where this tstate was created */
+    int suspended;
 
+    PyState_EnterFrame *enterframe;
+
+    Py_ssize_t import_depth;
+    PyMonitorSpaceFrame *monitorspace_frame;
+    PyMonitorSpaceFrame _base_monitorspace_frame;
+
+    struct _PyInterruptObject *interrupt_point;
+
+    /* Simple lock that doesn't employ deadlock detection */
+    PyCritical *critical_section;
+
+    /* The Monitor Space lock that this thread may be blocked on. */
+    struct _PyMonitorSpaceObject *active_lock;
+    struct _ts *lockwait_prev;
+    struct _ts *lockwait_next;
+    PyThread_type_cond lockwait_cond;
+
     /* XXX signal handlers should also be here */
 
+    void *malloc_cache[PYMALLOC_CACHE_SIZECLASSES][PYMALLOC_CACHE_COUNT];
+    void *gc_object_cache[PYGC_CACHE_SIZECLASSES][PYGC_CACHE_COUNT];
+
+    PyAsyncRefEntry async_refcounts[Py_ASYNCREFCOUNT_TABLE];
 } PyThreadState;
 
 
@@ -108,33 +181,28 @@
 PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);
 PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);
 
-PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *);
+PyAPI_FUNC(PyThreadState *) _PyThreadState_New(void);
 PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *);
-PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);
-#ifdef WITH_THREAD
-PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);
+PyAPI_FUNC(void) _PyThreadState_Delete(PyThreadState *tstate);
+
+PyAPI_FUNC(PyThreadState *) _PyThreadState_Get(void);
+#ifdef Py_BUILD_CORE
+PyAPI_DATA(__thread PyThreadState *) _py_local_tstate;
+static inline PyThreadState *
+PyThreadState_Get(void)
+{
+	PyThreadState *tstate = _py_local_tstate;
+	if (tstate == NULL)
+		Py_FatalError("PyThreadState_Get: no current thread");
+	return tstate;
+}
+#else
+#define PyThreadState_Get _PyThreadState_Get
 #endif
-
-PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void);
-PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *);
 PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void);
 PyAPI_FUNC(int) PyThreadState_SetAsyncExc(long, PyObject *);
 
 
-/* Variable and macro for in-line access to current thread state */
-
-PyAPI_DATA(PyThreadState *) _PyThreadState_Current;
-
-#ifdef Py_DEBUG
-#define PyThreadState_GET() PyThreadState_Get()
-#else
-#define PyThreadState_GET() (_PyThreadState_Current)
-#endif
-
-typedef
-    enum {PyGILState_LOCKED, PyGILState_UNLOCKED}
-        PyGILState_STATE;
-
 /* Ensure that the current thread is ready to call the Python
    C API, regardless of the current state of Python, or of its
    thread lock.  This may be called as many times as desired
@@ -154,9 +222,10 @@
 
    When the function returns, the current thread will hold the GIL.
 
-   Failure is a fatal error.
+   0 is returned if memory is unavailable.
 */
-PyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void);
+PyAPI_FUNC(PyState_EnterTag) PyState_Enter(void);
+PyAPI_FUNC(PyState_EnterTag) _PyState_EnterPreallocated(PyThreadState *);
 
 /* Release any resources previously acquired.  After this call, Python's
    state will be the same as it was prior to the corresponding
@@ -166,16 +235,9 @@
    Every call to PyGILState_Ensure must be matched by a call to
    PyGILState_Release on the same thread.
 */
-PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE);
+PyAPI_FUNC(void) PyState_Exit(PyState_EnterTag);
+PyAPI_FUNC(void) _PyState_ExitSimple(PyState_EnterFrame *);
 
-/* Helper/diagnostic function - get the current thread state for
-   this thread.  May return NULL if no GILState API has been used
-   on the current thread.  Note the main thread always has such a
-   thread-state, even if no auto-thread-state call has been made
-   on the main thread.
-*/
-PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void);
-
 /* The implementation of sys._current_frames()  Returns a dict mapping
    thread id to that thread's current frame.
 */
@@ -193,6 +255,115 @@
 /* hook for PyEval_GetFrame(), requested for Psyco */
 PyAPI_DATA(PyThreadFrameGetter) _PyThreadState_GetFrame;
 
+PyAPI_FUNC(int) PyThreadState_Tick(void);
+
+
+PyAPI_FUNC(void) PyState_EnterImport(void);
+PyAPI_FUNC(void) PyState_ExitImport(void);
+
+PyAPI_FUNC(void) PyState_StopTheWorld(void);
+PyAPI_FUNC(void) PyState_StartTheWorld(void);
+
+
+/* Prefered API for locking if PyState is involved.  Required if
+ * Py_INCREF/Py_DECREF are used.  The code is assumed to be a critical
+ * section (involving a known, fixed amount of code; entering other
+ * critical sections is an error.)  PyState_Suspend might be called
+ * while entering. */
+PyAPI_FUNC(PyCritical *) PyCritical_Allocate(Py_ssize_t);
+PyAPI_FUNC(void) PyCritical_Free(PyCritical *);
+PyAPI_FUNC(void) PyCritical_Enter(PyCritical *);
+PyAPI_FUNC(void) PyCritical_Exit(PyCritical *);
+/* This is just a bodge for deathqueue_wait.  It shouldn't be used in general */
+PyAPI_FUNC(void) _PyCritical_CondWait(PyCritical *, PyThread_type_cond);
+
+/* Most code only needs one critical section at a time.  They should use
+ * PyCRITICAL_NORMAL and be done with it.  Occasionally you'll need two
+ * specific critical sections at once, in which case you should add your
+ * defines and document them with your own little graph here.
+ *
+ * If there's enough independent graphs I may also add a "section" field,
+ * so you can't accidentally mix graphs.  Will I ever have a need for
+ * "universal" critical sections though, that can be entered while in
+ * any other critical section (except other universal critical sections)?
+ * XXX Using a stack-allocated critical section for INCREF/DECREF and the
+ * like would need a "universal" section field.
+ *
+ *    WEAKREF
+ *       |
+ *    HANDLE
+ *       |
+ *     QUEUE
+ */
+#define PyCRITICAL_WEAKREF_REF 2
+#define PyCRITICAL_WEAKREF_HANDLE 1
+#define PyCRITICAL_WEAKREF_QUEUE 0
+#define PyCRITICAL_NORMAL 0
+
+
+/* Interface for threads.
+
+   A module that plans to do a blocking system call (or something else
+   that lasts a long time and doesn't touch Python data) can allow other
+   threads to run as follows:
+
+	...preparations here...
+	Py_BEGIN_ALLOW_THREADS
+	...blocking system call here...
+	Py_END_ALLOW_THREADS
+	...interpret result here...
+
+   The Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS pair expands to a
+   {}-surrounded block.
+   To leave the block in the middle (e.g., with return), you must insert
+   a line containing Py_BLOCK_THREADS before the return, e.g.
+
+	if (...premature_exit...) {
+		Py_BLOCK_THREADS
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+
+   An alternative is:
+
+	Py_BLOCK_THREADS
+	if (...premature_exit...) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	Py_UNBLOCK_THREADS
+
+   For convenience, that the value of 'errno' is restored across
+   Py_END_ALLOW_THREADS and Py_BLOCK_THREADS.
+
+   WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND
+   Py_END_ALLOW_THREADS!!!
+
+   The function PyEval_InitThreads() should be called only from
+   initthread() in "threadmodule.c".
+
+   Note that not yet all candidates have been converted to use this
+   mechanism!
+*/
+
+#ifndef WITH_THREAD
+#error Threading support is now unconditional
+#endif
+
+PyAPI_FUNC(void) PyState_PrepareFork(void);
+PyAPI_FUNC(void) PyState_CleanupForkParent(void);
+PyAPI_FUNC(void) PyState_CleanupForkChild(void);
+PyAPI_FUNC(void) PyState_Suspend(void);
+PyAPI_FUNC(void) PyState_Resume(void);
+
+#define Py_BEGIN_ALLOW_THREADS PyState_Suspend();
+#define Py_BLOCK_THREADS PyState_Resume();
+#define Py_UNBLOCK_THREADS PyState_Suspend();
+#define Py_END_ALLOW_THREADS PyState_Resume();
+
+PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
+
+
 #ifdef __cplusplus
 }
 #endif
Index: Include/pythonrun.h
===================================================================
--- Include/pythonrun.h	(revision 58355)
+++ Include/pythonrun.h	(working copy)
@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-#define PyCF_MASK 0
+#define PyCF_MASK CO_FUTURE_SHARED_MODULE
 #define PyCF_MASK_OBSOLETE 0
 #define PyCF_SOURCE_IS_UTF8  0x0100
 #define PyCF_DONT_IMPLY_DEDENT 0x0200
@@ -120,6 +120,7 @@
 
 /* Internal -- various one-time initializations */
 PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
+PyAPI_FUNC(void) _Py_ThreadTools_Init(void);
 PyAPI_FUNC(PyObject *) _PySys_Init(void);
 PyAPI_FUNC(void) _PyImport_Init(void);
 PyAPI_FUNC(void) _PyExc_Init(void);
@@ -128,6 +129,14 @@
 PyAPI_FUNC(int) _PyInt_Init(void);
 PyAPI_FUNC(void) _PyFloat_Init(void);
 PyAPI_FUNC(int) PyBytes_Init(void);
+PyAPI_FUNC(void) _PyMethod_Init(void);
+PyAPI_FUNC(void) _PyTuple_Init(void);
+PyAPI_FUNC(void) _PyList_Init(void);
+PyAPI_FUNC(void) _PySet_Init(void);
+PyAPI_FUNC(void) _PyString_Init(void);
+PyAPI_FUNC(void) _PyCFunction_Init(void);
+PyAPI_FUNC(void) _PySignal_Init(void);
+PyAPI_FUNC(void) _PySignal_InitSigInt(int);
 
 /* Various internal finalizers */
 PyAPI_FUNC(void) _PyExc_Fini(void);
@@ -142,7 +151,9 @@
 PyAPI_FUNC(void) PyBytes_Fini(void);
 PyAPI_FUNC(void) PyInt_Fini(void);
 PyAPI_FUNC(void) PyFloat_Fini(void);
-PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
+PyAPI_FUNC(void) PyDict_Fini(void);
+PyAPI_FUNC(void) _PySignal_Fini(void);
+PyAPI_FUNC(void) _PySignal_FiniSigInt(void);
 
 /* Stuff with no proper home (yet) */
 PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *);
@@ -165,12 +176,7 @@
 PyAPI_FUNC(int) PyOS_CheckStack(void);
 #endif
 
-/* Signals */
-typedef void (*PyOS_sighandler_t)(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
 
-
 #ifdef __cplusplus
 }
 #endif
Index: Include/object.h
===================================================================
--- Include/object.h	(revision 58355)
+++ Include/object.h	(working copy)
@@ -4,7 +4,9 @@
 extern "C" {
 #endif
 
+#include <atomic_ops.h>
 
+
 /* Object and type object interface */
 
 /*
@@ -51,6 +53,12 @@
 whose size is determined when the object is allocated.
 */
 
+#define Py_REFOWNER_ASYNC ((AO_t)0)
+#define Py_REFOWNER_STATICINIT ((AO_t)-1)
+#define Py_REFOWNER_DELETED ((AO_t)-2)
+
+#define Py_REFCNT_DELETED ((AO_t)-42)
+
 /* Py_DEBUG implies Py_TRACE_REFS. */
 #if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
 #define Py_TRACE_REFS
@@ -77,12 +85,16 @@
 /* PyObject_HEAD defines the initial segment of every PyObject. */
 #define PyObject_HEAD		        PyObject ob_base;
 
-#define PyObject_HEAD_INIT(type)	\
+/* XXX FIXME the default for ob_sizeclass is a cludge */
+#define PyObject_HEAD_INIT_NOCOMMA(type)	\
 	{ _PyObject_EXTRA_INIT		\
-	1, type },
+	NULL, NULL, 1, Py_REFOWNER_STATICINIT, 1, _PyGC_REFS_UNTRACKED, type }
+#define PyObject_HEAD_INIT(type) PyObject_HEAD_INIT_NOCOMMA(type),
 
-#define PyVarObject_HEAD_INIT(type, size)	\
-	{ PyObject_HEAD_INIT(type) size },
+#define PyVarObject_HEAD_INIT_NOCOMMA(type, size) \
+	{ PyObject_HEAD_INIT(type) size }
+#define PyVarObject_HEAD_INIT(type, size) \
+	PyVarObject_HEAD_INIT_NOCOMMA(type, size),
 
 /* PyObject_VAR_HEAD defines the initial segment of all variable-size
  * container objects.  These end with a declaration of an array with 1
@@ -100,7 +112,12 @@
  */
 typedef struct _object {
 	_PyObject_HEAD_EXTRA
-	Py_ssize_t ob_refcnt;
+	struct _object *ob_prev;
+	struct _object *ob_next;
+	Py_ssize_t ob_sizeclass;
+	AO_t ob_refowner;
+	AO_t ob_refcnt;
+	AO_t ob_refcnt_trace;
 	struct _typeobject *ob_type;
 } PyObject;
 
@@ -109,10 +126,30 @@
 	Py_ssize_t ob_size; /* Number of items in variable part */
 } PyVarObject;
 
-#define Py_Refcnt(ob)		(((PyObject*)(ob))->ob_refcnt)
+//#define Py_Refcnt(ob)		(((PyObject*)(ob))->ob_refcnt)
 #define Py_Type(ob)		(((PyObject*)(ob))->ob_type)
 #define Py_Size(ob)		(((PyVarObject*)(ob))->ob_size)
 
+#include "pystate.h"
+
+#define Py_RefcntMatches(ob, count) (Py_RefcntSnoop(ob) == (count))
+
+#if 0
+static inline Py_ssize_t
+_Py_RefcntSnoop(PyObject *op)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+	void *owner = (void *)AO_load_full(&op->ob_refowner);
+	Py_ssize_t count = (Py_ssize_t)AO_load_full(&op->ob_refcnt);
+
+	if (owner == tstate)
+		return count;
+	else
+		return 1000000;  /* Arbitrary large value */
+}
+#endif
+#define Py_RefcntSnoop(ob) _Py_RefcntSnoop((PyObject*)(ob))
+
 /*
 Type objects contain a string containing the type name (to help somewhat
 in debugging), the allocation parameters (see PyObject_New() and
@@ -275,7 +312,6 @@
      inquiry bf_multisegment;
 } PyBufferProcs;
 
-typedef void (*freefunc)(void *);
 typedef void (*destructor)(PyObject *);
 typedef int (*printfunc)(PyObject *, FILE *, int);
 typedef PyObject *(*getattrfunc)(PyObject *, char *);
@@ -292,7 +328,7 @@
 typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *);
 typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
 typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
-typedef PyObject *(*allocfunc)(struct _typeobject *, Py_ssize_t);
+typedef int (*isshareablefunc)(PyObject *);
 
 typedef struct _typeobject {
 	PyObject_VAR_HEAD
@@ -326,7 +362,7 @@
 	PyBufferProcs *tp_as_buffer;
 
 	/* Flags to define presence of optional/expanded features */
-	long tp_flags;
+	unsigned long tp_flags;
 
 	const char *tp_doc; /* Documentation string */
 
@@ -358,17 +394,17 @@
 	descrsetfunc tp_descr_set;
 	Py_ssize_t tp_dictoffset;
 	initproc tp_init;
-	allocfunc tp_alloc;
 	newfunc tp_new;
-	freefunc tp_free; /* Low-level free-memory routine */
 	inquiry tp_is_gc; /* For PyObject_IS_GC */
 	PyObject *tp_bases;
 	PyObject *tp_mro; /* method resolution order */
 	PyObject *tp_cache;
 	PyObject *tp_subclasses;
 	PyObject *tp_weaklist;
-	destructor tp_del;
 
+	/* Freezing to allow sharing between threads */
+	isshareablefunc tp_isshareable;
+
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	Py_ssize_t tp_allocs;
@@ -416,10 +452,9 @@
 #define PyType_CheckExact(op) (Py_Type(op) == &PyType_Type)
 
 PyAPI_FUNC(int) PyType_Ready(PyTypeObject *);
-PyAPI_FUNC(PyObject *) PyType_GenericAlloc(PyTypeObject *, Py_ssize_t);
 PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
 					       PyObject *, PyObject *);
-PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
+PyAPI_FUNC(int) _PyType_LookupEx(PyTypeObject *, PyObject *, PyObject **);
 
 /* Generic operations on objects */
 PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
@@ -441,6 +476,7 @@
 PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
 PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *);
 PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
+PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr_NoCheck(PyObject *);
 PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *);
 PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *);
 PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *,
@@ -449,12 +485,15 @@
 PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);
 PyAPI_FUNC(int) PyObject_Not(PyObject *);
 PyAPI_FUNC(int) PyCallable_Check(PyObject *);
+PyAPI_FUNC(int) PyObject_IsShareable(PyObject *);
 
-PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *);
+PyAPI_FUNC(int) _PyObject_TryClearWeakref(PyObject *);
 
 /* A slot function whose address we need to compare */
 extern int _PyObject_SlotCompare(PyObject *, PyObject *);
 
+PyAPI_FUNC(void) _PyGC_AsyncRefcount_Flush(void);
+PyAPI_FUNC(void) _PyGC_RefMode_Promote(PyObject *);
 
 /* PyObject_Dir(obj) acts like Python __builtin__.dir(obj), returning a
    list of strings.  PyObject_Dir(NULL) is like __builtin__.dir(),
@@ -502,37 +541,48 @@
 */
 
 /* Set if the type object is dynamically allocated */
-#define Py_TPFLAGS_HEAPTYPE (1L<<9)
+#define Py_TPFLAGS_HEAPTYPE (1UL<<9)
 
 /* Set if the type allows subclassing */
-#define Py_TPFLAGS_BASETYPE (1L<<10)
+#define Py_TPFLAGS_BASETYPE (1UL<<10)
 
 /* Set if the type is 'ready' -- fully initialized */
-#define Py_TPFLAGS_READY (1L<<12)
+#define Py_TPFLAGS_READY (1UL<<12)
 
 /* Set while the type is being 'readied', to prevent recursive ready calls */
-#define Py_TPFLAGS_READYING (1L<<13)
+#define Py_TPFLAGS_READYING (1UL<<13)
 
 /* Objects support garbage collection (see objimp.h) */
-#define Py_TPFLAGS_HAVE_GC (1L<<14)
+#define Py_TPFLAGS_HAVE_GC (1UL<<14)
 
 /* These two bits are preserved for Stackless Python, next after this is 17 */
 #ifdef STACKLESS
-#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION (3L<<15)
+#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION (3UL<<15)
 #else
 #define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION 0
 #endif
 
+/* Type object is shareable */
+#define Py_TPFLAGS_SHAREABLE (1UL<<17)
+
+/* Type's tp_new will call PyObject_Complete itself.  Memory may not be
+ * wiped. */
+#define Py_TPFLAGS_SKIPWIPE (1UL<<18)
+
+/* Objects provide __finalize__ method */
+#define Py_TPFLAGS_HAVE_FINALIZE (1UL<<19)
+
 /* These flags are used to determine if a type is a subclass. */
-#define Py_TPFLAGS_INT_SUBCLASS		(1L<<23)
-#define Py_TPFLAGS_LONG_SUBCLASS	(1L<<24)
-#define Py_TPFLAGS_LIST_SUBCLASS	(1L<<25)
-#define Py_TPFLAGS_TUPLE_SUBCLASS	(1L<<26)
-#define Py_TPFLAGS_STRING_SUBCLASS	(1L<<27)
-#define Py_TPFLAGS_UNICODE_SUBCLASS	(1L<<28)
-#define Py_TPFLAGS_DICT_SUBCLASS	(1L<<29)
-#define Py_TPFLAGS_BASE_EXC_SUBCLASS	(1L<<30)
-#define Py_TPFLAGS_TYPE_SUBCLASS	(1L<<31)
+#define Py_TPFLAGS_MONITOR_SUBCLASS	(1UL<<22)
+#define Py_TPFLAGS_INT_SUBCLASS		(1UL<<23)
+#define Py_TPFLAGS_LONG_SUBCLASS	(1UL<<24)
+#define Py_TPFLAGS_LIST_SUBCLASS	(1UL<<25)
+#define Py_TPFLAGS_TUPLE_SUBCLASS	(1UL<<26)
+#define Py_TPFLAGS_STRING_SUBCLASS	(1UL<<27)
+#define Py_TPFLAGS_UNICODE_SUBCLASS	(1UL<<28)
+#define Py_TPFLAGS_DICT_SUBCLASS	(1UL<<29)
+#define Py_TPFLAGS_BASE_EXC_SUBCLASS	(1UL<<30)
+#define Py_TPFLAGS_TYPE_SUBCLASS	(1UL<<31)
 
 #define Py_TPFLAGS_DEFAULT  ( \
                              Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
@@ -571,7 +621,7 @@
 
 *** WARNING*** The Py_DECREF macro must have a side-effect-free argument
 since it may evaluate its argument multiple times.  (The alternative
-would be to mace it a proper function or assign it to a global temporary
+would be to make it a proper function or assign it to a global temporary
 variable first, both of which are slower; and in a multi-threaded
 environment the global variable trick is not safe.)
 */
@@ -586,28 +636,48 @@
  * #ifdefs (we used to do that -- it was impenetrable).
  */
 #ifdef Py_REF_DEBUG
-PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
-PyAPI_FUNC(void) _Py_NegativeRefcount(const char *fname,
-					    int lineno, PyObject *op);
+PyAPI_DATA(AO_t) _Py_RefTotal;
+PyAPI_FUNC(void) _Py_NegativeRefcount(const char *fname, int lineno,
+	PyObject *op, Py_ssize_t count);
 PyAPI_FUNC(PyObject *) _PyDict_Dummy(void);
 PyAPI_FUNC(PyObject *) _PySet_Dummy(void);
 PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
-#define _Py_INC_REFTOTAL	_Py_RefTotal++
-#define _Py_DEC_REFTOTAL	_Py_RefTotal--
-#define _Py_REF_DEBUG_COMMA	,
-#define _Py_CHECK_REFCNT(OP)					\
+//#define _Py_INC_REFTOTAL	_Py_RefTotal++
+static inline void
+_Py_INC_REFTOTAL(void)
+{
+#ifdef Py_REF_DEBUG
+	AO_fetch_and_add1_full(&_Py_RefTotal);
+#endif
+}
+//#define _Py_DEC_REFTOTAL	_Py_RefTotal--
+static inline void
+_Py_DEC_REFTOTAL(void)
+{
+#ifdef Py_REF_DEBUG
+	AO_fetch_and_sub1_full(&_Py_RefTotal);
+#endif
+}
+//#define _Py_REF_DEBUG_COMMA	,
+/*#define _Py_CHECK_REFCNT(OP)					\
 {	if (((PyObject*)OP)->ob_refcnt < 0)				\
 		_Py_NegativeRefcount(__FILE__, __LINE__,	\
 				     (PyObject *)(OP));		\
 }
+*/
 #else
-#define _Py_INC_REFTOTAL
-#define _Py_DEC_REFTOTAL
-#define _Py_REF_DEBUG_COMMA
-#define _Py_CHECK_REFCNT(OP)	/* a semicolon */;
+//#define _Py_INC_REFTOTAL
+#define _Py_INC_REFTOTAL()
+//#define _Py_DEC_REFTOTAL
+#define _Py_DEC_REFTOTAL()
+//#define _Py_REF_DEBUG_COMMA
+//#define _Py_CHECK_REFCNT(OP)	/* a semicolon */;
 #endif /* Py_REF_DEBUG */
 
 #ifdef COUNT_ALLOCS
+#ifdef WITH_FREETHREAD
+#error FIXME
+#endif
 PyAPI_FUNC(void) inc_count(PyTypeObject *);
 PyAPI_FUNC(void) dec_count(PyTypeObject *);
 #define _Py_INC_TPALLOCS(OP)	inc_count(Py_Type(OP))
@@ -623,9 +693,6 @@
 
 #ifdef Py_TRACE_REFS
 /* Py_TRACE_REFS is such major surgery that we call external routines. */
-PyAPI_FUNC(void) _Py_NewReference(PyObject *);
-PyAPI_FUNC(void) _Py_ForgetReference(PyObject *);
-PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
 PyAPI_FUNC(void) _Py_PrintReferences(FILE *);
 PyAPI_FUNC(void) _Py_PrintReferenceAddresses(FILE *);
 PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
@@ -634,28 +701,47 @@
 /* Without Py_TRACE_REFS, there's little enough to do that we expand code
  * inline.
  */
-#define _Py_NewReference(op) (				\
-	_Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA	\
-	_Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA		\
-	Py_Refcnt(op) = 1)
+#endif /* !Py_TRACE_REFS */
 
-#define _Py_ForgetReference(op) _Py_INC_TPFREES(op)
+//PyAPI_FUNC(void) _Py_NewReference(PyObject *);
+//PyAPI_FUNC(void) _Py_ForgetReference(PyObject *);
+PyAPI_FUNC(Py_ssize_t) _Py_RefcntSnoop(PyObject *);
 
-#define _Py_Dealloc(op) (				\
-	_Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA	\
-	(*Py_Type(op)->tp_dealloc)((PyObject *)(op)))
-#endif /* !Py_TRACE_REFS */
+#ifdef WITH_FREETHREAD
+PyAPI_FUNC(void) _Py_INCREF(PyObject *, PyThreadState *);
+PyAPI_FUNC(void) _Py_DECREF(PyObject *, PyThreadState *);
+PyAPI_FUNC(void) _Py_DECREF_ASYNC(PyObject *, PyThreadState *);
+#define Py_INCREF(op) _Py_INCREF((PyObject *)(op), PyThreadState_Get())
+#define Py_DECREF(op) _Py_DECREF((PyObject *)(op), PyThreadState_Get())
+#define Py_DECREF_ASYNC(op) _Py_DECREF_ASYNC((PyObject *)(op), PyThreadState_Get())
 
-#define Py_INCREF(op) (				\
-	_Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA	\
-	((PyObject*)(op))->ob_refcnt++)
+#define Py_INCREFTS(op) _Py_INCREF((PyObject *)(op), tstate)
+#define Py_DECREFTS(op) _Py_DECREF((PyObject *)(op), tstate)
+#else
+static inline void
+_Py_INCREF(PyObject *op)
+{
+        _Py_INC_REFTOTAL();
+        op->ob_refcnt++;
+}
 
-#define Py_DECREF(op)					\
-	if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA	\
-	    --((PyObject*)(op))->ob_refcnt != 0)		\
-		_Py_CHECK_REFCNT(op)			\
-	else						\
-		_Py_Dealloc((PyObject *)(op))
+static inline void
+_Py_DECREF(PyObject *op)
+{
+        _Py_DEC_REFTOTAL();
+        op->ob_refcnt--;
+        if (op->ob_refcnt == 0)
+                _Py_Dealloc(op);
+#ifdef Py_REF_DEBUG
+        else if (((Py_ssize_t)op->ob_refcnt) < 0)
+                _Py_NegativeRefcount(__FILE__, __LINE__, op, op->ob_refcnt);
+#endif
+}
+#define Py_INCREF(op) _Py_INCREF((PyObject *)(op))
+#define Py_DECREF(op) _Py_DECREF((PyObject *)(op))
+#define Py_INCREFTS Py_INCREF
+#define Py_DECREFTS Py_DECREF
+#endif /* WITH_FREETHREAD */
 
 /* Safely decref `op` and set `op` to NULL, especially useful in tp_clear
  * and tp_dealloc implementatons.
@@ -700,10 +786,22 @@
                 }				\
         } while (0)
 
+#define Py_CLEARTS(op)				\
+        do {                            	\
+                if (op) {			\
+                        PyObject *tmp = (PyObject *)(op);	\
+                        (op) = NULL;		\
+                        Py_DECREFTS(tmp);		\
+                }				\
+        } while (0)
+
 /* Macros to use in case the object pointer may be NULL: */
 #define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)
 #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)
 
+#define Py_XINCREFTS(op) if ((op) == NULL) ; else Py_INCREFTS(op)
+#define Py_XDECREFTS(op) if ((op) == NULL) ; else Py_DECREFTS(op)
+
 /*
 These are provided as conveniences to Python runtime embedders, so that
 they can have object code that is not dependent on Python compilation flags.
@@ -796,67 +894,6 @@
 times.
 */
 
-
-/* Trashcan mechanism, thanks to Christian Tismer.
-
-When deallocating a container object, it's possible to trigger an unbounded
-chain of deallocations, as each Py_DECREF in turn drops the refcount on "the
-next" object in the chain to 0.  This can easily lead to stack faults, and
-especially in threads (which typically have less stack space to work with).
-
-A container object that participates in cyclic gc can avoid this by
-bracketing the body of its tp_dealloc function with a pair of macros:
-
-static void
-mytype_dealloc(mytype *p)
-{
-        ... declarations go here ...
-
- 	PyObject_GC_UnTrack(p);	   // must untrack first
-	Py_TRASHCAN_SAFE_BEGIN(p)
-	... The body of the deallocator goes here, including all calls ...
-	... to Py_DECREF on contained objects.                         ...
-	Py_TRASHCAN_SAFE_END(p)
-}
-
-CAUTION:  Never return from the middle of the body!  If the body needs to
-"get out early", put a label immediately before the Py_TRASHCAN_SAFE_END
-call, and goto it.  Else the call-depth counter (see below) will stay
-above 0 forever, and the trashcan will never get emptied.
-
-How it works:  The BEGIN macro increments a call-depth counter.  So long
-as this counter is small, the body of the deallocator is run directly without
-further ado.  But if the counter gets large, it instead adds p to a list of
-objects to be deallocated later, skips the body of the deallocator, and
-resumes execution after the END macro.  The tp_dealloc routine then returns
-without deallocating anything (and so unbounded call-stack depth is avoided).
-
-When the call stack finishes unwinding again, code generated by the END macro
-notices this, and calls another routine to deallocate all the objects that
-may have been added to the list of deferred deallocations.  In effect, a
-chain of N deallocations is broken into N / PyTrash_UNWIND_LEVEL pieces,
-with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL.
-*/
-
-PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*);
-PyAPI_FUNC(void) _PyTrash_destroy_chain(void);
-PyAPI_DATA(int) _PyTrash_delete_nesting;
-PyAPI_DATA(PyObject *) _PyTrash_delete_later;
-
-#define PyTrash_UNWIND_LEVEL 50
-
-#define Py_TRASHCAN_SAFE_BEGIN(op) \
-	if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL) { \
-		++_PyTrash_delete_nesting;
-		/* The body of the deallocator is here. */
-#define Py_TRASHCAN_SAFE_END(op) \
-		--_PyTrash_delete_nesting; \
-		if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \
-			_PyTrash_destroy_chain(); \
-	} \
-	else \
-		_PyTrash_deposit_object((PyObject*)op);
-
 #ifdef __cplusplus
 }
 #endif
Index: Include/methodobject.h
===================================================================
--- Include/methodobject.h	(revision 58355)
+++ Include/methodobject.h	(working copy)
@@ -70,6 +70,9 @@
 
 #define METH_COEXIST   0x0040
 
+/* METH_SHARED allows a method to be shared between threads */
+#define METH_SHARED   0x0080
+
 typedef struct PyMethodChain {
     PyMethodDef *methods;		/* Methods of this type */
     struct PyMethodChain *link;	/* NULL or base type */
Index: Include/import.h
===================================================================
--- Include/import.h	(revision 58355)
+++ Include/import.h	(working copy)
@@ -13,6 +13,7 @@
 	char *name, PyObject *co, char *pathname);
 PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void);
 PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name);
+PyAPI_FUNC(PyObject *) PyImport_AddModuleEx(const char *name, int shared);
 PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name);
 PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name,
 	PyObject *globals, PyObject *locals, PyObject *fromlist, int level);
Index: Include/weakrefobject.h
===================================================================
--- Include/weakrefobject.h	(revision 58355)
+++ Include/weakrefobject.h	(working copy)
@@ -7,68 +7,215 @@
 #endif
 
 
+/* Needed for offsetof */
+#include "structmember.h"
+
+#include "pythread.h"
+
+
+/* XXX This should get moved into its own file */
+/* The way PyLinkedList is used is that all objects within a given
+ * linked list have the same layout, allowing you to use
+ * PyLinkedList_Restore to get back the original object.
+ *
+ * The sentinel needs special handling, either by checking for it before
+ * calling PyLinkedList_Restore, or by making it a valid object and
+ * checking after. */
+typedef struct _PyLinkedList PyLinkedList;
+struct _PyLinkedList {
+    PyLinkedList *prev;
+    PyLinkedList *next;
+};
+
+#define PyLinkedList_Restore(type, field, op) \
+    (type *)(((char *)(op)) - offsetof(type, field))
+
+#define PyLinkedList_Append(sentinel, op) PyLinkedList_InsertBefore(sentinel, op)
+static inline void
+PyLinkedList_InsertBefore(PyLinkedList *a, PyLinkedList *b)
+{
+    assert(a->prev != NULL && a->next != NULL);
+    assert(b->prev == NULL && b->next == NULL);
+
+    b->prev = a->prev;
+    a->prev->next = b;
+
+    b->next = a;
+    a->prev = b;
+}
+
+static inline void
+PyLinkedList_Remove(PyLinkedList *op)
+{
+    assert(op->prev != NULL && op->next != NULL);
+    assert(op->prev != op && op->next != op);
+
+    op->prev->next = op->next;
+    op->next->prev = op->prev;
+
+    op->prev = NULL;
+    op->next = NULL;
+}
+
+/*
+ * Iterate over a LinkedList.  Use like so:
+ *
+ *     PyLinkedList *handle_links = &queue->live_links;
+ *
+ *     while (PyLinkedList_Next(&queue->live_links, &handle_links)) {
+ *         handle = PyLinkedList_Restore(PyDeathQueueHandle, queue_links,
+ *             handle_links);
+ *         Py_VISIT(handle);
+ *     }
+ *
+ * CAUTION:  It isn't safe to modify the LinkedList while iterating.
+ */
+static inline int
+PyLinkedList_Next(PyLinkedList *sentinel, PyLinkedList **op)
+{
+    if ((*op)->next == sentinel)
+        return 0;
+    else {
+        *op = (*op)->next;
+        return 1;
+    }
+}
+
+static inline int
+PyLinkedList_Empty(PyLinkedList *sentinel)
+{
+    assert(sentinel->prev != NULL && sentinel->next != NULL);
+
+    if (sentinel->next == sentinel) {
+        assert(sentinel->prev == sentinel);
+        return 1;
+    } else {
+        assert(sentinel->prev != sentinel);
+        return 0;
+    }
+}
+
+static inline int
+PyLinkedList_Detatched(PyLinkedList *op)
+{
+    assert(op->prev != op && op->next != op);
+
+    if (op->next == NULL) {
+        assert(op->prev == NULL);
+        return 1;
+    } else {
+        assert(op->prev != NULL);
+        return 0;
+    }
+}
+
+
 typedef struct _PyWeakReference PyWeakReference;
+typedef struct _PyDeathQueueHandle PyDeathQueueHandle;
+typedef struct _PyDeathQueue PyDeathQueue;
+typedef struct _PyWeakBinding PyWeakBinding;
 
-/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType,
- * and CallableProxyType.
- */
 struct _PyWeakReference {
     PyObject_HEAD
 
+    /* Critical section protecting access to wr_object and our (not yet
+     * implemented) death notice list.  hash is NOT protected */
+    PyCritical *crit;
+
     /* The object to which this is a weak reference, or Py_None if none.
      * Note that this is a stealth reference:  wr_object's refcount is
      * not incremented to reflect this pointer.
      */
+    /* XXX it gets set to NULL now, not Py_None */
     PyObject *wr_object;
 
-    /* A callable to invoke when wr_object dies, or NULL if none. */
-    PyObject *wr_callback;
-
     /* A cache for wr_object's hash code.  As usual for hashes, this is -1
      * if the hash code isn't known yet.
      */
-    long hash;
+    /* XXX I'd much rather remove this, but to detect existing usage
+     * I'd have to make it an error. */
+    AO_t hash;
 
     /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL-
      * terminated list of weak references to it.  These are the list pointers.
      * If wr_object goes away, wr_object is set to Py_None, and these pointers
      * have no meaning then.
      */
-    PyWeakReference *wr_prev;
-    PyWeakReference *wr_next;
+    //PyWeakReference *wr_prev;
+    //PyWeakReference *wr_next;
+    PyLinkedList handle_links;
+
+    PyLinkedList binding_links;
 };
 
-PyAPI_DATA(PyTypeObject) _PyWeakref_RefType;
-PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType;
-PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType;
+PyAPI_DATA(PyTypeObject) _PyWeakref_Type;
 
-#define PyWeakref_CheckRef(op) PyObject_TypeCheck(op, &_PyWeakref_RefType)
-#define PyWeakref_CheckRefExact(op) \
-        (Py_Type(op) == &_PyWeakref_RefType)
-#define PyWeakref_CheckProxy(op) \
-        ((Py_Type(op) == &_PyWeakref_ProxyType) || \
-         (Py_Type(op) == &_PyWeakref_CallableProxyType))
+#define PyWeakref_Check(op) (Py_Type(op) == &_PyWeakref_Type)
+#define PyWeakref_CheckRefExact PyWeakref_Check
+#define PyWeakref_CheckRef PyWeakref_Check
 
-/* This macro calls PyWeakref_CheckRef() last since that can involve a
-   function call; this makes it more likely that the function call
-   will be avoided. */
-#define PyWeakref_Check(op) \
-        (PyWeakref_CheckRef(op) || PyWeakref_CheckProxy(op))
 
+PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob, PyObject *callback);
+/* Note that this DOES incref the returned object, if not NULL! */
+PyAPI_FUNC(PyObject *) PyWeakref_GetObjectEx(PyObject *ref);
+PyAPI_FUNC(PyObject *) PyWeakref_NewBinding(PyObject *ob, PyObject *value);
+PyAPI_FUNC(PyObject *) PyWeakref_GetBindingObject(PyObject *bind, PyObject **value);
 
-PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob,
-                                              PyObject *callback);
-PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob,
-                                                PyObject *callback);
-PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref);
+PyAPI_FUNC(void) _PyWeakref_ClearBindings(PyObject *ob, PyWeakReference *ref);
 
-PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head);
+#define _PY_GETWEAKREFPTR(o) \
+        ((PyWeakReference **) (((char *) (o)) + Py_Type(o)->tp_weaklistoffset))
 
-PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
 
-#define PyWeakref_GET_OBJECT(ref) (((PyWeakReference *)(ref))->wr_object)
+struct _PyDeathQueueHandle {
+    PyObject_HEAD
 
+    PyCritical *crit;
 
+    PyObject *payload;
+
+    PyWeakReference *weakref;
+    PyLinkedList weakref_links;
+
+    PyDeathQueue *queue;
+    PyLinkedList queue_links;
+};
+
+PyAPI_DATA(PyTypeObject) _PyDeathQueueHandle_Type;
+
+#define PyDeathQueueHandle_Check(op) \
+    (Py_Type(op) == &_PyDeathQueueHandle_Type)
+
+
+struct _PyDeathQueue {
+    PyObject_HEAD
+
+    PyCritical *crit;
+    PyThread_type_cond cond;
+
+    PyLinkedList live_links;
+    PyLinkedList dead_links;
+};
+
+PyAPI_DATA(PyTypeObject) _PyDeathQueue_Type;
+
+#define PyDeathQueue_Check(op) (Py_Type(op) == &_PyDeathQueue_Type)
+
+
+struct _PyWeakBinding {
+    PyObject_HEAD
+
+    PyWeakReference *weakref;
+    PyObject *value; /* This is actually owned by weakref->wr_object */
+
+    PyLinkedList weakref_links;
+};
+
+PyAPI_DATA(PyTypeObject) _PyWeakBinding_Type;
+
+#define PyWeakBinding_Check(op) (Py_Type(op) == &_PyWeakBinding_Type)
+
+
 #ifdef __cplusplus
 }
 #endif
Index: Include/tupleobject.h
===================================================================
--- Include/tupleobject.h	(revision 58355)
+++ Include/tupleobject.h	(working copy)
@@ -23,6 +23,7 @@
 
 typedef struct {
     PyObject_VAR_HEAD
+    AO_t shareable;
     PyObject *ob_item[1];
 
     /* ob_item contains space for 'ob_size' elements.
Index: Include/pythread.h
===================================================================
--- Include/pythread.h	(revision 58355)
+++ Include/pythread.h	(working copy)
@@ -2,43 +2,60 @@
 #ifndef Py_PYTHREAD_H
 #define Py_PYTHREAD_H
 
-#define NO_EXIT_PROG		/* don't define PyThread_exit_prog() */
-				/* (the result is no use of signals on SGI) */
-
 typedef void *PyThread_type_lock;
-typedef void *PyThread_type_sema;
+typedef void *PyThread_type_sem;
+typedef void *PyThread_type_cond;
+typedef void *PyThread_type_key;
+typedef struct {
+    /* Notes:
+     *   * We wrap pthread_t in a struct to ensure it's not misused.
+     *   * This is intended to be an opaque struct.
+     *   * No way to compare them is currently provided.  Compare PyThreadStates instead.
+     *   * No "not set" value is provided.  Put a flag beside it if you need one.
+     *   * Currently, the only use is for PyThread_send_signal.
+     */
 
+    /* XXX FIXME this needs to conditionalize the definition to whatever
+     * thread library is in use */
+    pthread_t _value;
+} PyThread_type_handle;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 PyAPI_FUNC(void) PyThread_init_thread(void);
-PyAPI_FUNC(long) PyThread_start_new_thread(void (*)(void *), void *);
-PyAPI_FUNC(void) PyThread_exit_thread(void);
-PyAPI_FUNC(void) PyThread__PyThread_exit_thread(void);
-PyAPI_FUNC(long) PyThread_get_thread_ident(void);
+PyAPI_FUNC(int) PyThread_start_new_thread(PyThread_type_handle *, void (*)(void *), void *);
 
-PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void);
-PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock);
-PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
-#define WAIT_LOCK	1
-#define NOWAIT_LOCK	0
-PyAPI_FUNC(void) PyThread_release_lock(PyThread_type_lock);
+PyAPI_FUNC(PyThread_type_handle) PyThread_get_handle(void);
+PyAPI_FUNC(void) PyThread_send_signal(PyThread_type_handle, int signum);
 
 PyAPI_FUNC(size_t) PyThread_get_stacksize(void);
 PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
 
-#ifndef NO_EXIT_PROG
-PyAPI_FUNC(void) PyThread_exit_prog(int);
-PyAPI_FUNC(void) PyThread__PyThread_exit_prog(int);
-#endif
+PyAPI_FUNC(PyThread_type_lock) PyThread_lock_allocate(void);
+PyAPI_FUNC(void) PyThread_lock_free(PyThread_type_lock);
+PyAPI_FUNC(void) PyThread_lock_acquire(PyThread_type_lock);
+PyAPI_FUNC(int) _PyThread_lock_tryacquire(PyThread_type_lock);
+PyAPI_FUNC(void) PyThread_lock_release(PyThread_type_lock);
 
+PyAPI_FUNC(PyThread_type_sem) PyThread_sem_allocate(int);
+PyAPI_FUNC(void) PyThread_sem_free(PyThread_type_sem);
+PyAPI_FUNC(void) PyThread_sem_wait(PyThread_type_sem);
+PyAPI_FUNC(void) PyThread_sem_post(PyThread_type_sem);
+
+PyAPI_FUNC(PyThread_type_cond) PyThread_cond_allocate(void);
+PyAPI_FUNC(void) PyThread_cond_free(PyThread_type_cond);
+PyAPI_FUNC(void) PyThread_cond_wait(PyThread_type_cond, PyThread_type_lock);
+PyAPI_FUNC(void) PyThread_cond_wakeone(PyThread_type_cond);
+PyAPI_FUNC(void) PyThread_cond_wakeall(PyThread_type_cond);
+
 /* Thread Local Storage (TLS) API */
-PyAPI_FUNC(int) PyThread_create_key(void);
-PyAPI_FUNC(void) PyThread_delete_key(int);
-PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
-PyAPI_FUNC(void *) PyThread_get_key_value(int);
-PyAPI_FUNC(void) PyThread_delete_key_value(int key);
+PyAPI_FUNC(PyThread_type_key) PyThread_create_key(void);
+PyAPI_FUNC(void) PyThread_delete_key(PyThread_type_key);
+PyAPI_FUNC(void) PyThread_set_key_value(PyThread_type_key, void *);
+PyAPI_FUNC(void *) PyThread_get_key_value(PyThread_type_key);
+PyAPI_FUNC(void) PyThread_delete_key_value(PyThread_type_key);
 
 #ifdef __cplusplus
 }
Index: Include/pyfpe.h
===================================================================
--- Include/pyfpe.h	(revision 58355)
+++ Include/pyfpe.h	(working copy)
@@ -126,6 +126,7 @@
  */
 
 #ifdef WANT_SIGFPE_HANDLER
+#error FPE currently broken.  Needs to be made thread-safe
 #include <signal.h>
 #include <setjmp.h>
 #include <math.h>
Index: Include/pysignal.h
===================================================================
--- Include/pysignal.h	(revision 0)
+++ Include/pysignal.h	(revision 0)
@@ -0,0 +1,16 @@
+#ifndef Py_PYSIGNAL_H
+#define Py_PYSIGNAL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*PyOS_sighandler_t)(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
+
+PyAPI_FUNC(void) PyOS_AfterFork(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_PYSIGNAL_H */
Index: Include/descrobject.h
===================================================================
--- Include/descrobject.h	(revision 58355)
+++ Include/descrobject.h	(working copy)
@@ -67,6 +67,10 @@
 	void *d_wrapped; /* This can be any function pointer */
 } PyWrapperDescrObject;
 
+typedef struct {
+    PyDescr_COMMON;
+} PyFinalizeAttrDescrObject;
+
 PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type;
 
 PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
@@ -77,6 +81,7 @@
 					       struct PyGetSetDef *);
 PyAPI_FUNC(PyObject *) PyDescr_NewWrapper(PyTypeObject *,
 						struct wrapperbase *, void *);
+PyAPI_FUNC(PyObject *) PyDescr_NewFinalizeAttr(PyTypeObject *, PyObject *);
 #define PyDescr_IsData(d) (Py_Type(d)->tp_descr_set != NULL)
 
 PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *);
Index: Include/compile.h
===================================================================
--- Include/compile.h	(revision 58355)
+++ Include/compile.h	(working copy)
@@ -24,6 +24,7 @@
 #define FUTURE_DIVISION "division"
 #define FUTURE_ABSOLUTE_IMPORT "absolute_import"
 #define FUTURE_WITH_STATEMENT "with_statement"
+#define FUTURE_SHARED_MODULE "shared_module"
 
 struct _mod; /* Declare the existence of this type */
 PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
Index: Include/intrcheck.h
===================================================================
--- Include/intrcheck.h	(revision 58355)
+++ Include/intrcheck.h	(working copy)
@@ -1,15 +0,0 @@
-
-#ifndef Py_INTRCHECK_H
-#define Py_INTRCHECK_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-PyAPI_FUNC(int) PyOS_InterruptOccurred(void);
-PyAPI_FUNC(void) PyOS_InitInterrupts(void);
-PyAPI_FUNC(void) PyOS_AfterFork(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_INTRCHECK_H */
Index: Include/modsupport.h
===================================================================
--- Include/modsupport.h	(revision 58355)
+++ Include/modsupport.h	(working copy)
@@ -41,7 +41,10 @@
 PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
 PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *);
 
+PyAPI_FUNC(int) PyArg_RequireShareable(const char *, PyObject *, PyObject *);
+PyAPI_FUNC(int) PyArg_RequireShareableReturn(const char *funcname, PyObject *innerfunc, PyObject *result);
 
+
 #define PYTHON_API_VERSION 1013
 #define PYTHON_API_STRING "1013"
 /* The API version is maintained (independently from the Python version)
@@ -116,6 +119,9 @@
 PyAPI_FUNC(PyObject *) Py_InitModule4(const char *name, PyMethodDef *methods,
                                       const char *doc, PyObject *self,
                                       int apiver);
+PyAPI_FUNC(PyObject *) Py_InitModule5(const char *name, PyMethodDef *methods,
+                                      const char *doc, PyObject *self,
+                                      int apiver, int shared);
 
 #define Py_InitModule(name, methods) \
 	Py_InitModule4(name, methods, (char *)NULL, (PyObject *)NULL, \
Index: Include/pyerrors.h
===================================================================
--- Include/pyerrors.h	(revision 58355)
+++ Include/pyerrors.h	(working copy)
@@ -69,13 +69,14 @@
 #ifdef Py_DEBUG
 #define _PyErr_OCCURRED() PyErr_Occurred()
 #else
-#define _PyErr_OCCURRED() (_PyThreadState_Current->curexc_type)
+#define _PyErr_OCCURRED() (PyThreadState_Get()->curexc_type)
 #endif
 
 /* Error testing and normalization */
 PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
 PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *);
 PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
+PyAPI_FUNC(PyObject *) PyErr_SimplifyException(PyObject *, PyObject *, PyObject *);
 
 /* Traceback manipulation (PEP 3134) */
 PyAPI_FUNC(int) PyException_SetTraceback(PyObject *, PyObject *);
@@ -126,6 +127,8 @@
 PyAPI_DATA(PyObject *) PyExc_KeyError;
 PyAPI_DATA(PyObject *) PyExc_KeyboardInterrupt;
 PyAPI_DATA(PyObject *) PyExc_MemoryError;
+PyAPI_DATA(PyObject *) PyExc_MultipleError;
+PyAPI_DATA(PyObject *) PyExc_Interrupted;
 PyAPI_DATA(PyObject *) PyExc_NameError;
 PyAPI_DATA(PyObject *) PyExc_OverflowError;
 PyAPI_DATA(PyObject *) PyExc_RuntimeError;
@@ -222,10 +225,6 @@
 				   const char *, int,
 				   const char *, PyObject *);
 
-/* In sigcheck.c or signalmodule.c */
-PyAPI_FUNC(int) PyErr_CheckSignals(void);
-PyAPI_FUNC(void) PyErr_SetInterrupt(void);
-
 /* Support for adding program text to SyntaxErrors */
 PyAPI_FUNC(void) PyErr_SyntaxLocation(const char *, int);
 PyAPI_FUNC(PyObject *) PyErr_ProgramText(const char *, int);
Index: configure.in
===================================================================
--- configure.in	(revision 58355)
+++ configure.in	(working copy)
@@ -1721,26 +1721,6 @@
 fi
 AC_MSG_RESULT($with_system_ffi)
 
-# Determine if signalmodule should be used.
-AC_SUBST(USE_SIGNAL_MODULE)
-AC_SUBST(SIGNAL_OBJS)
-AC_MSG_CHECKING(for --with-signal-module)
-AC_ARG_WITH(signal-module,
-            AC_HELP_STRING(--with-signal-module, disable/enable signal module))
-
-if test -z "$with_signal_module"
-then with_signal_module="yes"
-fi
-AC_MSG_RESULT($with_signal_module)
-
-if test "${with_signal_module}" = "yes"; then
-	USE_SIGNAL_MODULE=""
-	SIGNAL_OBJS=""
-else
-	USE_SIGNAL_MODULE="#"
-	SIGNAL_OBJS="Parser/intrcheck.o Python/sigcheck.o"
-fi
-
 # This is used to generate Setup.config
 AC_SUBST(USE_THREAD_MODULE)
 USE_THREAD_MODULE=""
@@ -2200,6 +2180,20 @@
 fi],
 [AC_MSG_RESULT(no)])
 
+# Check for --with-freethread
+AC_MSG_CHECKING(for --with-freethread)
+AC_ARG_WITH(freethread,
+            AC_HELP_STRING(--with-freethread, enable free threading),
+[
+if test "$withval" != no
+then
+  AC_DEFINE(WITH_FREETHREAD, 1,
+  [Define if you want to build an interpreter with free (scalable) threading.])
+  AC_MSG_RESULT(yes);
+else AC_MSG_RESULT(no);
+fi],
+[AC_MSG_RESULT(no)])
+
 # -I${DLINCLDIR} is added to the compile rule for importdl.o
 AC_SUBST(DLINCLDIR)
 DLINCLDIR=.
Index: Objects/complexobject.c
===================================================================
--- Objects/complexobject.c	(revision 58355)
+++ Objects/complexobject.c	(working copy)
@@ -188,9 +188,11 @@
 {
 	PyObject *op;
 
-	op = type->tp_alloc(type, 0);
-	if (op != NULL)
-		((PyComplexObject *)op)->cval = cval;
+	op = PyObject_New(type);
+	if (op == NULL)
+		return NULL;
+	((PyComplexObject *)op)->cval = cval;
+	PyObject_Complete(op);
 	return op;
 }
 
@@ -200,11 +202,17 @@
 	register PyComplexObject *op;
 
 	/* Inline PyObject_New */
-	op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
+	//op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
+	//op = (PyComplexObject *)_PyObject_GC_Malloc(sizeof(PyComplexObject));
+	/* XXX FIXME _PyObject_GC_Malloc already calls PyErr_NoMemory */
+	//if (op == NULL)
+	//	return PyErr_NoMemory();
+	//PyObject_INIT(op, &PyComplex_Type);
+	op = PyObject_NEW(PyComplexObject, &PyComplex_Type);
 	if (op == NULL)
-		return PyErr_NoMemory();
-	PyObject_INIT(op, &PyComplex_Type);
+		return NULL;
 	op->cval = cval;
+	PyObject_COMPLETE(op);
 	return (PyObject *) op;
 }
 
@@ -272,10 +280,11 @@
 			if (!(complex_str = PyUnicode_FromString("__complex__")))
 				return cv;
 		}
-		complexfunc = _PyType_Lookup(op->ob_type, complex_str);
-		/* complexfunc is a borrowed reference */
+		if (_PyType_LookupEx(op->ob_type, complex_str, &complexfunc) < 0)
+			return cv;
 		if (complexfunc) {
 			newop = PyObject_CallFunctionObjArgs(complexfunc, op, NULL);
+			Py_DECREF(complexfunc);
 			if (!newop)
 				return cv;
 		}
@@ -304,7 +313,7 @@
 static void
 complex_dealloc(PyObject *op)
 {
-	op->ob_type->tp_free(op);
+	PyObject_Del(op);
 }
 
 
@@ -1005,7 +1014,8 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+		Py_TPFLAGS_SHAREABLE | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	complex_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
@@ -1022,9 +1032,7 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	complex_new,				/* tp_new */
-	PyObject_Del,           		/* tp_free */
 };
 
 #endif
Index: Objects/codeobject.c
===================================================================
--- Objects/codeobject.c	(revision 58355)
+++ Objects/codeobject.c	(working copy)
@@ -287,7 +287,7 @@
 	Py_XDECREF(co->co_name);
 	Py_XDECREF(co->co_lnotab);
         if (co->co_zombieframe != NULL)
-                PyObject_GC_Del(co->co_zombieframe);
+                PyObject_DEL(co->co_zombieframe);
 	PyObject_DEL(co);
 }
 
@@ -431,7 +431,6 @@
 	0,				/* tp_descr_set */
 	0,				/* tp_dictoffset */
 	0,				/* tp_init */
-	0,				/* tp_alloc */
 	code_new,			/* tp_new */
 };
 
Index: Objects/object.c
===================================================================
--- Objects/object.c	(revision 58355)
+++ Objects/object.c	(working copy)
@@ -3,28 +3,31 @@
 
 #include "Python.h"
 #include "sliceobject.h" /* For PyEllipsis_Type */
+#include "monitorobject.h"
+#include "branchobject.h"
+#include "pythread.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #ifdef Py_REF_DEBUG
-Py_ssize_t _Py_RefTotal;
+AO_t _Py_RefTotal;
 
 Py_ssize_t
 _Py_GetRefTotal(void)
 {
 	PyObject *o;
-	Py_ssize_t total = _Py_RefTotal;
+	Py_ssize_t total = AO_load_full(&_Py_RefTotal);
         /* ignore the references to the dummy object of the dicts and sets
            because they are not reliable and not useful (now that the
            hash table code is well-tested) */
 	o = _PyDict_Dummy();
 	if (o != NULL)
-		total -= o->ob_refcnt;
+		total -= Py_RefcntSnoop(o);
 	o = _PySet_Dummy();
 	if (o != NULL)
-		total -= o->ob_refcnt;
+		total -= Py_RefcntSnoop(o);
 	return total;
 }
 #endif /* Py_REF_DEBUG */
@@ -41,10 +44,11 @@
  * exist only in a Py_TRACE_REFS build.
  */
 static PyObject refchain = {&refchain, &refchain};
+static PyThread_type_lock refchain_lock;
 
 /* Insert op at the front of the list of all objects.  If force is true,
  * op is added even if _ob_prev and _ob_next are non-NULL already.  If
- * force is false amd _ob_prev or _ob_next are non-NULL, do nothing.
+ * force is false and _ob_prev or _ob_next are non-NULL, do nothing.
  * force should be true if and only if op points to freshly allocated,
  * uninitialized memory, or you've unlinked op from the list and are
  * relinking it into the front.
@@ -56,6 +60,7 @@
 void
 _Py_AddToAllObjects(PyObject *op, int force)
 {
+	PyThread_lock_acquire(refchain_lock);
 #ifdef  Py_DEBUG
 	if (!force) {
 		/* If it's initialized memory, op must be in or out of
@@ -70,6 +75,7 @@
 		refchain._ob_next->_ob_prev = op;
 		refchain._ob_next = op;
 	}
+	PyThread_lock_release(refchain_lock);
 }
 #endif	/* Py_TRACE_REFS */
 
@@ -183,75 +189,21 @@
 #ifdef Py_REF_DEBUG
 /* Log a fatal error; doesn't return. */
 void
-_Py_NegativeRefcount(const char *fname, int lineno, PyObject *op)
+_Py_NegativeRefcount(const char *fname, int lineno, PyObject *op,
+	Py_ssize_t count)
 {
 	char buf[300];
 
 	PyOS_snprintf(buf, sizeof(buf),
 		      "%s:%i object at %p has negative ref count "
 		      "%" PY_FORMAT_SIZE_T "d",
-		      fname, lineno, op, op->ob_refcnt);
+		      fname, lineno, op, count);
 	Py_FatalError(buf);
 }
 
 #endif /* Py_REF_DEBUG */
 
-void
-Py_IncRef(PyObject *o)
-{
-    Py_XINCREF(o);
-}
 
-void
-Py_DecRef(PyObject *o)
-{
-    Py_XDECREF(o);
-}
-
-PyObject *
-PyObject_Init(PyObject *op, PyTypeObject *tp)
-{
-	if (op == NULL)
-		return PyErr_NoMemory();
-	/* Any changes should be reflected in PyObject_INIT (objimpl.h) */
-	Py_Type(op) = tp;
-	_Py_NewReference(op);
-	return op;
-}
-
-PyVarObject *
-PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
-{
-	if (op == NULL)
-		return (PyVarObject *) PyErr_NoMemory();
-	/* Any changes should be reflected in PyObject_INIT_VAR */
-	op->ob_size = size;
-	Py_Type(op) = tp;
-	_Py_NewReference((PyObject *)op);
-	return op;
-}
-
-PyObject *
-_PyObject_New(PyTypeObject *tp)
-{
-	PyObject *op;
-	op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
-	if (op == NULL)
-		return PyErr_NoMemory();
-	return PyObject_INIT(op, tp);
-}
-
-PyVarObject *
-_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
-{
-	PyVarObject *op;
-	const size_t size = _PyObject_VAR_SIZE(tp, nitems);
-	op = (PyVarObject *) PyObject_MALLOC(size);
-	if (op == NULL)
-		return (PyVarObject *)PyErr_NoMemory();
-	return PyObject_INIT_VAR(op, tp, nitems);
-}
-
 /* Implementation of PyObject_Print with recursion checking */
 static int
 internal_print(PyObject *op, FILE *fp, int flags, int nesting)
@@ -261,8 +213,6 @@
 		PyErr_SetString(PyExc_RuntimeError, "print recursion");
 		return -1;
 	}
-	if (PyErr_CheckSignals())
-		return -1;
 #ifdef USE_STACKCHECK
 	if (PyOS_CheckStack()) {
 		PyErr_SetString(PyExc_MemoryError, "stack overflow");
@@ -276,14 +226,14 @@
 		Py_END_ALLOW_THREADS
 	}
 	else {
-		if (op->ob_refcnt <= 0)
+		if (Py_RefcntSnoop(op) <= 0) {
 			/* XXX(twouters) cast refcount to long until %zd is
 			   universally available */
 			Py_BEGIN_ALLOW_THREADS
 			fprintf(fp, "<refcnt %ld at %p>",
-				(long)op->ob_refcnt, op);
+				(long)Py_RefcntSnoop(op), op);
 			Py_END_ALLOW_THREADS
-		else {
+		} else {
 			PyObject *s;
 			if (flags & Py_PRINT_RAW)
 				s = PyObject_Str(op);
@@ -345,7 +295,7 @@
 		fprintf(stderr, "NULL\n");
 	else {
 		fprintf(stderr, "object  : ");
-		(void)PyObject_Print(op, stderr, 0);
+		//(void)PyObject_Print(op, stderr, 0);
 		/* XXX(twouters) cast refcount to long until %zd is
 		   universally available */
 		fprintf(stderr, "\n"
@@ -353,7 +303,7 @@
 			"refcount: %ld\n"
 			"address : %p\n",
 			Py_Type(op)==NULL ? "NULL" : Py_Type(op)->tp_name,
-			(long)op->ob_refcnt,
+			(long)Py_RefcntSnoop(op),
 			op);
 	}
 }
@@ -362,8 +312,6 @@
 PyObject_Repr(PyObject *v)
 {
 	PyObject *res;
-	if (PyErr_CheckSignals())
-		return NULL;
 #ifdef USE_STACKCHECK
 	if (PyOS_CheckStack()) {
 		PyErr_SetString(PyExc_MemoryError, "stack overflow");
@@ -958,7 +906,7 @@
 		return err;
 	}
 	Py_DECREF(name);
-	assert(name->ob_refcnt >= 1);
+	assert(Py_RefcntSnoop(name) >= 1);
 	if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
 		PyErr_Format(PyExc_TypeError,
 			     "'%.100s' object has no attributes "
@@ -981,6 +929,17 @@
 PyObject **
 _PyObject_GetDictPtr(PyObject *obj)
 {
+	if (PyMonitor_Check(obj) &&
+			!PyMonitorSpace_IsCurrent(PyMonitor_GetMonitorSpace(obj))) {
+		return NULL;
+	}
+
+	return _PyObject_GetDictPtr_NoCheck(obj);
+}
+
+PyObject **
+_PyObject_GetDictPtr_NoCheck(PyObject *obj)
+{
 	Py_ssize_t dictoffset;
 	PyTypeObject *tp = Py_Type(obj);
 
@@ -1015,6 +974,7 @@
 PyObject *
 PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
 {
+	PyThreadState *tstate = PyThreadState_Get();
 	PyTypeObject *tp = Py_Type(obj);
 	PyObject *descr = NULL;
 	PyObject *res = NULL;
@@ -1029,14 +989,14 @@
 		return NULL;
 	}
 	else
-		Py_INCREF(name);
+		Py_INCREFTS(name);
 
 	if (tp->tp_dict == NULL) {
 		if (PyType_Ready(tp) < 0)
 			goto done;
 	}
 
-	/* Inline _PyType_Lookup */
+	/* Inline _PyType_LookupEx */
 	{
 		Py_ssize_t i, n;
 		PyObject *mro, *base, *dict;
@@ -1051,27 +1011,27 @@
 			assert(PyType_Check(base));
 			dict = ((PyTypeObject *)base)->tp_dict;
 			assert(dict && PyDict_Check(dict));
-			descr = PyDict_GetItem(dict, name);
+			if (PyDict_GetItemEx(dict, name, &descr) < 0)
+				goto done;
 			if (descr != NULL)
 				break;
 		}
 	}
 
-	Py_XINCREF(descr);
-
 	f = NULL;
 	if (descr != NULL) {
 		f = descr->ob_type->tp_descr_get;
 		if (f != NULL && PyDescr_IsData(descr)) {
 			res = f(descr, obj, (PyObject *)obj->ob_type);
-			Py_DECREF(descr);
+			Py_DECREFTS(descr);
 			goto done;
 		}
 	}
 
 	/* Inline _PyObject_GetDictPtr */
 	dictoffset = tp->tp_dictoffset;
-	if (dictoffset != 0) {
+	if (dictoffset != 0 && !(PyMonitor_Check(obj) &&
+			!PyMonitorSpace_IsCurrent(PyMonitor_GetMonitorSpace(obj)))) {
 		PyObject *dict;
 		if (dictoffset < 0) {
 			Py_ssize_t tsize;
@@ -1089,10 +1049,8 @@
 		dictptr = (PyObject **) ((char *)obj + dictoffset);
 		dict = *dictptr;
 		if (dict != NULL) {
-			res = PyDict_GetItem(dict, name);
-			if (res != NULL) {
-				Py_INCREF(res);
-				Py_XDECREF(descr);
+			if (PyDict_GetItemEx(dict, name, &res) <= 0) {
+				Py_XDECREFTS(descr);
 				goto done;
 			}
 		}
@@ -1100,7 +1058,7 @@
 
 	if (f != NULL) {
 		res = f(descr, obj, (PyObject *)Py_Type(obj));
-		Py_DECREF(descr);
+		Py_DECREFTS(descr);
 		goto done;
 	}
 
@@ -1114,7 +1072,7 @@
 		     "'%.50s' object has no attribute '%.400s'",
 		     tp->tp_name, PyUnicode_AsString(name));
   done:
-	Py_DECREF(name);
+	Py_DECREFTS(name);
 	return res;
 }
 
@@ -1122,7 +1080,7 @@
 PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
 {
 	PyTypeObject *tp = Py_Type(obj);
-	PyObject *descr;
+	PyObject *descr = NULL;
 	descrsetfunc f;
 	PyObject **dictptr;
 	int res = -1;
@@ -1141,7 +1099,8 @@
 			goto done;
 	}
 
-	descr = _PyType_Lookup(tp, name);
+	if (_PyType_LookupEx(tp, name, &descr) < 0)
+		goto done;
 	f = NULL;
 	if (descr != NULL) {
 		f = descr->ob_type->tp_descr_set;
@@ -1188,6 +1147,7 @@
 		     tp->tp_name, name);
   done:
 	Py_DECREF(name);
+	Py_XDECREF(descr);
 	return res;
 }
 
@@ -1242,6 +1202,16 @@
 	return x->ob_type->tp_call != NULL;
 }
 
+/* Test whether an object is shareable */
+
+int
+PyObject_IsShareable(PyObject *x)
+{
+	if (x->ob_type->tp_isshareable != NULL)
+		return x->ob_type->tp_isshareable(x);
+	return 0;
+}
+
 /* ------------------------- PyObject_Dir() helpers ------------------------- */
 
 /* Helper for PyObject_Dir.
@@ -1509,7 +1479,13 @@
 	Py_FatalError("deallocating None");
 }
 
+static int
+none_isshareable(PyObject *ignore)
+{
+	return 1;
+}
 
+
 static PyTypeObject PyNone_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"NoneType",
@@ -1524,13 +1500,46 @@
 	0,		/*tp_as_number*/
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
-	0,		/*tp_hash */
+	0,		/*tp_hash*/
+	0,		/*tp_call*/
+	0,		/*tp_str*/
+	0,		/*tp_getattro*/
+	0,		/*tp_setattro*/
+	0,		/*tp_as_buffer*/
+	Py_TPFLAGS_SHAREABLE,	/*tp_flags*/
+	0,		/* tp_doc */
+	0,		/* tp_traverse */
+	0,		/* tp_clear */
+	0,		/* tp_richcompare */
+	0,		/* tp_weaklistoffset */
+	0,		/* tp_iter */
+	0,		/* tp_iternext */
+	0,		/* tp_methods */
+	0,		/* tp_members */
+	0,		/* tp_getset */
+	0,		/* tp_base */
+	0,		/* tp_dict */
+	0,		/* tp_descr_get */
+	0,		/* tp_descr_set */
+	0,		/* tp_dictoffset */
+	0,		/* tp_init */
+	0,		/* tp_new */
+	0,		/* tp_is_gc */
+	0,		/* tp_bases */
+	0,		/* tp_mro */
+	0,		/* tp_cache */
+	0,		/* tp_subclasses */
+	0,		/* tp_weaklist */
+	none_isshareable,	/* tp_isshareable */
 };
 
+/*
 PyObject _Py_NoneStruct = {
   _PyObject_EXTRA_INIT
   1, &PyNone_Type
 };
+*/
+PyObject _Py_NoneStruct = PyObject_HEAD_INIT_NOCOMMA(&PyNone_Type);
 
 /* NotImplemented is an object that can be used to signal that an
    operation is not implemented for the given type combination. */
@@ -1556,22 +1565,64 @@
 	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_SHAREABLE,	/*tp_flags*/
+	0,		/* tp_doc */
+	0,		/* tp_traverse */
+	0,		/* tp_clear */
+	0,		/* tp_richcompare */
+	0,		/* tp_weaklistoffset */
+	0,		/* tp_iter */
+	0,		/* tp_iternext */
+	0,		/* tp_methods */
+	0,		/* tp_members */
+	0,		/* tp_getset */
+	0,		/* tp_base */
+	0,		/* tp_dict */
+	0,		/* tp_descr_get */
+	0,		/* tp_descr_set */
+	0,		/* tp_dictoffset */
+	0,		/* tp_init */
+	0,		/* tp_new */
+	0,		/* tp_is_gc */
+	0,		/* tp_bases */
+	0,		/* tp_mro */
+	0,		/* tp_cache */
+	0,		/* tp_subclasses */
+	0,		/* tp_weaklist */
+	none_isshareable,	/* tp_isshareable */
 };
 
+/*
 PyObject _Py_NotImplementedStruct = {
 	_PyObject_EXTRA_INIT
 	1, &PyNotImplemented_Type
 };
+*/
+PyObject _Py_NotImplementedStruct = PyObject_HEAD_INIT_NOCOMMA(&PyNotImplemented_Type);
 
+extern PyTypeObject PyRange_Type;
+extern PyTypeObject PyInterrupt_Type;
+
 void
 _Py_ReadyTypes(void)
 {
 	if (PyType_Ready(&PyType_Type) < 0)
 		Py_FatalError("Can't initialize 'type'");
 
-	if (PyType_Ready(&_PyWeakref_RefType) < 0)
+	if (PyType_Ready(&_PyWeakref_Type) < 0)
 		Py_FatalError("Can't initialize 'weakref'");
 
+	if (PyType_Ready(&_PyDeathQueueHandle_Type) < 0)
+		Py_FatalError("Can't initialize 'deathqueuehandle'");
+
+	if (PyType_Ready(&_PyDeathQueue_Type) < 0)
+		Py_FatalError("Can't initialize 'deathqueue'");
+
 	if (PyType_Ready(&PyBool_Type) < 0)
 		Py_FatalError("Can't initialize 'bool'");
 
@@ -1595,114 +1646,32 @@
 
 	if (PyType_Ready(&PyCode_Type) < 0)
 		Py_FatalError("Can't initialize 'code'");
-}
 
+	if (PyType_Ready(&PyRange_Type) < 0)
+		Py_FatalError("Can't initialize 'range'");
 
-#ifdef Py_TRACE_REFS
+	PySharedDict_Type.tp_base = &PyDict_Type;
+	if (PyType_Ready(&PySharedDict_Type) < 0)
+		Py_FatalError("Can't initialize 'shareddict'");
 
-void
-_Py_NewReference(PyObject *op)
-{
-	_Py_INC_REFTOTAL;
-	op->ob_refcnt = 1;
-	_Py_AddToAllObjects(op, 1);
-	_Py_INC_TPALLOCS(op);
-}
+	PyMonitorMeta_Type.tp_base = &PyType_Type;
+	if (PyType_Ready(&PyMonitorMeta_Type) < 0)
+		Py_FatalError("Can't initialize 'MonitorMeta'");
 
-void
-_Py_ForgetReference(register PyObject *op)
-{
-#ifdef SLOW_UNREF_CHECK
-        register PyObject *p;
-#endif
-	if (op->ob_refcnt < 0)
-		Py_FatalError("UNREF negative refcnt");
-	if (op == &refchain ||
-	    op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op)
-		Py_FatalError("UNREF invalid object");
-#ifdef SLOW_UNREF_CHECK
-	for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
-		if (p == op)
-			break;
-	}
-	if (p == &refchain) /* Not found */
-		Py_FatalError("UNREF unknown object");
-#endif
-	op->_ob_next->_ob_prev = op->_ob_prev;
-	op->_ob_prev->_ob_next = op->_ob_next;
-	op->_ob_next = op->_ob_prev = NULL;
-	_Py_INC_TPFREES(op);
-}
+	if (PyType_Ready(&PyMonitor_Type) < 0)
+		Py_FatalError("Can't initialize 'Monitor'");
 
-void
-_Py_Dealloc(PyObject *op)
-{
-	destructor dealloc = Py_Type(op)->tp_dealloc;
-	_Py_ForgetReference(op);
-	(*dealloc)(op);
-}
+	if (PyType_Ready(&PyMonitorSpace_Type) < 0)
+		Py_FatalError("Can't initialize 'MonitorSpace'");
 
-/* Print all live objects.  Because PyObject_Print is called, the
- * interpreter must be in a healthy state.
- */
-void
-_Py_PrintReferences(FILE *fp)
-{
-	PyObject *op;
-	fprintf(fp, "Remaining objects:\n");
-	for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
-		fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", op, op->ob_refcnt);
-		if (PyObject_Print(op, fp, 0) != 0)
-			PyErr_Clear();
-		putc('\n', fp);
-	}
-}
+	if (PyType_Ready(&PyBranch_Type) < 0)
+		Py_FatalError("Can't initialize 'branch'");
 
-/* Print the addresses of all live objects.  Unlike _Py_PrintReferences, this
- * doesn't make any calls to the Python C API, so is always safe to call.
- */
-void
-_Py_PrintReferenceAddresses(FILE *fp)
-{
-	PyObject *op;
-	fprintf(fp, "Remaining object addresses:\n");
-	for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)
-		fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", op,
-			op->ob_refcnt, Py_Type(op)->tp_name);
+	if (PyType_Ready(&PyInterrupt_Type) < 0)
+		Py_FatalError("Can't initialize 'Interrupt' type");
 }
 
-PyObject *
-_Py_GetObjects(PyObject *self, PyObject *args)
-{
-	int i, n;
-	PyObject *t = NULL;
-	PyObject *res, *op;
 
-	if (!PyArg_ParseTuple(args, "i|O", &n, &t))
-		return NULL;
-	op = refchain._ob_next;
-	res = PyList_New(0);
-	if (res == NULL)
-		return NULL;
-	for (i = 0; (n == 0 || i < n) && op != &refchain; i++) {
-		while (op == self || op == args || op == res || op == t ||
-		       (t != NULL && Py_Type(op) != (PyTypeObject *) t)) {
-			op = op->_ob_next;
-			if (op == &refchain)
-				return res;
-		}
-		if (PyList_Append(res, op) < 0) {
-			Py_DECREF(res);
-			return NULL;
-		}
-		op = op->_ob_next;
-	}
-	return res;
-}
-
-#endif
-
-
 /* Hack to force loading of cobject.o */
 PyTypeObject *_Py_cobject_hack = &PyCObject_Type;
 
@@ -1713,6 +1682,8 @@
 
 /* Python's malloc wrappers (see pymem.h) */
 
+#if 1
+#else
 void *
 PyMem_Malloc(size_t nbytes)
 {
@@ -1730,6 +1701,7 @@
 {
 	PyMem_FREE(p);
 }
+#endif
 
 
 /* These methods are used to control infinite recursion in repr, str, print,
@@ -1797,56 +1769,6 @@
 	}
 }
 
-/* Trashcan support. */
-
-/* Current call-stack depth of tp_dealloc calls. */
-int _PyTrash_delete_nesting = 0;
-
-/* List of objects that still need to be cleaned up, singly linked via their
- * gc headers' gc_prev pointers.
- */
-PyObject *_PyTrash_delete_later = NULL;
-
-/* Add op to the _PyTrash_delete_later list.  Called when the current
- * call-stack depth gets large.  op must be a currently untracked gc'ed
- * object, with refcount 0.  Py_DECREF must already have been called on it.
- */
-void
-_PyTrash_deposit_object(PyObject *op)
-{
-	assert(PyObject_IS_GC(op));
-	assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED);
-	assert(op->ob_refcnt == 0);
-	_Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later;
-	_PyTrash_delete_later = op;
-}
-
-/* Dealloccate all the objects in the _PyTrash_delete_later list.  Called when
- * the call-stack unwinds again.
- */
-void
-_PyTrash_destroy_chain(void)
-{
-	while (_PyTrash_delete_later) {
-		PyObject *op = _PyTrash_delete_later;
-		destructor dealloc = Py_Type(op)->tp_dealloc;
-
-		_PyTrash_delete_later =
-			(PyObject*) _Py_AS_GC(op)->gc.gc_prev;
-
-		/* Call the deallocator directly.  This used to try to
-		 * fool Py_DECREF into calling it indirectly, but
-		 * Py_DECREF was already called on this object, and in
-		 * assorted non-release builds calling Py_DECREF again ends
-		 * up distorting allocation statistics.
-		 */
-		assert(op->ob_refcnt == 0);
-		++_PyTrash_delete_nesting;
-		(*dealloc)(op);
-		--_PyTrash_delete_nesting;
-	}
-}
-
 #ifdef __cplusplus
 }
 #endif
Index: Objects/cellobject.c
===================================================================
--- Objects/cellobject.c	(revision 58355)
+++ Objects/cellobject.c	(working copy)
@@ -7,13 +7,12 @@
 {
 	PyCellObject *op;
 
-	op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
+	op = PyObject_NEW(PyCellObject, &PyCell_Type);
 	if (op == NULL)
 		return NULL;
 	op->ob_ref = obj;
 	Py_XINCREF(obj);
-
-	_PyObject_GC_TRACK(op);
+	PyObject_COMPLETE(op);
 	return (PyObject *)op;
 }
 
@@ -44,9 +43,8 @@
 static void
 cell_dealloc(PyCellObject *op)
 {
-	_PyObject_GC_UNTRACK(op);
 	Py_XDECREF(op->ob_ref);
-	PyObject_GC_Del(op);
+	PyObject_DEL(op);
 }
 
 static PyObject *
@@ -106,7 +104,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
  	0,					/* tp_doc */
  	(traverseproc)cell_traverse,		/* tp_traverse */
  	(inquiry)cell_clear,			/* tp_clear */
Index: Objects/methodobject.c
===================================================================
--- Objects/methodobject.c	(revision 58355)
+++ Objects/methodobject.c	(working copy)
@@ -3,29 +3,40 @@
 
 #include "Python.h"
 #include "structmember.h"
+#include "pythread.h"
 
+#ifdef USE_METHOD_FREELIST
 static PyCFunctionObject *free_list = NULL;
+static PyThread_type_lock free_list_lock;
+#endif
 
 PyObject *
 PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
 {
 	PyCFunctionObject *op;
+#ifdef USE_METHOD_FREELIST
+	PyThread_lock_acquire(free_list_lock);
 	op = free_list;
 	if (op != NULL) {
 		free_list = (PyCFunctionObject *)(op->m_self);
+		PyThread_lock_release(free_list_lock);
 		PyObject_INIT(op, &PyCFunction_Type);
+		_PyObject_GC_TRACK(op);
 	}
 	else {
-		op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+		PyThread_lock_release(free_list_lock);
+#endif
+		op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
 		if (op == NULL)
 			return NULL;
+#ifdef USE_METHOD_FREELIST
 	}
+#endif
 	op->m_ml = ml;
 	Py_XINCREF(self);
 	op->m_self = self;
 	Py_XINCREF(module);
 	op->m_module = module;
-	_PyObject_GC_TRACK(op);
 	return (PyObject *)op;
 }
 
@@ -67,7 +78,8 @@
 	PyObject *self = PyCFunction_GET_SELF(func);
 	Py_ssize_t size;
 
-	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
+	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC |
+			METH_COEXIST | METH_SHARED)) {
 	case METH_VARARGS:
 		if (kw == NULL || PyDict_Size(kw) == 0)
 			return (*meth)(self, arg);
@@ -113,11 +125,16 @@
 static void
 meth_dealloc(PyCFunctionObject *m)
 {
-	_PyObject_GC_UNTRACK(m);
 	Py_XDECREF(m->m_self);
 	Py_XDECREF(m->m_module);
+#ifdef USE_METHOD_FREELIST
+	PyThread_lock_acquire(free_list_lock);
 	m->m_self = (PyObject *)free_list;
 	free_list = m;
+	PyThread_lock_release(free_list_lock);
+#else
+	PyObject_DEL(m);
+#endif
 }
 
 static PyObject *
@@ -230,7 +247,15 @@
 	return x;
 }
 
+static int
+meth_isshareable(PyCFunctionObject *a)
+{
+	if (a->m_ml->ml_flags & METH_SHARED)
+		return 1;
+	return 0;
+}
 
+
 PyTypeObject PyCFunction_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"builtin_function_or_method",
@@ -264,6 +289,18 @@
 	meth_getsets,				/* tp_getset */
 	0,					/* tp_base */
 	0,					/* tp_dict */
+	0,					/* tp_descr_get */
+	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	(isshareablefunc)meth_isshareable,	/* tp_isshareable */
 };
 
 /* Find a method in a method chain */
@@ -303,16 +340,31 @@
 	return Py_FindMethodInChain(&chain, self, name);
 }
 
+void
+_PyCFunction_Init(void)
+{
+#ifdef USE_METHOD_FREELIST
+	free_list_lock = PyThread_lock_allocate();
+	if (!free_list_lock)
+		Py_FatalError("unable to allocate lock");
+#endif
+}
+
 /* Clear out the free list */
 
 void
 PyCFunction_Fini(void)
 {
+#ifdef USE_METHOD_FREELIST
 	while (free_list) {
 		PyCFunctionObject *v = free_list;
 		free_list = (PyCFunctionObject *)(v->m_self);
-		PyObject_GC_Del(v);
+		PyObject_DEL(v);
 	}
+
+	PyThread_lock_free(free_list_lock);
+	free_list_lock = NULL;
+#endif
 }
 
 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
Index: Objects/typeobject.c
===================================================================
--- Objects/typeobject.c	(revision 58355)
+++ Objects/typeobject.c	(working copy)
@@ -3,6 +3,7 @@
 #include "Python.h"
 #include "frameobject.h"
 #include "structmember.h"
+#include "monitorobject.h"
 
 #include <ctype.h>
 
@@ -90,15 +91,14 @@
 	char *s;
 
 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
-		mod = PyDict_GetItemString(type->tp_dict, "__module__");
-		if (!mod) { 
+		if (PyDict_GetItemStringEx(type->tp_dict, "__module__", &mod) < 0)
+			return NULL;
+		if (mod == NULL) {
 			PyErr_Format(PyExc_AttributeError, "__module__");
-			return 0;
+			return NULL;
 		}
-		Py_XINCREF(mod);
 		return mod;
-	}
-	else {
+	} else {
 		s = strrchr(type->tp_name, '.');
 		if (s != NULL)
 			return PyUnicode_FromStringAndSize(
@@ -150,7 +150,7 @@
 	PyTypeObject *subclass;
 	PyObject *ref, *subclasses, *old_mro;
 	Py_ssize_t i, n;
-
+#if 0
 	subclasses = type->tp_subclasses;
 	if (subclasses == NULL)
 		return 0;
@@ -182,6 +182,7 @@
 		if (mro_subclasses(subclass, temp) < 0)
 			return -1;
 	}
+#endif
 	return 0;
 }
 
@@ -342,18 +343,19 @@
 	PyObject *result;
 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL)
 		return PyUnicode_FromString(type->tp_doc);
-	result = PyDict_GetItemString(type->tp_dict, "__doc__");
+	if (PyDict_GetItemStringEx(type->tp_dict, "__doc--", &result) < 0)
+		return NULL;
 	if (result == NULL) {
-		result = Py_None;
-		Py_INCREF(result);
+		Py_INCREF(Py_None);
+		return Py_None;
 	}
-	else if (Py_Type(result)->tp_descr_get) {
-		result = Py_Type(result)->tp_descr_get(result, NULL,
-						       (PyObject *)type);
+	
+	if (Py_Type(result)->tp_descr_get) {
+		PyObject *tmp = Py_Type(result)->tp_descr_get(result,
+			NULL, (PyObject *)type);
+		Py_DECREF(result);
+		result = tmp;
 	}
-	else {
-		Py_INCREF(result);
-	}
 	return result;
 }
 
@@ -419,10 +421,49 @@
 		    (kwds == NULL ||
 		     (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
 			return obj;
+
 		/* If the returned object is not an instance of type,
 		   it won't be initialized. */
 		if (!PyType_IsSubtype(Py_Type(obj), type))
 			return obj;
+
+		if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_FINALIZE)) {
+			PyObject *queue, *handle;
+			PyObject *core = type->tp_new(type, args, kwds);
+			if (core == NULL) {
+				Py_DECREF(obj);
+				return NULL;
+			}
+			if (PyObject_SetAttrString(obj, "__finalizecore__", core) == -1) {
+				Py_DECREF(obj);
+				Py_DECREF(core);
+				return NULL;
+			}
+
+			queue = PySys_GetObject("finalizequeue");
+			if (queue == NULL) {
+				PyErr_SetString(PyExc_RuntimeError, "lost sys.finalizequeue");
+				Py_DECREF(obj);
+				Py_DECREF(core);
+				return NULL;
+			}
+			handle = PyObject_CallMethod(queue, "watch", "OO", obj, core);
+			//Py_DECREF(queue); // PySys_GetObject returns a borrowed reference
+			if (handle == NULL) {
+				Py_DECREF(obj);
+				Py_DECREF(core);
+				return NULL;
+			}
+			if (PyObject_SetAttrString(obj, "__finalizehandle__", handle) == -1) {
+				Py_DECREF(handle);
+				Py_DECREF(obj);
+				Py_DECREF(core);
+				return NULL;
+			}
+			Py_DECREF(handle);
+			Py_DECREF(core);
+		}
+
 		type = Py_Type(obj);
 		if (type->tp_init != NULL &&
 		    type->tp_init(obj, args, kwds) < 0) {
@@ -434,39 +475,9 @@
 }
 
 PyObject *
-PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
-{
-	PyObject *obj;
-	const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
-	/* note that we need to add one, for the sentinel */
-
-	if (PyType_IS_GC(type))
-		obj = _PyObject_GC_Malloc(size);
-	else
-		obj = (PyObject *)PyObject_MALLOC(size);
-
-	if (obj == NULL)
-		return PyErr_NoMemory();
-
-	memset(obj, '\0', size);
-
-	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
-		Py_INCREF(type);
-
-	if (type->tp_itemsize == 0)
-		PyObject_INIT(obj, type);
-	else
-		(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
-
-	if (PyType_IS_GC(type))
-		_PyObject_GC_TRACK(obj);
-	return obj;
-}
-
-PyObject *
 PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-	return type->tp_alloc(type, 0);
+	return PyObject_New(type);
 }
 
 /* Helpers for subtyping */
@@ -514,16 +525,19 @@
 	}
 
 	if (type->tp_dictoffset != base->tp_dictoffset) {
-		PyObject **dictptr = _PyObject_GetDictPtr(self);
+		PyObject **dictptr = _PyObject_GetDictPtr_NoCheck(self);
 		if (dictptr && *dictptr)
 			Py_VISIT(*dictptr);
 	}
 
+#if 0
+	/* XXX gc_traverse does this directly now */
 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
 		/* For a heaptype, the instances count as references
-		   to the type.	 Traverse the type so the collector
+		   to the type.  Traverse the type so the collector
 		   can find cycles involving this link. */
 		Py_VISIT(type);
+#endif
 
 	if (basetraverse)
 		return basetraverse(self, visit, arg);
@@ -585,93 +599,11 @@
 	type = Py_Type(self);
 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
 
-	/* Test whether the type has GC exactly once */
-
-	if (!PyType_IS_GC(type)) {
-		/* It's really rare to find a dynamic type that doesn't have
-		   GC; it can only happen when deriving from 'object' and not
-		   adding any slots or instance variables.  This allows
-		   certain simplifications: there's no need to call
-		   clear_slots(), or DECREF the dict, or clear weakrefs. */
-
-		/* Maybe call finalizer; exit early if resurrected */
-		if (type->tp_del) {
-			type->tp_del(self);
-			if (self->ob_refcnt > 0)
-				return;
-		}
-
-		/* Find the nearest base with a different tp_dealloc */
-		base = type;
-		while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
-			assert(Py_Size(base) == 0);
-			base = base->tp_base;
-			assert(base);
-		}
-
-		/* Call the base tp_dealloc() */
-		assert(basedealloc);
-		basedealloc(self);
-
-		/* Can't reference self beyond this point */
-		Py_DECREF(type);
-
-		/* Done */
-		return;
-	}
-
-	/* We get here only if the type has GC */
-
-	/* UnTrack and re-Track around the trashcan macro, alas */
-	/* See explanation at end of function for full disclosure */
-	PyObject_GC_UnTrack(self);
-	++_PyTrash_delete_nesting;
-	Py_TRASHCAN_SAFE_BEGIN(self);
-	--_PyTrash_delete_nesting;
-	/* DO NOT restore GC tracking at this point.  weakref callbacks
-	 * (if any, and whether directly here or indirectly in something we
-	 * call) may trigger GC, and if self is tracked at that point, it
-	 * will look like trash to GC and GC will try to delete self again.
+	/* Find the nearest base with a different tp_dealloc
+	 * Clear slots up to the nearest base with a different tp_dealloc
 	 */
-
-	/* Find the nearest base with a different tp_dealloc */
 	base = type;
 	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
-		base = base->tp_base;
-		assert(base);
-	}
-
-	/* If we added a weaklist, we clear it.	 Do this *before* calling
-	   the finalizer (__del__), clearing slots, or clearing the instance
-	   dict. */
-
-	if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
-		PyObject_ClearWeakRefs(self);
-
-	/* Maybe call finalizer; exit early if resurrected */
-	if (type->tp_del) {
-		_PyObject_GC_TRACK(self);
-		type->tp_del(self);
-		if (self->ob_refcnt > 0)
-			goto endlabel;	/* resurrected */
-		else
-			_PyObject_GC_UNTRACK(self);
-		/* New weakrefs could be created during the finalizer call.
-		    If this occurs, clear them out without calling their
-		    finalizers since they might rely on part of the object
-		    being finalized that has already been destroyed. */
-		if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {
-			/* Modeled after GET_WEAKREFS_LISTPTR() */
-			PyWeakReference **list = (PyWeakReference **) \
-				PyObject_GET_WEAKREFS_LISTPTR(self);
-			while (*list)
-				_PyWeakref_ClearRef(*list);
-		}
-	}
-
-	/*  Clear slots up to the nearest base with a different tp_dealloc */
-	base = type;
-	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
 		if (Py_Size(base))
 			clear_slots(base, self);
 		base = base->tp_base;
@@ -680,7 +612,7 @@
 
 	/* If we added a dict, DECREF it */
 	if (type->tp_dictoffset && !base->tp_dictoffset) {
-		PyObject **dictptr = _PyObject_GetDictPtr(self);
+		PyObject **dictptr = _PyObject_GetDictPtr_NoCheck(self);
 		if (dictptr != NULL) {
 			PyObject *dict = *dictptr;
 			if (dict != NULL) {
@@ -690,119 +622,9 @@
 		}
 	}
 
-	/* Call the base tp_dealloc(); first retrack self if
-	 * basedealloc knows about gc.
-	 */
-	if (PyType_IS_GC(base))
-		_PyObject_GC_TRACK(self);
+	/* Call the base tp_dealloc() */
 	assert(basedealloc);
 	basedealloc(self);
-
-	/* Can't reference self beyond this point */
-	Py_DECREF(type);
-
-  endlabel:
-	++_PyTrash_delete_nesting;
-	Py_TRASHCAN_SAFE_END(self);
-	--_PyTrash_delete_nesting;
-
-	/* Explanation of the weirdness around the trashcan macros:
-
-	   Q. What do the trashcan macros do?
-
-	   A. Read the comment titled "Trashcan mechanism" in object.h.
-	      For one, this explains why there must be a call to GC-untrack
-	      before the trashcan begin macro.	Without understanding the
-	      trashcan code, the answers to the following questions don't make
-	      sense.
-
-	   Q. Why do we GC-untrack before the trashcan and then immediately
-	      GC-track again afterward?
-
-	   A. In the case that the base class is GC-aware, the base class
-	      probably GC-untracks the object.	If it does that using the
-	      UNTRACK macro, this will crash when the object is already
-	      untracked.  Because we don't know what the base class does, the
-	      only safe thing is to make sure the object is tracked when we
-	      call the base class dealloc.  But...  The trashcan begin macro
-	      requires that the object is *untracked* before it is called.  So
-	      the dance becomes:
-
-		 GC untrack
-		 trashcan begin
-		 GC track
-
-	   Q. Why did the last question say "immediately GC-track again"?
-	      It's nowhere near immediately.
-
-	   A. Because the code *used* to re-track immediately.	Bad Idea.
-	      self has a refcount of 0, and if gc ever gets its hands on it
-	      (which can happen if any weakref callback gets invoked), it
-	      looks like trash to gc too, and gc also tries to delete self
-	      then.  But we're already deleting self.  Double dealloction is
-	      a subtle disaster.
-
-	   Q. Why the bizarre (net-zero) manipulation of
-	      _PyTrash_delete_nesting around the trashcan macros?
-
-	   A. Some base classes (e.g. list) also use the trashcan mechanism.
-	      The following scenario used to be possible:
-
-	      - suppose the trashcan level is one below the trashcan limit
-
-	      - subtype_dealloc() is called
-
-	      - the trashcan limit is not yet reached, so the trashcan level
-		is incremented and the code between trashcan begin and end is
-		executed
-
-	      - this destroys much of the object's contents, including its
-		slots and __dict__
-
-	      - basedealloc() is called; this is really list_dealloc(), or
-		some other type which also uses the trashcan macros
-
-	      - the trashcan limit is now reached, so the object is put on the
-		trashcan's to-be-deleted-later list
-
-	      - basedealloc() returns
-
-	      - subtype_dealloc() decrefs the object's type
-
-	      - subtype_dealloc() returns
-
-	      - later, the trashcan code starts deleting the objects from its
-		to-be-deleted-later list
-
-	      - subtype_dealloc() is called *AGAIN* for the same object
-
-	      - at the very least (if the destroyed slots and __dict__ don't
-		cause problems) the object's type gets decref'ed a second
-		time, which is *BAD*!!!
-
-	      The remedy is to make sure that if the code between trashcan
-	      begin and end in subtype_dealloc() is called, the code between
-	      trashcan begin and end in basedealloc() will also be called.
-	      This is done by decrementing the level after passing into the
-	      trashcan block, and incrementing it just before leaving the
-	      block.
-
-	      But now it's possible that a chain of objects consisting solely
-	      of objects whose deallocator is subtype_dealloc() will defeat
-	      the trashcan mechanism completely: the decremented level means
-	      that the effective level never reaches the limit.	 Therefore, we
-	      *increment* the level *before* entering the trashcan block, and
-	      matchingly decrement it after leaving.  This means the trashcan
-	      code will trigger a little early, but that's no big deal.
-
-	   Q. Are there any live examples of code in need of all this
-	      complexity?
-
-	   A. Yes.  See SF bug 668433 for code that crashed (when Python was
-	      compiled in debug mode) before the trashcan level manipulations
-	      were added.  For more discussion, see SF patches 581742, 575073
-	      and bug 574207.
-	*/
 }
 
 static PyTypeObject *solid_base(PyTypeObject *type);
@@ -841,14 +663,14 @@
 /* Internal routines to do a method lookup in the type
    without looking in the instance dictionary
    (so we can't use PyObject_GetAttr) but still binding
-   it to the instance.	The arguments are the object,
+   it to the instance.  The arguments are the object,
    the method name as a C string, and the address of a
    static variable used to cache the interned Python string.
 
    Two variants:
 
    - lookup_maybe() returns NULL without raising an exception
-     when the _PyType_Lookup() call fails;
+     when the _PyType_LookupEx() call fails;
 
    - lookup_method() always raises an exception upon errors.
 */
@@ -863,13 +685,15 @@
 		if (*attrobj == NULL)
 			return NULL;
 	}
-	res = _PyType_Lookup(Py_Type(self), *attrobj);
+	if (_PyType_LookupEx(Py_Type(self), *attrobj, &res) < 0)
+		return NULL;
 	if (res != NULL) {
 		descrgetfunc f;
-		if ((f = Py_Type(res)->tp_descr_get) == NULL)
-			Py_INCREF(res);
-		else
-			res = f(res, self, (PyObject *)(Py_Type(self)));
+		if ((f = Py_Type(res)->tp_descr_get) != NULL) {
+			PyObject *tmp = f(res, self, (PyObject *)(Py_Type(self)));
+			Py_DECREF(res);
+			res = tmp;
+		}
 	}
 	return res;
 }
@@ -1419,9 +1243,15 @@
 		if (dict_str == NULL)
 			return NULL;
 	}
-	descr = _PyType_Lookup(type, dict_str);
-	if (descr == NULL || !PyDescr_IsData(descr))
+
+	if (_PyType_LookupEx(type, dict_str, &descr) < 0)
 		return NULL;
+	if (descr == NULL)
+		return NULL;
+	if (!PyDescr_IsData(descr)) {
+		Py_DECREF(descr);
+		return NULL;
+	}
 
 	return descr;
 }
@@ -1559,17 +1389,17 @@
 };
 
 static int
-valid_identifier(PyObject *s)
+valid_identifier(PyObject *s, const char *name)
 {
 	if (!PyUnicode_Check(s)) {
 		PyErr_Format(PyExc_TypeError,
-			     "__slots__ items must be strings, not '%.200s'",
-			     Py_Type(s)->tp_name);
+			     "%s items must be strings, not '%.200s'",
+			     name, Py_Type(s)->tp_name);
 		return 0;
 	}
 	if (!PyUnicode_IsIdentifier(s)) {
-		PyErr_SetString(PyExc_TypeError,
-				"__slots__ must be identifiers");
+		PyErr_Format(PyExc_TypeError,
+				"%s must be identifiers", name);
 		return 0;
 	}
 	return 1;
@@ -1613,12 +1443,13 @@
 {
 	PyObject *name, *bases, *dict;
 	static char *kwlist[] = {"name", "bases", "dict", 0};
-	PyObject *slots, *tmp, *newslots;
+	PyObject *slots, *tmp, *newslots, *finalizeattrs;
 	PyTypeObject *type, *base, *tmptype, *winner;
 	PyHeapTypeObject *et;
 	PyMemberDef *mp;
 	Py_ssize_t i, nbases, nslots, slotoffset, add_dict, add_weak;
 	int j, may_add_dict, may_add_weak;
+	int shared, status;
 
 	assert(args != NULL && PyTuple_Check(args));
 	assert(kwds == NULL || PyDict_Check(kwds));
@@ -1705,8 +1536,29 @@
 		return NULL;
 	}
 
+	/* Check for a __shared__ attribute */
+	shared = 0;
+	if (PyDict_GetItemStringEx(dict, "__shared__", &tmp) < 0) {
+		Py_DECREF(bases);
+		return NULL;
+	}
+	if (tmp != NULL) {
+		shared = PyObject_IsTrue(tmp);
+		Py_DECREF(tmp);
+		if (shared == -1) {
+			Py_DECREF(bases);
+			return NULL;
+		}
+	}
+	/* XXX FIXME do an audit, ensure all possible attributes are
+	 * checked for shareability.  For now I'm going to be lazy and
+	 * just check the most obvious ones. */
+
 	/* Check for a __slots__ sequence variable in dict, and count it */
-	slots = PyDict_GetItemString(dict, "__slots__");
+	if (PyDict_GetItemStringEx(dict, "__slots__", &slots) < 0) {
+		Py_DECREF(bases);
+		return NULL;
+	}
 	nslots = 0;
 	add_dict = 0;
 	add_weak = 0;
@@ -1725,9 +1577,11 @@
 
 		/* Make it into a tuple */
 		if (PyUnicode_Check(slots))
-			slots = PyTuple_Pack(1, slots);
+			tmp = PyTuple_Pack(1, slots);
 		else
-			slots = PySequence_Tuple(slots);
+			tmp = PySequence_Tuple(slots);
+		Py_DECREF(slots);
+		slots = tmp;
 		if (slots == NULL) {
 			Py_DECREF(bases);
 			return NULL;
@@ -1750,7 +1604,7 @@
 		/* Check for valid slot names and two special cases */
 		for (i = 0; i < nslots; i++) {
 			PyObject *tmp = PyTuple_GET_ITEM(slots, i);
-			if (!valid_identifier(tmp))
+			if (!valid_identifier(tmp, "__slots__"))
 				goto bad_slots;
 			assert(PyUnicode_Check(tmp));
 			if (PyUnicode_CompareWithASCIIString(tmp, "__dict__") == 0) {
@@ -1839,7 +1693,9 @@
 	   "return NULL" may leak slots! */
 
 	/* Allocate the type object */
-	type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
+	/* XXX This assumes the allocator will allocate one extra slot
+	 * for the sentinal. */
+	type = PyObject_NEWVAR(PyTypeObject, metatype, nslots);
 	if (type == NULL) {
 		Py_XDECREF(slots);
 		Py_DECREF(bases);
@@ -1875,62 +1731,87 @@
 	type->tp_base = base;
 
 	/* Initialize tp_dict from passed-in dict */
-	type->tp_dict = dict = PyDict_Copy(dict);
+	if (shared)
+		type->tp_dict = dict = PyObject_CallFunction(
+			(PyObject *)&PySharedDict_Type, "(O)", dict);
+	else
+		type->tp_dict = dict = PyDict_Copy(dict);
 	if (dict == NULL) {
 		Py_DECREF(type);
 		return NULL;
 	}
 
 	/* Set __module__ in the dict */
-	if (PyDict_GetItemString(dict, "__module__") == NULL) {
-		tmp = PyEval_GetGlobals();
-		if (tmp != NULL) {
-			tmp = PyDict_GetItemString(tmp, "__name__");
+	if (PyDict_GetItemStringEx(dict, "__module__", &tmp) < 0) {
+		Py_DECREF(type);
+		return NULL;
+	}
+	if (tmp == NULL) {
+		PyObject *globals = PyEval_GetGlobals();
+		if (globals != NULL) {
+			if (PyDict_GetItemStringEx(globals, "__name__", &tmp) < 0)
+				return NULL;
 			if (tmp != NULL) {
 				if (PyDict_SetItemString(dict, "__module__",
-							 tmp) < 0)
+							 tmp) < 0) {
+					Py_DECREF(tmp);
 					return NULL;
+				}
+				Py_DECREF(tmp);
 			}
 		}
-	}
+	} else
+		Py_DECREF(tmp);
 
 	/* Set tp_doc to a copy of dict['__doc__'], if the latter is there
 	   and is a string.  The __doc__ accessor will first look for tp_doc;
 	   if that fails, it will still look into __dict__.
 	*/
 	{
-		PyObject *doc = PyDict_GetItemString(dict, "__doc__");
+		PyObject *doc;
+		if (PyDict_GetItemStringEx(dict, "__doc__", &doc) < 0) {
+			Py_DECREF(type);
+			return NULL;
+		}
 		if (doc != NULL && PyUnicode_Check(doc)) {
 			size_t n;
 			char *tp_doc;
 			const char *str = PyUnicode_AsString(doc);
 			if (str == NULL) {
 				Py_DECREF(type);
+				Py_DECREF(doc);
 				return NULL;
 			}
 			n = strlen(str);
 			tp_doc = (char *)PyObject_MALLOC(n+1);
 			if (tp_doc == NULL) {
 				Py_DECREF(type);
+				Py_DECREF(doc);
 				return NULL;
 			}
 			memcpy(tp_doc, str, n+1);
 			type->tp_doc = tp_doc;
 		}
+		Py_XDECREF(doc);
 	}
 
 	/* Special-case __new__: if it's a plain function,
 	   make it a static function */
-	tmp = PyDict_GetItemString(dict, "__new__");
+	if (PyDict_GetItemStringEx(dict, "__new__", &tmp) < 0) {
+		Py_DECREF(type);
+		return NULL;
+	}
 	if (tmp != NULL && PyFunction_Check(tmp)) {
-		tmp = PyStaticMethod_New(tmp);
-		if (tmp == NULL) {
+		PyObject *tmp2 = PyStaticMethod_New(tmp);
+		Py_DECREF(tmp);
+		if (tmp2 == NULL) {
 			Py_DECREF(type);
 			return NULL;
 		}
-		PyDict_SetItemString(dict, "__new__", tmp);
-		Py_DECREF(tmp);
-	}
+		PyDict_SetItemString(dict, "__new__", tmp2);
+		Py_DECREF(tmp2);
+	} else
+		Py_XDECREF(tmp);
 
 	/* Add descriptors for custom slots from __slots__, or for __dict__ */
 	mp = PyHeapType_GET_MEMBERS(et);
@@ -1989,15 +1870,43 @@
 		type->tp_flags |= Py_TPFLAGS_HAVE_GC;
 
 	/* Always override allocation strategy to use regular heap */
-	type->tp_alloc = PyType_GenericAlloc;
+	/* XXX This comment needs updating */
 	if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
-		type->tp_free = PyObject_GC_Del;
 		type->tp_traverse = subtype_traverse;
 		type->tp_clear = subtype_clear;
 	}
-	else
-		type->tp_free = PyObject_Del;
 
+	/* Activate sharing, check that the contents are shareable too */
+	if (shared) {
+		type->tp_flags |= Py_TPFLAGS_SHAREABLE;
+
+		for (i = 0; i < nbases; i++) {
+			tmp = PyTuple_GET_ITEM(bases, i);
+			if (!PyObject_IsShareable(tmp)) {
+				PyErr_SetString(PyExc_TypeError,
+					"Shared type given unshareable base");
+				Py_DECREF(type);
+				return NULL;
+			}
+		}
+	}
+
+	status = PyDict_ContainsString(dict, "__finalize__");
+	if (status < 0) {
+		Py_DECREF(type);
+		return NULL;
+	} else if (status > 0)
+		type->tp_flags |= Py_TPFLAGS_HAVE_FINALIZE;
+	else {
+		for (i = 0; i < nbases; i++) {
+			tmp = PyTuple_GET_ITEM(bases, i);
+			if (((PyTypeObject *)tmp)->tp_flags & Py_TPFLAGS_HAVE_FINALIZE) {
+				type->tp_flags |= Py_TPFLAGS_HAVE_FINALIZE;
+				break;
+			}
+		}
+	}
+
 	/* Initialize the rest */
 	if (PyType_Ready(type) < 0) {
 		Py_DECREF(type);
@@ -2007,16 +1916,63 @@
 	/* Put the proper slots in place */
 	fixup_slot_dispatchers(type);
 
+	/* Add __finalizeattrs__ */
+	if (PyDict_GetItemStringEx(dict, "__finalizeattrs__", &finalizeattrs) < 0) {
+		Py_DECREF(type);
+		return NULL;
+	}
+	if (finalizeattrs != NULL) {
+		/* Make it into a tuple */
+		if (PyUnicode_Check(finalizeattrs))
+			tmp = PyTuple_Pack(1, finalizeattrs);
+		else
+			tmp = PySequence_Tuple(finalizeattrs);
+		Py_DECREF(finalizeattrs);
+		finalizeattrs = tmp;
+		if (finalizeattrs == NULL) {
+			Py_DECREF(type);
+			return NULL;
+		}
+		assert(PyTuple_Check(finalizeattrs));
+
+		for (i = 0; i < PyTuple_GET_SIZE(finalizeattrs); i++) {
+			PyObject *descr;
+			PyObject *tmp = PyTuple_GET_ITEM(finalizeattrs, i);
+
+			if (!valid_identifier(tmp, "__finalizeattrs__")) {
+				Py_DECREF(type);
+				return NULL;
+			}
+
+			descr = PyDescr_NewFinalizeAttr(type, tmp);
+			if (descr == NULL) {
+				Py_DECREF(type);
+				return NULL;
+			}
+
+			if (PyDict_SetItem(type->tp_dict, tmp, descr) < 0) {
+				Py_DECREF(finalizeattrs);
+				Py_DECREF(descr);
+				Py_DECREF(type);
+				return NULL;
+			}
+		}
+		Py_DECREF(finalizeattrs);
+	}
+
 	return (PyObject *)type;
 }
 
-/* Internal API to look for a name through the MRO.
-   This returns a borrowed reference, and doesn't set an exception! */
-PyObject *
-_PyType_Lookup(PyTypeObject *type, PyObject *name)
+/* Internal API to look for a name through the MRO.  Return values:
+ * -1 Error, exception set (result set to NULL)
+ *  0 Success (result filled in with *NEW* reference)
+ * +1 Not found, no exception set (result set to NULL)
+ */
+int
+_PyType_LookupEx(PyTypeObject *type, PyObject *name, PyObject **result)
 {
 	Py_ssize_t i, n;
-	PyObject *mro, *res, *base, *dict;
+	PyObject *mro, *base, *dict;
 
 	/* Look in tp_dict of types in MRO */
 	mro = type->tp_mro;
@@ -2024,25 +1980,32 @@
 	/* If mro is NULL, the type is either not yet initialized
 	   by PyType_Ready(), or already cleared by type_clear().
 	   Either way the safest thing to do is to return NULL. */
-	if (mro == NULL)
-		return NULL;
+	if (mro == NULL) {
+		*result = NULL;
+		return 1;  /* XXX should this be -1 with an exception instead? */
+	}
 
 	assert(PyTuple_Check(mro));
 	n = PyTuple_GET_SIZE(mro);
 	for (i = 0; i < n; i++) {
 		base = PyTuple_GET_ITEM(mro, i);
 		assert(PyType_Check(base));
+
 		dict = ((PyTypeObject *)base)->tp_dict;
 		assert(dict && PyDict_Check(dict));
-		res = PyDict_GetItem(dict, name);
-		if (res != NULL)
-			return res;
+
+		if (PyDict_GetItemEx(dict, name, result) < 0)
+			return -1;
+		if (*result != NULL)
+			return 0;
 	}
-	return NULL;
+
+	*result = NULL;
+	return 1;
 }
 
 /* This is similar to PyObject_GenericGetAttr(),
-   but uses _PyType_Lookup() instead of just looking in type->tp_dict. */
+   but uses _PyType_LookupEx() instead of just looking in type->tp_dict. */
 static PyObject *
 type_getattro(PyTypeObject *type, PyObject *name)
 {
@@ -2060,7 +2023,8 @@
 	meta_get = NULL;
 
 	/* Look for the attribute in the metatype */
-	meta_attribute = _PyType_Lookup(metatype, name);
+	if (_PyType_LookupEx(metatype, name, &meta_attribute) < 0)
+		return NULL;
 
 	if (meta_attribute != NULL) {
 		meta_get = Py_Type(meta_attribute)->tp_descr_get;
@@ -2070,15 +2034,19 @@
 			 * writes. Assume the attribute is not overridden in
 			 * type's tp_dict (and bases): call the descriptor now.
 			 */
-			return meta_get(meta_attribute, (PyObject *)type,
-					(PyObject *)metatype);
+			attribute = meta_get(meta_attribute, (PyObject *)type,
+				(PyObject *)metatype);
+			Py_DECREF(meta_attribute);
+			return attribute;
 		}
-		Py_INCREF(meta_attribute);
 	}
 
 	/* No data descriptor found on metatype. Look in tp_dict of this
 	 * type and its bases */
-	attribute = _PyType_Lookup(type, name);
+	if (_PyType_LookupEx(type, name, &attribute) < 0) {
+		Py_XDECREF(meta_attribute);
+		return NULL;
+	}
 	if (attribute != NULL) {
 		/* Implement descriptor functionality, if any */
 		descrgetfunc local_get = Py_Type(attribute)->tp_descr_get;
@@ -2086,13 +2054,15 @@
 		Py_XDECREF(meta_attribute);
 
 		if (local_get != NULL) {
+			PyObject *tmp;
 			/* NULL 2nd argument indicates the descriptor was
 			 * found on the target object itself (or a base)  */
-			return local_get(attribute, (PyObject *)NULL,
-					 (PyObject *)type);
+			tmp = local_get(attribute, (PyObject *)NULL,
+				(PyObject *)type);
+			Py_DECREF(attribute);
+			return tmp;
 		}
 
-		Py_INCREF(attribute);
 		return attribute;
 	}
 
@@ -2142,10 +2112,9 @@
 {
 	PyHeapTypeObject *et;
 
+	printf("type_dealloc %s\n", type->tp_name);
 	/* Assert this is a heap-allocated type object */
 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
-	_PyObject_GC_UNTRACK(type);
-	PyObject_ClearWeakRefs((PyObject *)type);
 	et = (PyHeapTypeObject *)type;
 	Py_XDECREF(type->tp_base);
 	Py_XDECREF(type->tp_dict);
@@ -2159,7 +2128,7 @@
 	PyObject_Free((char *)type->tp_doc);
 	Py_XDECREF(et->ht_name);
 	Py_XDECREF(et->ht_slots);
-	Py_Type(type)->tp_free((PyObject *)type);
+	PyObject_DEL(type);
 }
 
 static PyObject *
@@ -2171,6 +2140,7 @@
 	list = PyList_New(0);
 	if (list == NULL)
 		return NULL;
+#if 0
 	raw = type->tp_subclasses;
 	if (raw == NULL)
 		return list;
@@ -2187,6 +2157,7 @@
 			}
 		}
 	}
+#endif
 	return list;
 }
 
@@ -2240,6 +2211,7 @@
 	   for heaptypes. */
 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
 
+#warning XXX FIXME this should check for subtypes of type and change ob_type to a known-safe value for HEAPTYPEs
 	/* The only field we need to clear is tp_mro, which is part of a
 	   hard cycle (its first element is the class itself) that won't
 	   be broken otherwise (it's a tuple and tuples don't have a
@@ -2276,6 +2248,12 @@
 	return type->tp_flags & Py_TPFLAGS_HEAPTYPE;
 }
 
+static int
+type_isshareable (PyTypeObject *type)
+{
+	return PyType_HasFeature(type, Py_TPFLAGS_SHAREABLE);
+}
+
 PyTypeObject PyType_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"type",					/* tp_name */
@@ -2297,7 +2275,8 @@
 	(setattrofunc)type_setattro,		/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
 	type_doc,				/* tp_doc */
 	(traverseproc)type_traverse,		/* tp_traverse */
 	(inquiry)type_clear,			/* tp_clear */
@@ -2314,10 +2293,14 @@
 	0,					/* tp_descr_set */
 	offsetof(PyTypeObject, tp_dict),	/* tp_dictoffset */
 	type_init,				/* tp_init */
-	0,					/* tp_alloc */
 	type_new,				/* tp_new */
-	PyObject_GC_Del,			/* tp_free */
 	(inquiry)type_is_gc,			/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	(isshareablefunc)type_isshareable,	/* tp_isshareable */
 };
 
 
@@ -2356,6 +2339,13 @@
    __init__() is overridden and __new__() is not overridden
    (IOW, if __new__() is overridden or __init__() is not overridden).
 
+       __new__     __init__    __new__     __init__
+      overridden  overridden  complains   complains
+   a.     no          no         yes         yes
+   b.     no         yes          no         yes
+   c.    yes          no         yes          no
+   d.    yes         yes         yes         yes
+
    However, for backwards compatibility, this breaks too much code.
    Therefore, in 2.6, we'll *warn* about excess arguments when both
    methods are overridden; for all other cases we'll use the above
@@ -2381,14 +2371,14 @@
 	if (excess_args(args, kwds)) {
 		PyTypeObject *type = Py_Type(self);
 		if (type->tp_init != object_init &&
-		    type->tp_new != object_new)
+		    type->tp_new != object_new) /* Condition d */
 		{
 			err = PyErr_WarnEx(PyExc_DeprecationWarning,
 				   "object.__init__() takes no parameters",
 				   1);
 		}
-		else if (type->tp_init != object_init ||
-			 type->tp_new == object_new)
+		else if (type->tp_init != object_init || /* Conditions b, d */
+			 type->tp_new == object_new) /* Conditions a, b */
 		{
 			PyErr_SetString(PyExc_TypeError,
 				"object.__init__() takes no parameters");
@@ -2404,14 +2394,14 @@
 	int err = 0;
 	if (excess_args(args, kwds)) {
 		if (type->tp_new != object_new &&
-		    type->tp_init != object_init)
+		    type->tp_init != object_init) /* Condition d */
 		{
 			err = PyErr_WarnEx(PyExc_DeprecationWarning,
 				   "object.__new__() takes no parameters",
 				   1);
 		}
-		else if (type->tp_new != object_new ||
-			 type->tp_init == object_init)
+		else if (type->tp_new != object_new || /* Conditions c, d */
+			 type->tp_init == object_init) /* Conditions a, c */
 		{
 			PyErr_SetString(PyExc_TypeError,
 				"object.__new__() takes no parameters");
@@ -2420,13 +2410,13 @@
 	}
 	if (err < 0)
 		return NULL;
-	return type->tp_alloc(type, 0);
+	return PyObject_New(type);
 }
 
 static void
 object_dealloc(PyObject *self)
 {
-	Py_Type(self)->tp_free(self);
+	PyObject_Del(self);
 }
 
 static PyObject *
@@ -2561,9 +2551,7 @@
 {
 	PyTypeObject *newbase, *oldbase;
 
-	if (newto->tp_dealloc != oldto->tp_dealloc ||
-	    newto->tp_free != oldto->tp_free)
-	{
+	if (newto->tp_dealloc != oldto->tp_dealloc) {
 		PyErr_Format(PyExc_TypeError,
 			     "%s assignment: "
 			     "'%s' deallocator differs from '%s'",
@@ -2670,10 +2658,12 @@
 	}
 
 	clsdict = ((PyTypeObject *)cls)->tp_dict;
-	slotnames = PyDict_GetItemString(clsdict, "__slotnames__");
-	if (slotnames != NULL && PyList_Check(slotnames)) {
-		Py_INCREF(slotnames);
-		return slotnames;
+	if (PyDict_GetItemStringEx(clsdict, "__slotnames__", &slotnames) < 0)
+		return NULL;
+	if (slotnames != NULL) {
+		if (PyList_Check(slotnames))
+			return slotnames;
+		Py_DECREF(slotnames);
 	}
 
 	copy_reg = import_copy_reg();
@@ -2906,10 +2896,14 @@
 			Py_DECREF(reduce);
 			return NULL;
 		}
-		objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict,
-						 "__reduce__");
+		if (PyDict_GetItemStringEx(PyBaseObject_Type.tp_dict,
+				"__reduce__", &objreduce) < 0) {
+			Py_DECREF(reduce);
+			return NULL;
+		}
 		override = (clsreduce != objreduce);
 		Py_DECREF(clsreduce);
+		Py_XDECREF(objreduce);
 		if (override) {
 			res = PyObject_CallObject(reduce, NULL);
 			Py_DECREF(reduce);
@@ -2961,6 +2955,31 @@
         return result;
 }
 
+static PyObject *
+object_finalize(PyObject *self, PyObject *args)
+{
+    PyObject *handle, *queue, *res;
+
+    handle = PyObject_GetAttrString(self, "__finalizehandle__");
+    if (handle == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Clear();
+        Py_INCREF(Py_None);
+        return Py_None;
+    } else if (handle == NULL)
+        return NULL;
+
+    queue = PySys_GetObject("finalizequeue");
+    if (queue == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "lost sys.finalizequeue");
+        Py_DECREF(handle);
+        return NULL;
+    }
+
+    res = PyObject_CallMethod(queue, "cancel", "O", handle);
+    //Py_DECREF(queue); // PySys_GetObject returns a borrowed reference
+    return res;
+}
+
 static PyMethodDef object_methods[] = {
 	{"__reduce_ex__", object_reduce_ex, METH_VARARGS,
 	 PyDoc_STR("helper for pickle")},
@@ -2968,6 +2987,8 @@
 	 PyDoc_STR("helper for pickle")},
         {"__format__", object_format, METH_VARARGS,
          PyDoc_STR("default object formatter")},
+        {"__finalize__", object_finalize, METH_NOARGS,
+         PyDoc_STR("base finalize method")},
 	{0}
 };
 
@@ -2992,7 +3013,8 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	PyObject_GenericSetAttr,		/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
 	PyDoc_STR("The most base type"),	/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
@@ -3009,9 +3031,7 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	object_init,				/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	object_new,				/* tp_new */
-	PyObject_Del,				/* tp_free */
 };
 
 
@@ -3024,9 +3044,14 @@
 
 	for (; meth->ml_name != NULL; meth++) {
 		PyObject *descr;
-		if (PyDict_GetItemString(dict, meth->ml_name) &&
-			!(meth->ml_flags & METH_COEXIST))
+		int status;
+
+		if ((status = PyDict_ContainsString(dict, meth->ml_name))) {
+			if (status < 0)
+				return -1;
+			if (!(meth->ml_flags & METH_COEXIST))
 				continue;
+		}
 		if (meth->ml_flags & METH_CLASS) {
 			if (meth->ml_flags & METH_STATIC) {
 				PyErr_SetString(PyExc_ValueError,
@@ -3061,8 +3086,12 @@
 
 	for (; memb->name != NULL; memb++) {
 		PyObject *descr;
-		if (PyDict_GetItemString(dict, memb->name))
+		if (PyDict_GetItemStringEx(dict, memb->name, &descr) < 0)
+			return -1;
+		if (descr != NULL) {
+			Py_DECREF(descr);
 			continue;
+		}
 		descr = PyDescr_NewMember(type, memb);
 		if (descr == NULL)
 			return -1;
@@ -3080,8 +3109,12 @@
 
 	for (; gsp->name != NULL; gsp++) {
 		PyObject *descr;
-		if (PyDict_GetItemString(dict, gsp->name))
+		if (PyDict_GetItemStringEx(dict, gsp->name, &descr) < 0)
+			return -1;
+		if (descr != NULL) {
+			Py_DECREF(descr);
 			continue;
+		}
 		descr = PyDescr_NewGetSet(type, gsp);
 
 		if (descr == NULL)
@@ -3156,6 +3189,8 @@
 		type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
 	else if (PyType_IsSubtype(base, &PyDict_Type))
 		type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
+	else if (PyType_IsSubtype(base, &PyMonitor_Type))
+		type->tp_flags |= Py_TPFLAGS_MONITOR_SUBCLASS;
 }
 
 /* Map rich comparison operators to their __xx__ namesakes */
@@ -3171,21 +3206,27 @@
 	"__hash__",
 };
 
+/* 1 is returned if a method is found, 0 if none are found, and -1 on error */
 static int
 overrides_cmp_or_hash(PyTypeObject *type)
 {
 	int i;
+	PyObject *tmp;
 	PyObject *dict = type->tp_dict;
 
 	assert(dict != NULL);
 	for (i = 0; i < 8; i++) {
-		if (PyDict_GetItemString(dict, name_op[i]) != NULL)
+		if (PyDict_GetItemStringEx(dict, name_op[i], &tmp) < 0)
+			return -1;
+		if (tmp != NULL) {
+			Py_DECREF(tmp);
 			return 1;
+		}
 	}
 	return 0;
 }
 
-static void
+static int
 inherit_slots(PyTypeObject *type, PyTypeObject *base)
 {
 	PyTypeObject *basebase;
@@ -3299,19 +3340,21 @@
 	/* tp_hash see tp_richcompare */
 	COPYSLOT(tp_call);
 	COPYSLOT(tp_str);
-	{
-		/* Copy comparison-related slots only when
-		   not overriding them anywhere */
-		if (type->tp_compare == NULL &&
-		    type->tp_richcompare == NULL &&
-		    type->tp_hash == NULL &&
-		    !overrides_cmp_or_hash(type))
-		{
+
+	/* Copy comparison-related slots only when
+	   not overriding them anywhere */
+	if (type->tp_compare == NULL && type->tp_richcompare == NULL &&
+			type->tp_hash == NULL) {
+		int status = overrides_cmp_or_hash(type);
+		if (status < 0)
+			return -1;
+		else if (status == 0) {
 			type->tp_compare = base->tp_compare;
 			type->tp_richcompare = base->tp_richcompare;
 			type->tp_hash = base->tp_hash;
 		}
 	}
+
 	{
 		COPYSLOT(tp_iter);
 		COPYSLOT(tp_iternext);
@@ -3320,28 +3363,12 @@
 		COPYSLOT(tp_descr_get);
 		COPYSLOT(tp_descr_set);
 		COPYSLOT(tp_dictoffset);
+		COPYSLOT(tp_isshareable);
 		COPYSLOT(tp_init);
-		COPYSLOT(tp_alloc);
 		COPYSLOT(tp_is_gc);
-		if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==
-		    (base->tp_flags & Py_TPFLAGS_HAVE_GC)) {
-			/* They agree about gc. */
-			COPYSLOT(tp_free);
-		}
-		else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
-			 type->tp_free == NULL &&
-			 base->tp_free == PyObject_Free) {
-			/* A bit of magic to plug in the correct default
-			 * tp_free function when a derived class adds gc,
-			 * didn't define tp_free, and the base uses the
-			 * default non-gc tp_free.
-			 */
-			type->tp_free = PyObject_GC_Del;
-		}
-		/* else they didn't agree about gc, and there isn't something
-		 * obvious to be done -- the type is on its own.
-		 */
 	}
+
+	return 0;
 }
 
 static int add_operators(PyTypeObject *);
@@ -3349,7 +3376,7 @@
 int
 PyType_Ready(PyTypeObject *type)
 {
-	PyObject *dict, *bases;
+	PyObject *dict, *bases, *doc;
 	PyTypeObject *base;
 	Py_ssize_t i, n;
 
@@ -3360,6 +3387,7 @@
 	assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
 
 	type->tp_flags |= Py_TPFLAGS_READYING;
+//	printf("Readying %s\n", type->tp_name);
 
 #ifdef Py_TRACE_REFS
 	/* PyType_Ready is the closest thing we have to a choke point
@@ -3387,12 +3415,12 @@
 			goto error;
 	}
 
-	/* Initialize ob_type if NULL.	This means extensions that want to be
+	/* Initialize ob_type if NULL.  This means extensions that want to be
 	   compilable separately on Windows can call PyType_Ready() instead of
 	   initializing the ob_type field of their type objects. */
 	/* The test for base != NULL is really unnecessary, since base is only
 	   NULL when type is &PyBaseObject_Type, and we know its ob_type is
-	   not NULL (it's initialized to &PyType_Type).	 But coverity doesn't
+	   not NULL (it's initialized to &PyType_Type).  But coverity doesn't
 	   know that. */
 	if (Py_Type(type) == NULL && base != NULL)
 		Py_Type(type) = Py_Type(base);
@@ -3450,29 +3478,20 @@
 	n = PyTuple_GET_SIZE(bases);
 	for (i = 1; i < n; i++) {
 		PyObject *b = PyTuple_GET_ITEM(bases, i);
-		if (PyType_Check(b))
-			inherit_slots(type, (PyTypeObject *)b);
+		if (PyType_Check(b)) {
+			if (inherit_slots(type, (PyTypeObject *)b))
+				goto error;
+		}
 	}
 
-	/* Sanity check for tp_free. */
-	if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
-	    (type->tp_free == NULL || type->tp_free == PyObject_Del)) {
-		/* This base class needs to call tp_free, but doesn't have
-		 * one, or its tp_free is for non-gc'ed objects.
-		 */
-		PyErr_Format(PyExc_TypeError, "type '%.100s' participates in "
-			     "gc and is a base type but has inappropriate "
-			     "tp_free slot",
-			     type->tp_name);
-		goto error;
-	}
-
 	/* if the type dictionary doesn't contain a __doc__, set it from
 	   the tp_doc slot.
 	 */
-	if (PyDict_GetItemString(type->tp_dict, "__doc__") == NULL) {
+	if (PyDict_GetItemStringEx(type->tp_dict, "__doc__", &doc) < 0)
+		goto error;
+	if (doc == NULL) {
 		if (type->tp_doc != NULL) {
-			PyObject *doc = PyUnicode_FromString(type->tp_doc);
+			doc = PyUnicode_FromString(type->tp_doc);
 			if (doc == NULL)
 				goto error;
 			PyDict_SetItemString(type->tp_dict, "__doc__", doc);
@@ -3481,7 +3500,8 @@
 			PyDict_SetItemString(type->tp_dict,
 					     "__doc__", Py_None);
 		}
-	}
+	} else
+		Py_DECREF(doc);
 
 	/* Hack for tp_hash and __hash__.
 	   If after all that, tp_hash is still NULL, and __hash__ is not in
@@ -3489,10 +3509,14 @@
 	   This signals that __hash__ is not inherited.
 	 */
 	if (type->tp_hash == NULL) {
-		if (PyDict_GetItemString(type->tp_dict, "__hash__") == NULL) {
+		PyObject *hash;
+		if (PyDict_GetItemStringEx(type->tp_dict, "__hash__", &hash) < 0)
+			goto error;
+		if (hash == NULL) {
 			if (PyDict_SetItemString(type->tp_dict, "__hash__", Py_None) < 0)
 				goto error;
-		}
+		} else
+			Py_DECREF(hash);
 	}
 
 	/* Some more special stuff */
@@ -3536,6 +3560,8 @@
 	int result;
 	PyObject *list, *ref, *newobj;
 
+        return 0; /* XXX FIXME brutal hack! */
+#if 0
 	list = base->tp_subclasses;
 	if (list == NULL) {
 		base->tp_subclasses = list = PyList_New(0);
@@ -3554,6 +3580,7 @@
 	result = PyList_Append(list, newobj);
 	Py_DECREF(newobj);
 	return result;
+#endif
 }
 
 static void
@@ -3562,6 +3589,8 @@
 	Py_ssize_t i;
 	PyObject *list, *ref;
 
+        return; /* XXX FIXME brutal hack! */
+#if 0
 	list = base->tp_subclasses;
 	if (list == NULL) {
 		return;
@@ -3577,6 +3606,7 @@
 			return;
 		}
 	}
+#endif
 }
 
 static int
@@ -4136,8 +4166,12 @@
 add_tp_new_wrapper(PyTypeObject *type)
 {
 	PyObject *func;
+	int status;
 
-	if (PyDict_GetItemString(type->tp_dict, "__new__") != NULL)
+	status = PyDict_ContainsString(type->tp_dict, "__new__");
+	if (status < 0)
+		return -1;
+	if (status > 0)
 		return 0;
 	func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);
 	if (func == NULL)
@@ -4286,12 +4320,14 @@
 		if (getitem_str == NULL)
 			return NULL;
 	}
-	func = _PyType_Lookup(Py_Type(self), getitem_str);
+
+	if (_PyType_LookupEx(Py_Type(self), getitem_str, &func) < 0)
+		return NULL;
 	if (func != NULL) {
-		if ((f = Py_Type(func)->tp_descr_get) == NULL)
-			Py_INCREF(func);
-		else {
-			func = f(func, self, (PyObject *)(Py_Type(self)));
+		if ((f = Py_Type(func)->tp_descr_get) != NULL) {
+			PyObject *tmp = f(func, self, (PyObject *)(Py_Type(self)));
+			Py_DECREF(func);
+			func = tmp;
 			if (func == NULL) {
 				return NULL;
 			}
@@ -4307,10 +4343,9 @@
 				return retval;
 			}
 		}
-	}
-	else {
+	} else
 		PyErr_SetObject(PyExc_AttributeError, getitem_str);
-	}
+
 	Py_XDECREF(args);
 	Py_XDECREF(ival);
 	Py_XDECREF(func);
@@ -4691,13 +4726,19 @@
 		if (getattribute_str == NULL)
 			return NULL;
 	}
-	getattr = _PyType_Lookup(tp, getattr_str);
+
+	if (_PyType_LookupEx(tp, getattr_str, &getattr) < 0)
+		return NULL;
 	if (getattr == NULL) {
 		/* No __getattr__ hook: use a simpler dispatcher */
 		tp->tp_getattro = slot_tp_getattro;
 		return slot_tp_getattro(self, name);
 	}
-	getattribute = _PyType_Lookup(tp, getattribute_str);
+
+	if (_PyType_LookupEx(tp, getattribute_str, &getattribute) < 0) {
+		Py_DECREF(getattr);
+		return NULL;
+	}
 	if (getattribute == NULL ||
 	    (Py_Type(getattribute) == &PyWrapperDescr_Type &&
 	     ((PyWrapperDescrObject *)getattribute)->d_wrapped ==
@@ -4705,10 +4746,14 @@
 		res = PyObject_GenericGetAttr(self, name);
 	else
 		res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL);
+	Py_XDECREF(getattribute);
+
 	if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
 		PyErr_Clear();
 		res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
 	}
+
+	Py_DECREF(getattr);
 	return res;
 }
 
@@ -4815,7 +4860,7 @@
 slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)
 {
 	PyTypeObject *tp = Py_Type(self);
-	PyObject *get;
+	PyObject *get, *res;
 	static PyObject *get_str = NULL;
 
 	if (get_str == NULL) {
@@ -4823,7 +4868,9 @@
 		if (get_str == NULL)
 			return NULL;
 	}
-	get = _PyType_Lookup(tp, get_str);
+
+	if (_PyType_LookupEx(tp, get_str, &get) < 0)
+		return NULL;
 	if (get == NULL) {
 		/* Avoid further slowdowns */
 		if (tp->tp_descr_get == slot_tp_descr_get)
@@ -4831,11 +4878,15 @@
 		Py_INCREF(self);
 		return self;
 	}
+
 	if (obj == NULL)
 		obj = Py_None;
 	if (type == NULL)
 		type = Py_None;
-	return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);
+
+	res = PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);
+	Py_DECREF(get);
+	return res;
 }
 
 static int
@@ -4914,67 +4965,7 @@
 	return x;
 }
 
-static void
-slot_tp_del(PyObject *self)
-{
-	static PyObject *del_str = NULL;
-	PyObject *del, *res;
-	PyObject *error_type, *error_value, *error_traceback;
 
-	/* Temporarily resurrect the object. */
-	assert(self->ob_refcnt == 0);
-	self->ob_refcnt = 1;
-
-	/* Save the current exception, if any. */
-	PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
-	/* Execute __del__ method, if any. */
-	del = lookup_maybe(self, "__del__", &del_str);
-	if (del != NULL) {
-		res = PyEval_CallObject(del, NULL);
-		if (res == NULL)
-			PyErr_WriteUnraisable(del);
-		else
-			Py_DECREF(res);
-		Py_DECREF(del);
-	}
-
-	/* Restore the saved exception. */
-	PyErr_Restore(error_type, error_value, error_traceback);
-
-	/* Undo the temporary resurrection; can't use DECREF here, it would
-	 * cause a recursive call.
-	 */
-	assert(self->ob_refcnt > 0);
-	if (--self->ob_refcnt == 0)
-		return;	/* this is the normal path out */
-
-	/* __del__ resurrected it!  Make it look like the original Py_DECREF
-	 * never happened.
-	 */
-	{
-		Py_ssize_t refcnt = self->ob_refcnt;
-		_Py_NewReference(self);
-		self->ob_refcnt = refcnt;
-	}
-	assert(!PyType_IS_GC(Py_Type(self)) ||
-	       _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
-	/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
-	 * we need to undo that. */
-	_Py_DEC_REFTOTAL;
-	/* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
-	 * chain, so no more to do there.
-	 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
-	 * _Py_NewReference bumped tp_allocs:  both of those need to be
-	 * undone.
-	 */
-#ifdef COUNT_ALLOCS
-	--Py_Type(self)->tp_frees;
-	--Py_Type(self)->tp_allocs;
-#endif
-}
-
-
 /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
    functions.  The offsets here are relative to the 'PyHeapTypeObject'
    structure, which incorporates the additional structures used for numbers,
@@ -5197,7 +5188,6 @@
 	       "see x.__class__.__doc__ for signature",
 	       PyWrapperFlag_KEYWORDS),
 	TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
-	TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),
 	{NULL}
 };
 
@@ -5302,29 +5292,30 @@
 		return p;
 	}
 	do {
-		descr = _PyType_Lookup(type, p->name_strobj);
+		if (_PyType_LookupEx(type, p->name_strobj, &descr) < 0)
+			Py_FatalError("Lookup failed in update_one_slot.  FIXME: propagate error");
 		if (descr == NULL)
 			continue;
+
 		if (Py_Type(descr) == &PyWrapperDescr_Type) {
 			void **tptr = resolve_slotdups(type, p->name_strobj);
+
 			if (tptr == NULL || tptr == ptr)
 				generic = p->function;
 			d = (PyWrapperDescrObject *)descr;
+
 			if (d->d_base->wrapper == p->wrapper &&
-			    PyType_IsSubtype(type, d->d_type))
-			{
+			    PyType_IsSubtype(type, d->d_type)) {
 				if (specific == NULL ||
 				    specific == d->d_wrapped)
 					specific = d->d_wrapped;
 				else
 					use_generic = 1;
 			}
-		}
-		else if (Py_Type(descr) == &PyCFunction_Type &&
+		} else if (Py_Type(descr) == &PyCFunction_Type &&
 			 PyCFunction_GET_FUNCTION(descr) ==
 			 (PyCFunction)tp_new_wrapper &&
-			 strcmp(p->name, "__new__") == 0)
-		{
+			 strcmp(p->name, "__new__") == 0) {
 			/* The __new__ wrapper is not a wrapper descriptor,
 			   so must be special-cased differently.
 			   If we don't do this, creating an instance will
@@ -5341,11 +5332,12 @@
 			   in this reasoning that requires additional
 			   sanity checks.  I'll buy the first person to
 			   point out a bug in this reasoning a beer. */
-		}
-		else {
+		} else {
 			use_generic = 1;
 			generic = p->function;
 		}
+
+		Py_DECREF(descr);
 	} while ((++p)->offset == offset);
 	if (specific && !use_generic)
 		*ptr = specific;
@@ -5477,6 +5469,7 @@
 	PyObject *ref, *subclasses, *dict;
 	Py_ssize_t i, n;
 
+#if 0
 	subclasses = type->tp_subclasses;
 	if (subclasses == NULL)
 		return 0;
@@ -5492,12 +5485,17 @@
 		assert(PyType_Check(subclass));
 		/* Avoid recursing down into unaffected classes */
 		dict = subclass->tp_dict;
-		if (dict != NULL && PyDict_Check(dict) &&
-		    PyDict_GetItem(dict, name) != NULL)
-			continue;
+		if (dict != NULL && PyDict_Check(dict)) {
+			int status = PyDict_Contains(dict, name);
+			if (status < 0)
+				return -1;
+			if (status > 0)
+				continue;
+		}
 		if (update_subclasses(subclass, name, callback, data) < 0)
 			return -1;
 	}
+#endif
 	return 0;
 }
 
@@ -5505,13 +5503,13 @@
    dictionary with method descriptors for function slots.  For each
    function slot (like tp_repr) that's defined in the type, one or more
    corresponding descriptors are added in the type's tp_dict dictionary
-   under the appropriate name (like __repr__).	Some function slots
+   under the appropriate name (like __repr__).  Some function slots
    cause more than one descriptor to be added (for example, the nb_add
    slot adds both __add__ and __radd__ descriptors) and some function
    slots compete for the same descriptor (for example both sq_item and
    mp_subscript generate a __getitem__ descriptor).
 
-   In the latter case, the first slotdef entry encoutered wins.	 Since
+   In the latter case, the first slotdef entry encoutered wins.  Since
    slotdef entries are sorted by the offset of the slot in the
    PyHeapTypeObject, this gives us some control over disambiguating
    between competing slots: the members of PyHeapTypeObject are listed
@@ -5536,6 +5534,7 @@
 {
 	PyObject *dict = type->tp_dict;
 	slotdef *p;
+	int status;
 	PyObject *descr;
 	void **ptr;
 
@@ -5546,7 +5545,10 @@
 		ptr = slotptr(type, p->offset);
 		if (!ptr || !*ptr)
 			continue;
-		if (PyDict_GetItem(dict, p->name_strobj))
+		status = PyDict_Contains(dict, p->name_strobj);
+		if (status < 0)
+			return -1;
+		if (status > 0)
 			continue;
 		descr = PyDescr_NewWrapper(type, p, *ptr);
 		if (descr == NULL)
@@ -5587,11 +5589,10 @@
 {
 	superobject *su = (superobject *)self;
 
-	_PyObject_GC_UNTRACK(self);
 	Py_XDECREF(su->obj);
 	Py_XDECREF(su->type);
 	Py_XDECREF(su->obj_type);
-	Py_Type(self)->tp_free(self);
+	PyObject_Del(self);
 }
 
 static PyObject *
@@ -5651,9 +5652,9 @@
 				dict = ((PyTypeObject *)tmp)->tp_dict;
 			else
 				continue;
-			res = PyDict_GetItem(dict, name);
+			if (PyDict_GetItemEx(dict, name, &res) < 0)
+				return NULL;
 			if (res != NULL) {
-				Py_INCREF(res);
 				f = Py_Type(res)->tp_descr_get;
 				if (f != NULL) {
 					tmp = f(res,
@@ -5790,7 +5791,7 @@
         if (type == NULL) {
 		/* Call super(), without args -- fill in from __class__
 		   and first local variable on the stack. */
-		PyFrameObject *f = PyThreadState_GET()->frame;
+		PyFrameObject *f = PyThreadState_Get()->frame;
 		PyCodeObject *co = f->f_code;
 		int i, n;
 		if (co == NULL) {
@@ -5913,7 +5914,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
 	super_doc,				/* tp_doc */
 	super_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -5930,7 +5931,5 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	super_init,				/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	PyType_GenericNew,			/* tp_new */
-	PyObject_GC_Del,			/* tp_free */
 };
Index: Objects/dictobject.c
===================================================================
--- Objects/dictobject.c	(revision 58355)
+++ Objects/dictobject.c	(working copy)
@@ -8,6 +8,8 @@
 */
 
 #include "Python.h"
+#include "pystate.h"
+#include "pythread.h"
 
 typedef PyDictEntry dictentry;
 typedef PyDictObject dictobject;
@@ -26,6 +28,132 @@
 	Py_DECREF(tup);
 }
 
+static inline int
+block_unshareable_keyvalue(PyObject *mp, PyObject *key, PyObject *value)
+{
+	if (PySharedDict_Check(mp) && !PyObject_IsShareable(key)) {
+		PyErr_Format(PyExc_TypeError,
+			"%.200s key must be shareable, "
+			"'%s' object is not",
+			mp->ob_type->tp_name, key->ob_type->tp_name);
+		return 1;
+	}
+	if (PySharedDict_Check(mp) && !PyObject_IsShareable(value)) {
+		PyErr_Format(PyExc_TypeError,
+			"%.200s value must be shareable, "
+			"'%s' object is not",
+			mp->ob_type->tp_name, value->ob_type->tp_name);
+		return 1;
+	}
+	return 0;
+}
+
+void
+_pydictlock_initstate_read(PyDict_LockState *lockstate)
+{
+    lockstate->doing_write = 0;
+    lockstate->skipped_lock = 0;
+}
+
+void
+_pydictlock_initstate_write(PyDict_LockState *lockstate)
+{
+    lockstate->doing_write = 1;
+    lockstate->skipped_lock = 0;
+}
+
+void
+_pydictlock_initstate_notshared(PyDict_LockState *lockstate)
+{
+    lockstate->doing_write = -1;
+    lockstate->skipped_lock = -1;
+}
+
+void
+_pydictlock_acquire(PyDictObject *mp, PyDict_LockState *lockstate)
+{
+    /* XXX FIXME this should allow a NULL lockstate if mp isn't a shareddict */
+    assert(lockstate);
+
+    if (PySharedDict_Check(mp)) {
+        PySharedDictObject *sd = (PySharedDictObject *)mp;
+        assert(lockstate->doing_write == 0 || lockstate->doing_write == 1);
+        assert(lockstate->skipped_lock == 0 || lockstate->skipped_lock == 1);
+
+        if (lockstate->doing_write) {
+            assert(!lockstate->skipped_lock);
+            PyCritical_Enter(sd->crit);
+
+            /* If the shareddict has entered readonly mode we use this
+             * expensive fallback to reset it.  This *should* be fairly
+             * rare. */
+            while (AO_load_acquire(&sd->readonly_mode)) {
+                PyCritical_Exit(sd->crit);
+                PyState_StopTheWorld();
+                AO_store_full(&sd->readonly_mode, 0);
+                sd->read_count = 0;
+                PyState_StartTheWorld();
+                PyCritical_Enter(sd->crit);
+            }
+
+            sd->read_count = 0;
+        } else {
+            /* XXX FIXME this should use a stack-allocated critical
+             * section if not using a real one */
+            if (AO_load_acquire(&sd->readonly_mode))
+                lockstate->skipped_lock = 1;
+            else {
+                PyCritical_Enter(sd->crit);
+                if (AO_load_acquire(&sd->readonly_mode)) {
+                    lockstate->skipped_lock = 1;
+                    PyCritical_Exit(sd->crit);
+                } else {
+                    sd->read_count++;
+                    //printf("Read count %d\n", sd->read_count);
+                    sd->read_count = 1;  /* XXX FIXME currently disabled */
+                    if (sd->read_count >= 10000) {
+                        /* Enter read-only mode */
+                        printf("Entering read-only mode%d\n", sd->read_count);
+                        AO_store_full(&sd->readonly_mode, 1);
+                        PyCritical_Exit(sd->crit);
+                        lockstate->skipped_lock = 1;
+                    } else
+                        lockstate->skipped_lock = 0;
+                }
+            }
+        }
+    }
+
+    /* It is an invariant that acquire/release are not called while the
+     * dict would need to be resized. */
+    assert(!(mp->ma_fill*3 >= (mp->ma_mask+1)*2));
+}
+
+void
+_pydictlock_release(PyDictObject *mp, PyDict_LockState *lockstate)
+{
+    assert(lockstate);
+
+    /* It is an invariant that acquire/release are not called while the
+     * dict would need to be resized. */
+    assert(!(mp->ma_fill*3 >= (mp->ma_mask+1)*2));
+
+    if (PySharedDict_Check(mp)) {
+        PySharedDictObject *sd = (PySharedDictObject *)mp;
+        assert(lockstate->doing_write == 0 || lockstate->doing_write == 1);
+        assert(lockstate->skipped_lock == 0 || lockstate->skipped_lock == 1);
+
+        if (lockstate->doing_write) {
+            assert(!lockstate->skipped_lock);
+            PyCritical_Exit(sd->crit);
+        } else {
+            /* XXX FIXME exit stack-allocated critical */
+            if (!lockstate->skipped_lock)
+                PyCritical_Exit(sd->crit);
+        }
+    }
+}
+
 /* Define this out if you don't want conversion statistics on exit. */
 #undef SHOW_CONVERSION_COUNTS
 
@@ -149,7 +277,8 @@
 
 /* forward declarations */
 static dictentry *
-lookdict_unicode(dictobject *mp, PyObject *key, long hash);
+lookdict_unicode(dictobject *mp, PyObject *key, long hash,
+    PyDict_LockState *lockstate);
 
 #ifdef SHOW_CONVERSION_COUNTS
 static long created = 0L;
@@ -181,13 +310,20 @@
 #define EMPTY_TO_MINSIZE(mp) do {					\
 	memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable));	\
 	(mp)->ma_used = (mp)->ma_fill = 0;				\
+	(mp)->ma_rebuilds = 0;						\
 	INIT_NONZERO_DICT_SLOTS(mp);					\
     } while(0)
 
+//#define USE_DICT_FREELIST
+
+#ifdef USE_DICT_FREELIST
 /* Dictionary reuse scheme to save calls to malloc, free, and memset */
 #define MAXFREEDICTS 80
 static PyDictObject *free_dicts[MAXFREEDICTS];
 static int num_free_dicts = 0;
+/* This lock is only used while the GIL is already held */
+static PyThread_type_lock free_dicts_lock;
+#endif
 
 PyObject *
 PyDict_New(void)
@@ -201,8 +337,11 @@
 		Py_AtExit(show_counts);
 #endif
 	}
+#ifdef USE_DICT_FREELIST
+	PyThread_lock_acquire(free_dicts_lock);
 	if (num_free_dicts) {
 		mp = free_dicts[--num_free_dicts];
+		PyThread_lock_release(free_dicts_lock);
 		assert (mp != NULL);
 		assert (Py_Type(mp) == &PyDict_Type);
 		_Py_NewReference((PyObject *)mp);
@@ -213,16 +352,19 @@
 		assert (mp->ma_table == mp->ma_smalltable);
 		assert (mp->ma_mask == PyDict_MINSIZE - 1);
 	} else {
-		mp = PyObject_GC_New(dictobject, &PyDict_Type);
+		PyThread_lock_release(free_dicts_lock);
+#endif
+		mp = PyObject_NEW(dictobject, &PyDict_Type);
 		if (mp == NULL)
 			return NULL;
 		EMPTY_TO_MINSIZE(mp);
+#ifdef USE_DICT_FREELIST
 	}
+#endif
 	mp->ma_lookup = lookdict_unicode;
 #ifdef SHOW_CONVERSION_COUNTS
 	++created;
 #endif
-	_PyObject_GC_TRACK(mp);
 	return (PyObject *)mp;
 }
 
@@ -251,17 +393,23 @@
 dictentry*.
 */
 static dictentry *
-lookdict(dictobject *mp, PyObject *key, register long hash)
+lookdict(dictobject *mp, PyObject *key, register long hash,
+		PyDict_LockState *lockstate)
 {
 	register size_t i;
 	register size_t perturb;
 	register dictentry *freeslot;
-	register size_t mask = (size_t)mp->ma_mask;
-	dictentry *ep0 = mp->ma_table;
+	register size_t mask;
+	dictentry *ep0;
 	register dictentry *ep;
 	register int cmp;
 	PyObject *startkey;
+	unsigned long long rebuilds;
 
+start:
+	mask = (size_t)mp->ma_mask;
+	ep0 = mp->ma_table;
+	rebuilds = mp->ma_rebuilds;
 	i = (size_t)hash & mask;
 	ep = &ep0[i];
 	if (ep->me_key == NULL || ep->me_key == key)
@@ -272,21 +420,33 @@
 	else {
 		if (ep->me_hash == hash) {
 			startkey = ep->me_key;
+			Py_INCREF(startkey);
+			_pydictlock_release(mp, lockstate);
 			cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
-			if (cmp < 0)
+			_pydictlock_acquire(mp, lockstate);
+			if (cmp < 0) {
+				_pydictlock_release(mp, lockstate);
+				Py_DECREF(startkey);
+				_pydictlock_acquire(mp, lockstate);
 				return NULL;
-			if (ep0 == mp->ma_table && ep->me_key == startkey) {
-				if (cmp > 0)
-					return ep;
 			}
-			else {
+			/* XXX use branch hinting? */
+			if (rebuilds != mp->ma_rebuilds || ep->me_key != startkey) {
 				/* The compare did major nasty stuff to the
 				 * dict:  start over.
 				 * XXX A clever adversary could prevent this
 				 * XXX from terminating.
- 				 */
- 				return lookdict(mp, key, hash);
- 			}
+				 */
+				_pydictlock_release(mp, lockstate);
+				Py_DECREF(startkey);
+				_pydictlock_acquire(mp, lockstate);
+				goto start;
+			}
+			assert(ep0 == mp->ma_table);
+			assert(mask == (size_t)mp->ma_mask);
+			Py_DECREF(startkey);
+			if (cmp > 0)
+				return ep;
 		}
 		freeslot = NULL;
 	}
@@ -302,21 +462,33 @@
 			return ep;
 		if (ep->me_hash == hash && ep->me_key != dummy) {
 			startkey = ep->me_key;
+			Py_INCREF(startkey);
+			_pydictlock_release(mp, lockstate);
 			cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
-			if (cmp < 0)
+			_pydictlock_acquire(mp, lockstate);
+			if (cmp < 0) {
+				_pydictlock_release(mp, lockstate);
+				Py_DECREF(startkey);
+				_pydictlock_acquire(mp, lockstate);
 				return NULL;
-			if (ep0 == mp->ma_table && ep->me_key == startkey) {
-				if (cmp > 0)
-					return ep;
 			}
-			else {
+			/* XXX use branch hinting? */
+			if (rebuilds != mp->ma_rebuilds || ep->me_key != startkey) {
 				/* The compare did major nasty stuff to the
 				 * dict:  start over.
 				 * XXX A clever adversary could prevent this
 				 * XXX from terminating.
  				 */
- 				return lookdict(mp, key, hash);
- 			}
+				_pydictlock_release(mp, lockstate);
+				Py_DECREF(startkey);
+				_pydictlock_acquire(mp, lockstate);
+				goto start;
+			}
+			Py_DECREF(startkey);
+			assert(ep0 == mp->ma_table);
+			assert(mask == (size_t)mp->ma_mask);
+			if (cmp > 0)
+				return ep;
 		}
 		else if (ep->me_key == dummy && freeslot == NULL)
 			freeslot = ep;
@@ -355,7 +527,8 @@
  * This is valuable because dicts with only unicode keys are very common.
  */
 static dictentry *
-lookdict_unicode(dictobject *mp, PyObject *key, register long hash)
+lookdict_unicode(dictobject *mp, PyObject *key, register long hash,
+		PyDict_LockState *lockstate)
 {
 	register size_t i;
 	register size_t perturb;
@@ -364,6 +537,8 @@
 	dictentry *ep0 = mp->ma_table;
 	register dictentry *ep;
 
+	assert(lockstate);
+
 	/* Make sure this function doesn't have to handle non-unicode keys,
 	   including subclasses of str; e.g., one reason to subclass
 	   unicodes is to override __eq__, and for speed we don't cater to
@@ -373,7 +548,7 @@
 		++converted;
 #endif
 		mp->ma_lookup = lookdict;
-		return lookdict(mp, key, hash);
+		return lookdict(mp, key, hash, lockstate);
 	}
 	i = hash & mask;
 	ep = &ep0[i];
@@ -413,26 +588,31 @@
 Returns -1 if an error occurred, or 0 on success.
 */
 static int
-insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
+insertdict(register dictobject *mp, PyObject *key, long hash,
+		PyObject *value, PyDict_LockState *lockstate)
 {
 	PyObject *old_value;
 	register dictentry *ep;
 	typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long);
 
 	assert(mp->ma_lookup != NULL);
-	ep = mp->ma_lookup(mp, key, hash);
+	ep = mp->ma_lookup(mp, key, hash, lockstate);
 	if (ep == NULL) {
+		_pydictlock_release(mp, lockstate);
 		Py_DECREF(key);
 		Py_DECREF(value);
+		_pydictlock_acquire(mp, lockstate);
 		return -1;
 	}
+
 	if (ep->me_value != NULL) {
 		old_value = ep->me_value;
 		ep->me_value = value;
+		_pydictlock_release(mp, lockstate);
 		Py_DECREF(old_value); /* which **CAN** re-enter */
 		Py_DECREF(key);
-	}
-	else {
+		_pydictlock_acquire(mp, lockstate);
+	} else {
 		if (ep->me_key == NULL)
 			mp->ma_fill++;
 		else {
@@ -545,6 +725,7 @@
 	mp->ma_used = 0;
 	i = mp->ma_fill;
 	mp->ma_fill = 0;
+	mp->ma_rebuilds++;
 
 	/* Copy the data over; this is refcount-neutral for active entries;
 	   dummy entries aren't copied over, of course */
@@ -580,10 +761,12 @@
 PyObject *
 PyDict_GetItem(PyObject *op, PyObject *key)
 {
+	PyThreadState *tstate = PyThreadState_Get();
 	long hash;
 	dictobject *mp = (dictobject *)op;
 	dictentry *ep;
-	PyThreadState *tstate;
+	PyDict_LockState lockstate;
+
 	if (!PyDict_Check(op))
 		return NULL;
 	if (!PyUnicode_CheckExact(key) ||
@@ -596,22 +779,24 @@
 		}
 	}
 
+	_pydictlock_initstate_notshared(&lockstate);
+
 	/* We can arrive here with a NULL tstate during initialization:
 	   try running "python -Wi" for an example related to string
 	   interning.  Let's just hope that no exception occurs then... */
-	tstate = _PyThreadState_Current;
+	/* XXX It's now impossible to have a NULL tstate */
 	if (tstate != NULL && tstate->curexc_type != NULL) {
 		/* preserve the existing exception */
 		PyObject *err_type, *err_value, *err_tb;
 		PyErr_Fetch(&err_type, &err_value, &err_tb);
-		ep = (mp->ma_lookup)(mp, key, hash);
+		ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
 		/* ignore errors */
 		PyErr_Restore(err_type, err_value, err_tb);
 		if (ep == NULL)
 			return NULL;
 	}
 	else {
-		ep = (mp->ma_lookup)(mp, key, hash);
+		ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
 		if (ep == NULL) {
 			PyErr_Clear();
 			return NULL;
@@ -630,6 +815,7 @@
 	long hash;
 	dictobject *mp = (dictobject *)op;
 	dictentry *ep;
+	PyDict_LockState lockstate;
 
 	if (!PyDict_Check(op)) {
 		PyErr_BadInternalCall();
@@ -644,12 +830,60 @@
 		}
 	}
 
-	ep = (mp->ma_lookup)(mp, key, hash);
+	_pydictlock_initstate_notshared(&lockstate);
+
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
 	if (ep == NULL)
 		return NULL;
 	return ep->me_value;
 }
 
+/* Yet another variant of PyDict_GetItem().  Return values:
+ * -1 Error, exception set (value set to NULL)
+ *  0 Success (value filled in with *NEW* reference)
+ * +1 Not found, no exception set (value set to NULL)
+ */
+int
+PyDict_GetItemEx(PyObject *op, PyObject *key, PyObject **value)
+{
+    long hash;
+    dictobject *mp = (dictobject *)op;
+    dictentry *ep;
+    PyDict_LockState lockstate;
+
+    *value = NULL;
+
+    if (!PyDict_Check(op)) {
+        PyErr_BadInternalCall();
+        return -1;
+    }
+    if (!PyUnicode_CheckExact(key) ||
+            (hash = ((PyUnicodeObject *) key)->hash) == -1) {
+        hash = PyObject_Hash(key);
+        if (hash == -1) {
+            return -1;
+        }
+    }
+
+    _pydictlock_initstate_read(&lockstate);
+
+    _pydictlock_acquire(mp, &lockstate);
+    ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+    if (ep == NULL) {
+        _pydictlock_release(mp, &lockstate);
+        return -1;
+    }
+
+    *value = ep->me_value;
+    Py_XINCREF(*value);
+    _pydictlock_release(mp, &lockstate);
+
+    if (*value)
+        return 0;
+    else
+        return 1;
+}
+
 /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
  * dictionary if it's merely replacing the value for an existing key.
  * This means that it's safe to loop over a dictionary with PyDict_Next()
@@ -659,9 +893,12 @@
 int
 PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
 {
+	PyThreadState *tstate = PyThreadState_Get();
 	register dictobject *mp;
 	register long hash;
 	register Py_ssize_t n_used;
+	PyDict_LockState lockstate;
+	int result;
 
 	if (!PyDict_Check(op)) {
 		PyErr_BadInternalCall();
@@ -670,19 +907,26 @@
 	assert(key);
 	assert(value);
 	mp = (dictobject *)op;
+	if (block_unshareable_keyvalue(op, key, value))
+		return -1;
 	if (!PyUnicode_CheckExact(key) ||
-	    (hash = ((PyUnicodeObject *) key)->hash) == -1)
-	{
+			(hash = ((PyUnicodeObject *) key)->hash) == -1) {
 		hash = PyObject_Hash(key);
 		if (hash == -1)
 			return -1;
 	}
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 	assert(mp->ma_fill <= mp->ma_mask);  /* at least one empty slot */
 	n_used = mp->ma_used;
-	Py_INCREF(value);
-	Py_INCREF(key);
-	if (insertdict(mp, key, hash, value) != 0)
+	Py_INCREFTS(value);
+	Py_INCREFTS(key);
+	if (insertdict(mp, key, hash, value, &lockstate) != 0) {
+		_pydictlock_release(mp, &lockstate);
 		return -1;
+	}
+
 	/* If we added a key, we can safely resize.  Otherwise just return!
 	 * If fill >= 2/3 size, adjust size.  Normally, this doubles or
 	 * quaduples the size, but it's also possible for the dict to shrink
@@ -697,9 +941,13 @@
 	 * Very large dictionaries (over 50K items) use doubling instead.
 	 * This may help applications with severe memory constraints.
 	 */
-	if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))
+	if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2)) {
+		_pydictlock_release(mp, &lockstate);
 		return 0;
-	return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used);
+	}
+	result = dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used);
+	_pydictlock_release(mp, &lockstate);
+	return result;
 }
 
 int
@@ -709,6 +957,7 @@
 	register long hash;
 	register dictentry *ep;
 	PyObject *old_value, *old_key;
+	PyDict_LockState lockstate;
 
 	if (!PyDict_Check(op)) {
 		PyErr_BadInternalCall();
@@ -722,10 +971,16 @@
 			return -1;
 	}
 	mp = (dictobject *)op;
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	if (ep == NULL) {
+		_pydictlock_release(mp, &lockstate);
 		return -1;
+	}
 	if (ep->me_value == NULL) {
+		_pydictlock_release(mp, &lockstate);
 		set_key_error(key);
 		return -1;
 	}
@@ -735,6 +990,7 @@
 	old_value = ep->me_value;
 	ep->me_value = NULL;
 	mp->ma_used--;
+	_pydictlock_release(mp, &lockstate);
 	Py_DECREF(old_value);
 	Py_DECREF(old_key);
 	return 0;
@@ -751,10 +1007,14 @@
 #ifdef Py_DEBUG
 	Py_ssize_t i, n;
 #endif
+	PyDict_LockState lockstate;
 
 	if (!PyDict_Check(op))
 		return;
 	mp = (dictobject *)op;
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 #ifdef Py_DEBUG
 	n = mp->ma_mask + 1;
 	i = 0;
@@ -784,6 +1044,7 @@
 		EMPTY_TO_MINSIZE(mp);
 	}
 	/* else it's a small table that's already empty */
+	_pydictlock_release(mp, &lockstate);
 
 	/* Now we can finally clear things.  If C had refcounts, we could
 	 * assert that the refcount on table is 1 now, i.e. that this function
@@ -830,12 +1091,18 @@
 	register Py_ssize_t i;
 	register Py_ssize_t mask;
 	register dictentry *ep;
+	PyDict_LockState lockstate;
 
 	if (!PyDict_Check(op))
 		return 0;
 	i = *ppos;
 	if (i < 0)
 		return 0;
+
+	_pydictlock_initstate_notshared(&lockstate);
+	_pydictlock_acquire((dictobject *)op, &lockstate);
+	_pydictlock_release((dictobject *)op, &lockstate);
+
 	ep = ((dictobject *)op)->ma_table;
 	mask = ((dictobject *)op)->ma_mask;
 	while (i <= mask && ep[i].me_value == NULL)
@@ -857,12 +1124,18 @@
 	register Py_ssize_t i;
 	register Py_ssize_t mask;
 	register dictentry *ep;
+	PyDict_LockState lockstate;
 
 	if (!PyDict_Check(op))
 		return 0;
 	i = *ppos;
 	if (i < 0)
 		return 0;
+
+	_pydictlock_initstate_notshared(&lockstate);
+	_pydictlock_acquire((dictobject *)op, &lockstate);
+	_pydictlock_release((dictobject *)op, &lockstate);
+
 	ep = ((dictobject *)op)->ma_table;
 	mask = ((dictobject *)op)->ma_mask;
 	while (i <= mask && ep[i].me_value == NULL)
@@ -878,6 +1151,47 @@
 	return 1;
 }
 
+/* Variant of PyDict_Next that provides *NEW* references to key and value */
+int
+PyDict_NextEx(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
+{
+	register Py_ssize_t i;
+	register Py_ssize_t mask;
+	register dictentry *ep;
+	PyDict_LockState lockstate;
+
+	if (!PyDict_Check(op))
+		return 0;
+	i = *ppos;
+	if (i < 0)
+		return 0;
+
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire((dictobject *)op, &lockstate);
+	ep = ((dictobject *)op)->ma_table;
+	mask = ((dictobject *)op)->ma_mask;
+	while (i <= mask && ep[i].me_value == NULL)
+		i++;
+	*ppos = i+1;
+	if (i > mask) {
+		_pydictlock_release((dictobject *)op, &lockstate);
+		return 0;
+	}
+
+	if (pkey) {
+		*pkey = ep[i].me_key;
+		Py_INCREF(*pkey);
+	}
+	if (pvalue) {
+		*pvalue = ep[i].me_value;
+		Py_INCREF(*pvalue);
+	}
+
+	_pydictlock_release((dictobject *)op, &lockstate);
+	return 1;
+}
+
 /* Methods */
 
 static void
@@ -885,8 +1199,6 @@
 {
 	register dictentry *ep;
 	Py_ssize_t fill = mp->ma_fill;
- 	PyObject_GC_UnTrack(mp);
-	Py_TRASHCAN_SAFE_BEGIN(mp)
 	for (ep = mp->ma_table; fill > 0; ep++) {
 		if (ep->me_key) {
 			--fill;
@@ -896,13 +1208,27 @@
 	}
 	if (mp->ma_table != mp->ma_smalltable)
 		PyMem_DEL(mp->ma_table);
-	if (num_free_dicts < MAXFREEDICTS && Py_Type(mp) == &PyDict_Type)
+#ifdef USE_DICT_FREELIST
+	PyThread_lock_acquire(free_dicts_lock);
+	if (num_free_dicts < MAXFREEDICTS && Py_Type(mp) == &PyDict_Type) {
 		free_dicts[num_free_dicts++] = mp;
-	else
-		Py_Type(mp)->tp_free((PyObject *)mp);
-	Py_TRASHCAN_SAFE_END(mp)
+		PyThread_lock_release(free_dicts_lock);
+	} else {
+		PyThread_lock_release(free_dicts_lock);
+#endif
+		PyObject_DEL(mp);
+#ifdef USE_DICT_FREELIST
+	}
+#endif
 }
 
+static void
+shareddict_dealloc(PySharedDictObject *mp)
+{
+    PyCritical_Free(mp->crit);
+    dict_dealloc((PyDictObject *)mp);
+}
+
 static PyObject *
 dict_repr(dictobject *mp)
 {
@@ -932,13 +1258,12 @@
 	/* Do repr() on each key+value pair, and insert ": " between them.
 	   Note that repr may mutate the dict. */
 	i = 0;
-	while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
+	while (PyDict_NextEx((PyObject *)mp, &i, &key, &value)) {
 		int status;
-		/* Prevent repr from deleting value during key format. */
-		Py_INCREF(value);
 		s = PyObject_Repr(key);
 		PyUnicode_Append(&s, colon);
 		PyUnicode_AppendAndDel(&s, PyObject_Repr(value));
+		Py_DECREF(key);
 		Py_DECREF(value);
 		if (s == NULL)
 			goto Done;
@@ -982,10 +1307,54 @@
 	return result;
 }
 
+static PyObject *
+shareddict_repr(dictobject *mp)
+{
+	PyObject *s = NULL, *inner = NULL, *name = NULL, *format = NULL;
+	PyObject *t = NULL;
+
+	format = PyString_FromString("%s(%s)");
+	if (format == NULL)
+		goto Done;
+
+	name = PyObject_GetAttrString((PyObject *)Py_Type(mp), "__name__");
+	if (name == NULL)
+		goto Done;
+
+	inner = dict_repr(mp);
+	if (inner == NULL)
+		goto Done;
+
+	t = PyTuple_New(2);
+	if (t == NULL)
+		goto Done;
+	PyTuple_SET_ITEM(t, 0, name);
+	name = NULL;
+	PyTuple_SET_ITEM(t, 1, inner);
+	inner = NULL;
+
+	s = PyString_Format(format, t);
+
+Done:
+	Py_XDECREF(format);
+	Py_XDECREF(name);
+	Py_XDECREF(inner);
+	Py_XDECREF(t);
+	return s;
+}
+
 static Py_ssize_t
 dict_length(dictobject *mp)
 {
-	return mp->ma_used;
+    Py_ssize_t len;
+    PyDict_LockState lockstate;
+
+    _pydictlock_initstate_read(&lockstate);
+    _pydictlock_acquire(mp, &lockstate);
+    len = mp->ma_used;
+    _pydictlock_release(mp, &lockstate);
+
+    return len;
 }
 
 static PyObject *
@@ -994,35 +1363,51 @@
 	PyObject *v;
 	long hash;
 	dictentry *ep;
-	assert(mp->ma_table != NULL);
+	PyDict_LockState lockstate;
+
 	if (!PyUnicode_CheckExact(key) ||
 	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
 		hash = PyObject_Hash(key);
 		if (hash == -1)
 			return NULL;
 	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
+
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
+	assert(mp->ma_table != NULL);
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	if (ep == NULL) {
+		_pydictlock_release(mp, &lockstate);
 		return NULL;
+	}
 	v = ep->me_value;
 	if (v == NULL) {
+		_pydictlock_release(mp, &lockstate);
 		if (!PyDict_CheckExact(mp)) {
 			/* Look up __missing__ method if we're a subclass. */
-		    	PyObject *missing;
+			PyObject *missing;
 			static PyObject *missing_str = NULL;
+
 			if (missing_str == NULL)
 				missing_str =
 				  PyUnicode_InternFromString("__missing__");
-			missing = _PyType_Lookup(Py_Type(mp), missing_str);
-			if (missing != NULL)
-				return PyObject_CallFunctionObjArgs(missing,
+
+			if (_PyType_LookupEx(Py_Type(mp), missing_str, &missing) < 0)
+				return NULL;
+			if (missing != NULL) {
+				v = PyObject_CallFunctionObjArgs(missing,
 					(PyObject *)mp, key, NULL);
+				Py_DECREF(missing);
+				return v;
+			}
 		}
 		set_key_error(key);
 		return NULL;
+	} else {
+		Py_INCREF(v);
+		_pydictlock_release(mp, &lockstate);
 	}
-	else
-		Py_INCREF(v);
 	return v;
 }
 
@@ -1048,19 +1433,29 @@
 	register Py_ssize_t i, j;
 	dictentry *ep;
 	Py_ssize_t mask, n;
+	PyDict_LockState lockstate;
+	unsigned long long rebuilds;
 
   again:
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 	n = mp->ma_used;
+	rebuilds = mp->ma_rebuilds;
+	_pydictlock_release(mp, &lockstate);
 	v = PyList_New(n);
 	if (v == NULL)
 		return NULL;
-	if (n != mp->ma_used) {
+	_pydictlock_acquire(mp, &lockstate);
+	if (rebuilds != mp->ma_rebuilds) {
+		_pydictlock_release(mp, &lockstate);
 		/* Durnit.  The allocations caused the dict to resize.
 		 * Just start over, this shouldn't normally happen.
 		 */
 		Py_DECREF(v);
 		goto again;
 	}
+	assert(n == mp->ma_used);
 	ep = mp->ma_table;
 	mask = mp->ma_mask;
 	for (i = 0, j = 0; i <= mask; i++) {
@@ -1072,6 +1467,7 @@
 		}
 	}
 	assert(j == n);
+	_pydictlock_release(mp, &lockstate);
 	return v;
 }
 
@@ -1082,19 +1478,29 @@
 	register Py_ssize_t i, j;
 	dictentry *ep;
 	Py_ssize_t mask, n;
+	PyDict_LockState lockstate;
+	unsigned long long rebuilds;
 
   again:
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 	n = mp->ma_used;
+	rebuilds = mp->ma_rebuilds;
+	_pydictlock_release(mp, &lockstate);
 	v = PyList_New(n);
 	if (v == NULL)
 		return NULL;
-	if (n != mp->ma_used) {
+	_pydictlock_acquire(mp, &lockstate);
+	if (rebuilds != mp->ma_rebuilds) {
+		_pydictlock_release(mp, &lockstate);
 		/* Durnit.  The allocations caused the dict to resize.
 		 * Just start over, this shouldn't normally happen.
 		 */
 		Py_DECREF(v);
 		goto again;
 	}
+	assert(n == mp->ma_used);
 	ep = mp->ma_table;
 	mask = mp->ma_mask;
 	for (i = 0, j = 0; i <= mask; i++) {
@@ -1106,6 +1512,7 @@
 		}
 	}
 	assert(j == n);
+	_pydictlock_release(mp, &lockstate);
 	return v;
 }
 
@@ -1117,13 +1524,20 @@
 	Py_ssize_t mask;
 	PyObject *item, *key, *value;
 	dictentry *ep;
+	PyDict_LockState lockstate;
+	unsigned long long rebuilds;
 
+  again:
+	_pydictlock_initstate_read(&lockstate);
+
 	/* Preallocate the list of tuples, to avoid allocations during
 	 * the loop over the items, which could trigger GC, which
 	 * could resize the dict. :-(
 	 */
-  again:
+	_pydictlock_acquire(mp, &lockstate);
 	n = mp->ma_used;
+	rebuilds = mp->ma_rebuilds;
+	_pydictlock_release(mp, &lockstate);
 	v = PyList_New(n);
 	if (v == NULL)
 		return NULL;
@@ -1135,7 +1549,9 @@
 		}
 		PyList_SET_ITEM(v, i, item);
 	}
-	if (n != mp->ma_used) {
+	_pydictlock_acquire(mp, &lockstate);
+	if (rebuilds != mp->ma_rebuilds) {
+		_pydictlock_release(mp, &lockstate);
 		/* Durnit.  The allocations caused the dict to resize.
 		 * Just start over, this shouldn't normally happen.
 		 */
@@ -1143,6 +1559,7 @@
 		goto again;
 	}
 	/* Nothing we do below makes any function calls. */
+	assert(n == mp->ma_used);
 	ep = mp->ma_table;
 	mask = mp->ma_mask;
 	for (i = 0, j = 0; i <= mask; i++) {
@@ -1157,6 +1574,7 @@
 		}
 	}
 	assert(j == n);
+	_pydictlock_release(mp, &lockstate);
 	return v;
 }
 
@@ -1173,6 +1591,8 @@
 	if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value))
 		return NULL;
 
+	assert(PyType_Check(cls));
+
 	d = PyObject_CallObject(cls, NULL);
 	if (d == NULL)
 		return NULL;
@@ -1182,15 +1602,20 @@
 		Py_ssize_t pos = 0;
 		PyObject *key;
 		long hash;
+		PyDict_LockState lockstate;
 
+		_pydictlock_initstate_notshared(&lockstate);
+
 		if (dictresize(mp, PySet_GET_SIZE(seq)))
 			return NULL;
 
 		while (_PySet_NextEntry(seq, &pos, &key, &hash)) {
 			Py_INCREF(key);
 			Py_INCREF(value);
-			if (insertdict(mp, key, hash, value))
+			if (insertdict(mp, key, hash, value, &lockstate)) {
+				Py_DECREF(d);
 				return NULL;
+			}
 		}
 		return d;
 	}
@@ -1224,7 +1649,8 @@
 }
 
 static int
-dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)
+dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
+		char *methname)
 {
 	PyObject *arg = NULL;
 	int result = 0;
@@ -1258,7 +1684,7 @@
    PyDict_{Update,Merge} update/merge from a mapping object.
 
    PyDict_MergeFromSeq2 updates/merges from any iterable object
-   producing iterable objects of length 2.
+   that produces iterable objects of length 2.
 */
 
 int
@@ -1280,6 +1706,7 @@
 	for (i = 0; ; ++i) {
 		PyObject *key, *value;
 		Py_ssize_t n;
+		int status;
 
 		fast = NULL;
 		item = PyIter_Next(it);
@@ -1311,10 +1738,16 @@
 		/* Update/merge with this (key, value) pair. */
 		key = PySequence_Fast_GET_ITEM(fast, 0);
 		value = PySequence_Fast_GET_ITEM(fast, 1);
-		if (override || PyDict_GetItem(d, key) == NULL) {
-			int status = PyDict_SetItem(d, key, value);
+		if (override) {
+			status = PyDict_SetItem(d, key, value);
 			if (status < 0)
 				goto Fail;
+		} else if ((status = PyDict_Contains(d, key))) {
+			if (status < 0)
+				goto Fail;
+			status = PyDict_SetItem(d, key, value);
+			if (status < 0)
+				goto Fail;
 		}
 		Py_DECREF(fast);
 		Py_DECREF(item);
@@ -1340,10 +1773,6 @@
 int
 PyDict_Merge(PyObject *a, PyObject *b, int override)
 {
-	register PyDictObject *mp, *other;
-	register Py_ssize_t i;
-	dictentry *entry;
-
 	/* We accept for the argument either a concrete dictionary object,
 	 * or an abstract "mapping" object.  For the former, we can do
 	 * things quite efficiently.  For the latter, we only require that
@@ -1353,9 +1782,17 @@
 		PyErr_BadInternalCall();
 		return -1;
 	}
-	mp = (dictobject*)a;
-	if (PyDict_CheckExact(b)) {
-		other = (dictobject*)b;
+	if (PyDict_CheckExact(b) && !PySharedDict_Check(a)) {
+		register PyDictObject *mp = (PyDictObject *)a;
+		register PyDictObject *other = (PyDictObject *)b;
+		register Py_ssize_t i;
+		dictentry *entry;
+		PyDict_LockState lockstate;
+
+		/* This branch is only used for normal dicts, so no
+		 * locking is necessary */
+		_pydictlock_initstate_notshared(&lockstate);
+
 		if (other == mp || other->ma_used == 0)
 			/* a.update(a) or a.update({}); nothing to do */
 			return 0;
@@ -1378,16 +1815,18 @@
 			if (entry->me_value != NULL &&
 			    (override ||
 			     PyDict_GetItem(a, entry->me_key) == NULL)) {
+				if (block_unshareable_keyvalue(a, entry->me_key,
+						entry->me_value))
+					return -1;
 				Py_INCREF(entry->me_key);
 				Py_INCREF(entry->me_value);
 				if (insertdict(mp, entry->me_key,
 					       (long)entry->me_hash,
-					       entry->me_value) != 0)
+					       entry->me_value, &lockstate) != 0)
 					return -1;
 			}
 		}
-	}
-	else {
+	} else {
 		/* Do it the generic, slower way */
 		PyObject *keys = PyMapping_Keys(b);
 		PyObject *iter;
@@ -1408,7 +1847,11 @@
 			return -1;
 
 		for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
-			if (!override && PyDict_GetItem(a, key) != NULL) {
+			if (!override && (status = PyDict_Contains(a, key))) {
+				if (status < 0) {
+					Py_DECREF(iter);
+					return -1;
+				}
 				Py_DECREF(key);
 				continue;
 			}
@@ -1465,7 +1908,7 @@
 		PyErr_BadInternalCall();
 		return -1;
 	}
-	return ((dictobject *)mp)->ma_used;
+	return dict_length((dictobject *)mp);
 }
 
 PyObject *
@@ -1503,41 +1946,41 @@
  * Uses only Py_EQ comparison.
  */
 static int
-dict_equal(dictobject *a, dictobject *b)
+dict_equal(PyObject *a, PyObject *b)
 {
-	Py_ssize_t i;
+    PyObject *key, *value;
+    Py_ssize_t i;
 
-	if (a->ma_used != b->ma_used)
-		/* can't be equal if # of entries differ */
-		return 0;
+    if (PyDict_Size(a) != PyDict_Size(b))
+        /* can't be equal if # of entries differ */
+        return 0;
 
-	/* Same # of entries -- check all of 'em.  Exit early on any diff. */
-	for (i = 0; i <= a->ma_mask; i++) {
-		PyObject *aval = a->ma_table[i].me_value;
-		if (aval != NULL) {
-			int cmp;
-			PyObject *bval;
-			PyObject *key = a->ma_table[i].me_key;
-			/* temporarily bump aval's refcount to ensure it stays
-			   alive until we're done with it */
-			Py_INCREF(aval);
-			/* ditto for key */
-			Py_INCREF(key);
-			bval = PyDict_GetItemWithError((PyObject *)b, key);
-			Py_DECREF(key);
-			if (bval == NULL) {
-				Py_DECREF(aval);
-				if (PyErr_Occurred())
-					return -1;
-				return 0;
-			}
-			cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
-			Py_DECREF(aval);
-			if (cmp <= 0)  /* error or not equal */
-				return cmp;
- 		}
-	}
-	return 1;
+    /* Same # of entries -- check all of 'em.  Exit early on any diff. */
+    i = 0;
+    while (PyDict_NextEx(a, &i, &key, &value)) {
+        PyObject *bvalue;
+        int cmp;
+
+        if (PyDict_GetItemEx(b, key, &bvalue) < 0) {
+            Py_DECREF(key);
+            Py_DECREF(value);
+            return -1;
+        }
+        if (bvalue == NULL) {
+            Py_DECREF(key);
+            Py_DECREF(value);
+            return 0;
+        }
+
+        cmp = PyObject_RichCompareBool(value, bvalue, Py_EQ);
+        Py_DECREF(key);
+        Py_DECREF(value);
+        Py_DECREF(bvalue);
+        if (cmp <= 0)  /* error or not equal */
+            return cmp;
+    }
+
+    return 1;
  }
 
 static PyObject *
@@ -1550,7 +1993,7 @@
 		res = Py_NotImplemented;
 	}
 	else if (op == Py_EQ || op == Py_NE) {
-		cmp = dict_equal((dictobject *)v, (dictobject *)w);
+		cmp = dict_equal(v, w);
 		if (cmp < 0)
 			return NULL;
 		res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
@@ -1564,47 +2007,37 @@
 static PyObject *
 dict_contains(register dictobject *mp, PyObject *key)
 {
-	long hash;
-	dictentry *ep;
+    PyObject *value;
 
-	if (!PyUnicode_CheckExact(key) ||
-	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
-		hash = PyObject_Hash(key);
-		if (hash == -1)
-			return NULL;
-	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
-		return NULL;
-	return PyBool_FromLong(ep->me_value != NULL);
+    if (PyDict_GetItemEx((PyObject *)mp, key, &value) < 0)
+        return NULL;
+
+    if (value == NULL)
+        return PyBool_FromLong(0);
+    else {
+        Py_DECREF(value);
+        return PyBool_FromLong(1);
+    }
 }
 
 static PyObject *
 dict_get(register dictobject *mp, PyObject *args)
 {
-	PyObject *key;
-	PyObject *failobj = Py_None;
-	PyObject *val = NULL;
-	long hash;
-	dictentry *ep;
+    PyObject *key;
+    PyObject *failobj = Py_None;
+    PyObject *val;
 
-	if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))
-		return NULL;
+    if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))
+        return NULL;
 
-	if (!PyUnicode_CheckExact(key) ||
-	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
-		hash = PyObject_Hash(key);
-		if (hash == -1)
-			return NULL;
-	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
-		return NULL;
-	val = ep->me_value;
-	if (val == NULL)
-		val = failobj;
-	Py_INCREF(val);
-	return val;
+    if (PyDict_GetItemEx((PyObject *)mp, key, &val) < 0)
+        return NULL;
+
+    if (val == NULL) {
+        Py_INCREF(failobj);
+        return failobj;
+    } else
+        return val;
 }
 
 
@@ -1616,6 +2049,7 @@
 	PyObject *val = NULL;
 	long hash;
 	dictentry *ep;
+	PyDict_LockState lockstate;
 
 	if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
 		return NULL;
@@ -1626,16 +2060,32 @@
 		if (hash == -1)
 			return NULL;
 	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
+	if (block_unshareable_keyvalue((PyObject *)mp, key, val))
 		return NULL;
+
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	if (ep == NULL) {
+		_pydictlock_release(mp, &lockstate);
+		return NULL;
+	}
 	val = ep->me_value;
-	if (val == NULL) {
+	if (val != NULL) {
+		Py_INCREF(val);
+		_pydictlock_release(mp, &lockstate);
+	} else {
+		_pydictlock_release(mp, &lockstate);
+		/* XXX FIXME: This uses two separate operations, meaning
+		 * it's not atomic.  This is wrong, but is it important
+		 * enough to fix? */
 		val = failobj;
 		if (PyDict_SetItem((PyObject*)mp, key, failobj))
 			val = NULL;
+		else
+			Py_INCREF(failobj);
 	}
-	Py_XINCREF(val);
 	return val;
 }
 
@@ -1654,10 +2104,23 @@
 	dictentry *ep;
 	PyObject *old_value, *old_key;
 	PyObject *key, *deflt = NULL;
+	PyDict_LockState lockstate;
 
 	if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt))
 		return NULL;
+
+	if (!PyUnicode_CheckExact(key) ||
+	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
+		hash = PyObject_Hash(key);
+		if (hash == -1)
+			return NULL;
+	}
+
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 	if (mp->ma_used == 0) {
+		_pydictlock_release(mp, &lockstate);
 		if (deflt) {
 			Py_INCREF(deflt);
 			return deflt;
@@ -1666,16 +2129,13 @@
 				"pop(): dictionary is empty");
 		return NULL;
 	}
-	if (!PyUnicode_CheckExact(key) ||
-	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
-		hash = PyObject_Hash(key);
-		if (hash == -1)
-			return NULL;
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	if (ep == NULL) {
+		_pydictlock_release(mp, &lockstate);
+		return NULL;
 	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	if (ep == NULL)
-		return NULL;
 	if (ep->me_value == NULL) {
+		_pydictlock_release(mp, &lockstate);
 		if (deflt) {
 			Py_INCREF(deflt);
 			return deflt;
@@ -1689,6 +2149,7 @@
 	old_value = ep->me_value;
 	ep->me_value = NULL;
 	mp->ma_used--;
+	_pydictlock_release(mp, &lockstate);
 	Py_DECREF(old_key);
 	return old_value;
 }
@@ -1699,6 +2160,7 @@
 	Py_ssize_t i = 0;
 	dictentry *ep;
 	PyObject *res;
+	PyDict_LockState lockstate;
 
 	/* Allocate the result tuple before checking the size.  Believe it
 	 * or not, this allocation could trigger a garbage collection which
@@ -1712,7 +2174,12 @@
 	res = PyTuple_New(2);
 	if (res == NULL)
 		return NULL;
+
+	_pydictlock_initstate_write(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
 	if (mp->ma_used == 0) {
+		_pydictlock_release(mp, &lockstate);
 		Py_DECREF(res);
 		PyErr_SetString(PyExc_KeyError,
 				"popitem(): dictionary is empty");
@@ -1748,6 +2215,7 @@
 	mp->ma_used--;
 	assert(mp->ma_table[0].me_value == NULL);
 	mp->ma_table[0].me_hash = i + 1;  /* next place to start */
+	_pydictlock_release(mp, &lockstate);
 	return res;
 }
 
@@ -1861,6 +2329,8 @@
 	long hash;
 	dictobject *mp = (dictobject *)op;
 	dictentry *ep;
+	int res;
+	PyDict_LockState lockstate;
 
 	if (!PyUnicode_CheckExact(key) ||
 	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
@@ -1868,8 +2338,14 @@
 		if (hash == -1)
 			return -1;
 	}
-	ep = (mp->ma_lookup)(mp, key, hash);
-	return ep == NULL ? -1 : (ep->me_value != NULL);
+
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	res = ep == NULL ? -1 : (ep->me_value != NULL);
+	_pydictlock_release(mp, &lockstate);
+	return res;
 }
 
 /* Internal version of PyDict_Contains used when the hash value is already known */
@@ -1878,9 +2354,16 @@
 {
 	dictobject *mp = (dictobject *)op;
 	dictentry *ep;
+	int res;
+	PyDict_LockState lockstate;
 
-	ep = (mp->ma_lookup)(mp, key, hash);
-	return ep == NULL ? -1 : (ep->me_value != NULL);
+	_pydictlock_initstate_read(&lockstate);
+
+	_pydictlock_acquire(mp, &lockstate);
+	ep = (mp->ma_lookup)(mp, key, hash, &lockstate);
+	res = ep == NULL ? -1 : (ep->me_value != NULL);
+	_pydictlock_release(mp, &lockstate);
+	return res;
 }
 
 /* Hack to implement "key in dict" */
@@ -1902,12 +2385,11 @@
 {
 	PyObject *self;
 
-	assert(type != NULL && type->tp_alloc != NULL);
-	self = type->tp_alloc(type, 0);
+	assert(type != NULL);
+	self = PyObject_New(type);
 	if (self != NULL) {
+		const size_t size = _PyObject_SIZE(type);
 		PyDictObject *d = (PyDictObject *)self;
-		/* It's guaranteed that tp->alloc zeroed out the struct. */
-		assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0);
 		INIT_NONZERO_DICT_SLOTS(d);
 		d->ma_lookup = lookdict_unicode;
 #ifdef SHOW_CONVERSION_COUNTS
@@ -1917,6 +2399,27 @@
 	return self;
 }
 
+static PyObject *
+shareddict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PySharedDictObject *self = (PySharedDictObject *)dict_new(
+        type, args, kwds);
+
+    if (self == NULL)
+        return NULL;
+
+    self->readonly_mode = 0;
+    self->read_count = 0;
+    self->crit = PyCritical_Allocate(PyCRITICAL_NORMAL);
+    if (self->crit == NULL) {
+        Py_DECREF(self);
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    return (PyObject *)self;
+}
+
 static int
 dict_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
@@ -1929,6 +2432,12 @@
 	return dictiter_new(dict, &PyDictIterKey_Type);
 }
 
+static int
+shareddict_isshareable (PyObject *self)
+{
+	return 1;
+}
+
 PyDoc_STRVAR(dictionary_doc,
 "dict() -> new empty dictionary.\n"
 "dict(mapping) -> new dictionary initialized from a mapping object's\n"
@@ -1961,7 +2470,8 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE, /* tp_flags */
 	dictionary_doc,				/* tp_doc */
 	dict_traverse,				/* tp_traverse */
 	dict_tp_clear,				/* tp_clear */
@@ -1978,11 +2488,58 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	dict_init,				/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	dict_new,				/* tp_new */
-	PyObject_GC_Del,        		/* tp_free */
 };
 
+PyTypeObject PySharedDict_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"shareddict",
+	sizeof(PySharedDictObject),
+	0,
+	(destructor)shareddict_dealloc,		/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	(reprfunc)shareddict_repr,		/* tp_repr */
+	0,					/* tp_as_number */
+	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 | Py_TPFLAGS_HAVE_GC |
+		Py_TPFLAGS_DICT_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
+	dictionary_doc,				/* tp_doc */
+	dict_traverse,				/* tp_traverse */
+	dict_tp_clear,				/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	0,					/* tp_methods */
+	0,					/* tp_members */
+	0,					/* tp_getset */
+	0,					/* tp_base */
+	0,					/* tp_dict */
+	0,					/* tp_descr_get */
+	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	dict_init,				/* tp_init */
+	shareddict_new,				/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	shareddict_isshareable,			/* tp_isshareable */
+};
+
 /* For backward compatibility with old dictionary interface */
 
 PyObject *
@@ -1998,6 +2555,19 @@
 }
 
 int
+PyDict_GetItemStringEx(PyObject *d, const char *key, PyObject **value)
+{
+	PyObject *keyobj;
+	int retvalue;
+	keyobj = PyUnicode_FromString(key);
+	if (keyobj == NULL)
+		return -1;
+	retvalue = PyDict_GetItemEx(d, keyobj, value);
+	Py_DECREF(keyobj);
+	return retvalue;
+}
+
+int
 PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
 {
 	PyObject *kv;
@@ -2024,6 +2594,19 @@
 	return err;
 }
 
+int
+PyDict_ContainsString(PyObject *d, const char *key)
+{
+	PyObject *keyobj;
+	int retvalue;
+	keyobj = PyUnicode_FromString(key);
+	if (keyobj == NULL)
+		return -1;
+	retvalue = PyDict_Contains(d, keyobj);
+	Py_DECREF(keyobj);
+	return retvalue;
+}
+
 /* Dictionary iterator types */
 
 typedef struct {
@@ -2039,14 +2622,14 @@
 dictiter_new(dictobject *dict, PyTypeObject *itertype)
 {
 	dictiterobject *di;
-	di = PyObject_New(dictiterobject, itertype);
+	di = PyObject_NEW(dictiterobject, itertype);
 	if (di == NULL)
 		return NULL;
 	Py_INCREF(dict);
 	di->di_dict = dict;
-	di->di_used = dict->ma_used;
+	di->di_used = dict_length(dict);
 	di->di_pos = 0;
-	di->len = dict->ma_used;
+	di->len = di->di_used;
 	if (itertype == &PyDictIterItem_Type) {
 		di->di_result = PyTuple_Pack(2, Py_None, Py_None);
 		if (di->di_result == NULL) {
@@ -2064,14 +2647,14 @@
 {
 	Py_XDECREF(di->di_dict);
 	Py_XDECREF(di->di_result);
-	PyObject_Del(di);
+	PyObject_DEL(di);
 }
 
 static PyObject *
 dictiter_len(dictiterobject *di)
 {
 	Py_ssize_t len = 0;
-	if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
+	if (di->di_dict != NULL && di->di_used == dict_length(di->di_dict))
 		len = di->len;
 	return PyInt_FromSize_t(len);
 }
@@ -2085,45 +2668,70 @@
  	{NULL,		NULL}		/* sentinel */
 };
 
-static PyObject *dictiter_iternextkey(dictiterobject *di)
+/* On success, returns 0 and sets key and value (with NEW references)
+ * On failure, returns -1, sets neither, and invalidates di */
+static int
+dictiter_iternext_common(dictiterobject *di, PyObject **key, PyObject **value)
 {
-	PyObject *key;
-	register Py_ssize_t i, mask;
-	register dictentry *ep;
-	dictobject *d = di->di_dict;
+    register Py_ssize_t i, mask;
+    register dictentry *ep;
+    dictobject *d = di->di_dict;
+    PyDict_LockState lockstate;
 
-	if (d == NULL)
-		return NULL;
-	assert (PyDict_Check(d));
+    if (d == NULL)
+        return -1;
+    assert (PyDict_Check(d));
 
-	if (di->di_used != d->ma_used) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"dictionary changed size during iteration");
-		di->di_used = -1; /* Make this state sticky */
-		return NULL;
-	}
+    _pydictlock_initstate_read(&lockstate);
 
-	i = di->di_pos;
-	if (i < 0)
-		goto fail;
-	ep = d->ma_table;
-	mask = d->ma_mask;
-	while (i <= mask && ep[i].me_value == NULL)
-		i++;
-	di->di_pos = i+1;
-	if (i > mask)
-		goto fail;
-	di->len--;
-	key = ep[i].me_key;
-	Py_INCREF(key);
-	return key;
+    _pydictlock_acquire(d, &lockstate);
+    /* We don't bother to check ma_rebuilds here.  We're not caching
+     * ma_table or ma_mask, so ma_used is good enough. */
+    if (di->di_used != d->ma_used) {
+        _pydictlock_release(d, &lockstate);
+        PyErr_SetString(PyExc_RuntimeError,
+                        "dictionary changed size during iteration");
+        di->di_used = -1; /* Make this state sticky */
+        return -1;
+    }
 
+    i = di->di_pos;
+    if (i < 0)
+        goto fail;
+    ep = d->ma_table;
+    mask = d->ma_mask;
+    while (i <= mask && ep[i].me_value == NULL)
+        i++;
+    di->di_pos = i+1;
+    if (i > mask)
+        goto fail;
+
+    di->len--;
+    *key = ep[i].me_key;
+    *value = ep[i].me_value;
+    Py_INCREF(*key);
+    Py_INCREF(*value);
+
+    _pydictlock_release(d, &lockstate);
+    return 0;
+
 fail:
-	Py_DECREF(d);
-	di->di_dict = NULL;
-	return NULL;
+    _pydictlock_release(d, &lockstate);
+    Py_DECREF(d);
+    di->di_dict = NULL;
+    return -1;
 }
 
+static PyObject *dictiter_iternextkey(dictiterobject *di)
+{
+    PyObject *key, *value;
+
+    if (dictiter_iternext_common(di, &key, &value))
+        return NULL;
+    Py_DECREF(value);
+    return key;
+}
+
 PyTypeObject PyDictIterKey_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"dictionary-keyiterator",		/* tp_name */
@@ -2157,43 +2765,15 @@
 	0,
 };
 
-static PyObject *dictiter_iternextvalue(dictiterobject *di)
+static PyObject *
+dictiter_iternextvalue(dictiterobject *di)
 {
-	PyObject *value;
-	register Py_ssize_t i, mask;
-	register dictentry *ep;
-	dictobject *d = di->di_dict;
+    PyObject *key, *value;
 
-	if (d == NULL)
-		return NULL;
-	assert (PyDict_Check(d));
-
-	if (di->di_used != d->ma_used) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"dictionary changed size during iteration");
-		di->di_used = -1; /* Make this state sticky */
-		return NULL;
-	}
-
-	i = di->di_pos;
-	mask = d->ma_mask;
-	if (i < 0 || i > mask)
-		goto fail;
-	ep = d->ma_table;
-	while ((value=ep[i].me_value) == NULL) {
-		i++;
-		if (i > mask)
-			goto fail;
-	}
-	di->di_pos = i+1;
-	di->len--;
-	Py_INCREF(value);
-	return value;
-
-fail:
-	Py_DECREF(d);
-	di->di_dict = NULL;
-	return NULL;
+    if (dictiter_iternext_common(di, &key, &value))
+        return NULL;
+    Py_DECREF(key);
+    return value;
 }
 
 PyTypeObject PyDictIterValue_Type = {
@@ -2231,55 +2811,25 @@
 
 static PyObject *dictiter_iternextitem(dictiterobject *di)
 {
-	PyObject *key, *value, *result = di->di_result;
-	register Py_ssize_t i, mask;
-	register dictentry *ep;
-	dictobject *d = di->di_dict;
+    PyObject *key, *value;
+    PyObject *result = di->di_result;
 
-	if (d == NULL)
-		return NULL;
-	assert (PyDict_Check(d));
+    if (dictiter_iternext_common(di, &key, &value))
+        return NULL;
 
-	if (di->di_used != d->ma_used) {
-		PyErr_SetString(PyExc_RuntimeError,
-				"dictionary changed size during iteration");
-		di->di_used = -1; /* Make this state sticky */
-		return NULL;
-	}
+    if (Py_RefcntMatches(result, 1)) {
+        Py_INCREF(result);
+        Py_DECREF(PyTuple_GET_ITEM(result, 0));
+        Py_DECREF(PyTuple_GET_ITEM(result, 1));
+    } else {
+        result = PyTuple_New(2);
+        if (result == NULL)
+            return NULL;
+    }
 
-	i = di->di_pos;
-	if (i < 0)
-		goto fail;
-	ep = d->ma_table;
-	mask = d->ma_mask;
-	while (i <= mask && ep[i].me_value == NULL)
-		i++;
-	di->di_pos = i+1;
-	if (i > mask)
-		goto fail;
-
-	if (result->ob_refcnt == 1) {
-		Py_INCREF(result);
-		Py_DECREF(PyTuple_GET_ITEM(result, 0));
-		Py_DECREF(PyTuple_GET_ITEM(result, 1));
-	} else {
-		result = PyTuple_New(2);
-		if (result == NULL)
-			return NULL;
-	}
-	di->len--;
-	key = ep[i].me_key;
-	value = ep[i].me_value;
-	Py_INCREF(key);
-	Py_INCREF(value);
-	PyTuple_SET_ITEM(result, 0, key);
-	PyTuple_SET_ITEM(result, 1, value);
-	return result;
-
-fail:
-	Py_DECREF(d);
-	di->di_dict = NULL;
-	return NULL;
+    PyTuple_SET_ITEM(result, 0, key);
+    PyTuple_SET_ITEM(result, 1, value);
+    return result;
 }
 
 PyTypeObject PyDictIterItem_Type = {
@@ -2332,7 +2882,7 @@
 dictview_dealloc(dictviewobject *dv)
 {
 	Py_XDECREF(dv->dv_dict);
-	PyObject_Del(dv);
+	PyObject_DEL(dv);
 }
 
 static Py_ssize_t
@@ -2340,7 +2890,7 @@
 {
 	Py_ssize_t len = 0;
 	if (dv->dv_dict != NULL)
-		len = dv->dv_dict->ma_used;
+		len = dict_length(dv->dv_dict);
 	return len;
 }
 
@@ -2359,7 +2909,7 @@
 			     type->tp_name, dict->ob_type->tp_name);
 		return NULL;
 	}
-	dv = PyObject_New(dictviewobject, type);
+	dv = PyObject_NEW(dictviewobject, type);
 	if (dv == NULL)
 		return NULL;
 	Py_INCREF(dict);
@@ -2656,19 +3206,22 @@
 dictitems_contains(dictviewobject *dv, PyObject *obj)
 {
 	PyObject *key, *value, *found;
+	int res;
+
 	if (dv->dv_dict == NULL)
 		return 0;
 	if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2)
 		return 0;
+
 	key = PyTuple_GET_ITEM(obj, 0);
 	value = PyTuple_GET_ITEM(obj, 1);
-	found = PyDict_GetItem((PyObject *)dv->dv_dict, key);
-	if (found == NULL) {
-		if (PyErr_Occurred())
-			return -1;
+	if (PyDict_GetItemEx((PyObject *)dv->dv_dict, key, &found) < 0)
+		return -1;
+	if (found == NULL)
 		return 0;
-	}
-	return PyObject_RichCompareBool(value, found, Py_EQ);
+	res = PyObject_RichCompareBool(value, found, Py_EQ);
+	Py_DECREF(found);
+	return res;
 }
 
 static PySequenceMethods dictitems_as_sequence = {
@@ -2789,3 +3342,24 @@
 {
 	return dictview_new(dict, &PyDictValues_Type);
 }
+
+/* Even type and object's initialization calls us, so we need a bare
+ * minimum of functionality to be ready even before them. */
+void
+_PyDict_PreInit(void)
+{
+#ifdef USE_DICT_FREELIST
+	free_dicts_lock = PyThread_lock_allocate();
+	if (!free_dicts_lock)
+		Py_FatalError("unable to allocate lock");
+#endif
+}
+
+void
+PyDict_Fini(void)
+{
+#ifdef USE_DICT_FREELIST
+	PyThread_lock_free(free_dicts_lock);
+	free_dicts_lock = NULL;
+#endif
+}
Index: Objects/weakrefobject.c
===================================================================
--- Objects/weakrefobject.c	(revision 58355)
+++ Objects/weakrefobject.c	(working copy)
@@ -2,181 +2,90 @@
 #include "structmember.h"
 
 
-#define GET_WEAKREFS_LISTPTR(o) \
-        ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
+static int deathqueue_clear(PyDeathQueue *self);
+static int PyDeathQueue_Cancel(PyDeathQueue *queue, PyDeathQueueHandle *handle);
+static PyObject *deathqueue_wait(PyDeathQueue *queue);
 
 
-Py_ssize_t
-_PyWeakref_GetWeakrefCount(PyWeakReference *head)
-{
-    Py_ssize_t count = 0;
-
-    while (head != NULL) {
-        ++count;
-        head = head->wr_next;
-    }
-    return count;
-}
-
-
 static void
-init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
+weakref_dealloc(PyWeakReference *self)
 {
-    self->hash = -1;
-    self->wr_object = ob;
-    Py_XINCREF(callback);
-    self->wr_callback = callback;
+    if (self->wr_object != NULL)
+        Py_FatalError("Still-valid weakref deleted!");
+    PyCritical_Free(self->crit);
+    PyObject_DEL(self);
 }
 
-static PyWeakReference *
-new_weakref(PyObject *ob, PyObject *callback)
-{
-    PyWeakReference *result;
-
-    result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
-    if (result) {
-        init_weakref(result, ob, callback);
-        PyObject_GC_Track(result);
-    }
-    return result;
-}
-
-
-/* This function clears the passed-in reference and removes it from the
- * list of weak references for the referent.  This is the only code that
- * removes an item from the doubly-linked list of weak references for an
- * object; it is also responsible for clearing the callback slot.
- */
-static void
-clear_weakref(PyWeakReference *self)
-{
-    PyObject *callback = self->wr_callback;
-
-    if (PyWeakref_GET_OBJECT(self) != Py_None) {
-        PyWeakReference **list = GET_WEAKREFS_LISTPTR(
-            PyWeakref_GET_OBJECT(self));
-
-        if (*list == self)
-	    /* If 'self' is the end of the list (and thus self->wr_next == NULL)
-	       then the weakref list itself (and thus the value of *list) will
-	       end up being set to NULL. */
-            *list = self->wr_next;
-        self->wr_object = Py_None;
-        if (self->wr_prev != NULL)
-            self->wr_prev->wr_next = self->wr_next;
-        if (self->wr_next != NULL)
-            self->wr_next->wr_prev = self->wr_prev;
-        self->wr_prev = NULL;
-        self->wr_next = NULL;
-    }
-    if (callback != NULL) {
-        Py_DECREF(callback);
-        self->wr_callback = NULL;
-    }
-}
-
-/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
- * the callback intact and uncalled.  It must be possible to call self's
- * tp_dealloc() after calling this, so self has to be left in a sane enough
- * state for that to work.  We expect tp_dealloc to decref the callback
- * then.  The reason for not letting clear_weakref() decref the callback
- * right now is that if the callback goes away, that may in turn trigger
- * another callback (if a weak reference to the callback exists) -- running
- * arbitrary Python code in the middle of gc is a disaster.  The convolution
- * here allows gc to delay triggering such callbacks until the world is in
- * a sane state again.
- */
-void
-_PyWeakref_ClearRef(PyWeakReference *self)
-{
-    PyObject *callback;
-
-    assert(self != NULL);
-    assert(PyWeakref_Check(self));
-    /* Preserve and restore the callback around clear_weakref. */
-    callback = self->wr_callback;
-    self->wr_callback = NULL;
-    clear_weakref(self);
-    self->wr_callback = callback;
-}
-
-static void
-weakref_dealloc(PyObject *self)
-{
-    PyObject_GC_UnTrack(self);
-    clear_weakref((PyWeakReference *) self);
-    Py_Type(self)->tp_free(self);
-}
-
-
 static int
-gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
+weakref_traverse(PyWeakReference *self, visitproc visit, void *arg)
 {
-    Py_VISIT(self->wr_callback);
     return 0;
 }
 
-
-static int
-gc_clear(PyWeakReference *self)
-{
-    clear_weakref(self);
-    return 0;
-}
-
-
 static PyObject *
-weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
+weakref_call(PyObject *self, PyObject *args, PyObject *kw)
 {
     static char *kwlist[] = {NULL};
+    PyObject *ob;
 
-    if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
-        PyObject *object = PyWeakref_GET_OBJECT(self);
-        Py_INCREF(object);
-        return (object);
+    if (!PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist))
+        return NULL;
+
+    ob = PyWeakref_GetObjectEx(self);
+    if (ob == NULL) {
+        Py_INCREF(Py_None);
+        ob = Py_None;
     }
-    return NULL;
+
+    return ob;
 }
 
-
 static long
 weakref_hash(PyWeakReference *self)
 {
-    if (self->hash != -1)
-        return self->hash;
-    if (PyWeakref_GET_OBJECT(self) == Py_None) {
+    PyObject *ob;
+    AO_t hash = AO_load_full(&self->hash);
+    if (hash != (AO_t)-1)
+        return (long)hash;
+
+    ob = PyWeakref_GetObjectEx((PyObject *)self);
+    if (ob == NULL) {
         PyErr_SetString(PyExc_TypeError, "weak object has gone away");
         return -1;
     }
-    self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
-    return self->hash;
+
+    hash = PyObject_Hash(ob);
+    Py_DECREF(ob);
+
+    AO_compare_and_swap(&self->hash, (AO_t)-1, hash);
+    return (long)AO_load_full(&self->hash);
 }
 
-
 static PyObject *
 weakref_repr(PyWeakReference *self)
 {
     char buffer[256];
-    if (PyWeakref_GET_OBJECT(self) == Py_None) {
+    PyObject *ob = PyWeakref_GetObjectEx((PyObject *)self);
+
+    if (ob == NULL)
         PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
-    }
     else {
-	char *name = NULL;
-	PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
-						   "__name__");
-	if (nameobj == NULL)
-		PyErr_Clear();
-	else if (PyUnicode_Check(nameobj))
-		name = PyUnicode_AsString(nameobj);
+        char *name = NULL;
+        PyObject *nameobj = PyObject_GetAttrString(ob, "__name__");
+
+        if (nameobj == NULL)
+            PyErr_Clear();
+        else if (PyUnicode_Check(nameobj))
+            name = PyUnicode_AsString(nameobj);
+
         PyOS_snprintf(buffer, sizeof(buffer),
-		      name ? "<weakref at %p; to '%.50s' at %p (%s)>"
-		           : "<weakref at %p; to '%.50s' at %p>",
-		      self,
-		      Py_Type(PyWeakref_GET_OBJECT(self))->tp_name,
-		      PyWeakref_GET_OBJECT(self),
-		      name);
-	Py_XDECREF(nameobj);
+                      name ? "<weakref at %p; to '%.50s' at %p (%s)>"
+                           : "<weakref at %p; to '%.50s' at %p>",
+                      self, Py_Type(ob)->tp_name, ob, name);
+        Py_XDECREF(nameobj);
+        Py_DECREF(ob);
     }
+
     return PyUnicode_FromString(buffer);
 }
 
@@ -185,147 +94,62 @@
    gone away, they are equal if they are identical. */
 
 static PyObject *
-weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
+weakref_richcompare(PyWeakReference *self, PyWeakReference *other, int op)
 {
+    PyObject *self_ob, *other_ob;
+    PyObject *res;
+
     if ((op != Py_EQ && op != Py_NE) ||
-	!PyWeakref_Check(self) ||
-	!PyWeakref_Check(other)) {
+            !PyWeakref_Check(self) ||
+            !PyWeakref_Check(other)) {
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
     }
-    if (PyWeakref_GET_OBJECT(self) == Py_None
-        || PyWeakref_GET_OBJECT(other) == Py_None) {
-        PyObject *res = self==other ? Py_True : Py_False;
-        Py_INCREF(res);
-        return res;
-    }
-    return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
-                                PyWeakref_GET_OBJECT(other), op);
-}
 
-/* Given the head of an object's list of weak references, extract the
- * two callback-less refs (ref and proxy).  Used to determine if the
- * shared references exist and to determine the back link for newly
- * inserted references.
- */
-static void
-get_basic_refs(PyWeakReference *head,
-               PyWeakReference **refp, PyWeakReference **proxyp)
-{
-    *refp = NULL;
-    *proxyp = NULL;
-
-    if (head != NULL && head->wr_callback == NULL) {
-        /* We need to be careful that the "basic refs" aren't
-           subclasses of the main types.  That complicates this a
-           little. */
-        if (PyWeakref_CheckRefExact(head)) {
-            *refp = head;
-            head = head->wr_next;
-        }
-        if (head != NULL
-            && head->wr_callback == NULL
-            && PyWeakref_CheckProxy(head)) {
-            *proxyp = head;
-            /* head = head->wr_next; */
-        }
+    if (self == other) {
+        Py_INCREF(Py_True);
+        return Py_True;
     }
-}
 
-/* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
-static void
-insert_after(PyWeakReference *newref, PyWeakReference *prev)
-{
-    newref->wr_prev = prev;
-    newref->wr_next = prev->wr_next;
-    if (prev->wr_next != NULL)
-        prev->wr_next->wr_prev = newref;
-    prev->wr_next = newref;
-}
+    self_ob = PyWeakref_GetObjectEx((PyObject *)self);
+    other_ob = PyWeakref_GetObjectEx((PyObject *)other);
 
-/* Insert 'newref' at the head of the list; 'list' points to the variable
- * that stores the head.
- */
-static void
-insert_head(PyWeakReference *newref, PyWeakReference **list)
-{
-    PyWeakReference *next = *list;
+    if (self_ob == NULL || other_ob == NULL) {
+        res = Py_False;
+        Py_INCREF(res);
+    } else
+        res = PyObject_RichCompare(self_ob, other_ob, op);
 
-    newref->wr_prev = NULL;
-    newref->wr_next = next;
-    if (next != NULL)
-        next->wr_prev = newref;
-    *list = newref;
+    Py_XDECREF(self_ob);
+    Py_XDECREF(other_ob);
+    return res;
 }
 
 static int
 parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
-                        PyObject **obp, PyObject **callbackp)
+                        PyObject **obp)
 {
     /* XXX Should check that kwargs == NULL or is empty. */
-    return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
+    return PyArg_UnpackTuple(args, funcname, 1, 1, obp);
 }
 
 static PyObject *
 weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    PyWeakReference *self = NULL;
-    PyObject *ob, *callback = NULL;
+    PyObject *ob;
 
-    if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
-        PyWeakReference *ref, *proxy;
-        PyWeakReference **list;
+    if (!parse_weakref_init_args("__new__", args, kwargs, &ob))
+        return NULL;
 
-        if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
-            PyErr_Format(PyExc_TypeError,
-                         "cannot create weak reference to '%s' object",
-                         Py_Type(ob)->tp_name);
-            return NULL;
-        }
-        if (callback == Py_None)
-            callback = NULL;
-        list = GET_WEAKREFS_LISTPTR(ob);
-        get_basic_refs(*list, &ref, &proxy);
-        if (callback == NULL && type == &_PyWeakref_RefType) {
-            if (ref != NULL) {
-                /* We can re-use an existing reference. */
-                Py_INCREF(ref);
-                return (PyObject *)ref;
-            }
-        }
-        /* We have to create a new reference. */
-        /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
-           list on ob can be mutated.  This means that the ref and
-           proxy pointers we got back earlier may have been collected,
-           so we need to compute these values again before we use
-           them. */
-        self = (PyWeakReference *) (type->tp_alloc(type, 0));
-        if (self != NULL) {
-            init_weakref(self, ob, callback);
-            if (callback == NULL && type == &_PyWeakref_RefType) {
-                insert_head(self, list);
-            }
-            else {
-                PyWeakReference *prev;
-
-                get_basic_refs(*list, &ref, &proxy);
-                prev = (proxy == NULL) ? ref : proxy;
-                if (prev == NULL)
-                    insert_head(self, list);
-                else
-                    insert_after(self, prev);
-            }
-        }
-    }
-    return (PyObject *)self;
+    return PyWeakref_NewRef(ob, NULL);
 }
 
 static int
 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-    PyObject *tmp;
+    PyObject *ob;
 
-    if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
+    if (parse_weakref_init_args("__init__", args, kwargs, &ob))
         return 0;
     else
         return 1;
@@ -333,31 +157,33 @@
 
 
 PyTypeObject
-_PyWeakref_RefType = {
+_PyWeakref_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "weakref",
     sizeof(PyWeakReference),
     0,
-    weakref_dealloc,            /*tp_dealloc*/
-    0,	                        /*tp_print*/
+    (destructor)weakref_dealloc,  /*tp_dealloc*/
+    0,                          /*tp_print*/
     0,                          /*tp_getattr*/
     0,                          /*tp_setattr*/
-    0,	                        /*tp_compare*/
+    0,                          /*tp_compare*/
     (reprfunc)weakref_repr,     /*tp_repr*/
     0,                          /*tp_as_number*/
     0,                          /*tp_as_sequence*/
     0,                          /*tp_as_mapping*/
     (hashfunc)weakref_hash,     /*tp_hash*/
-    (ternaryfunc)weakref_call,  /*tp_call*/
+    weakref_call,               /*tp_call*/
     0,                          /*tp_str*/
     0,                          /*tp_getattro*/
     0,                          /*tp_setattro*/
     0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
-        | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
+    /* There is only ever one weakref per object, so subclassing is
+     * unsupported. */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+        Py_TPFLAGS_SHAREABLE,  /*tp_flags*/
     0,                          /*tp_doc*/
-    (traverseproc)gc_traverse,  /*tp_traverse*/
-    (inquiry)gc_clear,          /*tp_clear*/
+    (traverseproc)weakref_traverse,  /*tp_traverse*/
+    0,                          /*tp_clear*/
     (richcmpfunc)weakref_richcompare,	/*tp_richcompare*/
     0,                          /*tp_weaklistoffset*/
     0,                          /*tp_iter*/
@@ -371,548 +197,990 @@
     0,                          /*tp_descr_set*/
     0,                          /*tp_dictoffset*/
     weakref___init__,           /*tp_init*/
-    PyType_GenericAlloc,        /*tp_alloc*/
     weakref___new__,            /*tp_new*/
-    PyObject_GC_Del,            /*tp_free*/
 };
 
 
-static int
-proxy_checkref(PyWeakReference *proxy)
+static void
+deathqueuehandle_dealloc(PyDeathQueueHandle *self)
 {
-    if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
-        PyErr_SetString(PyExc_ReferenceError,
-                        "weakly-referenced object no longer exists");
-        return 0;
+    /* queue holds a reference to us, so we should never get deleted
+     * without clearing us first. */
+    assert(self->weakref == NULL);
+    assert(self->queue == NULL);
+    assert(PyLinkedList_Detatched(&self->weakref_links));
+    assert(PyLinkedList_Detatched(&self->queue_links));
+    PyCritical_Free(self->crit);
+    PyObject_DEL(self);
+}
+
+static PyObject *
+deathqueuehandle_repr(PyDeathQueueHandle *self)
+{
+    char buffer[256];
+    PyObject *payload;
+    PyWeakReference *weakref;
+
+    PyCritical_Enter(self->crit);
+    payload = self->payload;
+    weakref = self->weakref;
+    Py_XINCREF(payload);
+    Py_XINCREF(weakref);
+    PyCritical_Exit(self->crit);
+
+    if (payload == NULL)
+        PyOS_snprintf(buffer, sizeof(buffer),
+            "<deathqueuehandle at %p; cancelled/processed>", self);
+    else {
+        char *name = NULL;
+        char *state = (weakref != NULL) ? "live" : "dead";
+        PyObject *nameobj = PyObject_GetAttrString(payload, "__name__");
+
+        if (nameobj == NULL)
+            PyErr_Clear();
+        else if (PyUnicode_Check(nameobj))
+            name = PyUnicode_AsString(nameobj);
+
+        if (name != NULL)
+            PyOS_snprintf(buffer, sizeof(buffer),
+                "<deathqueuehandle at %p; payload '%.50s' at %p (%s); %s>",
+                self, Py_Type(payload)->tp_name, payload, name, state);
+        else
+            PyOS_snprintf(buffer, sizeof(buffer),
+                "<deathqueuehandle at %p; payload '%.50s' at %p; %s>",
+                self, Py_Type(payload)->tp_name, payload, state);
+        Py_XDECREF(nameobj);
     }
-    return 1;
+
+    Py_XDECREF(payload);
+    Py_XDECREF(weakref);
+
+    return PyUnicode_FromString(buffer);
 }
 
+static int
+deathqueuehandle_traverse(PyDeathQueueHandle *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->payload);
+    Py_VISIT(self->weakref);
+    return 0;
+}
 
-/* If a parameter is a proxy, check that it is still "live" and wrap it,
- * replacing the original value with the raw object.  Raises ReferenceError
- * if the param is a dead proxy.
- */
-#define UNWRAP(o) \
-        if (PyWeakref_CheckProxy(o)) { \
-            if (!proxy_checkref((PyWeakReference *)o)) \
-                return NULL; \
-            o = PyWeakref_GET_OBJECT(o); \
-        }
 
-#define UNWRAP_I(o) \
-        if (PyWeakref_CheckProxy(o)) { \
-            if (!proxy_checkref((PyWeakReference *)o)) \
-                return -1; \
-            o = PyWeakref_GET_OBJECT(o); \
-        }
+PyTypeObject
+_PyDeathQueueHandle_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "deathqueuehandle",
+    sizeof(PyDeathQueueHandle),
+    0,
+    (destructor)deathqueuehandle_dealloc,  /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_compare*/
+    (reprfunc)deathqueuehandle_repr,  /*tp_repr*/
+    0,                          /*tp_as_number*/
+    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 | Py_TPFLAGS_HAVE_GC |
+        Py_TPFLAGS_SHAREABLE,  /*tp_flags*/
+    0,                          /*tp_doc*/
+    (traverseproc)deathqueuehandle_traverse,  /*tp_traverse*/
+    0,                          /*tp_clear*/
+    0,                          /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    0,                          /*tp_methods*/
+    0,                          /*tp_members*/
+    0,                          /*tp_getset*/
+    0,                          /*tp_base*/
+    0,                          /*tp_dict*/
+    0,                          /*tp_descr_get*/
+    0,                          /*tp_descr_set*/
+    0,                          /*tp_dictoffset*/
+    0,                          /*tp_init*/
+    0,                          /*tp_new*/
+};
 
-#define WRAP_UNARY(method, generic) \
-    static PyObject * \
-    method(PyObject *proxy) { \
-        UNWRAP(proxy); \
-        return generic(proxy); \
+
+static void
+deathqueue_dealloc(PyDeathQueue *self)
+{
+    deathqueue_clear(self);
+
+    if (Py_RefcntSnoop(self) != 1) {
+        /* Another thread is trying to manipulate us.  Probably a
+         * handle getting set to dead.  We can finish deleting later. */
+        PyObject_REVIVE(self);
+        Py_DECREF_ASYNC(self);
+    } else {
+        assert(PyLinkedList_Empty(&self->live_links));
+        assert(PyLinkedList_Empty(&self->dead_links));
+        PyCritical_Free(self->crit);
+        PyThread_cond_free(self->cond);
+        PyObject_DEL(self);
     }
+}
 
-#define WRAP_BINARY(method, generic) \
-    static PyObject * \
-    method(PyObject *x, PyObject *y) { \
-        UNWRAP(x); \
-        UNWRAP(y); \
-        return generic(x, y); \
+static int
+deathqueue_traverse(PyDeathQueue *queue, visitproc visit, void *arg)
+{
+    PyDeathQueueHandle *handle;
+    PyLinkedList *handle_links;
+
+    handle_links = &queue->live_links;
+    while (PyLinkedList_Next(&queue->live_links, &handle_links)) {
+        handle = PyLinkedList_Restore(PyDeathQueueHandle, queue_links,
+            handle_links);
+        Py_VISIT(handle);
     }
 
-/* Note that the third arg needs to be checked for NULL since the tp_call
- * slot can receive NULL for this arg.
- */
-#define WRAP_TERNARY(method, generic) \
-    static PyObject * \
-    method(PyObject *proxy, PyObject *v, PyObject *w) { \
-        UNWRAP(proxy); \
-        UNWRAP(v); \
-        if (w != NULL) \
-            UNWRAP(w); \
-        return generic(proxy, v, w); \
+    handle_links = &queue->dead_links;
+    while (PyLinkedList_Next(&queue->dead_links, &handle_links)) {
+        handle = PyLinkedList_Restore(PyDeathQueueHandle, queue_links,
+            handle_links);
+        Py_VISIT(handle);
     }
 
+    return 0;
+}
 
-/* direct slots */
+static int
+deathqueue_clear(PyDeathQueue *queue)
+{
+    /* When called by the tracing GC (not deathqueue_dealloc), we don't
+     * need to deal with the critical sections, as the tracing GC won't
+     * run while a thread is in one.  It won't hurt either though. */
+    while (1) {
+        PyDeathQueueHandle *handle;
 
-WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
-WRAP_UNARY(proxy_str, PyObject_Str)
-WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
+        PyCritical_Enter(queue->crit);
+        if (!PyLinkedList_Empty(&queue->live_links)) {
+            handle = PyLinkedList_Restore(PyDeathQueueHandle,
+                queue_links, queue->live_links.next);
+            Py_INCREF(handle);
+        } else
+            handle = NULL;
+        PyCritical_Exit(queue->crit);
 
+        if (handle != NULL) {
+            if (PyDeathQueue_Cancel(queue, handle))
+                Py_FatalError("deathqueue_clear failed when calling "
+                    "PyDeathQueue_Cancel");
+        } else
+            break;
+    }
+
+    while (1) {
+        PyDeathQueueHandle *handle;
+
+        PyCritical_Enter(queue->crit);
+        if (!PyLinkedList_Empty(&queue->dead_links)) {
+            handle = PyLinkedList_Restore(PyDeathQueueHandle,
+                queue_links, queue->dead_links.next);
+            Py_INCREF(handle);
+        } else
+            handle = NULL;
+        PyCritical_Exit(queue->crit);
+
+        if (handle != NULL) {
+            if (PyDeathQueue_Cancel(queue, handle))
+                Py_FatalError("deathqueue_clear failed when calling "
+                    "PyDeathQueue_Cancel");
+        } else
+            break;
+    }
+
+    return 0;
+}
+
 static PyObject *
-proxy_repr(PyWeakReference *proxy)
+deathqueue___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    char buf[160];
-    PyOS_snprintf(buf, sizeof(buf),
-		  "<weakproxy at %p to %.100s at %p>", proxy,
-		  Py_Type(PyWeakref_GET_OBJECT(proxy))->tp_name,
-		  PyWeakref_GET_OBJECT(proxy));
-    return PyUnicode_FromString(buf);
+    PyDeathQueue *queue;
+
+    static char *kwlist[] = {NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
+        return NULL;
+
+    queue = PyObject_NEW(PyDeathQueue, &_PyDeathQueue_Type);
+    if (queue == NULL)
+        return NULL;
+
+    queue->crit = PyCritical_Allocate(PyCRITICAL_WEAKREF_QUEUE);
+    if (queue->crit == NULL) {
+        PyObject_DEL(queue);
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    queue->cond = PyThread_cond_allocate();
+    if (queue->cond == NULL) {
+        PyCritical_Free(queue->cond);
+        PyObject_DEL(queue);
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    queue->live_links.prev = &queue->live_links;
+    queue->live_links.next = &queue->live_links;
+    queue->dead_links.prev = &queue->dead_links;
+    queue->dead_links.next = &queue->dead_links;
+
+    return (PyObject *)queue;
 }
 
-
 static int
-proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
+deathqueue___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-    if (!proxy_checkref(proxy))
-        return -1;
-    return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
+    static char *kwlist[] = {NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
+        return 1;
+
+    return 0;
 }
 
 static PyObject *
-proxy_richcompare(PyObject *proxy, PyObject *v, int op)
+deathqueue_watch(PyDeathQueue *queue, PyObject *args)
 {
-    UNWRAP(proxy);
-    UNWRAP(v);
-    return PyObject_RichCompare(proxy, v, op);
-}
+    PyObject *obj, *payload;
+    PyWeakReference *ref;
+    PyDeathQueueHandle *handle;
 
-/* number slots */
-WRAP_BINARY(proxy_add, PyNumber_Add)
-WRAP_BINARY(proxy_sub, PyNumber_Subtract)
-WRAP_BINARY(proxy_mul, PyNumber_Multiply)
-WRAP_BINARY(proxy_mod, PyNumber_Remainder)
-WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
-WRAP_TERNARY(proxy_pow, PyNumber_Power)
-WRAP_UNARY(proxy_neg, PyNumber_Negative)
-WRAP_UNARY(proxy_pos, PyNumber_Positive)
-WRAP_UNARY(proxy_abs, PyNumber_Absolute)
-WRAP_UNARY(proxy_invert, PyNumber_Invert)
-WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
-WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
-WRAP_BINARY(proxy_and, PyNumber_And)
-WRAP_BINARY(proxy_xor, PyNumber_Xor)
-WRAP_BINARY(proxy_or, PyNumber_Or)
-WRAP_UNARY(proxy_int, PyNumber_Int)
-WRAP_UNARY(proxy_long, PyNumber_Long)
-WRAP_UNARY(proxy_float, PyNumber_Float)
-WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
-WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
-WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
-WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
-WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
-WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
-WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
-WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
-WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
-WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
+    if (!PyArg_UnpackTuple(args, "watch", 2, 2, &obj, &payload))
+        return NULL;
 
-static int
-proxy_bool(PyWeakReference *proxy)
-{
-    PyObject *o = PyWeakref_GET_OBJECT(proxy);
-    if (!proxy_checkref(proxy))
-        return -1;
-    return PyObject_IsTrue(o);
+    if (!PyObject_IsShareable(payload)) {
+        PyErr_Format(PyExc_TypeError,
+            "deathqueue.watch()'s payload argument must be shareable, '%s' object "
+            "is not", payload->ob_type->tp_name);
+        return NULL;
+    }
+
+    ref = (PyWeakReference *)PyWeakref_NewRef(obj, NULL);
+    if (ref == NULL)
+        return NULL;
+
+    handle = PyObject_NEW(PyDeathQueueHandle, &_PyDeathQueueHandle_Type);
+    if (handle == NULL) {
+        Py_DECREF(ref);
+        return NULL;
+    }
+
+    handle->crit = PyCritical_Allocate(PyCRITICAL_WEAKREF_HANDLE);
+    if (handle->crit == NULL) {
+        PyObject_DEL(handle);
+        Py_DECREF(ref);
+        return NULL;
+    }
+
+    PyCritical_Enter(ref->crit);
+    /* We skip handle->crit as nobody else has a reference to handle yet. */
+    PyCritical_Enter(queue->crit);
+
+    assert(ref->wr_object != NULL);
+
+    /* The underlying ownership order is queue -> handle -> weakref.
+     * queue needs a reference to us, but handle doesn't INCREF them
+     * (they clear our pointer if they get deleted), and we already have
+     * a reference to weakref. */
+    Py_INCREF(handle);
+
+    Py_INCREF(payload);
+    handle->payload = payload;
+    handle->queue = queue;
+    handle->weakref = ref;
+
+    PyLinkedList_Append(&ref->handle_links, &handle->weakref_links);
+    PyLinkedList_Append(&queue->live_links, &handle->queue_links);
+
+    PyCritical_Exit(queue->crit);
+    PyCritical_Exit(ref->crit);
+
+    return (PyObject *)handle;
 }
 
-static void
-proxy_dealloc(PyWeakReference *self)
+PyObject *
+deathqueue_cancel(PyDeathQueue *queue, PyObject *args)
 {
-    if (self->wr_callback != NULL)
-        PyObject_GC_UnTrack((PyObject *)self);
-    clear_weakref(self);
-    PyObject_GC_Del(self);
+    PyDeathQueueHandle *handle;
+
+    if (!PyArg_UnpackTuple(args, "cancel", 1, 1, &handle))
+        return NULL;
+
+    if (!PyDeathQueueHandle_Check(handle)) {
+        PyErr_Format(PyExc_TypeError, "cancel expected deathqueuehandle "
+            "(not \"%.200s\")", Py_Type(handle)->tp_name);
+        return NULL;
+    }
+
+    if (PyDeathQueue_Cancel(queue, handle))
+        return NULL;
+
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
-/* sequence slots */
-
+/* Warning: this function deletes queue's reference to handle.  If the
+ * caller doesn't have their own reference to handle, it may be gone by
+ * the time this function returns. */
 static int
-proxy_contains(PyWeakReference *proxy, PyObject *value)
+PyDeathQueue_Cancel(PyDeathQueue *queue, PyDeathQueueHandle *handle)
 {
-    if (!proxy_checkref(proxy))
-        return -1;
-    return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
-}
+    PyWeakReference *ref;
+    int decref_weakref = 0;
 
+    /* "climb" up the ordered critical sections */
+    PyCritical_Enter(handle->crit);
+    ref = handle->weakref;
+    Py_XINCREF(ref);
+    PyCritical_Exit(handle->crit);
 
-/* mapping slots */
+    /* Begin entering all 3 critical sections (weakref, handle, queue) */
+    if (ref != NULL)
+        PyCritical_Enter(ref->crit);
+    PyCritical_Enter(handle->crit);
 
-static Py_ssize_t
-proxy_length(PyWeakReference *proxy)
-{
-    if (!proxy_checkref(proxy))
-        return -1;
-    return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
+    /* Early out if we've got nothing to do */
+    if (handle->queue != queue) {
+        PyDeathQueue *badqueue = handle->queue;
+        PyCritical_Exit(handle->crit);
+        if (ref != NULL)
+            PyCritical_Exit(ref->crit);
+        Py_XDECREF(ref);
+
+        if (handle->queue == NULL) {
+            /* Already cleared */
+            return 0;
+        } else {
+            /* Wrong queue! */
+            PyErr_Format(PyExc_ValueError, "cancel called on %p queue "
+                "but handle %p is for %p queue", queue, handle, badqueue);
+            return 1;
+        }
+    }
+
+    PyCritical_Enter(queue->crit);
+
+    /* The real work of this function */
+    if (handle->weakref != NULL) {
+        PyLinkedList_Remove(&handle->weakref_links);
+        handle->weakref = NULL;
+        decref_weakref = 1;
+    }
+
+    PyLinkedList_Remove(&handle->queue_links);
+    handle->queue = NULL;
+
+    /* Exit the critical sections */
+    PyCritical_Exit(queue->crit);
+    PyCritical_Exit(handle->crit);
+    if (ref != NULL)
+        PyCritical_Exit(ref->crit);
+
+    /* Finally, cleanup */
+    Py_DECREF(handle);  /* queue -> handle reference */
+    Py_XDECREF(ref);  /* our reference */
+    if (decref_weakref)
+        Py_DECREF(ref);  /* handle -> weakref reference */
+
+    return 0;
 }
 
-WRAP_BINARY(proxy_getitem, PyObject_GetItem)
-
+/* Returns 0 for success and 1 for empty */
 static int
-proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
+pop_common(PyDeathQueue *queue, PyObject **payload)
 {
-    if (!proxy_checkref(proxy))
-        return -1;
+    PyDeathQueueHandle *handle;
 
-    if (value == NULL)
-        return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
-    else
-        return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
+    while (1) {
+        PyCritical_Enter(queue->crit);
+        if (PyLinkedList_Empty(&queue->dead_links)) {
+            PyCritical_Exit(queue->crit);
+            return 1;
+        }
+        handle = PyLinkedList_Restore(PyDeathQueueHandle, queue_links,
+            queue->dead_links.next);
+        Py_INCREF(handle);
+        PyCritical_Exit(queue->crit);
+
+        PyCritical_Enter(handle->crit);
+        PyCritical_Enter(queue->crit);
+
+        if (handle->queue == NULL) {
+            /* Another thread popped the handle on us, or cancelled it */
+            PyCritical_Exit(queue->crit);
+            PyCritical_Exit(handle->crit);
+            Py_DECREF(handle);
+            continue;
+        }
+
+        assert(handle->weakref == NULL);
+        PyLinkedList_Remove(&handle->queue_links);
+        *payload = handle->payload;
+        handle->payload = NULL;  /* We steal their reference */
+        handle->queue = NULL;
+
+        PyCritical_Exit(queue->crit);
+        PyCritical_Exit(handle->crit);
+
+        Py_DECREF(handle);
+        return 0;
+    }
 }
 
-/* iterator slots */
+static PyObject *
+deathqueue_pop(PyDeathQueue *queue)
+{
+    PyObject *payload, *x;
 
+    while (1) {
+        x = deathqueue_wait(queue);
+        if (x == NULL)
+            return NULL;
+        Py_DECREF(x);
+        if (!pop_common(queue, &payload))
+            return payload;
+    }
+}
+
 static PyObject *
-proxy_iter(PyWeakReference *proxy)
+deathqueue_trypop(PyDeathQueue *queue)
 {
-    if (!proxy_checkref(proxy))
+    PyObject *payload;
+
+    if (pop_common(queue, &payload)) {
+        PyErr_SetString(PyExc_ValueError, "trypop from empty deathqueue");
         return NULL;
-    return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
+    } else
+        return payload;
 }
 
+static int
+deathqueue_bool(PyDeathQueue *queue)
+{
+    int result;
+
+    PyCritical_Enter(queue->crit);
+    result = !PyLinkedList_Empty(&queue->dead_links);
+    PyCritical_Exit(queue->crit);
+
+    return result;
+}
+
 static PyObject *
-proxy_iternext(PyWeakReference *proxy)
+deathqueue_wait(PyDeathQueue *queue)
 {
-    if (!proxy_checkref(proxy))
-        return NULL;
-    return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
+    /* Using this method is racey, giving you extra wakeups and forcing
+     * you to have retry loops, so we don't bother to add another retry
+     * loop inside it. */
+    PyCritical_Enter(queue->crit);
+
+    if (PyLinkedList_Empty(&queue->dead_links))
+        _PyCritical_CondWait(queue->crit, queue->cond);
+
+    PyCritical_Exit(queue->crit);
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 
-static PyNumberMethods proxy_as_number = {
-    proxy_add,              /*nb_add*/
-    proxy_sub,              /*nb_subtract*/
-    proxy_mul,              /*nb_multiply*/
-    proxy_mod,              /*nb_remainder*/
-    proxy_divmod,           /*nb_divmod*/
-    proxy_pow,              /*nb_power*/
-    proxy_neg,              /*nb_negative*/
-    proxy_pos,              /*nb_positive*/
-    proxy_abs,              /*nb_absolute*/
-    (inquiry)proxy_bool,    /*nb_bool*/
-    proxy_invert,           /*nb_invert*/
-    proxy_lshift,           /*nb_lshift*/
-    proxy_rshift,           /*nb_rshift*/
-    proxy_and,              /*nb_and*/
-    proxy_xor,              /*nb_xor*/
-    proxy_or,               /*nb_or*/
-    0,                      /*nb_reserved*/
-    proxy_int,              /*nb_int*/
-    proxy_long,             /*nb_long*/
-    proxy_float,            /*nb_float*/
-    0,                      /*nb_oct*/
-    0,                      /*nb_hex*/
-    proxy_iadd,             /*nb_inplace_add*/
-    proxy_isub,             /*nb_inplace_subtract*/
-    proxy_imul,             /*nb_inplace_multiply*/
-    proxy_imod,             /*nb_inplace_remainder*/
-    proxy_ipow,             /*nb_inplace_power*/
-    proxy_ilshift,          /*nb_inplace_lshift*/
-    proxy_irshift,          /*nb_inplace_rshift*/
-    proxy_iand,             /*nb_inplace_and*/
-    proxy_ixor,             /*nb_inplace_xor*/
-    proxy_ior,              /*nb_inplace_or*/
-};
+PyDoc_STRVAR(watch_doc,
+"deathqueue.watch(obj, payload) -> handle.  payload is returned from\n\
+deathqueue.pop() once obj dies, unless canceled first.");
 
-static PySequenceMethods proxy_as_sequence = {
-    (lenfunc)proxy_length,      /*sq_length*/
-    0,                          /*sq_concat*/
-    0,                          /*sq_repeat*/
-    0,                          /*sq_item*/
-    0,                          /*sq_slice*/
-    0,                          /*sq_ass_item*/
-    0,				 /*sq_ass_slice*/
-    (objobjproc)proxy_contains, /* sq_contains */
-};
+PyDoc_STRVAR(cancel_doc,
+"deathqueue.cancel(handle) -> None.  Cancels watching of associated obj.");
 
-static PyMappingMethods proxy_as_mapping = {
-    (lenfunc)proxy_length,        /*mp_length*/
-    proxy_getitem,                /*mp_subscript*/
-    (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
-};
+PyDoc_STRVAR(pop_doc,
+"deathqueue.pop() -> payload.  Returns the payload passed to\n\
+deathqueue.watch().  Blocks if no watched objects have died yet.");
 
+PyDoc_STRVAR(trypop_doc,
+"deathqueue.trypop() -> payload.  Used once bool(deathqueue) or\n\
+deathqueue.wait() indicate a watched obj has died; returns the payload\n\
+passed to deathqueue.watch().");
 
-PyTypeObject
-_PyWeakref_ProxyType = {
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    "weakproxy",
-    sizeof(PyWeakReference),
-    0,
-    /* methods */
-    (destructor)proxy_dealloc,          /* tp_dealloc */
-    0,				        /* tp_print */
-    0,				        /* tp_getattr */
-    0, 				        /* tp_setattr */
-    0,				        /* tp_compare */
-    (reprfunc)proxy_repr,	        /* tp_repr */
-    &proxy_as_number,		        /* tp_as_number */
-    &proxy_as_sequence,		        /* tp_as_sequence */
-    &proxy_as_mapping,		        /* tp_as_mapping */
-    0,	                                /* tp_hash */
-    0,	                                /* tp_call */
-    proxy_str,                          /* tp_str */
-    proxy_getattr,                      /* tp_getattro */
-    (setattrofunc)proxy_setattr,        /* tp_setattro */
-    0,				        /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
-    0,                                  /* tp_doc */
-    (traverseproc)gc_traverse,          /* tp_traverse */
-    (inquiry)gc_clear,                  /* tp_clear */
-    proxy_richcompare,                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    (getiterfunc)proxy_iter,            /* tp_iter */
-    (iternextfunc)proxy_iternext,       /* tp_iternext */
+PyDoc_STRVAR(wait_doc,
+"deathqueue.wait() -> None.  Does not return until a watched obj has\n\
+died.  This function is interruptible.");
+
+static PyNumberMethods deathqueue_as_number = {
+    0,                              /*nb_add*/
+    0,                              /*nb_subtract*/
+    0,                              /*nb_multiply*/
+    0,                              /*nb_remainder*/
+    0,                              /*nb_divmod*/
+    0,                              /*nb_power*/
+    0,                              /*nb_negative*/
+    0,                              /*nb_positive*/
+    0,                              /*nb_absolute*/
+    (inquiry)deathqueue_bool,       /*nb_bool*/
 };
 
+static PyMethodDef deathqueue_methods[] = {
+    {"watch",       (PyCFunction)deathqueue_watch,      METH_VARARGS, watch_doc},
+    {"cancel",      (PyCFunction)deathqueue_cancel,     METH_VARARGS, cancel_doc},
+    {"pop",         (PyCFunction)deathqueue_pop,        METH_NOARGS, pop_doc},
+    {"trypop",      (PyCFunction)deathqueue_trypop,     METH_NOARGS, trypop_doc},
+    {"wait",        (PyCFunction)deathqueue_wait,       METH_NOARGS, wait_doc},
+    {NULL}
+};
 
+static int
+deathqueue_isshareable (PyDeathQueue *queue)
+{
+    return 1;
+}
+
 PyTypeObject
-_PyWeakref_CallableProxyType = {
+_PyDeathQueue_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    "weakcallableproxy",
-    sizeof(PyWeakReference),
+    "deathqueue",
+    sizeof(PyDeathQueue),
     0,
-    /* methods */
-    (destructor)proxy_dealloc,          /* tp_dealloc */
-    0,				        /* tp_print */
-    0,				        /* tp_getattr */
-    0, 				        /* tp_setattr */
-    0,				        /* tp_compare */
-    (unaryfunc)proxy_repr,	        /* tp_repr */
-    &proxy_as_number,		        /* tp_as_number */
-    &proxy_as_sequence,		        /* tp_as_sequence */
-    &proxy_as_mapping,		        /* tp_as_mapping */
-    0,	                                /* tp_hash */
-    proxy_call,	                        /* tp_call */
-    proxy_str,	                        /* tp_str */
-    proxy_getattr,                      /* tp_getattro */
-    (setattrofunc)proxy_setattr,        /* tp_setattro */
-    0,				        /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
-    0,                                  /* tp_doc */
-    (traverseproc)gc_traverse,          /* tp_traverse */
-    (inquiry)gc_clear,                  /* tp_clear */
-    proxy_richcompare,                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    (getiterfunc)proxy_iter,            /* tp_iter */
-    (iternextfunc)proxy_iternext,       /* tp_iternext */
+    (destructor)deathqueue_dealloc,  /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_compare*/
+    0,                          /*tp_repr*/
+    &deathqueue_as_number,      /*tp_as_number*/
+    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 | Py_TPFLAGS_HAVE_GC |
+        Py_TPFLAGS_SHAREABLE,  /*tp_flags*/
+    0,                          /*tp_doc*/
+    (traverseproc)deathqueue_traverse,  /*tp_traverse*/
+    0,                          /*tp_clear*/
+    0,                          /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    deathqueue_methods,         /*tp_methods*/
+    0,                          /*tp_members*/
+    0,                          /*tp_getset*/
+    0,                          /*tp_base*/
+    0,                          /*tp_dict*/
+    0,                          /*tp_descr_get*/
+    0,                          /*tp_descr_set*/
+    0,                          /*tp_dictoffset*/
+    deathqueue___init__,        /*tp_init*/
+    deathqueue___new__,         /*tp_new*/
+    0,                          /*tp_is_gc*/
+    0,                          /*tp_bases*/
+    0,                          /*tp_mro*/
+    0,                          /*tp_cache*/
+    0,                          /*tp_subclasses*/
+    0,                          /*tp_weaklist*/
+    (isshareablefunc)deathqueue_isshareable,    /*tp_isshareable*/
 };
 
 
-
 PyObject *
 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
 {
-    PyWeakReference *result = NULL;
-    PyWeakReference **list;
-    PyWeakReference *ref, *proxy;
+    PyWeakReference **ptr;
+    PyWeakReference *ref;
 
     if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
         PyErr_Format(PyExc_TypeError,
-		     "cannot create weak reference to '%s' object",
+                     "cannot create weak reference to '%s' object",
                      Py_Type(ob)->tp_name);
         return NULL;
     }
-    list = GET_WEAKREFS_LISTPTR(ob);
-    get_basic_refs(*list, &ref, &proxy);
-    if (callback == Py_None)
-        callback = NULL;
-    if (callback == NULL)
-        /* return existing weak reference if it exists */
-        result = ref;
-    if (result != NULL)
-        Py_INCREF(result);
-    else {
-        /* Note: new_weakref() can trigger cyclic GC, so the weakref
-           list on ob can be mutated.  This means that the ref and
-           proxy pointers we got back earlier may have been collected,
-           so we need to compute these values again before we use
-           them. */
-        result = new_weakref(ob, callback);
-        if (result != NULL) {
-            get_basic_refs(*list, &ref, &proxy);
-            if (callback == NULL) {
-                if (ref == NULL)
-                    insert_head(result, list);
-                else {
-                    /* Someone else added a ref without a callback
-                       during GC.  Return that one instead of this one
-                       to avoid violating the invariants of the list
-                       of weakrefs for ob. */
-                    Py_DECREF(result);
-                    Py_INCREF(ref);
-                    result = ref;
-                }
-            }
-            else {
-                PyWeakReference *prev;
+    if (callback != NULL) {
+        PyErr_Format(PyExc_TypeError,
+            "weakrefs no longer support callbacks");
+        return NULL;
+    }
 
-                prev = (proxy == NULL) ? ref : proxy;
-                if (prev == NULL)
-                    insert_head(result, list);
-                else
-                    insert_after(result, prev);
-            }
-        }
+    ptr = _PY_GETWEAKREFPTR(ob);
+
+    /* XXX FIXME We should have some sort of fake critical section to
+     * ensure the tracing GC doesn't activate and delete the weakref */
+
+    /* Use the existing ref if there is one */
+    ref = (PyWeakReference *)AO_load_full((AO_t *)ptr);
+    if (ref != NULL) {
+        Py_INCREF(ref);
+        return (PyObject *)ref;
     }
-    return (PyObject *) result;
+
+    /* If there isn't a ref we start creating one */
+    ref = PyObject_NEW(PyWeakReference, &_PyWeakref_Type);
+    ref->crit = PyCritical_Allocate(PyCRITICAL_WEAKREF_REF);
+    if (ref->crit == NULL) {
+        PyObject_DEL(ref);
+        PyErr_NoMemory();
+        return NULL;
+    }
+    ref->hash = (AO_t)-1;
+    ref->wr_object = ob;
+    ref->handle_links.prev = &ref->handle_links;
+    ref->handle_links.next = &ref->handle_links;
+    ref->binding_links.prev = &ref->binding_links;
+    ref->binding_links.next = &ref->binding_links;
+
+    if (!AO_compare_and_swap_full((AO_t *)ptr, (AO_t)NULL, (AO_t)ref)) {
+        /* Another thread beat us to it.  Use theirs instead. */
+        Py_DECREF(ref);
+        ref = (PyWeakReference *)AO_load_full((AO_t *)ptr);
+        assert(ref != NULL);
+    }
+
+    /* ob has the original reference, so we need another one to return
+     * to our caller */
+    Py_INCREF(ref);
+    return (PyObject *)ref;
 }
 
 
+/* Unlike the old function, this DOES include an INCREF */
 PyObject *
-PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
+PyWeakref_GetObjectEx(PyObject *ref_)
 {
-    PyWeakReference *result = NULL;
-    PyWeakReference **list;
-    PyWeakReference *ref, *proxy;
+    PyObject *ob;
+    PyWeakReference *ref = (PyWeakReference *)ref_;
 
-    if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
-        PyErr_Format(PyExc_TypeError,
-		     "cannot create weak reference to '%s' object",
-                     Py_Type(ob)->tp_name);
+    if (ref == NULL || !PyWeakref_Check(ref)) {
+        PyErr_BadInternalCall();
         return NULL;
     }
-    list = GET_WEAKREFS_LISTPTR(ob);
-    get_basic_refs(*list, &ref, &proxy);
-    if (callback == Py_None)
-        callback = NULL;
-    if (callback == NULL)
-        /* attempt to return an existing weak reference if it exists */
-        result = proxy;
-    if (result != NULL)
-        Py_INCREF(result);
-    else {
-        /* Note: new_weakref() can trigger cyclic GC, so the weakref
-           list on ob can be mutated.  This means that the ref and
-           proxy pointers we got back earlier may have been collected,
-           so we need to compute these values again before we use
-           them. */
-        result = new_weakref(ob, callback);
-        if (result != NULL) {
-            PyWeakReference *prev;
 
-            if (PyCallable_Check(ob))
-                Py_Type(result) = &_PyWeakref_CallableProxyType;
-            else
-                Py_Type(result) = &_PyWeakref_ProxyType;
-            get_basic_refs(*list, &ref, &proxy);
-            if (callback == NULL) {
-                if (proxy != NULL) {
-                    /* Someone else added a proxy without a callback
-                       during GC.  Return that one instead of this one
-                       to avoid violating the invariants of the list
-                       of weakrefs for ob. */
-                    Py_DECREF(result);
-                    Py_INCREF(result = proxy);
-                    goto skip_insert;
-                }
-                prev = ref;
-            }
-            else
-                prev = (proxy == NULL) ? ref : proxy;
+    PyCritical_Enter(ref->crit);
+    ob = ref->wr_object;
+    Py_XINCREF(ob);
+    PyCritical_Exit(ref->crit);
 
-            if (prev == NULL)
-                insert_head(result, list);
-            else
-                insert_after(result, prev);
-        skip_insert:
-            ;
+    return ob;
+}
+
+int
+_PyWeakref_TryDelete(PyObject *object, PyWeakReference *ref)
+{
+    PyCritical_Enter(ref->crit);
+    assert(ref->wr_object == object);
+    if (Py_RefcntSnoop(object) != 1) {
+        /* Brought back from the brink of death! */
+        PyCritical_Exit(ref->crit);
+        return 1;
+    } else {
+        ref->wr_object = NULL;
+
+        while (!PyLinkedList_Empty(&ref->handle_links)) {
+            PyDeathQueueHandle *handle = PyLinkedList_Restore(
+                PyDeathQueueHandle, weakref_links, ref->handle_links.next);
+
+            PyCritical_Enter(handle->crit);
+            assert(handle->queue != NULL);
+            PyCritical_Enter(handle->queue->crit);
+
+            PyLinkedList_Remove(&handle->weakref_links);
+            handle->weakref = NULL;
+            /* There should always be one reference remaining, borrowed
+             * from the caller. */
+            Py_DECREF(ref);
+
+            PyLinkedList_Remove(&handle->queue_links);
+            PyLinkedList_Append(&handle->queue->dead_links, &handle->queue_links);
+            PyThread_cond_wakeall(handle->queue->cond);
+
+            PyCritical_Exit(handle->queue->crit);
+            PyCritical_Exit(handle->crit);
         }
+
+        PyCritical_Exit(ref->crit);
+
+        _PyWeakref_ClearBindings(object, ref);
+
+        return 0;
     }
-    return (PyObject *) result;
 }
 
+/* XXX This version will actually be called by Py_Dealloc and may
+ * indicate the object is not to be deleted after all. */
+/* XXX FIXME this whole function should get moved into gcmodule.c */
+int
+_PyObject_TryClearWeakref(PyObject *object)
+{
+    PyWeakReference **ptr;
+    PyWeakReference *ref;
+    int result;
 
+    if (object == NULL ||
+            !PyType_SUPPORTS_WEAKREFS(Py_Type(object)) ||
+            !Py_RefcntMatches(object, 1)) {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+    ptr = _PY_GETWEAKREFPTR(object);
+
+    ref = (PyWeakReference *)AO_load_full((AO_t *)ptr);
+    if (ref == NULL)
+        return 0;
+    Py_INCREF(ref);
+
+    result = _PyWeakref_TryDelete(object, ref);
+
+    Py_DECREF(ref);
+    return result;
+}
+
+
 PyObject *
-PyWeakref_GetObject(PyObject *ref)
+PyWeakref_NewBinding(PyObject *ob, PyObject *value)
 {
-    if (ref == NULL || !PyWeakref_Check(ref)) {
-        PyErr_BadInternalCall();
+    PyWeakReference *ref;
+    PyWeakBinding *bind;
+
+    bind = PyObject_NEW(PyWeakBinding, &_PyWeakBinding_Type);
+    if (bind == NULL)
         return NULL;
+
+    ref = (PyWeakReference *)PyWeakref_NewRef(ob, NULL);
+    if (ref == NULL) {
+        PyObject_DEL(bind);
+        return NULL;
     }
-    return PyWeakref_GET_OBJECT(ref);
+
+    PyCritical_Enter(ref->crit);
+    assert(ref->wr_object != NULL);
+    bind->weakref = ref;
+    Py_INCREF(value); /* This is actually owned by ob */
+    bind->value = value;
+    PyLinkedList_Append(&ref->binding_links, &bind->weakref_links);
+    PyCritical_Exit(ref->crit);
+
+    return (PyObject *)bind;
 }
 
-/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
- * handle_weakrefs().
- */
-static void
-handle_callback(PyWeakReference *ref, PyObject *callback)
+PyObject *
+PyWeakref_GetBindingObject(PyObject *bind_, PyObject **value)
 {
-    PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
+    PyObject *ob;
+    PyWeakBinding *bind = (PyWeakBinding *)bind_;
 
-    if (cbresult == NULL)
-        PyErr_WriteUnraisable(callback);
-    else
-        Py_DECREF(cbresult);
+    if (bind == NULL || !PyWeakBinding_Check(bind) || value == NULL) {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
+
+    PyCritical_Enter(bind->weakref->crit);
+    if (!PyLinkedList_Detatched(&bind->weakref_links) &&
+            bind->weakref->wr_object != NULL) {
+        ob = bind->weakref->wr_object;
+        Py_INCREF(ob);
+        *value = bind->value;
+        Py_INCREF(*value);
+        PyCritical_Exit(bind->weakref->crit);
+        return ob;
+    } else {
+        PyCritical_Exit(bind->weakref->crit);
+        *value = NULL;
+        return NULL;
+    }
 }
 
-/* This function is called by the tp_dealloc handler to clear weak references.
- *
- * This iterates through the weak references for 'object' and calls callbacks
- * for those references which have one.  It returns when all callbacks have
- * been attempted.
- */
 void
-PyObject_ClearWeakRefs(PyObject *object)
+_PyWeakref_ClearBindings(PyObject *ob, PyWeakReference *ref)
 {
-    PyWeakReference **list;
+    /* Deleting the values may cause another binding to be deleted,
+     * reentering the critical section.  Thus the hoops about making
+     * sure all the bindings we want stay alive long enough, and exiting
+     * the critical section while calling DECREF */
+    PyLinkedList *binding_links;
+    PyWeakBinding *bind;
+    PyObject *value;
 
-    if (object == NULL
-        || !PyType_SUPPORTS_WEAKREFS(Py_Type(object))
-        || object->ob_refcnt != 0) {
-        PyErr_BadInternalCall();
-        return;
+    PyCritical_Enter(ref->crit);
+    binding_links = &ref->binding_links;
+    assert(ref->wr_object == NULL);
+
+    while (PyLinkedList_Next(&ref->binding_links, &binding_links)) {
+        bind = PyLinkedList_Restore(PyWeakBinding, weakref_links,
+            binding_links);
+        Py_INCREF(bind);
     }
-    list = GET_WEAKREFS_LISTPTR(object);
-    /* Remove the callback-less basic and proxy references */
-    if (*list != NULL && (*list)->wr_callback == NULL) {
-        clear_weakref(*list);
-        if (*list != NULL && (*list)->wr_callback == NULL)
-            clear_weakref(*list);
+
+    while (!PyLinkedList_Empty(&ref->binding_links)) {
+        bind = PyLinkedList_Restore(PyWeakBinding, weakref_links,
+            ref->binding_links.next);
+
+        PyLinkedList_Remove(&bind->weakref_links);
+        value = bind->value;
+        bind->value = NULL;
+
+        PyCritical_Exit(ref->crit);
+        Py_DECREF(bind);
+        Py_DECREF(value);
+        PyCritical_Enter(ref->crit);
     }
-    if (*list != NULL) {
-        PyWeakReference *current = *list;
-        Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
-        int restore_error = PyErr_Occurred() ? 1 : 0;
-        PyObject *err_type, *err_value, *err_tb;
 
-        if (restore_error)
-            PyErr_Fetch(&err_type, &err_value, &err_tb);
-        if (count == 1) {
-            PyObject *callback = current->wr_callback;
+    PyCritical_Exit(ref->crit);
+}
 
-            current->wr_callback = NULL;
-            clear_weakref(current);
-            if (callback != NULL) {
-                handle_callback(current, callback);
-                Py_DECREF(callback);
-            }
-        }
-        else {
-            PyObject *tuple;
-            Py_ssize_t i = 0;
-    
-            tuple = PyTuple_New(count * 2);
-            if (tuple == NULL) {
-                if (restore_error)
-                    PyErr_Fetch(&err_type, &err_value, &err_tb);
-                return;
-            }
+static void
+weakbind_dealloc(PyWeakBinding *bind)
+{
+    PyCritical_Enter(bind->weakref->crit);
+    if (!PyLinkedList_Detatched(&bind->weakref_links)) {
+        PyObject *value;
+        assert(bind->value);
+        PyLinkedList_Remove(&bind->weakref_links);
+        value = bind->value;
+        bind->value = NULL;
+        /* At this point we've taken ob's reference to value and now
+         * own it directly. */
+        PyCritical_Exit(bind->weakref->crit);
+        Py_DECREF(value);
+    } else
+        PyCritical_Exit(bind->weakref->crit);
 
-            for (i = 0; i < count; ++i) {
-                PyWeakReference *next = current->wr_next;
+    if (Py_RefcntSnoop(bind) != 1) {
+        /* Another thread is trying to manipulate us.  Probably a
+         * clearing all the bindings for a weakref.  We can finish
+         * deleting later. */
+        PyObject_REVIVE(bind);
+        Py_DECREF_ASYNC(bind);
+        return;
+    }
 
-                Py_INCREF(current);
-                PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
-                PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
-                current->wr_callback = NULL;
-                clear_weakref(current);
-                current = next;
-            }
-            for (i = 0; i < count; ++i) {
-                PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
+    Py_DECREF(bind->weakref);
 
-                if (callback != NULL) {
-                    PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
-                    handle_callback((PyWeakReference *)item, callback);
-                }
-            }
-            Py_DECREF(tuple);
-        }
-        if (restore_error)
-            PyErr_Restore(err_type, err_value, err_tb);
+    PyObject_DEL(bind);
+}
+
+static int
+weakbind_traverse(PyWeakBinding *bind, visitproc visit, void *arg)
+{
+    Py_VISIT(bind->weakref);
+    return 0;
+}
+
+static PyObject *
+weakbind_call(PyObject *bind, PyObject *args, PyObject *kw)
+{
+    static char *kwlist[] = {NULL};
+    PyObject *ob, *value;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist))
+        return NULL;
+
+    ob = PyWeakref_GetBindingObject(bind, &value);
+
+    if (ob == NULL)
+        return Py_BuildValue("OO", Py_None, Py_None);
+    else
+        return Py_BuildValue("NN", ob, value);
+}
+
+static PyObject *
+weakbind_repr(PyWeakBinding *bind)
+{
+    char buffer[256];
+    PyObject *ob, *value;
+
+    ob = PyWeakref_GetBindingObject((PyObject *)bind, &value);
+
+    if (ob == NULL)
+        PyOS_snprintf(buffer, sizeof(buffer), "<weakbinding at %p; dead>", bind);
+    else {
+        PyOS_snprintf(buffer, sizeof(buffer),
+            "<weakbinding at %p; from '%.50s' at %p to '%.50s' at %p>",
+            bind, Py_Type(ob)->tp_name, ob, Py_Type(value)->tp_name, value);
+        Py_DECREF(ob);
+        Py_DECREF(value);
     }
+
+    return PyUnicode_FromString(buffer);
 }
+
+static int
+parse_weakbind_init_args(char *funcname, PyObject *args, PyObject *kwargs,
+                        PyObject **obp, PyObject **valuep)
+{
+    /* XXX Should check that kwargs == NULL or is empty. */
+    return PyArg_UnpackTuple(args, funcname, 2, 2, obp, valuep);
+}
+
+static PyObject *
+weakbind___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *ob, *value;
+
+    if (!parse_weakbind_init_args("__new__", args, kwargs, &ob, &value))
+        return NULL;
+
+    return PyWeakref_NewBinding(ob, value);
+}
+
+static int
+weakbind___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *ob, *value;
+
+    if (parse_weakbind_init_args("__init__", args, kwargs, &ob, &value))
+        return 0;
+    else
+        return 1;
+}
+
+
+PyTypeObject
+_PyWeakBinding_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "weakbinding",
+    sizeof(PyWeakBinding),
+    0,
+    (destructor)weakbind_dealloc,  /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_compare*/
+    (reprfunc)weakbind_repr,    /*tp_repr*/
+    0,                          /*tp_as_number*/
+    0,                          /*tp_as_sequence*/
+    0,                          /*tp_as_mapping*/
+    0,                          /*tp_hash*/
+    weakbind_call,              /*tp_call*/
+    0,                          /*tp_str*/
+    0,                          /*tp_getattro*/
+    0,                          /*tp_setattro*/
+    0,                          /*tp_as_buffer*/
+    /* subclassing is unsupported */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+        Py_TPFLAGS_SHAREABLE,  /*tp_flags*/
+    0,                          /*tp_doc*/
+    (traverseproc)weakbind_traverse,  /*tp_traverse*/
+    0,                          /*tp_clear*/
+    0,                          /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    0,                          /*tp_methods*/
+    0,                          /*tp_members*/
+    0,                          /*tp_getset*/
+    0,                          /*tp_base*/
+    0,                          /*tp_dict*/
+    0,                          /*tp_descr_get*/
+    0,                          /*tp_descr_set*/
+    0,                          /*tp_dictoffset*/
+    weakbind___init__,          /*tp_init*/
+    weakbind___new__,           /*tp_new*/
+};
Index: Objects/unicodeobject.c
===================================================================
--- Objects/unicodeobject.c	(revision 58355)
+++ Objects/unicodeobject.c	(working copy)
@@ -41,6 +41,7 @@
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
+#include "pythread.h"
 
 #include "unicodeobject.h"
 #include "ucnhash.h"
@@ -51,6 +52,8 @@
 #include <windows.h>
 #endif
 
+//#define USE_UNICODE_FREELIST
+
 /* Limit for the Unicode object free list */
 
 #define MAX_UNICODE_FREELIST_SIZE       1024
@@ -94,6 +97,21 @@
 extern "C" {
 #endif
 
+/* Use only if you know it's a string */
+static inline int
+PyUnicode_SnoopState(PyUnicodeObject *op)
+{
+    /* XXX Just what is required here?  This all needs to be audited/fixed anyway.. */
+    //return (int)AO_load_full(&op->state);
+    return (int)AO_load_acquire(&op->state);
+}
+
+static inline void
+PyUnicode_SetState(PyUnicodeObject *op, int state)
+{
+    AO_store_full(&op->state, state);
+}
+
 /* This dictionary holds all interned unicode strings.  Note that references
    to strings in this dictionary are *not* counted in the string's ob_refcnt.
    When the interned string reaches a refcnt of 0 the string deallocation
@@ -103,10 +121,16 @@
    count of a string is:  s->ob_refcnt + (s->ob_sstate?2:0)
 */
 static PyObject *interned;
+/* Some dict and list operations will be called while holding
+ * interned_critical.  This is dangerous, but presumably unavoidable. */
+static PyCritical *interned_critical;
 
+#ifdef USE_UNICODE_FREELIST
 /* Free list for Unicode objects */
 static PyUnicodeObject *unicode_freelist;
 static int unicode_freelist_size;
+static PyCritical *unicode_freelist_critical;
+#endif
 
 /* The empty Unicode object is shared to improve performance. */
 static PyUnicodeObject *unicode_empty;
@@ -248,35 +272,42 @@
         return unicode_empty;
     }
 
+#ifdef USE_UNICODE_FREELIST
     /* Unicode freelist & memory allocation */
+    PyCritical_Enter(unicode_freelist_critical);
     if (unicode_freelist) {
         unicode = unicode_freelist;
         unicode_freelist = *(PyUnicodeObject **)unicode;
         unicode_freelist_size--;
-	if (unicode->str) {
-	    /* Keep-Alive optimization: we only upsize the buffer,
-	       never downsize it. */
-	    if ((unicode->length < length) &&
+        PyCritical_Exit(unicode_freelist_critical);
+        if (unicode->str) {
+            /* Keep-Alive optimization: we only upsize the buffer,
+               never downsize it. */
+            if ((unicode->length < length) &&
                 unicode_resize(unicode, length) < 0) {
-		PyMem_DEL(unicode->str);
-		goto onError;
-	    }
-	}
+                PyMem_DEL(unicode->str);
+                goto onError;
+            }
+        }
         else {
-	    unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
+            unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
         }
         PyObject_INIT(unicode, &PyUnicode_Type);
     }
     else {
-        unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);
+        PyCritical_Exit(unicode_freelist_critical);
+#endif
+        unicode = PyObject_NEW(PyUnicodeObject, &PyUnicode_Type);
         if (unicode == NULL)
             return NULL;
-	unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
+        unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
+#ifdef USE_UNICODE_FREELIST
     }
+#endif
 
     if (!unicode->str) {
-	PyErr_NoMemory();
-	goto onError;
+        PyErr_NoMemory();
+        goto onError;
     }
     /* Initialize the first element to guard against cases where
      * the caller fails before initializing str -- unicode_resize()
@@ -294,55 +325,80 @@
     return unicode;
 
  onError:
-    _Py_ForgetReference((PyObject *)unicode);
-    PyObject_Del(unicode);
+    PyObject_DEL(unicode);
     return NULL;
 }
 
+/* There's many assumptions built in here about what we can do safely. */
 static
 void unicode_dealloc(register PyUnicodeObject *unicode)
 {
-    switch (PyUnicode_CHECK_INTERNED(unicode)) {
-        case SSTATE_NOT_INTERNED:
-            break;
+    int state = PyUnicode_SnoopState(unicode);
+    assert(Py_RefcntSnoop(unicode) == 1);
+    assert(unicode->state == SSTATE_NOT_INTERNED ||
+        unicode->state == SSTATE_INTERNED);
 
-        case SSTATE_INTERNED_MORTAL:
-            /* revive dead object temporarily for DelItem */
-            Py_Refcnt(unicode) = 3;
-            if (PyDict_DelItem(interned, (PyObject *)unicode) != 0)
-                Py_FatalError(
-                    "deletion of interned unicode string failed");
-            break;
+    if (state == SSTATE_INTERNED) {
+        PyCritical_Enter(interned_critical);
+        if (Py_RefcntSnoop(unicode) > 1) {
+            PyCritical_Exit(interned_critical);
+            /* An asynchronous DECREF is used to ensure we
+             * don't become recursive and risk blowing our
+             * stack. */
+            PyObject_REVIVE(unicode);
+            Py_DECREF_ASYNC(unicode);
+            return;
+        }
 
-        case SSTATE_INTERNED_IMMORTAL:
-            Py_FatalError("Immortal interned unicode string died.");
+        /* We got a refcnt of 0 then we must be the owner of it, and the
+         * only remaining reference is this interned, which we hold the
+         * lock to.  Thus, we can safely alter the refcnt. */
+        /* We're assuming PyDict_DelItem won't do anything that might
+         * release the PyState */
+        //((PyObject *)unicode)->ob_refowner = (AO_t)PyThreadState_Get();
+        //((PyObject *)unicode)->ob_refcnt = 3;
+        Py_INCREF(unicode);
+        Py_INCREF(unicode);
+        if (PyDict_DelItem(interned, (PyObject *)unicode) != 0)
+            Py_FatalError("deletion of interned unicode string failed");
 
-        default:
-            Py_FatalError("Inconsistent interned unicode string state.");
+        assert(Py_RefcntSnoop(unicode) == 1);
+
+        //((PyObject *)unicode)->ob_refcnt = 0;
+
+        PyCritical_Exit(interned_critical);
     }
 
+#ifdef USE_UNICODE_FREELIST
+    PyCritical_Enter(unicode_freelist_critical);
     if (PyUnicode_CheckExact(unicode) &&
 	unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) {
+	PyObject *defenc;
         /* Keep-Alive optimization */
 	if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
 	    PyMem_DEL(unicode->str);
 	    unicode->str = NULL;
 	    unicode->length = 0;
 	}
-	if (unicode->defenc) {
-	    Py_DECREF(unicode->defenc);
-	    unicode->defenc = NULL;
-	}
+	defenc = unicode->defenc;
+	unicode->defenc = NULL;
 	/* Add to free list */
         *(PyUnicodeObject **)unicode = unicode_freelist;
         unicode_freelist = unicode;
         unicode_freelist_size++;
+	PyCritical_Exit(unicode_freelist_critical);
+	Py_XDECREF(defenc);
     }
     else {
+	PyCritical_Exit(unicode_freelist_critical);
+#endif
 	PyMem_DEL(unicode->str);
 	Py_XDECREF(unicode->defenc);
-	Py_Type(unicode)->tp_free((PyObject *)unicode);
+	assert(Py_RefcntSnoop(unicode) == 1);
+        PyObject_DEL(unicode);
+#ifdef USE_UNICODE_FREELIST
     }
+#endif
 }
 
 int PyUnicode_Resize(PyObject **unicode, Py_ssize_t length)
@@ -355,7 +411,7 @@
 	return -1;
     }
     v = (PyUnicodeObject *)*unicode;
-    if (v == NULL || !PyUnicode_Check(v) || Py_Refcnt(v) != 1 || length < 0) {
+    if (v == NULL || !PyUnicode_Check(v) || !Py_RefcntMatches(v, 1) || length < 0) {
 	PyErr_BadInternalCall();
 	return -1;
     }
@@ -4012,7 +4068,7 @@
 /* Charmap encoding: the lookup table */
 
 struct encoding_map{
-  PyObject_HEAD
+  PyObject_VAR_HEAD
   unsigned char level1[32];
   int count2, count3;
   unsigned char level23[1];
@@ -4035,14 +4091,14 @@
 static void
 encoding_map_dealloc(PyObject* o)
 {
-	PyObject_FREE(o);
+	PyObject_Del(o);
 }
 
 static PyTypeObject EncodingMapType = {
 	PyVarObject_HEAD_INIT(NULL, 0)
         "EncodingMap",          /*tp_name*/
         sizeof(struct encoding_map),   /*tp_basicsize*/
-        0,                      /*tp_itemsize*/
+        sizeof(char),           /*tp_itemsize*/
         /* methods */
         encoding_map_dealloc,   /*tp_dealloc*/
         0,                      /*tp_print*/
@@ -4076,9 +4132,7 @@
         0,                      /*tp_descr_set*/
         0,                      /*tp_dictoffset*/
         0,                      /*tp_init*/
-        0,                      /*tp_alloc*/
         0,                      /*tp_new*/
-        0,                      /*tp_free*/
         0,                      /*tp_is_gc*/
 };
 
@@ -4157,11 +4211,14 @@
     }
 
     /* Create a three-level trie */
-    result = PyObject_MALLOC(sizeof(struct encoding_map) +
-                             16*count2 + 128*count3 - 1);
-    if (!result)
-        return PyErr_NoMemory();
-    PyObject_Init(result, &EncodingMapType);
+    //result = PyObject_MALLOC(sizeof(struct encoding_map) +
+    //                         16*count2 + 128*count3 - 1);
+    //if (!result)
+    //    return PyErr_NoMemory();
+    //PyObject_Init(result, &EncodingMapType);
+    result = PyObject_NewVar(&EncodingMapType, 16*count2 + 128*count3 - 1);
+    if (result == NULL)
+        return NULL;
     mresult = (struct encoding_map*)result;
     mresult->count2 = count2;
     mresult->count3 = count3;
@@ -7848,7 +7905,11 @@
 static PyObject*
 unicode_freelistsize(PyUnicodeObject *self)
 {
-    return PyInt_FromLong(unicode_freelist_size);
+    int size;
+    PyCritical_Enter(unicode_freelist_critical);
+    size = unicode_freelist_size;
+    PyCritical_Exit(unicode_freelist_critical);
+    return PyInt_FromLong(size);
 }
 #endif
 
@@ -8855,15 +8916,15 @@
 	if (tmp == NULL)
 		return NULL;
 	assert(PyUnicode_Check(tmp));
-	pnew = (PyUnicodeObject *) type->tp_alloc(type, n = tmp->length);
+	n = tmp->length;
+	pnew = PyObject_NEW(PyUnicodeObject, type);
 	if (pnew == NULL) {
 		Py_DECREF(tmp);
 		return NULL;
 	}
 	pnew->str = PyMem_NEW(Py_UNICODE, n+1);
 	if (pnew->str == NULL) {
-		_Py_ForgetReference((PyObject *)pnew);
-		PyObject_Del(pnew);
+		PyObject_DEL(pnew);
 		Py_DECREF(tmp);
 		return PyErr_NoMemory();
 	}
@@ -8874,6 +8935,12 @@
 	return (PyObject *)pnew;
 }
 
+static int
+unicode_isshareable (PyObject *v)
+{
+	return PyUnicode_CheckExact(v);
+}
+
 PyDoc_STRVAR(unicode_doc,
 "str(string [, encoding[, errors]]) -> object\n\
 \n\
@@ -8905,7 +8972,8 @@
     0,			 		/* tp_setattro */
     &unicode_as_buffer,			/* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
-        Py_TPFLAGS_UNICODE_SUBCLASS,	/* tp_flags */
+        Py_TPFLAGS_UNICODE_SUBCLASS |
+        Py_TPFLAGS_SHAREABLE,		/* tp_flags */
     unicode_doc,			/* tp_doc */
     0,					/* tp_traverse */
     0,					/* tp_clear */
@@ -8922,15 +8990,37 @@
     0,					/* tp_descr_set */
     0,					/* tp_dictoffset */
     0,					/* tp_init */
-    0,					/* tp_alloc */
     unicode_new,			/* tp_new */
-    PyObject_Del,      		/* tp_free */
+    0,					/* tp_is_gc */
+    0,					/* tp_bases */
+    0,					/* tp_mro */
+    0,					/* tp_cache */
+    0,					/* tp_subclasses */
+    0,					/* tp_weaklist */
+    unicode_isshareable,		/* tp_isshareable */
 };
 
 /* Initialize the Unicode implementation */
 
-void _PyUnicode_Init(void)
+/* Even type and object's initialization calls us, so we need a bare
+ * minimum of functionality to be ready even before them. */
+void
+_PyUnicode_PreInit(void)
 {
+    interned_critical = PyCritical_Allocate(PyCRITICAL_NORMAL);
+    if (!interned_critical)
+        Py_FatalError("unable to allocate lock");
+
+#ifdef USE_UNICODE_FREELIST
+    unicode_freelist_critical = PyCritical_Allocate(PyCRITICAL_NORMAL);
+    if (!unicode_freelist_critical)
+        Py_FatalError("unable to allocate lock");
+#endif
+}
+
+void
+_PyUnicode_Init(void)
+{
     int i;
 
     /* XXX - move this array to unicodectype.c ? */
@@ -8946,8 +9036,10 @@
     };
 
     /* Init the implementation */
-    unicode_freelist = NULL;
-    unicode_freelist_size = 0;
+#ifdef USE_UNICODE_FREELIST
+    assert(unicode_freelist == NULL && unicode_freelist_size == 0 &&
+	unicode_empty == NULL);
+#endif
     unicode_empty = _PyUnicode_New(0);
     if (!unicode_empty)
 	return;
@@ -8983,6 +9075,7 @@
 	}
     }
 
+#ifdef USE_UNICODE_FREELIST
     for (u = unicode_freelist; u != NULL;) {
 	PyUnicodeObject *v = u;
 	u = *(PyUnicodeObject **)u;
@@ -8993,64 +9086,76 @@
     }
     unicode_freelist = NULL;
     unicode_freelist_size = 0;
+#endif
 }
 
 void
-PyUnicode_InternInPlace(PyObject **p)
+_PyUnicode_PostFini(void)
 {
-	register PyUnicodeObject *s = (PyUnicodeObject *)(*p);
-	PyObject *t;
-	if (s == NULL || !PyUnicode_Check(s))
-		Py_FatalError(
-		    "PyUnicode_InternInPlace: unicode strings only please!");
-	/* If it's a subclass, we don't really know what putting
-	   it in the interned dict might do. */
-	if (!PyUnicode_CheckExact(s))
-		return;
-	if (PyUnicode_CHECK_INTERNED(s))
-		return;
-	if (interned == NULL) {
-		interned = PyDict_New();
-		if (interned == NULL) {
-			PyErr_Clear(); /* Don't leave an exception */
-			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
+    PyCritical_Free(interned_critical);
+    interned_critical = NULL;
 
-	if (t) {
-		Py_INCREF(t);
-		Py_DECREF(*p);
-		*p = t;
-		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 */
-	Py_Refcnt(s) -= 2;
-	PyUnicode_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL;
+#ifdef USE_UNICODE_FREELIST
+    PyCritical_Free(unicode_freelist_critical);
+    unicode_freelist_critical = NULL;
+#endif
 }
 
 void
-PyUnicode_InternImmortal(PyObject **p)
+PyUnicode_InternInPlace(PyObject **p)
 {
-	PyUnicode_InternInPlace(p);
-	if (PyUnicode_CHECK_INTERNED(*p) != SSTATE_INTERNED_IMMORTAL) {
-		PyUnicode_CHECK_INTERNED(*p) = SSTATE_INTERNED_IMMORTAL;
-		Py_INCREF(*p);
-	}
+    register PyUnicodeObject *s = (PyUnicodeObject *)(*p);
+    PyObject *t;
+    if (s == NULL || !PyUnicode_Check(s))
+        Py_FatalError(
+            "PyUnicode_InternInPlace: unicode strings only please!");
+    /* If it's a subclass, we don't really know what putting
+       it in the interned dict might do. */
+    if (!PyUnicode_CheckExact(s))
+        return;
+    if (PyUnicode_SnoopState(s))
+        return;
+
+    PyCritical_Enter(interned_critical);
+    if (interned == NULL) {
+        interned = PyDict_New();
+        if (interned == NULL) {
+            PyCritical_Exit(interned_critical);
+            PyErr_Clear(); /* Don't leave an exception */
+            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) {
+        assert(PyUnicode_CheckExact(t));
+        Py_INCREF(t);
+        PyCritical_Exit(interned_critical);
+        Py_DECREF(*p);
+        *p = t;
+        return;
+    }
+
+    PyThreadState_Get()->recursion_critical = 1;
+    if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) {
+        PyCritical_Exit(interned_critical);
+        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 */
+    Py_DECREF(s);
+    Py_DECREF(s);
+    PyUnicode_SetState(s, SSTATE_INTERNED);
+    PyCritical_Exit(interned_critical);
 }
 
 PyObject *
@@ -9065,15 +9170,23 @@
 
 void _Py_ReleaseInternedUnicodeStrings(void)
 {
-	PyObject *keys;
-	PyUnicodeObject *s;
+	PyObject *keys, *temp;
 	Py_ssize_t i, n;
-	Py_ssize_t immortal_size = 0, mortal_size = 0;
+	Py_ssize_t mortal_size = 0;
+	PyThreadState *tstate = PyThreadState_Get();
 
-	if (interned == NULL || !PyDict_Check(interned))
+	PyCritical_Enter(interned_critical);
+	if (AO_load_full(&tstate->interp->tstate_count) != 1)
+		Py_FatalError("Attempting to release interned strings while "
+			"multiple threads exist");
+
+	if (interned == NULL || !PyDict_Check(interned)) {
+		PyCritical_Exit(interned_critical);
 		return;
+	}
 	keys = PyDict_Keys(interned);
 	if (keys == NULL || !PyList_Check(keys)) {
+		PyCritical_Exit(interned_critical);
 		PyErr_Clear();
 		return;
 	}
@@ -9087,31 +9200,30 @@
 	fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",
 		n);
 	for (i = 0; i < n; i++) {
-		s = (PyUnicodeObject *) PyList_GET_ITEM(keys, i);
-		switch (s->state) {
-		case SSTATE_NOT_INTERNED:
-			/* XXX Shouldn't happen */
-			break;
-		case SSTATE_INTERNED_IMMORTAL:
-			Py_Refcnt(s) += 1;
-			immortal_size += s->length;
-			break;
-		case SSTATE_INTERNED_MORTAL:
-			Py_Refcnt(s) += 2;
-			mortal_size += s->length;
-			break;
-		default:
+		PyUnicodeObject *s = (PyUnicodeObject *) PyList_GET_ITEM(keys, i);
+		void *owner = (void *)AO_load_full(&((PyObject *)s)->ob_refowner);
+		if (PyUnicode_SnoopState(s) != SSTATE_INTERNED)
 			Py_FatalError("Inconsistent interned string state.");
-		}
+
+		if (owner == (void *)Py_REFOWNER_STATICINIT) {
+			/* Inline _PyGC_RefMode_Promote */
+			((PyObject *)s)->ob_refowner = (AO_t)tstate;
+		} else if (owner != tstate)
+			Py_FatalError("Interned string has wrong owner");
+
+		Py_INCREF(s);
+		Py_INCREF(s);
+		mortal_size += s->length;
 		s->state = SSTATE_NOT_INTERNED;
 	}
 	fprintf(stderr, "total size of all interned strings: "
-			"%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d "
-			"mortal/immortal\n", mortal_size, immortal_size);
+			"%" PY_FORMAT_SIZE_T "d\n", mortal_size);
+	temp = interned;
+	interned = NULL;
+	PyCritical_Exit(interned_critical);
 	Py_DECREF(keys);
-	PyDict_Clear(interned);
-	Py_DECREF(interned);
-	interned = NULL;
+	PyDict_Clear(temp);
+	Py_DECREF(temp);
 }
 
 
@@ -9126,9 +9238,8 @@
 static void
 unicodeiter_dealloc(unicodeiterobject *it)
 {
-	_PyObject_GC_UNTRACK(it);
 	Py_XDECREF(it->it_seq);
-	PyObject_GC_Del(it);
+	PyObject_DEL(it);
 }
 
 static int
@@ -9222,13 +9333,12 @@
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	it = PyObject_GC_New(unicodeiterobject, &PyUnicodeIter_Type);
+	it = PyObject_NEW(unicodeiterobject, &PyUnicodeIter_Type);
 	if (it == NULL)
 		return NULL;
 	it->it_index = 0;
 	Py_INCREF(seq);
 	it->it_seq = (PyUnicodeObject *)seq;
-	_PyObject_GC_TRACK(it);
 	return (PyObject *)it;
 }
 
Index: Objects/tupleobject.c
===================================================================
--- Objects/tupleobject.c	(revision 58355)
+++ Objects/tupleobject.c	(working copy)
@@ -3,6 +3,10 @@
 
 #include "Python.h"
 
+#ifdef WITH_FREETHREAD
+#define MAXSAVESIZE 1  /* Disabled to remove lock contention */
+#endif
+
 /* Speed optimization to avoid frequent malloc/free of small tuples */
 #ifndef MAXSAVESIZE
 #define MAXSAVESIZE	20  /* Largest tuple to save on free list */
@@ -48,11 +52,11 @@
 		fast_tuple_allocs++;
 #endif
 		/* Inline PyObject_InitVar */
-#ifdef Py_TRACE_REFS
-		Py_Size(op) = size;
-		Py_Type(op) = &PyTuple_Type;
-#endif
-		_Py_NewReference((PyObject *)op);
+//#ifdef Py_TRACE_REFS
+//		Py_Size(op) = size;
+//		Py_Type(op) = &PyTuple_Type;
+//#endif
+//		_Py_NewReference((PyObject *)op);
 	}
 	else
 #endif
@@ -65,20 +69,20 @@
 		{
 			return PyErr_NoMemory();
 		}
-		op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
+		op = PyObject_NEWVAR(PyTupleObject, &PyTuple_Type, size);
 		if (op == NULL)
 			return NULL;
 	}
 	for (i=0; i < size; i++)
 		op->ob_item[i] = NULL;
 #if MAXSAVESIZE > 0
+	/* XXX FIXME this isn't threadsafe and should probably be done elsewhere */
 	if (size == 0) {
 		free_tuples[0] = op;
 		++num_free_tuples[0];
 		Py_INCREF(op);	/* extra INCREF so that this is never freed */
 	}
 #endif
-	_PyObject_GC_TRACK(op);
 	return (PyObject *) op;
 }
 
@@ -112,7 +116,7 @@
 {
 	register PyObject *olditem;
 	register PyObject **p;
-	if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
+	if (!PyTuple_Check(op) || !Py_RefcntMatches(op, 1)) {
 		Py_XDECREF(newitem);
 		PyErr_BadInternalCall();
 		return -1;
@@ -161,8 +165,6 @@
 {
 	register Py_ssize_t i;
 	register Py_ssize_t len =  Py_Size(op);
-	PyObject_GC_UnTrack(op);
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (len > 0) {
 		i = len;
 		while (--i >= 0)
@@ -175,13 +177,11 @@
 			op->ob_item[0] = (PyObject *) free_tuples[len];
 			num_free_tuples[len]++;
 			free_tuples[len] = op;
-			goto done; /* return */
+			return;
 		}
 #endif
 	}
-	Py_Type(op)->tp_free((PyObject *)op);
-done:
-	Py_TRASHCAN_SAFE_END(op)
+	PyObject_DEL(op);
 }
 
 static PyObject *
@@ -531,7 +531,7 @@
 	if (tmp == NULL)
 		return NULL;
 	assert(PyTuple_Check(tmp));
-	newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
+	newobj = PyObject_NewVar(type, n = PyTuple_GET_SIZE(tmp));
 	if (newobj == NULL)
 		return NULL;
 	for (i = 0; i < n; i++) {
@@ -634,6 +634,23 @@
 	0
 };
 
+static int
+tuple_isshareable (PyTupleObject *v)
+{
+    Py_ssize_t i;
+
+    if (AO_load_full(&v->shareable))
+        return 1;
+
+    for (i = 0; i < Py_Size(v); i++) {
+        if (!PyObject_IsShareable(PyTuple_GET_ITEM(v, i)))
+            return 0;
+    }
+
+    AO_store_full(&v->shareable, 1);
+    return 1;
+}
+
 static PyObject *tuple_iter(PyObject *seq);
 
 PyTypeObject PyTuple_Type = {
@@ -657,7 +674,8 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, /* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
 	tuple_doc,				/* tp_doc */
  	(traverseproc)tupletraverse,		/* tp_traverse */
 	0,					/* tp_clear */
@@ -674,9 +692,14 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	tuple_new,				/* tp_new */
-	PyObject_GC_Del,        		/* tp_free */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	(isshareablefunc)tuple_isshareable,	/* tp_isshareable */
 };
 
 /* The following function breaks the notion that tuples are immutable:
@@ -696,7 +719,8 @@
 
 	v = (PyTupleObject *) *pv;
 	if (v == NULL || Py_Type(v) != &PyTuple_Type ||
-	    (Py_Size(v) != 0 && Py_Refcnt(v) != 1)) {
+	    (Py_Size(v) != 0 && !Py_RefcntMatches(v, 1)) ||
+	    v == free_tuples[0]) {
 		*pv = 0;
 		Py_XDECREF(v);
 		PyErr_BadInternalCall();
@@ -715,32 +739,28 @@
 		return *pv == NULL ? -1 : 0;
 	}
 
-	/* XXX UNREF/NEWREF interface should be more symmetrical */
-	_Py_DEC_REFTOTAL;
-	_PyObject_GC_UNTRACK(v);
-	_Py_ForgetReference((PyObject *) v);
 	/* DECREF items deleted by shrinkage */
-	for (i = newsize; i < oldsize; i++) {
-		Py_XDECREF(v->ob_item[i]);
-		v->ob_item[i] = NULL;
-	}
-	sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
+	for (i = newsize; i < oldsize; i++)
+		Py_CLEAR(v->ob_item[i]);
+
+	sv = PyObject_RESIZE(PyTupleObject, v, newsize);
 	if (sv == NULL) {
 		*pv = NULL;
-		PyObject_GC_Del(v);
+		/* XXX FIXME this leaks any remaining contents */
+		PyObject_DEL(v);
 		return -1;
 	}
-	_Py_NewReference((PyObject *) sv);
-	/* Zero out items added by growing */
-	if (newsize > oldsize)
-		memset(&sv->ob_item[oldsize], 0,
-		       sizeof(*sv->ob_item) * (newsize - oldsize));
+
 	*pv = (PyObject *) sv;
-	_PyObject_GC_TRACK(sv);
 	return 0;
 }
 
 void
+_PyTuple_Init(void)
+{
+}
+
+void
 PyTuple_Fini(void)
 {
 #if MAXSAVESIZE > 0
@@ -756,7 +776,7 @@
 		while (p) {
 			q = p;
 			p = (PyTupleObject *)(p->ob_item[0]);
-			PyObject_GC_Del(q);
+			PyObject_DEL(q);
 		}
 	}
 #endif
@@ -773,9 +793,8 @@
 static void
 tupleiter_dealloc(tupleiterobject *it)
 {
-	_PyObject_GC_UNTRACK(it);
 	Py_XDECREF(it->it_seq);
-	PyObject_GC_Del(it);
+	PyObject_DEL(it);
 }
 
 static int
@@ -867,12 +886,11 @@
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
+	it = PyObject_NEW(tupleiterobject, &PyTupleIter_Type);
 	if (it == NULL)
 		return NULL;
 	it->it_index = 0;
 	Py_INCREF(seq);
 	it->it_seq = (PyTupleObject *)seq;
-	_PyObject_GC_TRACK(it);
 	return (PyObject *)it;
 }
Index: Objects/boolobject.c
===================================================================
--- Objects/boolobject.c	(revision 58355)
+++ Objects/boolobject.c	(working copy)
@@ -80,6 +80,12 @@
 	return PyBool_FromLong((a == Py_True) ^ (b == Py_True));
 }
 
+static int
+bool_isshareable (PyObject *self)
+{
+	return 1;
+}
+
 /* Doc string */
 
 PyDoc_STRVAR(bool_doc,
@@ -153,7 +159,7 @@
 	0,					/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
 	bool_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
@@ -170,8 +176,14 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	bool_new,				/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	bool_isshareable,			/* tp_isshareable */
 };
 
 /* The objects representing bool values False and True */
Index: Objects/rangeobject.c
===================================================================
--- Objects/rangeobject.c	(revision 58355)
+++ Objects/rangeobject.c	(working copy)
@@ -54,6 +54,8 @@
     rangeobject *obj = NULL;
     PyObject *start = NULL, *stop = NULL, *step = NULL;
 
+    if (!(type->tp_flags & Py_TPFLAGS_READY))
+        Py_FatalError("range type (or subtype) isn't initialized");
     if (!_PyArg_NoKeywords("range()", kw))
         return NULL;
 
@@ -81,7 +83,7 @@
             goto Fail;
     }
 
-    obj = PyObject_New(rangeobject, &PyRange_Type);
+    obj = PyObject_NEW(rangeobject, &PyRange_Type);
     if (obj == NULL)
         goto Fail;
     obj->start = start;
@@ -107,6 +109,7 @@
     Py_DECREF(r->start);
     Py_DECREF(r->stop);
     Py_DECREF(r->step);
+    PyObject_DEL(r);
 }
 
 /* Return number of items in range (lo, hi, step), when arguments are
@@ -291,7 +294,7 @@
 	PyObject_GenericGetAttr,  /* tp_getattro */
 	0,			/* tp_setattro */
 	0,			/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
 	range_doc,		/* tp_doc */
 	0,			/* tp_traverse */
 	0,			/* tp_clear */
@@ -308,7 +311,6 @@
 	0,			/* tp_descr_set */
 	0,			/* tp_dictoffset */
 	0,			/* tp_init */
-	0,			/* tp_alloc */
 	range_new,		/* tp_new */
 };
 
@@ -404,7 +406,6 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	rangeiter_new,				/* tp_new */
 };
 
@@ -440,7 +441,7 @@
 static PyObject *
 int_range_iter(long start, long stop, long step)
 {
-    rangeiterobject *it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
+    rangeiterobject *it = PyObject_NEW(rangeiterobject, &Pyrangeiter_Type);
     if (it == NULL)
         return NULL;
     it->start = start;
@@ -481,6 +482,7 @@
     Py_XDECREF(r->start);
     Py_XDECREF(r->step);
     Py_XDECREF(r->len);
+    PyObject_DEL(r);
 }
 
 static PyObject *
@@ -565,7 +567,7 @@
                       PyLong_AsLong(r->stop),
                       PyLong_AsLong(r->step));
 
-    it = PyObject_New(longrangeiterobject, &Pylongrangeiter_Type);
+    it = PyObject_NEW(longrangeiterobject, &Pylongrangeiter_Type);
     if (it == NULL)
         return NULL;
 
@@ -625,7 +627,7 @@
         return int_range_iter(new_start, new_stop, -step);
     }
 
-    it = PyObject_New(longrangeiterobject, &Pylongrangeiter_Type);
+    it = PyObject_NEW(longrangeiterobject, &Pylongrangeiter_Type);
     if (it == NULL)
         return NULL;
 
@@ -655,7 +657,7 @@
     it->step = PyNumber_Negative(range->step);
     if (!it->step) {
         Py_DECREF(it->start);
-        PyObject_Del(it);
+        PyObject_DEL(it);
         return NULL;
     }
 
@@ -672,6 +674,198 @@
 
 create_failure:
     Py_XDECREF(len);
-    PyObject_Del(it);
+    PyObject_DEL(it);
     return NULL;
 }
+
+
+/* DUMMY */
+PyTypeObject PyFakeRange_Type;
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *start;
+	PyObject *stop;
+	PyObject *step;
+	long	x_index;
+	long	x_start;
+	long	x_step;
+	long	x_len;
+} fakerangeobject;
+
+static PyObject *
+fakerange_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+    fakerangeobject *obj = NULL;
+    PyObject *start = NULL, *stop = NULL, *step = NULL;
+
+    if (!_PyArg_NoKeywords("range()", kw))
+        return NULL;
+
+    if (PyTuple_Size(args) <= 1) {
+        if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
+            goto Fail;
+        stop = PyNumber_Index(stop);
+        if (!stop)
+            goto Fail;
+        start = PyInt_FromLong(0);
+        step = PyInt_FromLong(1);
+        if (!start || !step)
+            goto Fail;
+    }
+    else {
+        if (!PyArg_UnpackTuple(args, "range", 2, 3,
+                               &start, &stop, &step))
+            goto Fail;
+
+        /* Convert borrowed refs to owned refs */
+        start = PyNumber_Index(start);
+        stop = PyNumber_Index(stop);
+        step = validate_step(step);
+        if (!start || !stop || !step)
+            goto Fail;
+    }
+
+    obj = PyObject_NEW(fakerangeobject, &PyFakeRange_Type);
+    if (obj == NULL)
+        goto Fail;
+    obj->start = start;
+    obj->stop = stop;
+    obj->step = step;
+    Py_INCREF(obj->start);
+    Py_INCREF(obj->stop);
+    Py_INCREF(obj->step);
+    obj->x_start = PyLong_AsLong(start);
+    //obj->x_stop = PyLong_AsLong(stop);
+    obj->x_step = PyLong_AsLong(step);
+    if (obj->x_step > 0)
+        obj->x_len = get_len_of_range(obj->x_start, PyLong_AsLong(stop), obj->x_step);
+    else
+        obj->x_len = get_len_of_range(PyLong_AsLong(stop), obj->x_start, -obj->x_step);
+    obj->x_index = 0;
+    return (PyObject *) obj;
+
+Fail:
+    //Py_XDECREF(start);
+    //Py_XDECREF(stop);
+    //Py_XDECREF(step);
+    return NULL;
+}
+
+static void
+fakerange_dealloc(rangeobject *r)
+{
+    printf("Fakerange dealloc\n");
+    Py_DECREF(r->start);
+    Py_DECREF(r->stop);
+    Py_DECREF(r->step);
+    r->start = NULL;
+    r->stop = NULL;
+    r->step = NULL;
+    PyObject_DEL(r);
+}
+
+static PyObject *
+fakerange_iter(PyObject *seq)
+{
+    Py_INCREF(seq);
+    return seq;
+}
+
+#include <pthread.h>
+AO_t rocky;
+AO_t bullwinkle[16];
+AO_t bob;
+
+static PyObject *
+fakerange_next(fakerangeobject *r)
+{
+#if 1
+    int i;
+    bullwinkle[0] = 0;
+    for (i = 0; i < 1000; i++) {
+        //AO_fetch_and_add1(&rocky);
+        //AO_fetch_and_sub1(&rocky);
+        //(void)AO_load_full(&bob);
+        //(void)AO_load_full(&bob);
+        //printf("%p %p\n", &rocky, &bob);
+        //static pthread_mutex_t rocky = PTHREAD_MUTEX_INITIALIZER;
+        //pthread_mutex_lock(&rocky);
+        //pthread_mutex_unlock(&rocky);
+        //static AO_t rocky;
+        //while (1) {
+        //    AO_t prev = AO_load_full(&rocky);
+        //    if (AO_compare_and_swap(&rocky, prev, prev + 1))
+        //        break;
+        //}
+        //while (1) {
+        //    AO_t prev = AO_load_full(&rocky);
+        //    if (AO_compare_and_swap(&rocky, prev, prev - 1))
+        //        break;
+        //}
+    }
+    if (r->x_index < r->x_len) {
+        r->x_index++;
+        //Py_INCREF(Py_None);
+        //return Py_None;
+        //free(malloc(sizeof(PyVarObject)+4));
+        Py_INCREF(r->start);
+        return r->start;
+    }
+    return NULL;
+#elif 0
+    if (r->x_index < r->x_len) {
+        PyObject *foo;
+        r->x_index++;
+        foo = PyInt_FromLong(100000);
+        //printf("Foo: %p\n", foo);
+        return foo;
+    }
+    return NULL;
+#else
+    if (r->x_index < r->x_len)
+        return PyInt_FromLong(r->x_start + (r->x_index++) * r->x_step);
+    return NULL;
+#endif
+}
+
+PyTypeObject PyFakeRange_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"fakerange",		/* Name of this type */
+	sizeof(fakerangeobject),	/* Basic object size */
+	0,			/* Item size for varobject */
+	(destructor)fakerange_dealloc, /* tp_dealloc */
+	0,			/* tp_print */
+	0,			/* tp_getattr */
+	0,			/* tp_setattr */
+	0,			/* tp_compare */
+	(reprfunc)range_repr,	/* tp_repr */
+	0,			/* tp_as_number */
+	&range_as_sequence,	/* tp_as_sequence */
+	0,			/* tp_as_mapping */
+	0,			/* tp_hash */
+	0,			/* tp_call */
+	0,			/* tp_str */
+	PyObject_GenericGetAttr,  /* tp_getattro */
+	0,			/* tp_setattro */
+	0,			/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
+	range_doc,		/* tp_doc */
+	0,			/* tp_traverse */
+	0,			/* tp_clear */
+	0,			/* tp_richcompare */
+	0,			/* tp_weaklistoffset */
+	fakerange_iter,		/* tp_iter */
+	(iternextfunc)fakerange_next,		/* tp_iternext */
+	range_methods,		/* tp_methods */
+	0,			/* tp_members */
+	0,			/* tp_getset */
+	0,			/* tp_base */
+	0,			/* tp_dict */
+	0,			/* tp_descr_get */
+	0,			/* tp_descr_set */
+	0,			/* tp_dictoffset */
+	0,			/* tp_init */
+	fakerange_new,		/* tp_new */
+};
+
Index: Objects/interruptobject.c
===================================================================
--- Objects/interruptobject.c	(revision 0)
+++ Objects/interruptobject.c	(revision 0)
@@ -0,0 +1,342 @@
+
+#include "Python.h"
+#include "interruptobject.h"
+#include "pystate.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* PyInterrupt */
+
+PyInterruptObject *
+PyInterrupt_New(void (*callback_c)(struct _PyInterruptQueue *, void *),
+		void *arg, PyObject *callback_python)
+{
+	PyInterruptObject *point;
+
+	if (!callback_c && !callback_python)
+		Py_FatalError("PyInterrupt_New called with no callback");
+	if (callback_c && callback_python)
+		Py_FatalError("PyInterrupt_New called with both callbacks");
+
+	point = PyObject_NEW(PyInterruptObject, &PyInterrupt_Type);
+	if (point == NULL)
+		return NULL;
+	point->lock = PyThread_lock_allocate();
+	if (!point->lock) {
+		PyObject_DEL(point);
+		PyErr_NoMemory();
+		return NULL;
+	}
+
+	Py_XINCREF(callback_python);
+	point->interrupted = 0;
+	point->parent = NULL;
+	point->child = NULL;
+	point->notify_parent_int_c = callback_c;
+	point->arg = arg;
+	point->notify_parent_int_python = callback_python;
+	point->next = NULL;
+
+	return point;
+}
+
+void
+PyInterrupt_Push(PyInterruptObject *point)
+{
+	int run_callbacks = 0;
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(point->parent == NULL);
+	assert(point->child == NULL);
+
+	point->parent = tstate->interrupt_point;
+	if (point->parent) {
+		PyThread_lock_acquire(point->parent->lock);
+		assert(point->parent->child == NULL);
+		point->parent->child = point;
+		if (point->parent->interrupted) {
+			run_callbacks = 1;
+		}
+		PyThread_lock_release(point->parent->lock);
+	}
+	tstate->interrupt_point = point;
+
+	if (run_callbacks) {
+		PyInterruptQueue queue;
+
+		PyInterruptQueue_Init(&queue);
+		PyInterruptQueue_AddFromParent(&queue, point);
+		PyInterruptQueue_Finish(&queue);
+	}
+}
+
+void
+PyInterrupt_Pop(PyInterruptObject *point)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(point->child == NULL);
+	if (point != tstate->interrupt_point)
+		Py_FatalError("Popping wrong interrupt point");
+
+	tstate->interrupt_point = point->parent;
+	if (point->parent != NULL) {
+		PyThread_lock_acquire(point->parent->lock);
+		assert(point->parent->child == point);
+		point->parent->child = NULL;
+		PyThread_lock_release(point->parent->lock);
+		point->parent = NULL;
+	}
+
+	PyThread_lock_acquire(point->lock);
+	/* Other threads may still reference us, but they'll now have no effect */
+	PyThread_lock_release(point->lock);
+}
+
+static void
+interrupt_dealloc(PyInterruptObject *point)
+{
+	assert(point->notify_parent_int_c || point->notify_parent_int_python);
+	assert(!(point->notify_parent_int_c && point->notify_parent_int_python));
+	assert(point->parent == NULL);
+	assert(point->child == NULL);
+	assert(point->next == NULL);
+
+	Py_XDECREF(point->notify_parent_int_python);
+	PyThread_lock_free(point->lock);
+}
+
+static int
+interrupt_traverse(PyInterruptObject *point, visitproc visit, void *arg)
+{
+	Py_VISIT(point->notify_parent_int_python);
+	return 0;
+}
+
+static PyObject *
+interrupt_interrupt(PyInterruptObject *point)
+{
+	PyInterruptQueue queue;
+
+	PyInterruptQueue_Init(&queue);
+	PyInterruptQueue_Add(&queue, point);
+	PyInterruptQueue_Finish(&queue);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static int
+interrupt_isshareable(PyObject *obj)
+{
+	return 1;
+}
+
+PyDoc_STRVAR(interrupt_doc,
+"FIXME");
+
+static PyMethodDef interrupt_methods[] = {
+	{"interrupt", (PyCFunction)interrupt_interrupt, METH_NOARGS|METH_SHARED, interrupt_doc},
+ 	{NULL,		NULL}		/* sentinel */
+};
+
+PyTypeObject PyInterrupt_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"Interrupt",
+	sizeof(PyInterruptObject),
+	0,
+	(destructor)interrupt_dealloc,		/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	0,					/* tp_repr */
+	0,					/* tp_as_number */
+	0,					/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	PyObject_GenericGetAttr,		/* tp_getattro */
+	0,					/* tp_setattro */
+	0,					/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ 	0,					/* tp_doc */
+ 	(traverseproc)interrupt_traverse,	/* tp_traverse */
+	0,					/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	interrupt_methods,			/* tp_methods */
+	0,					/* tp_members */
+	0,					/* tp_getset */
+	0,					/* tp_base */
+	0,					/* tp_dict */
+	0,					/* tp_descr_get */
+	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	interrupt_isshareable,			/* tp_isshareable */
+};
+
+
+void
+PyInterruptQueue_Init(PyInterruptQueue *queue)
+{
+	queue->head = NULL;
+	queue->tail = NULL;
+}
+
+void
+PyInterruptQueue_Add(PyInterruptQueue *queue, PyInterruptObject *point)
+{
+	PyThread_lock_acquire(point->lock);
+	if (!point->interrupted) {
+		point->interrupted = 1;
+
+		if (point->child)
+			PyInterruptQueue_AddFromParent(queue, point->child);
+	}
+	PyThread_lock_release(point->lock);
+}
+
+void
+PyInterruptQueue_AddFromParent(PyInterruptQueue *queue, PyInterruptObject *point)
+{
+	PyThread_lock_acquire(point->lock);
+	assert(point->next == NULL);
+	if (point->parent != NULL) {
+		if (point->notify_parent_int_c) {
+			point->notify_parent_int_c(queue, point->arg);
+		} else {
+			assert(point->notify_parent_int_python);
+			if (queue->tail) {
+				queue->tail->next = point;
+				queue->tail = point;
+			} else {
+				queue->head = point;
+				queue->tail = point;
+			}
+			Py_INCREF(point);
+		}
+	}
+	PyThread_lock_release(point->lock);
+}
+
+void
+PyInterruptQueue_Finish(PyInterruptQueue *queue)
+{
+	while (queue->head) {
+		PyObject *result;
+		PyInterruptObject *point = queue->head;
+		queue->head = point->next;
+		point->next = NULL;
+
+		/* XXX FIXME returning True should implicitly call
+		 * .interrupt().  Maybe? */
+		result = PyObject_CallObject(point->notify_parent_int_python, NULL);
+		if (result == NULL)
+			PyErr_WriteUnraisable(point->notify_parent_int_python);
+		else
+			Py_DECREF(result);
+
+		Py_DECREF(point);
+	}
+}
+
+
+/* Returns 0 if we're not in an interrupted state,
+ * 1 and raises an exception if we are */
+int
+PyCancel_Check(void)
+{
+    PyThreadState *tstate = PyThreadState_Get();
+
+    PyThread_lock_acquire(tstate->interrupt_point->lock);
+    if (tstate->interrupt_point->interrupted) {
+        PyThread_lock_release(tstate->interrupt_point->lock);
+        PyErr_SetNone(PyExc_Interrupted);
+        return 1;
+    }
+    PyThread_lock_release(tstate->interrupt_point->lock);
+    return 0;
+}
+
+
+#warning blah blah signal interrupt API should have retries
+/* XXX FIXME the signal handler thread should be used to send the signal multiple times, if the first attempt doesn't work.  Actually, the signal handler itself should mark it as received, and the retry should check if the call actually stopped.
+ * Or should whoever's running the interrupt callback do the retry?  Just have them stick around until the interruption process finishes.
+ */
+void
+PyCancel_SignalEnter(void)
+{
+    // wipe state
+    // allocate lock
+    // allocate semaphore
+    // setup interrupt callback
+    // PyState_Suspend();
+    // grab lock
+    // mark as active (interrupt callback may now actually send signal)
+    // release lock
+    Py_FatalError("PyCancel_SignalEnter not implemented");
+}
+
+void
+PyCancel_SignalExit(void)
+{
+    // grab lock
+    // mark as inactive
+    // post semaphore
+    // XXX FIXME blah, I need more work to coordinate teardown with the interrupt callback
+    // release lock
+    // PyState_Resume();
+    // Remove interrupt callback
+    // ??? release lock
+    // ??? release semaphore
+    // I need to track that the interrupt callback has started, and if so I have to wake them up and then either wait for them to signal me that they've exited, or let them do the cleanup.  The number of context switches seems the same either way, and I think it'd be simpler if it was always this function doing the cleanup.
+    // XXX FIXME this should also save errno
+    Py_FatalError("PyCancel_SignalExit not implemented");
+}
+
+int
+PyCancel_Poll(int fd)
+{
+    Py_FatalError("PyCancel_Poll not implemented");
+}
+
+#if 0
+int
+PyCancel_WaitForMultipleObjects(...)
+{
+    Py_FatalError("PyCancel_WaitForMultipleObjects not implemented");
+}
+#endif
+
+int
+PyCancel_Sleep(double secs)
+{
+    Py_FatalError("PyCancel_Sleep not implemented");
+}
+
+/* XXX FIXME consider replacing this with Sleep(Inf) */
+int
+PyCancel_SleepForever(void)
+{
+    Py_FatalError("PyCancel_SleepForever not implemented");
+}
+
+
+#ifdef __cplusplus
+}
+#endif
Index: Objects/descrobject.c
===================================================================
--- Objects/descrobject.c	(revision 58355)
+++ Objects/descrobject.c	(working copy)
@@ -2,14 +2,14 @@
 
 #include "Python.h"
 #include "structmember.h" /* Why is this not included in Python.h? */
+#include "monitorobject.h"
 
 static void
 descr_dealloc(PyDescrObject *descr)
 {
-	_PyObject_GC_UNTRACK(descr);
 	Py_XDECREF(descr->d_type);
 	Py_XDECREF(descr->d_name);
-	PyObject_GC_Del(descr);
+	PyObject_DEL(descr);
 }
 
 static PyObject *
@@ -58,6 +58,13 @@
 			  "<slot wrapper '%V' of '%s' objects>");
 }
 
+static PyObject *
+finalizeattr_repr(PyFinalizeAttrDescrObject *descr)
+{
+    return descr_repr((PyDescrObject *)descr,
+        "<finalizeattr '%V' of '%s' objects>");
+}
+
 static int
 descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
 {
@@ -134,6 +141,12 @@
 
 	if (descr_check((PyDescrObject *)descr, obj, &res))
 		return res;
+	if (PyMonitor_Check(obj) &&
+			!PyMonitorSpace_IsCurrent(PyMonitor_GetMonitorSpace(obj))) {
+		PyErr_SetString(PyExc_AttributeError,
+			descr->d_member->name);
+		return NULL;
+	}
 	return PyMember_GetOne((char *)obj, descr->d_member);
 }
 
@@ -163,9 +176,49 @@
 	return PyWrapper_New((PyObject *)descr, obj);
 }
 
+static PyObject *
+finalizeattr_get(PyFinalizeAttrDescrObject *descr, PyObject *obj, PyObject *type)
+{
+    PyObject *res, *core;
+
+    if (descr_check((PyDescrObject *)descr, obj, &res))
+        return res;
+
+    core = PyObject_GetAttrString(obj, "__finalizecore__");
+    if (core == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Clear();
+        Py_INCREF(Py_None);
+        core = Py_None;
+    }
+
+    if (core == NULL)
+        return NULL;
+
+    if (core == Py_None) {
+        PyObject *dict;
+
+        Py_DECREF(core);
+
+        dict = PyObject_GetAttrString(obj, "__dict__");
+        if (dict == NULL)
+            return NULL;
+
+        if (PyDict_GetItemEx(dict, descr->d_name, &res) > 0)
+            PyErr_Format(PyExc_AttributeError,
+                "'%.50s' object has no attribute '%.400s'",
+                ((PyTypeObject *)type)->tp_name,
+                PyUnicode_AsString(descr->d_name));
+        Py_DECREF(dict);
+        return res;
+    } else {
+        res = PyObject_GetAttr(core, descr->d_name);
+        Py_DECREF(core);
+        return res;
+    }
+}
+
 static int
-descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
-	       int *pres)
+descr_setcheck(PyDescrObject *descr, PyObject *obj)
 {
 	assert(obj != NULL);
 	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
@@ -175,8 +228,7 @@
 			     descr_name(descr), "?",
 			     descr->d_type->tp_name,
 			     obj->ob_type->tp_name);
-		*pres = -1;
-		return 1;
+		return -1;
 	}
 	return 0;
 }
@@ -184,20 +236,25 @@
 static int
 member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
 {
-	int res;
-
-	if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
-		return res;
+	if (descr_setcheck((PyDescrObject *)descr, obj))
+		return -1;
+	if (PyMonitor_Check(obj) &&
+			!PyMonitorSpace_IsCurrent(PyMonitor_GetMonitorSpace(obj))) {
+		PyErr_Format(PyExc_AttributeError,
+			"descriptor '%.200s' for '%.100s' objects "
+			"can't be applied from outside of Monitor",
+			descr->d_member->name,
+			descr->d_type->tp_name);
+		return -1;
+	}
 	return PyMember_SetOne((char *)obj, descr->d_member, value);
 }
 
 static int
 getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
 {
-	int res;
-
-	if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
-		return res;
+	if (descr_setcheck((PyDescrObject *)descr, obj))
+		return -1;
 	if (descr->d_getset->set != NULL)
 		return descr->d_getset->set(obj, value,
 					    descr->d_getset->closure);
@@ -208,6 +265,50 @@
 	return -1;
 }
 
+static int
+finalizeattr_set(PyFinalizeAttrDescrObject *descr, PyObject *obj, PyObject *value)
+{
+    PyObject *core;
+
+    if (descr_setcheck((PyDescrObject *)descr, obj))
+        return -1;
+
+    core = PyObject_GetAttrString(obj, "__finalizecore__");
+    if (core == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Clear();
+        Py_INCREF(Py_None);
+        core = Py_None;
+    }
+
+    if (core == NULL)
+        return -1;
+
+    if (core == Py_None) {
+        int res;
+        PyObject *dict;
+
+        Py_DECREF(core);
+
+        dict = PyObject_GetAttrString(obj, "__dict__");
+        if (dict == NULL)
+            return -1;
+
+        if (value == NULL)
+            res = PyDict_DelItem(dict, descr->d_name);
+        else
+            res = PyDict_SetItem(dict, descr->d_name, value);
+        Py_DECREF(dict);
+        return res;
+    } else {
+        if (PyObject_SetAttr(core, descr->d_name, value) == -1) {
+            Py_DECREF(core);
+            return -1;
+        }
+        Py_DECREF(core);
+        return 0;
+    }
+}
+
 static PyObject *
 methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
 {
@@ -375,6 +476,17 @@
 	{0}
 };
 
+static PyObject *
+finalizeattr_get_doc(PyFinalizeAttrDescrObject *descr, void *closure)
+{
+    return PyUnicode_FromString("Finalize Attribute proxy");
+}
+
+static PyGetSetDef finalizeattr_getset[] = {
+    {"__doc__", (getter)finalizeattr_get_doc},
+    {0}
+};
+
 static int
 descr_traverse(PyObject *self, visitproc visit, void *arg)
 {
@@ -383,6 +495,13 @@
 	return 0;
 }
 
+static int
+descr_isshareable(PyObject *self)
+{
+	/* XXX FIXME Pure hack */
+	return 1;
+}
+
 static PyTypeObject PyMethodDescr_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"method_descriptor",
@@ -403,7 +522,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	0,					/* tp_doc */
 	descr_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -441,7 +560,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	0,					/* tp_doc */
 	descr_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -478,7 +597,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	0,					/* tp_doc */
 	descr_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -493,6 +612,16 @@
 	0,					/* tp_dict */
 	(descrgetfunc)member_get,		/* tp_descr_get */
 	(descrsetfunc)member_set,		/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	descr_isshareable,			/* tp_isshareable */
 };
 
 static PyTypeObject PyGetSetDescr_Type = {
@@ -515,7 +644,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	0,					/* tp_doc */
 	descr_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -530,6 +659,16 @@
 	0,					/* tp_dict */
 	(descrgetfunc)getset_get,		/* tp_descr_get */
 	(descrsetfunc)getset_set,		/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	descr_isshareable,			/* tp_isshareable */
 };
 
 PyTypeObject PyWrapperDescr_Type = {
@@ -552,7 +691,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
 	0,					/* tp_doc */
 	descr_traverse,				/* tp_traverse */
 	0,					/* tp_clear */
@@ -567,14 +706,71 @@
 	0,					/* tp_dict */
 	(descrgetfunc)wrapperdescr_get,		/* tp_descr_get */
 	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	descr_isshareable,			/* tp_isshareable */
 };
 
+PyTypeObject PyFinalizeAttrDescr_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"finalizeattr_descriptor",
+	sizeof(PyFinalizeAttrDescrObject),
+	0,
+	(destructor)descr_dealloc,		/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	(reprfunc)finalizeattr_repr,		/* tp_repr */
+	0,					/* tp_as_number */
+	0,					/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	PyObject_GenericGetAttr,		/* tp_getattro */
+	0,					/* tp_setattro */
+	0,					/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
+	0,					/* tp_doc */
+	descr_traverse,				/* tp_traverse */
+	0,					/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	0,					/* tp_methods */
+	descr_members,				/* tp_members */
+	finalizeattr_getset,			/* tp_getset */
+	0,					/* tp_base */
+	0,					/* tp_dict */
+	(descrgetfunc)finalizeattr_get,		/* tp_descr_get */
+	(descrsetfunc)finalizeattr_set,		/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	descr_isshareable,			/* tp_isshareable */
+};
+
 static PyDescrObject *
 descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
 {
 	PyDescrObject *descr;
 
-	descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
+	descr = PyObject_NEW(PyDescrObject, descrtype);
 	if (descr != NULL) {
 		Py_XINCREF(type);
 		descr->d_type = type;
@@ -594,8 +790,10 @@
 
 	descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
 						 type, method->ml_name);
-	if (descr != NULL)
-		descr->d_method = method;
+	if (descr == NULL)
+		return NULL;
+	descr->d_method = method;
+	PyObject_COMPLETE(descr);
 	return (PyObject *)descr;
 }
 
@@ -606,8 +804,10 @@
 
 	descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
 						 type, method->ml_name);
-	if (descr != NULL)
-		descr->d_method = method;
+	if (descr == NULL)
+		return NULL;
+	descr->d_method = method;
+	PyObject_COMPLETE(descr);
 	return (PyObject *)descr;
 }
 
@@ -618,8 +818,10 @@
 
 	descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
 						 type, member->name);
-	if (descr != NULL)
-		descr->d_member = member;
+	if (descr == NULL)
+		return NULL;
+	descr->d_member = member;
+	PyObject_COMPLETE(descr);
 	return (PyObject *)descr;
 }
 
@@ -630,8 +832,10 @@
 
 	descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
 						 type, getset->name);
-	if (descr != NULL)
-		descr->d_getset = getset;
+	if (descr == NULL)
+		return NULL;
+	descr->d_getset = getset;
+	PyObject_COMPLETE(descr);
 	return (PyObject *)descr;
 }
 
@@ -642,14 +846,28 @@
 
 	descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
 						 type, base->name);
-	if (descr != NULL) {
-		descr->d_base = base;
-		descr->d_wrapped = wrapped;
-	}
+	if (descr == NULL)
+		return NULL;
+	descr->d_base = base;
+	descr->d_wrapped = wrapped;
+	PyObject_COMPLETE(descr);
 	return (PyObject *)descr;
 }
 
+PyObject *
+PyDescr_NewFinalizeAttr(PyTypeObject *type, PyObject *name)
+{
+    PyFinalizeAttrDescrObject *descr;
 
+    descr = (PyFinalizeAttrDescrObject *)descr_new(&PyFinalizeAttrDescr_Type,
+        type, PyUnicode_AsString(name));
+    if (descr == NULL)
+        return NULL;
+    PyObject_COMPLETE(descr);
+    return (PyObject *)descr;
+}
+
+
 /* --- Readonly proxy for dictionaries (actually any mapping) --- */
 
 /* This has no reason to be in this file except that adding new files is a
@@ -773,9 +991,8 @@
 static void
 proxy_dealloc(proxyobject *pp)
 {
-	_PyObject_GC_UNTRACK(pp);
 	Py_DECREF(pp->dict);
-	PyObject_GC_Del(pp);
+	PyObject_DEL(pp);
 }
 
 static PyObject *
@@ -831,7 +1048,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
  	0,					/* tp_doc */
 	proxy_traverse,				/* tp_traverse */
  	0,					/* tp_clear */
@@ -853,11 +1070,11 @@
 {
 	proxyobject *pp;
 
-	pp = PyObject_GC_New(proxyobject, &proxytype);
+	pp = PyObject_NEW(proxyobject, &proxytype);
 	if (pp != NULL) {
 		Py_INCREF(dict);
 		pp->dict = dict;
-		_PyObject_GC_TRACK(pp);
+		PyObject_COMPLETE(pp);
 	}
 	return (PyObject *)pp;
 }
@@ -877,12 +1094,9 @@
 static void
 wrapper_dealloc(wrapperobject *wp)
 {
-	PyObject_GC_UnTrack(wp);
-	Py_TRASHCAN_SAFE_BEGIN(wp)
 	Py_XDECREF(wp->descr);
 	Py_XDECREF(wp->self);
-	PyObject_GC_Del(wp);
-	Py_TRASHCAN_SAFE_END(wp)
+	PyObject_DEL(wp);
 }
 
 static int
@@ -991,6 +1205,14 @@
 	return 0;
 }
 
+static int
+wrapper_isshareable(wrapperobject *wp)
+{
+	/* XXX FIXME I doubt this is sufficiently strict */
+	return PyObject_IsShareable((PyObject *)wp->descr->d_type) &&
+		PyObject_IsShareable(wp->self);
+}
+
 static PyTypeObject wrappertype = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
 	"method-wrapper",			/* tp_name */
@@ -1012,7 +1234,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SKIPWIPE, /* tp_flags */
  	0,					/* tp_doc */
 	wrapper_traverse,			/* tp_traverse */
  	0,					/* tp_clear */
@@ -1027,6 +1249,16 @@
 	0,					/* tp_dict */
 	0,					/* tp_descr_get */
 	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_new */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	(isshareablefunc)wrapper_isshareable,	/* tp_isshareable */
 };
 
 PyObject *
@@ -1039,13 +1271,13 @@
 	descr = (PyWrapperDescrObject *)d;
 	assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
 
-	wp = PyObject_GC_New(wrapperobject, &wrappertype);
+	wp = PyObject_NEW(wrapperobject, &wrappertype);
 	if (wp != NULL) {
 		Py_INCREF(descr);
 		wp->descr = descr;
 		Py_INCREF(self);
 		wp->self = self;
-		_PyObject_GC_TRACK(wp);
+		PyObject_COMPLETE(wp);
 	}
 	return (PyObject *)wp;
 }
@@ -1105,12 +1337,11 @@
 {
 	propertyobject *gs = (propertyobject *)self;
 
-	_PyObject_GC_UNTRACK(self);
 	Py_XDECREF(gs->prop_get);
 	Py_XDECREF(gs->prop_set);
 	Py_XDECREF(gs->prop_del);
 	Py_XDECREF(gs->prop_doc);
-	self->ob_type->tp_free(self);
+	PyObject_Del(self);
 }
 
 static PyObject *
@@ -1243,7 +1474,7 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
  	property_doc,				/* tp_doc */
 	property_traverse,			/* tp_traverse */
  	0,					/* tp_clear */
@@ -1260,7 +1491,5 @@
 	property_descr_set,			/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	property_init,				/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	PyType_GenericNew,			/* tp_new */
-	PyObject_GC_Del,               		/* tp_free */
 };
Index: Objects/memoryobject.c
===================================================================
--- Objects/memoryobject.c	(revision 58355)
+++ Objects/memoryobject.c	(working copy)
@@ -28,9 +28,9 @@
 {
 	PyMemoryViewObject *mview;
 
-	mview = (PyMemoryViewObject *)PyObject_New(PyMemoryViewObject,
-						   &PyMemoryView_Type);
-	if (mview == NULL) return NULL;
+	mview = PyObject_NEW(PyMemoryViewObject, &PyMemoryView_Type);
+	if (mview == NULL)
+		return NULL;
 	mview->base = NULL;
 	mview->view = *info;
 	return (PyObject *)mview;
@@ -48,7 +48,7 @@
                 return NULL;
         }
 
-        mview = (PyMemoryViewObject *)PyObject_New(PyMemoryViewObject,
+        mview = (PyMemoryViewObject *)PyObject_NEW(PyMemoryViewObject,
                                                    &PyMemoryView_Type);
         if (mview == NULL) return NULL;
 
@@ -211,7 +211,7 @@
                 return NULL;
         }
 
-        mem = PyObject_New(PyMemoryViewObject, &PyMemoryView_Type);
+        mem = PyObject_NEW(PyMemoryViewObject, &PyMemoryView_Type);
         if (mem == NULL) return NULL;
 
         view = &PyMemoryView(mem);
@@ -564,7 +564,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	&memory_as_buffer,			/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
 	memory_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
@@ -581,6 +581,5 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	memory_new,				/* tp_new */
 };
Index: Objects/genobject.c
===================================================================
--- Objects/genobject.c	(revision 58355)
+++ Objects/genobject.c	(working copy)
@@ -14,35 +14,49 @@
 	return 0;
 }
 
+static inline int
+bitcount(AO_t num)
+{
+	int count = 0;
+	while (num) {
+		count += num & 1;
+		num >>= 1;
+	}
+	return count;
+}
+
 static void
 gen_dealloc(PyGenObject *gen)
 {
-	PyObject *self = (PyObject *) gen;
-
-	_PyObject_GC_UNTRACK(gen);
-
-	if (gen->gi_weakreflist != NULL)
-		PyObject_ClearWeakRefs(self);
-
-	_PyObject_GC_TRACK(self);
-
 	if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {
-		/* Generator is paused, so we need to close */
-		Py_Type(gen)->tp_del(self);
-		if (self->ob_refcnt > 0)
-			return;		/* resurrected.  :( */
+		/* XXX We should require all generators with "try"
+		 * blocks to be bound to the stack before first running
+		 * them, making this impossible. */
+		static AO_t warning_count = 0;
+		AO_t current = AO_fetch_and_add1_full(&warning_count) + 1;
+
+		/* This might get printed out of order, but who cares?
+		 * Heck, there's no guarantee the printing itself is
+		 * atomic. */
+		/* All we do here is check for powers of 2.  The key to
+		 * this test is that the only time your mask won't
+		 * include your most-significant-bit is when it rolls
+		 * over from 0x100 to 0xFF. */
+		if (current != 0 && !(current & (current - 1)))
+			fprintf(stderr, "Warning: deleting paused "
+				"generator without closing, %lu times\n",
+				current);
 	}
 
-	_PyObject_GC_UNTRACK(self);
 	Py_CLEAR(gen->gi_frame);
-	PyObject_GC_Del(gen);
+	PyObject_DEL(gen);
 }
 
 
 static PyObject *
 gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
 {
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = PyThreadState_Get();
 	PyFrameObject *f = gen->gi_frame;
 	PyObject *result;
 
@@ -142,69 +156,8 @@
 	return NULL;
 }
 
-static void
-gen_del(PyObject *self)
-{
-        PyObject *res;
-        PyObject *error_type, *error_value, *error_traceback;
-	PyGenObject *gen = (PyGenObject *)self;
 
-	if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
-		/* Generator isn't paused, so no need to close */
-		return;
 
-        /* Temporarily resurrect the object. */
-        assert(self->ob_refcnt == 0);
-        self->ob_refcnt = 1;
-
-        /* Save the current exception, if any. */
-        PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
-	res = gen_close(gen, NULL);
-
-	if (res == NULL)
-		PyErr_WriteUnraisable(self);
-	else
-		Py_DECREF(res);
-
-        /* Restore the saved exception. */
-        PyErr_Restore(error_type, error_value, error_traceback);
-
-        /* Undo the temporary resurrection; can't use DECREF here, it would
-         * cause a recursive call.
-         */
-        assert(self->ob_refcnt > 0);
-        if (--self->ob_refcnt == 0)
-                return; /* this is the normal path out */
-
-        /* close() resurrected it!  Make it look like the original Py_DECREF
-         * never happened.
-         */
-        {
-                Py_ssize_t refcnt = self->ob_refcnt;
-                _Py_NewReference(self);
-                self->ob_refcnt = refcnt;
-        }
-        assert(PyType_IS_GC(self->ob_type) &&
-               _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
-
-        /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
-         * we need to undo that. */
-        _Py_DEC_REFTOTAL;
-        /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
-         * chain, so no more to do there.
-         * If COUNT_ALLOCS, the original decref bumped tp_frees, and
-         * _Py_NewReference bumped tp_allocs:  both of those need to be
-         * undone.
-         */
-#ifdef COUNT_ALLOCS
-        --self->ob_type->tp_frees;
-        --self->ob_type->tp_allocs;
-#endif
-}
-
-
-
 PyDoc_STRVAR(throw_doc,
 "throw(typ[,val[,tb]]) -> raise exception in generator,\n\
 return next yielded value or raise StopIteration.");
@@ -332,22 +285,19 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	0,					/* tp_new */
-	0,					/* tp_free */
 	0,					/* tp_is_gc */
 	0,					/* tp_bases */
 	0,					/* tp_mro */
 	0,					/* tp_cache */
 	0,					/* tp_subclasses */
 	0,					/* tp_weaklist */
-	gen_del,				/* tp_del */
 };
 
 PyObject *
 PyGen_New(PyFrameObject *f)
 {
-	PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
+	PyGenObject *gen = PyObject_NEW(PyGenObject, &PyGen_Type);
 	if (gen == NULL) {
 		Py_DECREF(f);
 		return NULL;
@@ -355,7 +305,6 @@
 	gen->gi_frame = f;
 	gen->gi_running = 0;
 	gen->gi_weakreflist = NULL;
-	_PyObject_GC_TRACK(gen);
 	return (PyObject *)gen;
 }
 
Index: Objects/bufferobject.c
===================================================================
--- Objects/bufferobject.c	(revision 58355)
+++ Objects/bufferobject.c	(working copy)
@@ -171,7 +171,6 @@
 PyObject *
 PyBuffer_New(Py_ssize_t size)
 {
-	PyObject *o;
 	PyBufferObject * b;
 
 	if (size < 0) {
@@ -181,10 +180,13 @@
 	}
 	/* XXX: check for overflow in multiply */
 	/* Inline PyObject_New */
-	o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
-	if (o == NULL)
-		return PyErr_NoMemory();
-	b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
+	//o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
+	//if (o == NULL)
+	//	return PyErr_NoMemory();
+	//b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
+	b = PyObject_NEWVAR(PyBufferObject, &PyBuffer_Type, size);
+	if (b == NULL)
+		return NULL;
 
 	b->b_base = NULL;
 	b->b_ptr = (void *)(b + 1);
@@ -193,7 +195,7 @@
 	b->b_readonly = 0;
 	b->b_hash = -1;
 
-	return o;
+	return (PyObject *)b;
 }
 
 /* Methods */
@@ -702,7 +704,7 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	&buffer_as_buffer,			/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,	/* tp_flags */
 	buffer_doc,				/* tp_doc */
 	0,					/* tp_traverse */
 	0,					/* tp_clear */
@@ -719,6 +721,5 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
 	buffer_new,				/* tp_new */
 };
Index: Objects/listobject.c
===================================================================
--- Objects/listobject.c	(revision 58355)
+++ Objects/listobject.c	(working copy)
@@ -1,6 +1,7 @@
 /* List object implementation */
 
 #include "Python.h"
+#include "pythread.h"
 
 #ifdef STDC_HEADERS
 #include <stddef.h>
@@ -63,22 +64,40 @@
 	return 0;
 }
 
+#ifdef USE_LIST_FREELIST
 /* Empty list reuse scheme to save calls to malloc and free */
 #define MAXFREELISTS 80
 static PyListObject *free_lists[MAXFREELISTS];
 static int num_free_lists = 0;
+static PyThread_type_lock free_lists_lock;
+#endif
 
 void
+_PyList_Init(void)
+{
+#ifdef USE_LIST_FREELIST
+	free_lists_lock = PyThread_lock_allocate();
+	if (!free_lists_lock)
+		Py_FatalError("unable to allocate lock");
+#endif
+}
+
+void
 PyList_Fini(void)
 {
+#ifdef USE_LIST_FREELIST
 	PyListObject *op;
 
 	while (num_free_lists) {
 		num_free_lists--;
 		op = free_lists[num_free_lists]; 
 		assert(PyList_CheckExact(op));
-		PyObject_GC_Del(op);
+		PyObject_DEL(op);
 	}
+
+	PyThread_lock_free(free_lists_lock);
+	free_lists_lock = NULL;
+#endif
 }
 
 PyObject *
@@ -95,15 +114,22 @@
 	/* Check for overflow */
 	if (nbytes / sizeof(PyObject *) != (size_t)size)
 		return PyErr_NoMemory();
+#ifdef USE_LIST_FREELIST
+	PyThread_lock_acquire(free_lists_lock);
 	if (num_free_lists) {
 		num_free_lists--;
 		op = free_lists[num_free_lists];
-		_Py_NewReference((PyObject *)op);
+		PyThread_lock_release(free_lists_lock);
+		//_Py_NewReference((PyObject *)op);
 	} else {
-		op = PyObject_GC_New(PyListObject, &PyList_Type);
+		PyThread_lock_release(free_lists_lock);
+#endif
+		op = PyObject_NEW(PyListObject, &PyList_Type);
 		if (op == NULL)
 			return NULL;
+#ifdef USE_LIST_FREELIST
 	}
+#endif
 	if (size <= 0)
 		op->ob_item = NULL;
 	else {
@@ -116,7 +142,7 @@
 	}
 	Py_Size(op) = size;
 	op->allocated = size;
-	_PyObject_GC_TRACK(op);
+
 	return (PyObject *) op;
 }
 
@@ -252,8 +278,6 @@
 list_dealloc(PyListObject *op)
 {
 	Py_ssize_t i;
-	PyObject_GC_UnTrack(op);
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (op->ob_item != NULL) {
 		/* Do it backwards, for Christian Tismer.
 		   There's a simple test case where somehow this reduces
@@ -265,11 +289,18 @@
 		}
 		PyMem_FREE(op->ob_item);
 	}
-	if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op))
+#ifdef USE_LIST_FREELIST
+	PyThread_lock_acquire(free_lists_lock);
+	if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op)) {
 		free_lists[num_free_lists++] = op;
-	else
-		Py_Type(op)->tp_free((PyObject *)op);
-	Py_TRASHCAN_SAFE_END(op)
+		PyThread_lock_release(free_lists_lock);
+	} else {
+		PyThread_lock_release(free_lists_lock);
+#endif
+		PyObject_DEL(op);
+#ifdef USE_LIST_FREELIST
+	}
+#endif
 }
 
 static PyObject *
@@ -1832,7 +1863,7 @@
 {
 	Py_XDECREF(so->key);
 	Py_XDECREF(so->value);
-	PyObject_Del(so);
+	PyObject_DEL(so);
 }
 
 /* Returns a new reference to a sortwrapper.
@@ -1843,7 +1874,7 @@
 {
 	sortwrapperobject *so;
 
-	so = PyObject_New(sortwrapperobject, &sortwrapper_type);
+	so = PyObject_NEW(sortwrapperobject, &sortwrapper_type);
 	if (so == NULL)
 		return NULL;
 	so->key = key;
@@ -1880,7 +1911,7 @@
 cmpwrapper_dealloc(cmpwrapperobject *co)
 {
 	Py_XDECREF(co->func);
-	PyObject_Del(co);
+	PyObject_DEL(co);
 }
 
 static PyObject *
@@ -1933,7 +1964,7 @@
 {
 	cmpwrapperobject *co;
 
-	co = PyObject_New(cmpwrapperobject, &cmpwrapper_type);
+	co = PyObject_NEW(cmpwrapperobject, &cmpwrapper_type);
 	if (co == NULL)
 		return NULL;
 	Py_INCREF(cmpfunc);
@@ -2358,7 +2389,7 @@
 	if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
 		return -1;
 
-	/* Verify list invariants established by PyType_GenericAlloc() */
+	/* Verify list invariants established by PyObject_New() */
 	assert(0 <= Py_Size(self));
 	assert(Py_Size(self) <= self->allocated || self->allocated == -1);
 	assert(self->ob_item != NULL ||
@@ -2677,7 +2708,8 @@
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
  	list_doc,				/* tp_doc */
  	(traverseproc)list_traverse,		/* tp_traverse */
  	(inquiry)list_clear,			/* tp_clear */
@@ -2694,9 +2726,7 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	(initproc)list_init,			/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	PyType_GenericNew,			/* tp_new */
-	PyObject_GC_Del,			/* tp_free */
 };
 
 
@@ -2764,22 +2794,20 @@
 		PyErr_BadInternalCall();
 		return NULL;
 	}
-	it = PyObject_GC_New(listiterobject, &PyListIter_Type);
+	it = PyObject_NEW(listiterobject, &PyListIter_Type);
 	if (it == NULL)
 		return NULL;
 	it->it_index = 0;
 	Py_INCREF(seq);
 	it->it_seq = (PyListObject *)seq;
-	_PyObject_GC_TRACK(it);
 	return (PyObject *)it;
 }
 
 static void
 listiter_dealloc(listiterobject *it)
 {
-	_PyObject_GC_UNTRACK(it);
 	Py_XDECREF(it->it_seq);
-	PyObject_GC_Del(it);
+	PyObject_DEL(it);
 }
 
 static int
@@ -2880,23 +2908,21 @@
 {
 	listreviterobject *it;
 
-	it = PyObject_GC_New(listreviterobject, &PyListRevIter_Type);
+	it = PyObject_NEW(listreviterobject, &PyListRevIter_Type);
 	if (it == NULL)
 		return NULL;
 	assert(PyList_Check(seq));
 	it->it_index = PyList_GET_SIZE(seq) - 1;
 	Py_INCREF(seq);
 	it->it_seq = seq;
-	PyObject_GC_Track(it);
 	return (PyObject *)it;
 }
 
 static void
 listreviter_dealloc(listreviterobject *it)
 {
-	PyObject_GC_UnTrack(it);
 	Py_XDECREF(it->it_seq);
-	PyObject_GC_Del(it);
+	PyObject_DEL(it);
 }
 
 static int
Index: Objects/fileobject.c
===================================================================
--- Objects/fileobject.c	(revision 58355)
+++ Objects/fileobject.c	(working copy)
@@ -95,7 +95,7 @@
 					"EOF when reading a line");
 		}
 		else if (s[len-1] == '\n') {
-			if (result->ob_refcnt == 1)
+			if (Py_RefcntSnoop(result) == 1)
 				_PyString_Resize(&result, len-1);
 			else {
 				PyObject *v;
@@ -115,7 +115,7 @@
 					"EOF when reading a line");
 		}
 		else if (s[len-1] == '\n') {
-			if (result->ob_refcnt == 1)
+			if (Py_RefcntSnoop(result) == 1)
 				PyUnicode_Resize(&result, len-1);
 			else {
 				PyObject *v;
Index: Objects/stringlib/string_format.h
===================================================================
--- Objects/stringlib/string_format.h	(revision 58355)
+++ Objects/stringlib/string_format.h	(working copy)
@@ -485,7 +485,7 @@
 
     /* Initialize cached value */
     if (format_str == NULL) {
-        /* Initialize static variable needed by _PyType_Lookup */
+        /* Initialize static variable needed by _PyType_LookupEx */
         format_str = PyUnicode_FromString("__format__");
         if (format_str == NULL)
             return NULL;
@@ -501,8 +501,9 @@
     if (spec == NULL)
         goto done;
 
-    /* Find the (unbound!) __format__ method (a borrowed reference) */
-    meth = _PyType_Lookup(Py_Type(fieldobj), format_str);
+    /* Find the (unbound!) __format__ method */
+    if (_PyType_LookupEx(Py_Type(fieldobj), format_str, &meth) < 0)
+        goto done;
     if (meth == NULL) {
         PyErr_Format(PyExc_TypeError,
                      "Type %.100s doesn't define __format__",
@@ -512,6 +513,7 @@
 
     /* And call it, binding it to the value */
     result = PyObject_CallFunctionObjArgs(meth, fieldobj, spec, NULL);
+    Py_DECREF(meth);
     if (result == NULL)
         goto done;
 
@@ -967,7 +969,7 @@
 formatteriter_dealloc(formatteriterobject *it)
 {
     Py_XDECREF(it->str);
-    PyObject_FREE(it);
+    PyObject_DEL(it);
 }
 
 /* returns a tuple:
@@ -1089,7 +1091,7 @@
 {
     formatteriterobject *it;
 
-    it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
+    it = PyObject_NEW(formatteriterobject, &PyFormatterIter_Type);
     if (it == NULL)
         return NULL;
 
@@ -1127,7 +1129,7 @@
 fieldnameiter_dealloc(fieldnameiterobject *it)
 {
     Py_XDECREF(it->str);
-    PyObject_FREE(it);
+    PyObject_DEL(it);
 }
 
 /* returns a tuple:
@@ -1229,7 +1231,7 @@
     PyObject *first_obj = NULL;
     PyObject *result = NULL;
 
-    it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
+    it = PyObject_NEW(fieldnameiterobject, &PyFieldNameIter_Type);
     if (it == NULL)
         return NULL;
 
Index: Objects/moduleobject.c
===================================================================
--- Objects/moduleobject.c	(revision 58355)
+++ Objects/moduleobject.c	(working copy)
@@ -17,13 +17,22 @@
 PyObject *
 PyModule_New(const char *name)
 {
+	return PyModule_NewEx(name, 0);
+}
+
+PyObject *
+PyModule_NewEx(const char *name, int shared)
+{
 	PyModuleObject *m;
 	PyObject *nameobj;
-	m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
+	m = PyObject_NEW(PyModuleObject, &PyModule_Type);
 	if (m == NULL)
 		return NULL;
 	nameobj = PyUnicode_FromString(name);
-	m->md_dict = PyDict_New();
+	if (shared)
+		m->md_dict = PyObject_CallObject((PyObject *)&PySharedDict_Type, NULL);
+	else
+		m->md_dict = PyDict_New();
 	if (m->md_dict == NULL || nameobj == NULL)
 		goto fail;
 	if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
@@ -31,7 +40,6 @@
 	if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
 		goto fail;
 	Py_DECREF(nameobj);
-	PyObject_GC_Track(m);
 	return (PyObject *)m;
 
  fail:
@@ -59,19 +67,22 @@
 {
 	PyObject *d;
 	PyObject *nameobj;
+	const char *retval;
 	if (!PyModule_Check(m)) {
 		PyErr_BadArgument();
 		return NULL;
 	}
 	d = ((PyModuleObject *)m)->md_dict;
-	if (d == NULL ||
-	    (nameobj = PyDict_GetItemString(d, "__name__")) == NULL ||
-	    !PyUnicode_Check(nameobj))
-	{
+	if (d == NULL || PyDict_GetItemStringEx(d, "__name__", &nameobj) > 0) {
 		PyErr_SetString(PyExc_SystemError, "nameless module");
 		return NULL;
 	}
-	return PyUnicode_AsString(nameobj);
+	if (nameobj == NULL)
+		return NULL;
+	retval = PyUnicode_AsString(nameobj);
+	Py_DECREF(nameobj);
+#warning XXX FIXME PyModule_GetName is racey (not thread-safe)
+	return retval;
 }
 
 const char *
@@ -114,7 +125,7 @@
 
 	/* First, clear only names starting with a single underscore */
 	pos = 0;
-	while (PyDict_Next(d, &pos, &key, &value)) {
+	while (PyDict_NextEx(d, &pos, &key, &value)) {
 		if (value != Py_None && PyUnicode_Check(key)) {
 			const char *s = PyUnicode_AsString(key);
 			if (s[0] == '_' && s[1] != '_') {
@@ -123,11 +134,13 @@
 				PyDict_SetItem(d, key, Py_None);
 			}
 		}
+		Py_DECREF(key);
+		Py_DECREF(value);
 	}
 
 	/* Next, clear all names except for __builtins__ */
 	pos = 0;
-	while (PyDict_Next(d, &pos, &key, &value)) {
+	while (PyDict_NextEx(d, &pos, &key, &value)) {
 		if (value != Py_None && PyUnicode_Check(key)) {
 			const char *s = PyUnicode_AsString(key);
 			if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
@@ -136,6 +149,8 @@
 				PyDict_SetItem(d, key, Py_None);
 			}
 		}
+		Py_DECREF(key);
+		Py_DECREF(value);
 	}
 
 	/* Note: we leave __builtins__ in place, so that destructors
@@ -171,12 +186,11 @@
 static void
 module_dealloc(PyModuleObject *m)
 {
-	PyObject_GC_UnTrack(m);
 	if (m->md_dict != NULL) {
 		_PyModule_Clear((PyObject *)m);
 		Py_DECREF(m->md_dict);
 	}
-	Py_Type(m)->tp_free((PyObject *)m);
+	PyObject_DEL(m);
 }
 
 static PyObject *
@@ -208,6 +222,18 @@
 	return 0;
 }
 
+static int
+module_isshareable(PyModuleObject *m)
+{
+	/* XXX FIXME HACK! */
+	const char *name = PyModule_GetName((PyObject *)m);
+	if (strcmp(name, "sys") == 0 || strcmp(name, "os") == 0 ||
+			strcmp(name, "io") == 0)
+		return 1;
+
+	return PyObject_IsShareable(m->md_dict);
+}
+
 PyDoc_STRVAR(module_doc,
 "module(name[, doc])\n\
 \n\
@@ -235,7 +261,8 @@
 	PyObject_GenericSetAttr,		/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,		/* tp_flags */
+		Py_TPFLAGS_BASETYPE |
+		Py_TPFLAGS_SHAREABLE,		/* tp_flags */
 	module_doc,				/* tp_doc */
 	(traverseproc)module_traverse,		/* tp_traverse */
 	0,					/* tp_clear */
@@ -252,7 +279,12 @@
 	0,					/* tp_descr_set */
 	offsetof(PyModuleObject, md_dict),	/* tp_dictoffset */
 	(initproc)module_init,			/* tp_init */
-	PyType_GenericAlloc,			/* tp_alloc */
 	PyType_GenericNew,			/* tp_new */
-	PyObject_GC_Del,		        /* tp_free */
+	0,					/* tp_is_gc */
+	0,					/* tp_bases */
+	0,					/* tp_mro */
+	0,					/* tp_cache */
+	0,					/* tp_subclasses */
+	0,					/* tp_weaklist */
+	(isshareablefunc)module_isshareable,	/* tp_isshareable */
 };
Index: Objects/bytesobject.c
===================================================================
--- Objects/bytesobject.c	(revision 58355)
+++ Objects/bytesobject.c	(working copy)
@@ -21,7 +21,7 @@
 int
 PyBytes_Init(void)
 {
-    nullbytes = PyObject_New(PyBytesObject, &PyBytes_Type);
+    nullbytes = PyObject_NEW(PyBytesObject, &PyBytes_Type);
     if (nullbytes == NULL)
         return 0;
     nullbytes->ob_bytes = NULL;
@@ -112,7 +112,7 @@
 
     assert(size >= 0);
 
-    new = PyObject_New(PyBytesObject, &PyBytes_Type);
+    new = PyObject_NEW(PyBytesObject, &PyBytes_Type);
     if (new == NULL)
         return NULL;
 
@@ -1025,7 +1025,7 @@
     if (self->ob_bytes != 0) {
         PyMem_Free(self->ob_bytes);
     }
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 
@@ -3005,7 +3005,7 @@
     0,                                  /* tp_setattro */
     &bytes_as_buffer,                   /* tp_as_buffer */
     /* bytes is 'final' or 'sealed' */
-    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SHAREABLE,  /* tp_flags */
     bytes_doc,                          /* tp_doc */
     0,                                  /* tp_traverse */
     0,                                  /* tp_clear */
@@ -3022,7 +3022,5 @@
     0,                                  /* tp_descr_set */
     0,                                  /* tp_dictoffset */
     (initproc)bytes_init,               /* tp_init */
-    PyType_GenericAlloc,                /* tp_alloc */
     PyType_GenericNew,                  /* tp_new */
-    PyObject_Del,                       /* tp_free */
 };
Index: Objects/monitorobject.c
===================================================================
--- Objects/monitorobject.c	(revision 0)
+++ Objects/monitorobject.c	(revision 0)
@@ -0,0 +1,534 @@
+
+#include "Python.h"
+#include "ceval.h"
+#include "monitorobject.h"
+
+/* MonitorMeta methods */
+
+static void
+MonitorMeta_dealloc(PyTypeObject *self)
+{
+	PyObject_DEL(self);
+}
+
+static PyObject *
+MonitorMeta_call(PyTypeObject *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *monitorspace;
+	PyObject *super;
+	PyObject *nextmethod;
+	PyObject *enter;
+	Py_ssize_t size, i;
+	PyObject *built_args;
+	PyObject *result;
+
+	assert(PyTuple_Check(args));
+
+	/* This can all be summed up as:
+	   monitorspace = MonitorSpace()
+	   nextmethod = super(MonitorMeta, self).__call__
+	   return monitorspace.enter(nextmethod, *args, **kwargs)
+	 */
+
+	monitorspace = PyObject_CallObject((PyObject *)&PyMonitorSpace_Type, NULL);
+	if (monitorspace == NULL)
+		return NULL;
+
+	super = PyEval_CallFunction((PyObject *)&PySuper_Type, "OO",
+		&PyMonitorMeta_Type, self);
+	if (super == NULL) {
+		Py_DECREF(monitorspace);
+		return NULL;
+	}
+
+	nextmethod = PyObject_GetAttrString(super, "__call__");
+	Py_DECREF(super);
+	if (nextmethod == NULL) {
+		Py_DECREF(monitorspace);
+		return NULL;
+	}
+
+	size = PyTuple_Size(args) + 1;
+	built_args = PyTuple_New(size);
+	if (built_args == NULL) {
+		Py_DECREF(monitorspace);
+		Py_DECREF(nextmethod);
+		return NULL;
+	}
+	PyTuple_SET_ITEM(built_args, 0, nextmethod); /* Steals our reference */
+	nextmethod = NULL;
+	for (i = 1; i < size; i++) {
+		PyObject *item = PyTuple_GET_ITEM(args, i-1);
+		Py_INCREF(item);
+		PyTuple_SET_ITEM(built_args, i, item);
+	}
+
+	enter = PyObject_GetAttrString(monitorspace, "enter");
+	if (enter == NULL) {
+		Py_DECREF(monitorspace);
+		Py_DECREF(built_args);
+		return NULL;
+	}
+
+	result = PyEval_CallObjectWithKeywords(enter, built_args, kwds);
+
+	Py_DECREF(monitorspace);
+	Py_DECREF(built_args);
+	Py_DECREF(enter);
+
+	return result;
+}
+
+static int
+MonitorMeta_traverse(PyTypeObject *self, visitproc visit, void *arg)
+{
+	return 0;
+}
+
+PyTypeObject PyMonitorMeta_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"_threadtoolsmodule.MonitorMeta",	/*tp_name*/
+	sizeof(PyHeapTypeObject),	/*tp_basicsize*/
+	0/*sizeof(PyMemberDef)*/,	/*tp_itemsize*/
+	(destructor)MonitorMeta_dealloc,	/*tp_dealloc*/
+	0,			/*tp_print*/
+	0,			/*tp_getattr*/
+	0,			/*tp_setattr*/
+	0,			/*tp_compare*/
+	0,			/*tp_repr*/
+	0,			/*tp_as_number*/
+	0,			/*tp_as_sequence*/
+	0,			/*tp_as_mapping*/
+	0,			/*tp_hash*/
+	(ternaryfunc)MonitorMeta_call,	/*tp_call*/
+	0,			/*tp_str*/
+	PyObject_GenericGetAttr,	/*tp_getattro*/
+	0,			/*tp_setattro*/
+	0,			/*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+		Py_TPFLAGS_BASETYPE |
+		Py_TPFLAGS_SHAREABLE,	/*tp_flags*/
+	0,			/*tp_doc*/
+	(traverseproc)MonitorMeta_traverse,	/*tp_traverse*/
+	0,			/*tp_clear*/
+	0,			/*tp_richcompare*/
+	0,			/*tp_weaklistoffset*/
+	0,			/*tp_iter*/
+	0,			/*tp_iternext*/
+	0,			/*tp_methods*/
+	0,			/*tp_members*/
+	0,			/*tp_getset*/
+	0,			/*tp_base*/
+	0,			/*tp_dict*/
+	0,			/*tp_descr_get*/
+	0,			/*tp_descr_set*/
+	0,			/*tp_dictoffset*/
+	0,			/*tp_init*/
+	0,			/*tp_new*/
+};
+/* --------------------------------------------------------------------- */
+
+
+/* Monitor methods */
+
+static void
+Monitor_dealloc(PyMonitorObject *self)
+{
+	PyObject *monitorspace = self->mon_monitorspace;
+	PyObject_DEL(self);
+	Py_DECREF(monitorspace);
+}
+
+static PyObject *
+Monitor_enter(PyMonitorObject *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *monitorspace_enter;
+	PyObject *result;
+
+	monitorspace_enter = PyObject_GetAttrString(self->mon_monitorspace, "enter");
+	if (monitorspace_enter == NULL)
+	    return NULL;
+
+	result = PyEval_CallObjectWithKeywords(monitorspace_enter, args, kwds);
+	Py_DECREF(monitorspace_enter);
+	return result;
+}
+
+static int
+Monitor_traverse(PyMonitorObject *self, visitproc visit, void *arg)
+{
+	Py_VISIT(self->mon_monitorspace);
+	return 0;
+}
+
+static PyObject *
+Monitor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *self;
+
+	assert(type != NULL);
+	self = PyObject_New(type);
+	if (self != NULL) {
+		PyMonitorObject *x = (PyMonitorObject *)self;
+		x->mon_monitorspace = PyMonitorSpace_GetCurrent();
+		if (x->mon_monitorspace == NULL) {
+			PyObject_Del(self);
+			return NULL;
+		}
+	}
+	return self;
+}
+
+static int
+Monitor_isshareable (PyObject *self)
+{
+	return 1;
+}
+
+PyDoc_STRVAR(Monitor_enter__doc__, "enter(func, *args, **kwargs) -> object");
+
+static PyMethodDef Monitor_methods[] = {
+	{"enter",	(PyCFunction)Monitor_enter,	METH_VARARGS | METH_KEYWORDS,
+		Monitor_enter__doc__},
+	{NULL,		NULL}		/* sentinel */
+};
+
+PyTypeObject PyMonitor_Type = {
+	PyVarObject_HEAD_INIT(&PyMonitorMeta_Type, 0)
+	"_threadtoolsmodule.Monitor",	/*tp_name*/
+	sizeof(PyMonitorObject),	/*tp_basicsize*/
+	0,			/*tp_itemsize*/
+	(destructor)Monitor_dealloc,	/*tp_dealloc*/
+	0,			/*tp_print*/
+	0,			/*tp_getattr*/
+	0,			/*tp_setattr*/
+	0,			/*tp_compare*/
+	0,			/*tp_repr*/
+	0,			/*tp_as_number*/
+	0,			/*tp_as_sequence*/
+	0,			/*tp_as_mapping*/
+	0,			/*tp_hash*/
+	0,			/*tp_call*/
+	0,			/*tp_str*/
+	PyObject_GenericGetAttr,	/*tp_getattro*/
+	0,			/*tp_setattro*/
+	0,			/*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_MONITOR_SUBCLASS |
+		Py_TPFLAGS_SHAREABLE,	/*tp_flags*/
+	0,			/*tp_doc*/
+	(traverseproc)Monitor_traverse,	/*tp_traverse*/
+	0,			/*tp_clear*/
+	0,			/*tp_richcompare*/
+	0,			/*tp_weaklistoffset*/
+	0,			/*tp_iter*/
+	0,			/*tp_iternext*/
+	Monitor_methods,	/*tp_methods*/
+	0,			/*tp_members*/
+	0,			/*tp_getset*/
+	0,			/*tp_base*/
+	0,			/*tp_dict*/
+	0,			/*tp_descr_get*/
+	0,			/*tp_descr_set*/
+	0,			/*tp_dictoffset*/
+	0,			/*tp_init*/
+	Monitor_new,		/*tp_new*/
+	0,			/*tp_is_gc*/
+	0,			/*tp_bases*/
+	0,			/*tp_mro*/
+	0,			/*tp_cache*/
+	0,			/*tp_subclasses*/
+	0,			/*tp_weaklist*/
+	Monitor_isshareable,	/*tp_isshareable*/
+};
+/* --------------------------------------------------------------------- */
+
+
+/* MonitorSpace methods */
+
+static void
+waitqueue_push(PyMonitorSpaceObject *queue, PyThreadState *tstate)
+{
+	if (queue->first_waiter) {
+		tstate->lockwait_prev = queue->last_waiter;
+		tstate->lockwait_next = NULL;
+		queue->last_waiter->lockwait_next = tstate;
+		queue->last_waiter = tstate;
+	} else {
+		tstate->lockwait_prev = NULL;
+		tstate->lockwait_next = NULL;
+		queue->first_waiter = tstate;
+		queue->last_waiter = tstate;
+	}
+}
+
+static void
+waitqueue_pop(PyMonitorSpaceObject *queue, PyThreadState *tstate)
+{
+	if (tstate->lockwait_prev != NULL)
+		tstate->lockwait_prev->lockwait_next = tstate->lockwait_next;
+	if (tstate->lockwait_next != NULL)
+		tstate->lockwait_next->lockwait_prev = tstate->lockwait_prev;
+
+	if (queue->first_waiter == tstate)
+		queue->first_waiter = tstate->lockwait_next;
+	if (queue->last_waiter == tstate)
+		queue->last_waiter = tstate->lockwait_prev;
+
+	tstate->lockwait_next = NULL;
+	tstate->lockwait_prev = NULL;
+}
+
+static int
+lock_enter(PyMonitorSpaceObject *self)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+	assert(tstate->active_lock == NULL);
+
+	tstate->active_lock = self;
+	PyState_Suspend();
+	PyThread_lock_acquire(self->lock);
+
+	if (self->lock_holder == NULL)
+		self->lock_holder = tstate;
+	else {
+		waitqueue_push(self, tstate);
+		while (self->lock_holder != NULL)
+			PyThread_cond_wait(tstate->lockwait_cond, self->lock);
+		waitqueue_pop(self, tstate);
+		self->lock_holder = tstate;
+	}
+
+	PyThread_lock_release(self->lock);
+	PyState_Resume();
+	tstate->active_lock = NULL;
+
+	return 0;
+}
+
+static int
+lock_exit(PyMonitorSpaceObject *self)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+	assert(tstate->active_lock == NULL);
+
+	tstate->active_lock = self;
+	PyState_Suspend();
+	PyThread_lock_acquire(self->lock);
+
+	assert(self->lock_holder == tstate);
+	self->lock_holder = NULL;
+	if (self->first_waiter) {
+		/* Ensure there's at least one thread that's awake. */
+		PyThread_cond_wakeone(self->first_waiter->lockwait_cond);
+	}
+
+	PyThread_lock_release(self->lock);
+	PyState_Resume();
+	tstate->active_lock = NULL;
+
+	return 0;
+}
+
+static PyObject *
+monitorspace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *self;
+
+	assert(type != NULL);
+	self = PyObject_New(type);
+	if (self != NULL) {
+		PyMonitorSpaceObject *x = (PyMonitorSpaceObject *)self;
+		x->lock = PyThread_lock_allocate();
+		if (x->lock == NULL) {
+			PyObject_Del(self);
+			PyErr_SetString(PyExc_RuntimeError, "can't allocate lock");
+			return NULL;
+		}
+		x->lock_holder = NULL;
+		x->first_waiter = NULL;
+		x->last_waiter = NULL;
+	}
+	return self;
+}
+
+static void
+monitorspace_dealloc(PyMonitorSpaceObject *self)
+{
+	assert(self->lock_holder == NULL);
+	assert(self->first_waiter == NULL);
+	assert(self->last_waiter == NULL);
+	PyThread_lock_free(self->lock);
+	PyObject_DEL(self);
+}
+
+void
+_PyMonitorSpace_Push(PyMonitorSpaceFrame *frame, struct _PyMonitorSpaceObject *monitorspace)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(frame != NULL);
+	assert(frame->prevframe == NULL);
+
+	frame->prevframe = tstate->monitorspace_frame;
+	frame->monitorspace = monitorspace;
+	tstate->monitorspace_frame = frame;
+	Py_XINCREF(monitorspace);
+}
+
+void
+_PyMonitorSpace_Pop(PyMonitorSpaceFrame *frame)
+{
+	struct _PyMonitorSpaceObject *monitorspace;
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(frame != NULL);
+	if (tstate->monitorspace_frame != frame)
+		Py_FatalError("Pop of non-top monitorspace frame");
+
+        monitorspace = frame->monitorspace;
+	tstate->monitorspace_frame = frame->prevframe;
+	frame->prevframe = NULL;
+	frame->monitorspace = NULL;
+	Py_XDECREF(monitorspace);
+}
+
+static PyObject *
+monitorspace_enter(PyMonitorSpaceObject *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *func;
+	PyObject *smallargs;
+	PyObject *result;
+	PyMonitorSpaceFrame frame = PyMonitorSpaceFrame_INIT;
+
+	if (PyTuple_Size(args) < 1) {
+		PyErr_SetString(PyExc_TypeError,
+			"Monitor.enter() needs a function to be called");
+		return NULL;
+	}
+
+	func = PyTuple_GetItem(args, 0);
+
+	if (!PyObject_IsShareable(func)) {
+		PyErr_Format(PyExc_TypeError,
+			"Function argument must be shareable, '%s' object "
+			"is not", func->ob_type->tp_name);
+		return NULL;
+	}
+
+	smallargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args));
+	if (smallargs == NULL) {
+		return NULL;
+	}
+
+	if (!PyArg_RequireShareable("Monitor.enter", smallargs, kwds)) {
+		Py_DECREF(smallargs);
+		return NULL;
+	}
+
+	lock_enter(self);
+	_PyMonitorSpace_Push(&frame, self);
+
+	result = PyEval_CallObjectWithKeywords(func, smallargs, kwds);
+	if (!PyArg_RequireShareableReturn("Monitor.enter", func, result)) {
+		Py_XDECREF(result);
+		result = NULL;
+	}
+	Py_DECREF(smallargs);
+
+	_PyMonitorSpace_Pop(&frame);
+	lock_exit(self);
+
+	return result;
+}
+
+int
+PyMonitorSpace_IsCurrent(struct _PyMonitorSpaceObject *monitorspace)
+{
+	PyThreadState *tstate = PyThreadState_Get();
+
+	assert(monitorspace != NULL);
+	return tstate->monitorspace_frame->monitorspace == monitorspace;
+}
+
+/* Returns a NEW reference */
+PyObject *
+PyMonitorSpace_GetCurrent(void)
+{
+    PyThreadState *tstate = PyThreadState_Get();
+    PyObject *monitorspace = (PyObject *)tstate->monitorspace_frame->monitorspace;
+
+    if (monitorspace == NULL) {
+        monitorspace = PyObject_CallObject((PyObject *)&PyMonitorSpace_Type, NULL);
+        if (monitorspace == NULL)
+            return NULL;
+        assert(tstate->monitorspace_frame->monitorspace == NULL);
+        tstate->monitorspace_frame->monitorspace =
+            (struct _PyMonitorSpaceObject *)monitorspace;
+    }
+
+    Py_INCREF(monitorspace);
+    return monitorspace;
+}
+
+static int
+monitorspace_isshareable (PyObject *self)
+{
+	return 1;
+}
+
+PyDoc_STRVAR(monitorspace_enter__doc__, "enter(func, *args, **kwargs) -> object");
+
+static PyMethodDef monitorspace_methods[] = {
+	{"enter",	(PyCFunction)monitorspace_enter,	METH_VARARGS | METH_KEYWORDS,
+		monitorspace_enter__doc__},
+	{NULL,		NULL}		/* sentinel */
+};
+
+PyTypeObject PyMonitorSpace_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"_threadtoolsmodule.MonitorSpace",	/*tp_name*/
+	sizeof(PyMonitorSpaceObject),	/*tp_basicsize*/
+	0,			/*tp_itemsize*/
+	(destructor)monitorspace_dealloc,	/*tp_dealloc*/
+	0,			/*tp_print*/
+	0,			/*tp_getattr*/
+	0,			/*tp_setattr*/
+	0,			/*tp_compare*/
+	0,			/*tp_repr*/
+	0,			/*tp_as_number*/
+	0,			/*tp_as_sequence*/
+	0,			/*tp_as_mapping*/
+	0,			/*tp_hash*/
+	0,			/*tp_call*/
+	0,			/*tp_str*/
+	PyObject_GenericGetAttr,	/*tp_getattro*/
+	0,			/*tp_setattro*/
+	0,			/*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+		Py_TPFLAGS_SHAREABLE,	/*tp_flags*/
+	0,			/*tp_doc*/
+	0,			/*tp_traverse*/
+	0,			/*tp_clear*/
+	0,			/*tp_richcompare*/
+	0,			/*tp_weaklistoffset*/
+	0,			/*tp_iter*/
+	0,			/*tp_iternext*/
+	monitorspace_methods,	/*tp_methods*/
+	0,			/*tp_members*/
+	0,			/*tp_getset*/
+	0,			/*tp_base*/
+	0,			/*tp_dict*/
+	0,			/*tp_descr_get*/
+	0,			/*tp_descr_set*/
+	0,			/*tp_dictoffset*/
+	0,			/*tp_init*/
+	monitorspace_new,		/*tp_new*/
+	0,			/*tp_is_gc*/
+	0,			/*tp_bases*/
+	0,			/*tp_mro*/
+	0,			/*tp_cache*/
+	0,			/*tp_subclasses*/
+	0,			/*tp_weaklist*/
+	monitorspace_isshareable,	/*tp_isshareable*/
+};
Index: Objects/frameobject.c
===================================================================
--- Objects/frameobject.c	(revision 58355)
+++ Objects/frameobject.c	(working copy)
@@ -6,6 +6,7 @@
 #include "frameobject.h"
 #include "opcode.h"
 #include "structmember.h"
+#include "pythread.h"
 
 #undef MIN
 #undef MAX
@@ -392,51 +393,58 @@
    frames could provoke free_list into growing without bound.
 */
 
+#ifndef WITH_FREETHREAD
+#define USE_FRAME_FREELIST
+#endif
+
+#ifdef USE_FRAME_FREELIST
 static PyFrameObject *free_list = NULL;
 static int numfree = 0;		/* number of frames currently in free_list */
 #define MAXFREELIST 200		/* max value for numfree */
+#endif
 
 static void
 frame_dealloc(PyFrameObject *f)
 {
+	PyThreadState *tstate = PyThreadState_Get();
 	PyObject **p, **valuestack;
 	PyCodeObject *co;
 
-	PyObject_GC_UnTrack(f);
-	Py_TRASHCAN_SAFE_BEGIN(f)
 	/* Kill all local variables */
 	valuestack = f->f_valuestack;
 	for (p = f->f_localsplus; p < valuestack; p++)
-		Py_CLEAR(*p);
+		Py_CLEARTS(*p);
 
 	/* Free stack */
 	if (f->f_stacktop != NULL) {
 		for (p = valuestack; p < f->f_stacktop; p++)
-			Py_XDECREF(*p);
+			Py_XDECREFTS(*p);
 	}
 
-	Py_XDECREF(f->f_back);
-	Py_DECREF(f->f_builtins);
-	Py_DECREF(f->f_globals);
-	Py_CLEAR(f->f_locals);
-	Py_CLEAR(f->f_trace);
-	Py_CLEAR(f->f_exc_type);
-	Py_CLEAR(f->f_exc_value);
-	Py_CLEAR(f->f_exc_traceback);
+	Py_XDECREFTS(f->f_back);
+	Py_DECREFTS(f->f_builtins);
+	Py_DECREFTS(f->f_globals);
+	Py_CLEARTS(f->f_locals);
+	Py_CLEARTS(f->f_trace);
+	Py_CLEARTS(f->f_exc_type);
+	Py_CLEARTS(f->f_exc_value);
+	Py_CLEARTS(f->f_exc_traceback);
 
 	co = f->f_code;
+#ifdef USE_FRAME_FREELIST
 	if (co->co_zombieframe == NULL)
 		co->co_zombieframe = f;
 	else if (numfree < MAXFREELIST) {
 		++numfree;
 		f->f_back = free_list;
 		free_list = f;
-	}
-	else 
-		PyObject_GC_Del(f);
+	} else
+		PyObject_DEL(f);
+#else
+	PyObject_DEL(f);
+#endif
 
-	Py_DECREF(co);
-	Py_TRASHCAN_SAFE_END(f)
+	Py_DECREFTS(co);
 }
 
 static int
@@ -562,7 +570,8 @@
 	}
 #endif
 	if (back == NULL || back->f_globals != globals) {
-		builtins = PyDict_GetItem(globals, builtin_object);
+		if (PyDict_GetItemEx(globals, builtin_object, &builtins) < 0)
+			return NULL;
 		if (builtins) {
 			if (PyModule_Check(builtins)) {
 				builtins = PyModule_GetDict(builtins);
@@ -572,7 +581,7 @@
 				builtins = NULL;
 		}
 		if (builtins == NULL) {
-			/* No builtins!	 Make up a minimal one
+			/* No builtins!  Make up a minimal one
 			   Give them 'None', at least. */
 			builtins = PyDict_New();
 			if (builtins == NULL ||
@@ -581,7 +590,7 @@
 				return NULL;
 		}
 		else
-			Py_INCREF(builtins);
+			Py_INCREFTS(builtins);
 
 	}
 	else {
@@ -589,27 +598,32 @@
 		   Save a lookup and a call. */
 		builtins = back->f_builtins;
 		assert(builtins != NULL && PyDict_Check(builtins));
-		Py_INCREF(builtins);
+		Py_INCREFTS(builtins);
 	}
+#ifdef USE_FRAME_FREELIST
 	if (code->co_zombieframe != NULL) {
 		f = code->co_zombieframe;
 		code->co_zombieframe = NULL;
 		_Py_NewReference((PyObject *)f);
 		assert(f->f_code == code);
-	}
-	else {
+	} else
+#endif
+        {
 		Py_ssize_t extras, ncells, nfrees;
 		ncells = PyTuple_GET_SIZE(code->co_cellvars);
 		nfrees = PyTuple_GET_SIZE(code->co_freevars);
 		extras = code->co_stacksize + code->co_nlocals + ncells +
 		    nfrees;
+#ifdef USE_FRAME_FREELIST
 		if (free_list == NULL) {
-		    f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
+#endif
+		    f = PyObject_NEWVAR(PyFrameObject, &PyFrame_Type,
 			extras);
 		    if (f == NULL) {
-			    Py_DECREF(builtins);
+			    Py_DECREFTS(builtins);
 			    return NULL;
 		    }
+#ifdef USE_FRAME_FREELIST
 		}
 		else {
 		    assert(numfree > 0);
@@ -617,14 +631,23 @@
 		    f = free_list;
 		    free_list = free_list->f_back;
 		    if (Py_Size(f) < extras) {
+#if 0
 			    f = PyObject_GC_Resize(PyFrameObject, f, extras);
 			    if (f == NULL) {
-				    Py_DECREF(builtins);
+				    Py_DECREFTS(builtins);
 				    return NULL;
 			    }
+#else
+			    PyObject *tmp = PyObject_RESIZE(PyFrameObject, f, extras);
+			    if (tmp == NULL) {
+				Py_DECREF(f);
+				return NULL;
+			    }
+#endif
 		    }
 		    _Py_NewReference((PyObject *)f);
 		}
+#endif
 
 		f->f_code = code;
 		extras = code->co_nlocals + ncells + nfrees;
@@ -637,10 +660,10 @@
 	}
 	f->f_stacktop = f->f_valuestack;
 	f->f_builtins = builtins;
-	Py_XINCREF(back);
+	Py_XINCREFTS(back);
 	f->f_back = back;
-	Py_INCREF(code);
-	Py_INCREF(globals);
+	Py_INCREFTS(code);
+	Py_INCREFTS(globals);
 	f->f_globals = globals;
 	/* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
 	if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==
@@ -649,7 +672,7 @@
 	else if (code->co_flags & CO_NEWLOCALS) {
 		locals = PyDict_New();
 		if (locals == NULL) {
-			Py_DECREF(f);
+			Py_DECREFTS(f);
 			return NULL;
 		}
 		f->f_locals = locals;
@@ -657,7 +680,7 @@
 	else {
 		if (locals == NULL)
 			locals = globals;
-		Py_INCREF(locals);
+		Py_INCREFTS(locals);
 		f->f_locals = locals;
 	}
 	f->f_tstate = tstate;
@@ -666,7 +689,6 @@
 	f->f_lineno = code->co_firstlineno;
 	f->f_iblock = 0;
 
-	_PyObject_GC_TRACK(f);
 	return f;
 }
 
@@ -886,13 +908,15 @@
 void
 PyFrame_Fini(void)
 {
+#ifdef USE_FRAME_FREELIST
 	while (free_list != NULL) {
 		PyFrameObject *f = free_list;
 		free_list = free_list->f_back;
-		PyObject_GC_Del(f);
+		PyObject_DEL(f);
 		--numfree;
 	}
 	assert(numfree == 0);
+#endif
 	Py_XDECREF(builtin_object);
 	builtin_object = NULL;
 }
Index: Objects/exceptions.c
===================================================================
--- Objects/exceptions.c	(revision 58355)
+++ Objects/exceptions.c	(working copy)
@@ -23,7 +23,7 @@
 {
     PyBaseExceptionObject *self;
 
-    self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
+    self = PyObject_NEW(PyBaseExceptionObject, type);
     if (!self)
         return NULL;
     /* the dict is created on the fly in PyObject_GenericSetAttr */
@@ -66,9 +66,8 @@
 static void
 BaseException_dealloc(PyBaseExceptionObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     BaseException_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -327,7 +326,7 @@
     PyObject_GenericSetAttr,    /*tp_setattro*/
     0,                          /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
-    	Py_TPFLAGS_BASE_EXC_SUBCLASS,  /*tp_flags*/
+    	Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_SHAREABLE,  /*tp_flags*/
     PyDoc_STR("Common base class for all exceptions"), /* tp_doc */
     (traverseproc)BaseException_traverse, /* tp_traverse */
     (inquiry)BaseException_clear, /* tp_clear */
@@ -344,7 +343,6 @@
     0,                          /* tp_descr_set */
     offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */
     (initproc)BaseException_init, /* tp_init */
-    0,                          /* tp_alloc */
     BaseException_new,          /* tp_new */
 };
 /* the CPython API expects exceptions to be (PyObject *) - both a hold-over
@@ -362,11 +360,11 @@
     sizeof(PyBaseExceptionObject), \
     0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \
     0, 0, 0, 0, 0, 0, 0, \
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE, \
     PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \
     (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
     0, 0, 0, offsetof(PyBaseExceptionObject, dict), \
-    (initproc)BaseException_init, 0, BaseException_new,\
+    (initproc)BaseException_init, BaseException_new,\
 }; \
 PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 
@@ -377,11 +375,11 @@
     sizeof(Py ## EXCSTORE ## Object), \
     0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
     0, 0, 0, 0, 0, \
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE, \
     PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
     (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
     0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
-    (initproc)EXCSTORE ## _init, 0, BaseException_new,\
+    (initproc)EXCSTORE ## _init, BaseException_new,\
 }; \
 PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 
@@ -392,12 +390,12 @@
     sizeof(Py ## EXCSTORE ## Object), 0, \
     (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
     (reprfunc)EXCSTR, 0, 0, 0, \
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE, \
     PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
     (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
     EXCMEMBERS, 0, &_ ## EXCBASE, \
     0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
-    (initproc)EXCSTORE ## _init, 0, BaseException_new,\
+    (initproc)EXCSTORE ## _init, BaseException_new,\
 }; \
 PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
 
@@ -463,9 +461,8 @@
 static void
 SystemExit_dealloc(PySystemExitObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     SystemExit_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -568,9 +565,8 @@
 static void
 EnvironmentError_dealloc(PyEnvironmentErrorObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     EnvironmentError_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -689,9 +685,8 @@
 static void
 WindowsError_dealloc(PyWindowsErrorObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     WindowsError_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -887,9 +882,8 @@
 static void
 SyntaxError_dealloc(PySyntaxErrorObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     SyntaxError_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -1335,9 +1329,8 @@
 static void
 UnicodeError_dealloc(PyUnicodeErrorObject *self)
 {
-    _PyObject_GC_UNTRACK(self);
     UnicodeError_clear(self);
-    Py_Type(self)->tp_free((PyObject *)self);
+    PyObject_DEL(self);
 }
 
 static int
@@ -1414,11 +1407,11 @@
     sizeof(PyUnicodeErrorObject), 0,
     (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     (reprfunc)UnicodeEncodeError_str, 0, 0, 0,
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE,
     PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse,
     (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
     0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
-    (initproc)UnicodeEncodeError_init, 0, BaseException_new,
+    (initproc)UnicodeEncodeError_init, BaseException_new,
 };
 PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError;
 
@@ -1475,11 +1468,11 @@
     sizeof(PyUnicodeErrorObject), 0,
     (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     (reprfunc)UnicodeDecodeError_str, 0, 0, 0,
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE,
     PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse,
     (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
     0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
-    (initproc)UnicodeDecodeError_init, 0, BaseException_new,
+    (initproc)UnicodeDecodeError_init, BaseException_new,
 };
 PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError;
 
@@ -1561,11 +1554,11 @@
     sizeof(PyUnicodeErrorObject), 0,
     (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     (reprfunc)UnicodeTranslateError_str, 0, 0, 0,
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SHAREABLE,
     PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse,
     (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
     0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
-    (initproc)UnicodeTranslateError_init, 0, BaseException_new,
+    (initproc)UnicodeTranslateError_init, BaseException_new,
 };
 PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError;
 
@@ -1641,7 +1634,17 @@
  */
 SimpleExtendsException(PyExc_Exception, BufferError, "Buffer error.");
 
+/*
+ *    MultipleError extends Exception
+ */
+SimpleExtendsException(PyExc_Exception, MultipleError, "Multiple errors.");
 
+/*
+ *    Interrupted extends Exception
+ */
+SimpleExtendsException(PyExc_Exception, Interrupted, "Thread interrupted by parent.");
+
+
 /* Warning category docstrings */
 
 /*
@@ -1799,6 +1802,8 @@
     PRE_INIT(ReferenceError)
     PRE_INIT(BufferError)
     PRE_INIT(MemoryError)
+    PRE_INIT(MultipleError)
+    PRE_INIT(Interrupted)
     PRE_INIT(Warning)
     PRE_INIT(UserWarning)
     PRE_INIT(DeprecationWarning)
@@ -1859,6 +1864,8 @@
     POST_INIT(ReferenceError)
     POST_INIT(BufferError)
     POST_INIT(MemoryError)
+    POST_INIT(MultipleError)
+    POST_INIT(Interrupted)
     POST_INIT(Warning)
     POST_INIT(UserWarning)
     POST_INIT(DeprecationWarning)
Index: Objects/setobject.c
===================================================================
--- Objects/setobject.c	(revision 58355)
+++ Objects/setobject.c	(working copy)
@@ -50,10 +50,13 @@
 	INIT_NONZERO_SET_SLOTS(so);				\
     } while(0)
 
+#ifdef USE_SETS_FREELIST
 /* Reuse scheme to save calls to malloc, free, and memset */
 #define MAXFREESETS 80
 static PySetObject *free_sets[MAXFREESETS];
 static int num_free_sets = 0;
+static PyThread_type_lock free_sets_lock;
+#endif
 
 /*
 The basic lookup function used by all operations.
@@ -545,10 +548,6 @@
 {
 	register setentry *entry;
 	Py_ssize_t fill = so->fill;
-	PyObject_GC_UnTrack(so);
-	Py_TRASHCAN_SAFE_BEGIN(so)
-	if (so->weakreflist != NULL)
-		PyObject_ClearWeakRefs((PyObject *) so);
 
 	for (entry = so->table; fill > 0; entry++) {
 		if (entry->key) {
@@ -558,11 +557,18 @@
 	}
 	if (so->table != so->smalltable)
 		PyMem_DEL(so->table);
-	if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so))
+#ifdef USE_SETS_FREELIST
+	PyThread_lock_acquire(free_sets_lock);
+	if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so)) {
 		free_sets[num_free_sets++] = so;
-	else 
-		Py_Type(so)->tp_free(so);
-	Py_TRASHCAN_SAFE_END(so)
+		PyThread_lock_release(free_sets_lock);
+	} else {
+		PyThread_lock_release(free_sets_lock);
+#endif
+		PyObject_DEL(so);
+#ifdef USE_SETS_FREELIST
+	}
+#endif
 }
 
 static PyObject *
@@ -792,7 +798,7 @@
 setiter_dealloc(setiterobject *si)
 {
 	Py_XDECREF(si->si_set);
-	PyObject_Del(si);
+	PyObject_DEL(si);
 }
 
 static PyObject *
@@ -885,7 +891,7 @@
 static PyObject *
 set_iter(PySetObject *so)
 {
-	setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type);
+	setiterobject *si = PyObject_NEW(setiterobject, &PySetIter_Type);
 	if (si == NULL)
 		return NULL;
 	Py_INCREF(so);
@@ -972,22 +978,27 @@
 	}
 
 	/* create PySetObject structure */
+#ifdef USE_SETS_FREELIST
+	PyThread_lock_acquire(free_sets_lock);
 	if (num_free_sets && 
 	    (type == &PySet_Type  ||  type == &PyFrozenSet_Type)) {
 		so = free_sets[--num_free_sets];
+		PyThread_lock_release(free_sets_lock);
 		assert (so != NULL && PyAnySet_CheckExact(so));
 		Py_Type(so) = type;
-		_Py_NewReference((PyObject *)so);
+		//_Py_NewReference((PyObject *)so);
 		EMPTY_TO_MINSIZE(so);
 		PyObject_GC_Track(so);
 	} else {
-		so = (PySetObject *)type->tp_alloc(type, 0);
+		PyThread_lock_release(free_sets_lock);
+#endif
+		so = PyObject_NEW(PySetObject, type);
 		if (so == NULL)
 			return NULL;
-		/* tp_alloc has already zeroed the structure */
-		assert(so->table == NULL && so->fill == 0 && so->used == 0);
 		INIT_NONZERO_SET_SLOTS(so);
+#ifdef USE_SETS_FREELIST
 	}
+#endif
 
 	so->lookup = set_lookkey_string;
 	so->weakreflist = NULL;
@@ -1038,17 +1049,34 @@
 }
 
 void
+_PySet_Init(void)
+{
+#ifdef USE_SETS_FREELIST
+	free_sets_lock = PyThread_lock_allocate();
+	if (!free_sets_lock)
+		Py_FatalError("unable to allocate lock");
+#endif
+}
+
+void
 PySet_Fini(void)
 {
+#ifdef USE_SETS_FREELIST
 	PySetObject *so;
 
 	while (num_free_sets) {
 		num_free_sets--;
 		so = free_sets[num_free_sets];
-		PyObject_GC_Del(so);
+		PyObject_DEL(so);
 	}
+#endif
 	Py_CLEAR(dummy);
 	Py_CLEAR(emptyfrozenset);
+
+#ifdef USE_SETS_FREELIST
+	PyThread_lock_free(free_sets_lock);
+	free_sets_lock = NULL;
+#endif
 }
 
 static PyObject *
@@ -1926,7 +1954,8 @@
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_SHAREABLE,
+					/* tp_flags */
 	set_doc,			/* tp_doc */
 	(traverseproc)set_traverse,	/* tp_traverse */
 	(inquiry)set_clear_internal,	/* tp_clear */
@@ -1943,9 +1972,7 @@
 	0,				/* tp_descr_set */
 	0,				/* tp_dictoffset */
 	(initproc)set_init,		/* tp_init */
-	PyType_GenericAlloc,		/* tp_alloc */
 	set_new,			/* tp_new */
-	PyObject_GC_Del,		/* tp_free */
 };
 
 /* frozenset object ********************************************************/
@@ -2019,7 +2046,8 @@
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_SHAREABLE,
+					/* tp_flags */
 	frozenset_doc,			/* tp_doc */
 	(traverseproc)set_traverse,	/* tp_traverse */
 	(inquiry)set_clear_internal,	/* tp_clear */
@@ -2036,9 +2064,7 @@
 	0,				/* tp_descr_set */
 	0,				/* tp_dictoffset */
 	0,				/* tp_init */
-	PyType_GenericAlloc,		/* tp_alloc */
 	frozenset_new,			/* tp_new */
-	PyObject_GC_Del,		/* tp_free */
 };
 
 
Index: Objects/funcobject.c
===================================================================
--- Objects/funcobject.c	(revision 58355)
+++ Objects/funcobject.c	(working copy)
@@ -9,7 +9,7 @@
 PyObject *
 PyFunction_New(PyObject *code, PyObject *globals)
 {
-	PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
+	PyFunctionObject *op = PyObject_NEW(PyFunctionObject,
 					    &PyFunction_Type);
 	static PyObject *__name__ = 0;
 	if (op != NULL) {
@@ -50,15 +50,14 @@
 				return NULL;
 			}
 		}
-		module = PyDict_GetItem(globals, __name__);
-		if (module) {
-		    Py_INCREF(module);
-		    op->func_module = m
