Simplified AssureWritable().
diff --git a/python/message.c b/python/message.c
index 1b3a7bb..69a9322 100644
--- a/python/message.c
+++ b/python/message.c
@@ -474,14 +474,18 @@
   const upb_fielddef* f = PyUpb_CMessage_GetFieldDef(m);
   m->ptr.msg = upb_msg_new(upb_fielddef_msgsubdef(f), arena);
   m->def = (uintptr_t)upb_fielddef_msgsubdef(f);
+  PyUpb_ObjCache_Add(m->ptr.msg, &m->ob_base);
   return f;
 }
 
-static void PyUpb_CMessage_SetField(PyUpb_CMessage* p, const upb_fielddef* cf,
-                                    PyUpb_CMessage* c, upb_arena* arena) {
-  upb_msg_set(p->ptr.msg, cf, (upb_msgval){.msg_val = c->ptr.msg}, arena);
-  PyUpb_WeakMap_Delete(p->unset_subobj_map, cf);
-  PyUpb_ObjCache_Add(c->ptr.msg, &c->ob_base);
+static void PyUpb_CMessage_SetField(PyUpb_CMessage* parent,
+                                    const upb_fielddef* f,
+                                    PyUpb_CMessage* child, upb_arena* arena) {
+  upb_msgval msgval = {.msg_val = PyUpb_CMessage_GetMsg(child)};
+  upb_msg_set(PyUpb_CMessage_GetMsg(parent), f, msgval, arena);
+  PyUpb_WeakMap_Delete(parent->unset_subobj_map, f);
+  // Releases a ref previously owned by child->ptr.parent of our child.
+  Py_DECREF(child);
 }
 
 /*
@@ -502,29 +506,32 @@
  * Post-condition:
  *   PyUpb_CMessage_IsUnset(self) is false
  */
-void PyUpb_CMessage_AssureWritable(PyUpb_CMessage* child) {
-  if (!PyUpb_CMessage_IsUnset(child)) return;
+void PyUpb_CMessage_AssureWritable(PyUpb_CMessage* self) {
+  if (!PyUpb_CMessage_IsUnset(self)) return;
+  upb_arena* arena = PyUpb_Arena_Get(self->arena);
+
   // This is a non-present message. We need to create a real upb_msg for this
   // object and every parent until we reach a present message.
-  upb_arena* arena = PyUpb_Arena_Get(child->arena);
-
-  PyUpb_CMessage* next_parent = NULL;
-  PyUpb_CMessage* parent = child->ptr.parent;
+  PyUpb_CMessage* child = self;
+  PyUpb_CMessage* parent = self->ptr.parent;
   const upb_fielddef* child_f = PyUpb_CMessage_InitAsMsg(child, arena);
+  Py_INCREF(child);  // To avoid a special-case in PyUpb_CMessage_SetField().
+
   do {
+    PyUpb_CMessage* next_parent = parent->ptr.parent;
     const upb_fielddef* parent_f = NULL;
     if (PyUpb_CMessage_IsUnset(parent)) {
-      next_parent = parent->ptr.parent;
       parent_f = PyUpb_CMessage_InitAsMsg(parent, arena);
     }
     PyUpb_CMessage_SetField(parent, child_f, child, arena);
-    Py_DECREF(&child->ob_base);
-    child_f = parent_f;
     child = parent;
+    child_f = parent_f;
     parent = next_parent;
-  } while (PyUpb_CMessage_IsUnset(child));
+  } while (child_f);
 
-  child->version++;
+  // Releases ref previously owned by child->ptr.parent of our child.
+  Py_DECREF(child);
+  self->version++;
 }
 
 static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self);