Vladimir Marangozov's long-awaited malloc restructuring.
For more comments, read the patches@python.org archives.
For documentation read the comments in mymalloc.h and objimpl.h.

(This is not exactly what Vladimir posted to the patches list; I've
made a few changes, and Vladimir sent me a fix in private email for a
problem that only occurs in debug mode.  I'm also holding back on his
change to main.c, which seems unnecessary to me.)
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 005d709..f70d19b 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -70,7 +70,8 @@
 	if (nbytes / sizeof(PyObject *) != (size_t)size) {
 		return PyErr_NoMemory();
 	}
-	op = (PyListObject *) malloc(sizeof(PyListObject));
+	/* PyObject_NewVar is inlined */
+	op = (PyListObject *) PyObject_MALLOC(sizeof(PyListObject));
 	if (op == NULL) {
 		return PyErr_NoMemory();
 	}
@@ -78,17 +79,15 @@
 		op->ob_item = NULL;
 	}
 	else {
-		op->ob_item = (PyObject **) malloc(nbytes);
+		op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
 		if (op->ob_item == NULL) {
-			free((ANY *)op);
+			PyObject_FREE(op);
 			return PyErr_NoMemory();
 		}
 	}
-	op->ob_type = &PyList_Type;
-	op->ob_size = size;
+	PyObject_INIT_VAR(op, &PyList_Type, size);
 	for (i = 0; i < size; i++)
 		op->ob_item[i] = NULL;
-	_Py_NewReference((PyObject *)op);
 	return (PyObject *) op;
 }
 
@@ -225,9 +224,9 @@
 		while (--i >= 0) {
 			Py_XDECREF(op->ob_item[i]);
 		}
-		free((ANY *)op->ob_item);
+		PyMem_FREE(op->ob_item);
 	}
-	free((ANY *)op);
+	PyObject_DEL(op);
 	Py_TRASHCAN_SAFE_END(op)
 }
 
@@ -501,7 +500,8 @@
 	else { /* Insert d items; recycle ihigh-ilow items */
 		NRESIZE(item, PyObject *, a->ob_size + d);
 		if (item == NULL) {
-			PyMem_XDEL(recycle);
+			if (recycle != NULL)
+				PyMem_DEL(recycle);
 			PyErr_NoMemory();
 			return -1;
 		}