Adds implementations for most descriptor objects.
diff --git a/python/descriptor_pool.c b/python/descriptor_pool.c
index 159d7c6..7b43457 100644
--- a/python/descriptor_pool.c
+++ b/python/descriptor_pool.c
@@ -41,6 +41,11 @@
   PyObject* db;
 } PyUpb_DescriptorPool;
 
+PyObject *PyUpb_DescriptorPool_GetDefaultPool() {
+  PyUpb_ModuleState *s = PyUpb_ModuleState_Get();
+  return s->default_pool;
+}
+
 static PyObject* PyUpb_DescriptorPool_DoCreate(PyTypeObject* type,
                                                PyObject* db) {
   PyUpb_DescriptorPool* pool = PyObject_GC_New(PyUpb_DescriptorPool, type);
@@ -48,9 +53,14 @@
   pool->db = db;
   Py_XINCREF(pool->db);
   PyObject_GC_Track(&pool->ob_base);
+  PyUpb_ObjCache_Add(pool->symtab, &pool->ob_base);
   return &pool->ob_base;
 }
 
+upb_symtab *PyUpb_DescriptorPool_GetSymtab(PyObject *pool) {
+  return ((PyUpb_DescriptorPool*)pool)->symtab;
+}
+
 static int PyUpb_DescriptorPool_Traverse(PyUpb_DescriptorPool* self,
                                          visitproc visit, void* arg) {
   Py_VISIT(self->db);
@@ -62,10 +72,17 @@
   return 0;
 }
 
+PyObject* PyUpb_DescriptorPool_Get(const upb_symtab *symtab) {
+  PyObject *pool = PyUpb_ObjCache_Get(symtab);
+  assert(pool);
+  return pool;
+}
+
 static void PyUpb_DescriptorPool_Dealloc(PyUpb_DescriptorPool* self) {
   upb_symtab_free(self->symtab);
   PyUpb_DescriptorPool_Clear(self);
-  PyObject_GC_Del(self);
+  PyUpb_ObjCache_Delete(self->symtab);
+  PyUpb_Dealloc(self);
 }
 
 /*
@@ -132,7 +149,7 @@
     goto done;
   }
 
-  result = PyUpb_FileDescriptor_GetOrCreateWrapper(filedef, _self);
+  result = PyUpb_FileDescriptor_Get(filedef);
 
 done:
   upb_arena_free(arena);
@@ -157,7 +174,7 @@
     return PyErr_Format(PyExc_KeyError, "Couldn't find extension %.200s", name);
   }
 
-  return PyUpb_FieldDescriptor_GetOrCreateWrapper(field, _self);
+  return PyUpb_FieldDescriptor_Get(field);
 }
 
 static PyMethodDef PyUpb_DescriptorPool_Methods[] = {