From cff35e2c4b57d2db81686cbb17f86b65430372fc Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Thu, 1 May 2025 00:38:43 +0700
Subject: [PATCH v1 4/5] Get rid of RT_CHILD_PTR

* Change RT_PTR_SET_LOCAL to RT_PTR_GET_LOCAL
* Split out the node initialization functionality of RT_ALLOC_NODE
  to RT_INIT_NODE_* functions

This was orignally part of a series for tagging child pointers
with the node kind.

The purpose for bitmap heap scan is to allow callers to allotate
their own memory. Likely not all of this is strictly necessary.
---
 src/include/lib/radixtree.h | 446 ++++++++++++++++++------------------
 1 file changed, 225 insertions(+), 221 deletions(-)

diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index b0902988ee1..86647eaae93 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -202,6 +202,7 @@
 #define RT_GET_SLOT_RECURSIVE RT_MAKE_NAME(get_slot_recursive)
 #define RT_DELETE_RECURSIVE RT_MAKE_NAME(delete_recursive)
 #define RT_ALLOC_NODE RT_MAKE_NAME(alloc_node)
+#define RT_INIT_NODE RT_MAKE_NAME(init_node)
 #define RT_ALLOC_LEAF RT_MAKE_NAME(alloc_leaf)
 #define RT_FREE_NODE RT_MAKE_NAME(free_node)
 #define RT_FREE_LEAF RT_MAKE_NAME(free_leaf)
@@ -209,7 +210,7 @@
 #define RT_EXTEND_UP RT_MAKE_NAME(extend_up)
 #define RT_EXTEND_DOWN RT_MAKE_NAME(extend_down)
 #define RT_COPY_COMMON RT_MAKE_NAME(copy_common)
-#define RT_PTR_SET_LOCAL RT_MAKE_NAME(ptr_set_local)
+#define RT_PTR_GET_LOCAL RT_MAKE_NAME(ptr_get_local)
 #define RT_NODE_16_SEARCH_EQ RT_MAKE_NAME(node_16_search_eq)
 #define RT_NODE_4_GET_INSERTPOS RT_MAKE_NAME(node_4_get_insertpos)
 #define RT_NODE_16_GET_INSERTPOS RT_MAKE_NAME(node_16_get_insertpos)
@@ -251,7 +252,6 @@
 #define RT_HANDLE RT_MAKE_NAME(handle)
 #endif
 #define RT_NODE RT_MAKE_NAME(node)
-#define RT_CHILD_PTR RT_MAKE_NAME(child_ptr)
 #define RT_NODE_ITER RT_MAKE_NAME(node_iter)
 #define RT_NODE_4 RT_MAKE_NAME(node_4)
 #define RT_NODE_16 RT_MAKE_NAME(node_16)
@@ -410,21 +410,6 @@ typedef struct RT_NODE
 #define RT_PTR_ALLOC_IS_VALID(ptr) PointerIsValid(ptr)
 #endif
 
-/*
- * A convenience type used when we need to work with a DSA pointer as well
- * as its local pointer. For local memory, both members are the same, so
- * we use a union.
- */
-#ifdef RT_SHMEM
-typedef struct RT_CHILD_PTR
-#else
-typedef union RT_CHILD_PTR
-#endif
-{
-	RT_PTR_ALLOC alloc;
-	RT_NODE    *local;
-}			RT_CHILD_PTR;
-
 
 /*
  * Helper macros and functions for value storage.
@@ -733,7 +718,8 @@ struct RT_RADIX_TREE
 /* state for iterating over a single node */
 typedef struct RT_NODE_ITER
 {
-	RT_CHILD_PTR node;
+	RT_PTR_ALLOC nodealloc;
+	RT_NODE    *node;
 
 	/*
 	 * The next index of the chunk array in RT_NODE_KIND_4 and RT_NODE_KIND_16
@@ -764,11 +750,13 @@ struct RT_ITER
 /* verification (available only in assert-enabled builds) */
 static void RT_VERIFY_NODE(RT_NODE * node);
 
-static inline void
-RT_PTR_SET_LOCAL(RT_RADIX_TREE * tree, RT_CHILD_PTR * node)
+static inline RT_NODE *
+RT_PTR_GET_LOCAL(RT_RADIX_TREE * tree, RT_PTR_ALLOC nodealloc)
 {
 #ifdef RT_SHMEM
-	node->local = dsa_get_address(tree->dsa, node->alloc);
+	return dsa_get_address(tree->dsa, nodealloc);
+#else
+	return nodealloc;
 #endif
 }
 
@@ -828,30 +816,35 @@ RT_SHIFT_GET_MAX_VAL(int shift)
 		return (UINT64CONST(1) << (shift + RT_SPAN)) - 1;
 }
 
-/*
- * Allocate a new node with the given node kind and size class.
- */
-static inline RT_CHILD_PTR
-RT_ALLOC_NODE(RT_RADIX_TREE * tree, const uint8 kind, const RT_SIZE_CLASS size_class)
+static inline RT_PTR_ALLOC
+RT_ALLOC_NODE(RT_RADIX_TREE * tree, const RT_SIZE_CLASS size_class)
 {
-	RT_CHILD_PTR allocnode;
-	RT_NODE    *node;
 	size_t		allocsize;
+	RT_PTR_ALLOC nodealloc;
 
 	allocsize = RT_SIZE_CLASS_INFO[size_class].allocsize;
 
 #ifdef RT_SHMEM
-	allocnode.alloc = dsa_allocate(tree->dsa, allocsize);
+	nodealloc = dsa_allocate(tree->dsa, allocsize);
 #else
-	allocnode.alloc = (RT_PTR_ALLOC) MemoryContextAlloc(tree->node_slabs[size_class],
-														allocsize);
+	nodealloc = (RT_PTR_ALLOC) MemoryContextAlloc(tree->node_slabs[size_class],
+												  allocsize);
 #endif
 
-	RT_PTR_SET_LOCAL(tree, &allocnode);
-	node = allocnode.local;
+#ifdef RT_DEBUG
+	/* update the statistics */
+	tree->ctl->num_nodes[size_class]++;
+#endif
 
-	/* initialize contents */
+	return nodealloc;
+}
 
+/*
+ * Initialize the given node with the necessary metadata.
+ */
+static inline void
+RT_INIT_NODE(RT_NODE * node, const uint8 kind, const RT_SIZE_CLASS size_class)
+{
 	switch (kind)
 	{
 		case RT_NODE_KIND_4:
@@ -882,35 +875,27 @@ RT_ALLOC_NODE(RT_RADIX_TREE * tree, const uint8 kind, const RT_SIZE_CLASS size_c
 	 * because that node doesn't need to introspect this value.
 	 */
 	node->fanout = RT_SIZE_CLASS_INFO[size_class].fanout;
-
-#ifdef RT_DEBUG
-	/* update the statistics */
-	tree->ctl->num_nodes[size_class]++;
-#endif
-
-	return allocnode;
 }
 
 /*
  * Allocate a new leaf.
  */
-static RT_CHILD_PTR
+static RT_PTR_ALLOC
 RT_ALLOC_LEAF(RT_RADIX_TREE * tree, size_t allocsize)
 {
-	RT_CHILD_PTR leaf;
+	RT_PTR_ALLOC leafalloc;
 
 #ifdef RT_SHMEM
-	leaf.alloc = dsa_allocate(tree->dsa, allocsize);
-	RT_PTR_SET_LOCAL(tree, &leaf);
+	leafalloc = dsa_allocate(tree->dsa, allocsize);
 #else
-	leaf.alloc = (RT_PTR_ALLOC) MemoryContextAlloc(tree->leaf_context, allocsize);
+	leafalloc = (RT_PTR_ALLOC) MemoryContextAlloc(tree->leaf_context, allocsize);
 #endif
 
 #ifdef RT_DEBUG
 	tree->ctl->num_leaves++;
 #endif
 
-	return leaf;
+	return leafalloc;
 }
 
 /*
@@ -918,23 +903,24 @@ RT_ALLOC_LEAF(RT_RADIX_TREE * tree, size_t allocsize)
  * This is a separate function in case other fields are added.
  */
 static inline void
-RT_COPY_COMMON(RT_CHILD_PTR newnode, RT_CHILD_PTR oldnode)
+RT_COPY_COMMON(RT_NODE * newnode, RT_NODE * oldnode)
 {
-	(newnode.local)->count = (oldnode.local)->count;
+	newnode->count = oldnode->count;
 }
 
 /* Free the given node */
 static void
-RT_FREE_NODE(RT_RADIX_TREE * tree, RT_CHILD_PTR node)
+RT_FREE_NODE(RT_RADIX_TREE * tree, RT_PTR_ALLOC nodealloc)
 {
 #ifdef RT_DEBUG
 	int			i;
+	RT_NODE    *node = RT_PTR_GET_LOCAL(tree, nodealloc);
 
 	/* update the statistics */
 
 	for (i = 0; i < RT_NUM_SIZE_CLASSES; i++)
 	{
-		if ((node.local)->fanout == RT_SIZE_CLASS_INFO[i].fanout)
+		if (node->fanout == RT_SIZE_CLASS_INFO[i].fanout)
 			break;
 	}
 
@@ -950,9 +936,9 @@ RT_FREE_NODE(RT_RADIX_TREE * tree, RT_CHILD_PTR node)
 #endif
 
 #ifdef RT_SHMEM
-	dsa_free(tree->dsa, node.alloc);
+	dsa_free(tree->dsa, nodealloc);
 #else
-	pfree(node.alloc);
+	pfree(nodealloc);
 #endif
 }
 
@@ -1094,7 +1080,8 @@ RT_NODE_SEARCH(RT_NODE * node, uint8 chunk)
 RT_SCOPE	RT_VALUE_TYPE *
 RT_FIND(RT_RADIX_TREE * tree, uint64 key)
 {
-	RT_CHILD_PTR node;
+	RT_PTR_ALLOC nodealloc;
+	RT_NODE    *node;
 	RT_PTR_ALLOC *slot = NULL;
 	int			shift;
 
@@ -1106,18 +1093,18 @@ RT_FIND(RT_RADIX_TREE * tree, uint64 key)
 		return NULL;
 
 	Assert(RT_PTR_ALLOC_IS_VALID(tree->ctl->root));
-	node.alloc = tree->ctl->root;
+	nodealloc = tree->ctl->root;
 	shift = tree->ctl->start_shift;
 
 	/* Descend the tree */
 	while (shift >= 0)
 	{
-		RT_PTR_SET_LOCAL(tree, &node);
-		slot = RT_NODE_SEARCH(node.local, RT_GET_KEY_CHUNK(key, shift));
+		node = RT_PTR_GET_LOCAL(tree, nodealloc);
+		slot = RT_NODE_SEARCH(node, RT_GET_KEY_CHUNK(key, shift));
 		if (slot == NULL)
 			return NULL;
 
-		node.alloc = *slot;
+		nodealloc = *slot;
 		shift -= RT_SPAN;
 	}
 
@@ -1125,8 +1112,8 @@ RT_FIND(RT_RADIX_TREE * tree, uint64 key)
 		return (RT_VALUE_TYPE *) slot;
 	else
 	{
-		RT_PTR_SET_LOCAL(tree, &node);
-		return (RT_VALUE_TYPE *) node.local;
+		node = RT_PTR_GET_LOCAL(tree, nodealloc);
+		return (RT_VALUE_TYPE *) node;
 	}
 }
 
@@ -1270,9 +1257,8 @@ RT_COPY_ARRAYS_FOR_INSERT(uint8 *dst_chunks, RT_PTR_ALLOC * dst_children,
 }
 
 static inline RT_PTR_ALLOC *
-RT_ADD_CHILD_256(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
+RT_ADD_CHILD_256(RT_RADIX_TREE * tree, RT_NODE_256 * n256, uint8 chunk)
 {
-	RT_NODE_256 *n256 = (RT_NODE_256 *) node.local;
 	int			idx = RT_BM_IDX(chunk);
 	int			bitnum = RT_BM_BIT(chunk);
 
@@ -1286,20 +1272,22 @@ RT_ADD_CHILD_256(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
 }
 
 static pg_noinline RT_PTR_ALLOC *
-RT_GROW_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node,
+RT_GROW_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_48 * n48,
 				uint8 chunk)
 {
-	RT_NODE_48 *n48 = (RT_NODE_48 *) node.local;
-	RT_CHILD_PTR newnode;
+	RT_PTR_ALLOC newalloc;
+	RT_NODE    *newnode;
 	RT_NODE_256 *new256;
 	int			i = 0;
 
 	/* initialize new node */
-	newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_256, RT_CLASS_256);
-	new256 = (RT_NODE_256 *) newnode.local;
+	newalloc = RT_ALLOC_NODE(tree, RT_CLASS_256);
+	newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+	RT_INIT_NODE(newnode, RT_NODE_KIND_256, RT_CLASS_256);
+	new256 = (RT_NODE_256 *) newnode;
 
 	/* copy over the entries */
-	RT_COPY_COMMON(newnode, node);
+	RT_COPY_COMMON((RT_NODE *) new256, (RT_NODE *) n48);
 	for (int word_num = 0; word_num < RT_BM_IDX(RT_NODE_MAX_SLOTS); word_num++)
 	{
 		bitmapword	bitmap = 0;
@@ -1326,16 +1314,15 @@ RT_GROW_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR n
 	}
 
 	/* free old node and update reference in parent */
-	*parent_slot = newnode.alloc;
-	RT_FREE_NODE(tree, node);
+	RT_FREE_NODE(tree, *parent_slot);
+	*parent_slot = newalloc;
 
-	return RT_ADD_CHILD_256(tree, newnode, chunk);
+	return RT_ADD_CHILD_256(tree, new256, chunk);
 }
 
 static inline RT_PTR_ALLOC *
-RT_ADD_CHILD_48(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
+RT_ADD_CHILD_48(RT_RADIX_TREE * tree, RT_NODE_48 * n48, uint8 chunk)
 {
-	RT_NODE_48 *n48 = (RT_NODE_48 *) node.local;
 	int			insertpos;
 	int			idx = 0;
 	bitmapword	w,
@@ -1371,25 +1358,27 @@ RT_ADD_CHILD_48(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
 }
 
 static pg_noinline RT_PTR_ALLOC *
-RT_GROW_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node,
+RT_GROW_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_16 * n16,
 				uint8 chunk)
 {
-	RT_NODE_16 *n16 = (RT_NODE_16 *) node.local;
 	int			insertpos;
 
 	if (n16->base.fanout < RT_FANOUT_16_HI)
 	{
-		RT_CHILD_PTR newnode;
+		RT_PTR_ALLOC newalloc;
+		RT_NODE    *newnode;
 		RT_NODE_16 *new16;
 
 		Assert(n16->base.fanout == RT_FANOUT_16_LO);
 
 		/* initialize new node */
-		newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_16, RT_CLASS_16_HI);
-		new16 = (RT_NODE_16 *) newnode.local;
+		newalloc = RT_ALLOC_NODE(tree, RT_CLASS_16_HI);
+		newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+		RT_INIT_NODE(newnode, RT_NODE_KIND_16, RT_CLASS_16_HI);
+		new16 = (RT_NODE_16 *) newnode;
 
 		/* copy over existing entries */
-		RT_COPY_COMMON(newnode, node);
+		RT_COPY_COMMON((RT_NODE *) new16, (RT_NODE *) n16);
 		Assert(n16->base.count == RT_FANOUT_16_LO);
 		insertpos = RT_NODE_16_GET_INSERTPOS(n16, chunk);
 		RT_COPY_ARRAYS_FOR_INSERT(new16->chunks, new16->children,
@@ -1403,14 +1392,15 @@ RT_GROW_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR n
 		RT_VERIFY_NODE((RT_NODE *) new16);
 
 		/* free old node and update references */
-		RT_FREE_NODE(tree, node);
-		*parent_slot = newnode.alloc;
+		RT_FREE_NODE(tree, *parent_slot);
+		*parent_slot = newalloc;
 
 		return &new16->children[insertpos];
 	}
 	else
 	{
-		RT_CHILD_PTR newnode;
+		RT_PTR_ALLOC newalloc;
+		RT_NODE    *newnode;
 		RT_NODE_48 *new48;
 		int			idx,
 					bit;
@@ -1418,11 +1408,13 @@ RT_GROW_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR n
 		Assert(n16->base.fanout == RT_FANOUT_16_HI);
 
 		/* initialize new node */
-		newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_48, RT_CLASS_48);
-		new48 = (RT_NODE_48 *) newnode.local;
+		newalloc = RT_ALLOC_NODE(tree, RT_CLASS_48);
+		newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+		RT_INIT_NODE(newnode, RT_NODE_KIND_48, RT_CLASS_48);
+		new48 = (RT_NODE_48 *) newnode;
 
 		/* copy over the entries */
-		RT_COPY_COMMON(newnode, node);
+		RT_COPY_COMMON((RT_NODE *) new48, (RT_NODE *) n16);
 		for (int i = 0; i < RT_FANOUT_16_HI; i++)
 			new48->slot_idxs[n16->chunks[i]] = i;
 		memcpy(&new48->children[0], &n16->children[0], RT_FANOUT_16_HI * sizeof(new48->children[0]));
@@ -1450,17 +1442,16 @@ RT_GROW_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR n
 		RT_VERIFY_NODE((RT_NODE *) new48);
 
 		/* free old node and update reference in parent */
-		*parent_slot = newnode.alloc;
-		RT_FREE_NODE(tree, node);
+		RT_FREE_NODE(tree, *parent_slot);
+		*parent_slot = newalloc;
 
 		return &new48->children[insertpos];
 	}
 }
 
 static inline RT_PTR_ALLOC *
-RT_ADD_CHILD_16(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
+RT_ADD_CHILD_16(RT_RADIX_TREE * tree, RT_NODE_16 * n16, uint8 chunk)
 {
-	RT_NODE_16 *n16 = (RT_NODE_16 *) node.local;
 	int			insertpos = RT_NODE_16_GET_INSERTPOS(n16, chunk);
 
 	/* shift chunks and children */
@@ -1477,20 +1468,22 @@ RT_ADD_CHILD_16(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
 }
 
 static pg_noinline RT_PTR_ALLOC *
-RT_GROW_NODE_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node,
+RT_GROW_NODE_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_4 * n4,
 			   uint8 chunk)
 {
-	RT_NODE_4  *n4 = (RT_NODE_4 *) (node.local);
-	RT_CHILD_PTR newnode;
+	RT_PTR_ALLOC newalloc;
+	RT_NODE    *newnode;
 	RT_NODE_16 *new16;
 	int			insertpos;
 
 	/* initialize new node */
-	newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_16, RT_CLASS_16_LO);
-	new16 = (RT_NODE_16 *) newnode.local;
+	newalloc = RT_ALLOC_NODE(tree, RT_CLASS_16_LO);
+	newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+	RT_INIT_NODE(newnode, RT_NODE_KIND_16, RT_CLASS_16_LO);
+	new16 = (RT_NODE_16 *) newnode;
 
 	/* copy over existing entries */
-	RT_COPY_COMMON(newnode, node);
+	RT_COPY_COMMON((RT_NODE *) new16, (RT_NODE *) n4);
 	Assert(n4->base.count == RT_FANOUT_4);
 	insertpos = RT_NODE_4_GET_INSERTPOS(n4, chunk, RT_FANOUT_4);
 	RT_COPY_ARRAYS_FOR_INSERT(new16->chunks, new16->children,
@@ -1504,16 +1497,15 @@ RT_GROW_NODE_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR no
 	RT_VERIFY_NODE((RT_NODE *) new16);
 
 	/* free old node and update reference in parent */
-	*parent_slot = newnode.alloc;
-	RT_FREE_NODE(tree, node);
+	RT_FREE_NODE(tree, *parent_slot);
+	*parent_slot = newalloc;
 
 	return &new16->children[insertpos];
 }
 
 static inline RT_PTR_ALLOC *
-RT_ADD_CHILD_4(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
+RT_ADD_CHILD_4(RT_RADIX_TREE * tree, RT_NODE_4 * n4, uint8 chunk)
 {
-	RT_NODE_4  *n4 = (RT_NODE_4 *) (node.local);
 	int			count = n4->base.count;
 	int			insertpos = RT_NODE_4_GET_INSERTPOS(n4, chunk, count);
 
@@ -1539,36 +1531,40 @@ RT_ADD_CHILD_4(RT_RADIX_TREE * tree, RT_CHILD_PTR node, uint8 chunk)
  * child pointer with the pointer to the new larger node.
  */
 static inline RT_PTR_ALLOC *
-RT_NODE_INSERT(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node,
+RT_NODE_INSERT(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE * n,
 			   uint8 chunk)
 {
-	RT_NODE    *n = node.local;
-
 	switch (n->kind)
 	{
 		case RT_NODE_KIND_4:
 			{
+				RT_NODE_4  *n4 = (RT_NODE_4 *) n;
+
 				if (unlikely(RT_NODE_MUST_GROW(n)))
-					return RT_GROW_NODE_4(tree, parent_slot, node, chunk);
+					return RT_GROW_NODE_4(tree, parent_slot, n4, chunk);
 
-				return RT_ADD_CHILD_4(tree, node, chunk);
+				return RT_ADD_CHILD_4(tree, n4, chunk);
 			}
 		case RT_NODE_KIND_16:
 			{
+				RT_NODE_16 *n16 = (RT_NODE_16 *) n;
+
 				if (unlikely(RT_NODE_MUST_GROW(n)))
-					return RT_GROW_NODE_16(tree, parent_slot, node, chunk);
+					return RT_GROW_NODE_16(tree, parent_slot, n16, chunk);
 
-				return RT_ADD_CHILD_16(tree, node, chunk);
+				return RT_ADD_CHILD_16(tree, n16, chunk);
 			}
 		case RT_NODE_KIND_48:
 			{
+				RT_NODE_48 *n48 = (RT_NODE_48 *) n;
+
 				if (unlikely(RT_NODE_MUST_GROW(n)))
-					return RT_GROW_NODE_48(tree, parent_slot, node, chunk);
+					return RT_GROW_NODE_48(tree, parent_slot, n48, chunk);
 
-				return RT_ADD_CHILD_48(tree, node, chunk);
+				return RT_ADD_CHILD_48(tree, (RT_NODE_48 *) n, chunk);
 			}
 		case RT_NODE_KIND_256:
-			return RT_ADD_CHILD_256(tree, node, chunk);
+			return RT_ADD_CHILD_256(tree, (RT_NODE_256 *) n, chunk);
 		default:
 			pg_unreachable();
 	}
@@ -1589,17 +1585,20 @@ RT_EXTEND_UP(RT_RADIX_TREE * tree, uint64 key)
 	/* Grow tree upwards until start shift can accommodate the key */
 	while (shift < target_shift)
 	{
-		RT_CHILD_PTR node;
+		RT_PTR_ALLOC nodealloc;
+		RT_NODE    *node;
 		RT_NODE_4  *n4;
 
-		node = RT_ALLOC_NODE(tree, RT_NODE_KIND_4, RT_CLASS_4);
-		n4 = (RT_NODE_4 *) node.local;
+		nodealloc = RT_ALLOC_NODE(tree, RT_CLASS_4);
+		node = RT_PTR_GET_LOCAL(tree, nodealloc);
+		RT_INIT_NODE(node, RT_NODE_KIND_4, RT_CLASS_4);
+		n4 = (RT_NODE_4 *) node;
 		n4->base.count = 1;
 		n4->chunks[0] = 0;
 		n4->children[0] = tree->ctl->root;
 
 		/* Update the root */
-		tree->ctl->root = node.alloc;
+		tree->ctl->root = nodealloc;
 
 		shift += RT_SPAN;
 	}
@@ -1616,29 +1615,34 @@ RT_EXTEND_UP(RT_RADIX_TREE * tree, uint64 key)
 static pg_noinline RT_PTR_ALLOC *
 RT_EXTEND_DOWN(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, uint64 key, int shift)
 {
-	RT_CHILD_PTR node,
-				child;
+	RT_PTR_ALLOC childalloc;
+	RT_NODE    *child;
+	RT_NODE    *node;
 	RT_NODE_4  *n4;
 
 	/*
 	 * The child pointer of the first node in the chain goes in the
 	 * caller-provided slot.
 	 */
-	child = RT_ALLOC_NODE(tree, RT_NODE_KIND_4, RT_CLASS_4);
-	*parent_slot = child.alloc;
+	childalloc = RT_ALLOC_NODE(tree, RT_CLASS_4);
+	*parent_slot = childalloc;
+	child = RT_PTR_GET_LOCAL(tree, childalloc);
+	RT_INIT_NODE(child, RT_NODE_KIND_4, RT_CLASS_4);
 
 	node = child;
 	shift -= RT_SPAN;
 
 	while (shift > 0)
 	{
-		child = RT_ALLOC_NODE(tree, RT_NODE_KIND_4, RT_CLASS_4);
+		childalloc = RT_ALLOC_NODE(tree, RT_CLASS_4);
+		child = RT_PTR_GET_LOCAL(tree, childalloc);
+		RT_INIT_NODE(child, RT_NODE_KIND_4, RT_CLASS_4);
 
 		/* We open-code the insertion ourselves, for speed. */
-		n4 = (RT_NODE_4 *) node.local;
+		n4 = (RT_NODE_4 *) node;
 		n4->base.count = 1;
 		n4->chunks[0] = RT_GET_KEY_CHUNK(key, shift);
-		n4->children[0] = child.alloc;
+		n4->children[0] = childalloc;
 
 		node = child;
 		shift -= RT_SPAN;
@@ -1646,7 +1650,7 @@ RT_EXTEND_DOWN(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, uint64 key, int
 	Assert(shift == 0);
 
 	/* Reserve slot for the value. */
-	n4 = (RT_NODE_4 *) node.local;
+	n4 = (RT_NODE_4 *) node;
 	n4->chunks[0] = RT_GET_KEY_CHUNK(key, 0);
 	n4->base.count = 1;
 
@@ -1664,12 +1668,11 @@ static RT_PTR_ALLOC *
 RT_GET_SLOT_RECURSIVE(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, uint64 key, int shift, bool *found)
 {
 	RT_PTR_ALLOC *slot;
-	RT_CHILD_PTR node;
+	RT_NODE    *node;
 	uint8		chunk = RT_GET_KEY_CHUNK(key, shift);
 
-	node.alloc = *parent_slot;
-	RT_PTR_SET_LOCAL(tree, &node);
-	slot = RT_NODE_SEARCH(node.local, chunk);
+	node = RT_PTR_GET_LOCAL(tree, *parent_slot);
+	slot = RT_NODE_SEARCH(node, chunk);
 
 	if (slot == NULL)
 	{
@@ -1712,7 +1715,7 @@ RT_GET_SLOT(RT_RADIX_TREE * tree, uint64 key, bool * found)
 	{
 		if (tree->ctl->num_keys == 0)
 		{
-			RT_CHILD_PTR node;
+			RT_PTR_ALLOC nodealloc;
 			RT_NODE_4  *n4;
 			int			start_shift = RT_KEY_GET_SHIFT(key);
 
@@ -1722,9 +1725,8 @@ RT_GET_SLOT(RT_RADIX_TREE * tree, uint64 key, bool * found)
 			 * code inserting into the root node and extend downward from
 			 * there.
 			 */
-			node.alloc = tree->ctl->root;
-			RT_PTR_SET_LOCAL(tree, &node);
-			n4 = (RT_NODE_4 *) node.local;
+			nodealloc = tree->ctl->root;
+			n4 = (RT_NODE_4 *) RT_PTR_GET_LOCAL(tree, nodealloc);
 			n4->base.count = 1;
 			n4->chunks[0] = RT_GET_KEY_CHUNK(key, start_shift);
 
@@ -1784,33 +1786,36 @@ RT_SET_SLOT(RT_RADIX_TREE * tree, void * slot_v, RT_VALUE_TYPE * value_p, bool f
 	}
 	else
 	{
-		RT_CHILD_PTR leaf;
+		RT_PTR_ALLOC leafalloc;
+		RT_VALUE_TYPE *leaf;
 
 		if (found && !RT_CHILDPTR_IS_VALUE(*slot))
 		{
 			Assert(RT_PTR_ALLOC_IS_VALID(*slot));
-			leaf.alloc = *slot;
-			RT_PTR_SET_LOCAL(tree, &leaf);
+			leafalloc = *slot;
+			leaf = (RT_VALUE_TYPE *) RT_PTR_GET_LOCAL(tree, leafalloc);
 
-			if (RT_GET_VALUE_SIZE((RT_VALUE_TYPE *) leaf.local) != value_sz)
+			if (RT_GET_VALUE_SIZE(leaf) != value_sz)
 			{
 				/*
 				 * different sizes, so first free the existing leaf before
 				 * allocating a new one
 				 */
 				RT_FREE_LEAF(tree, *slot);
-				leaf = RT_ALLOC_LEAF(tree, value_sz);
-				*slot = leaf.alloc;
+				leafalloc = RT_ALLOC_LEAF(tree, value_sz);
+				*slot = leafalloc;
+				leaf = (RT_VALUE_TYPE *) RT_PTR_GET_LOCAL(tree, leafalloc);
 			}
 		}
 		else
 		{
 			/* allocate new leaf and store it in the child array */
-			leaf = RT_ALLOC_LEAF(tree, value_sz);
-			*slot = leaf.alloc;
+			leafalloc = RT_ALLOC_LEAF(tree, value_sz);
+			*slot = leafalloc;
+			leaf = (RT_VALUE_TYPE *) RT_PTR_GET_LOCAL(tree, leafalloc);
 		}
 
-		memcpy(leaf.local, value_p, value_sz);
+		memcpy(leaf, value_p, value_sz);
 	}
 
 	return found;
@@ -1849,7 +1854,8 @@ RT_CREATE(MemoryContext ctx)
 #endif
 {
 	RT_RADIX_TREE *tree;
-	RT_CHILD_PTR rootnode;
+	RT_PTR_ALLOC rootalloc;
+	RT_NODE    *rootnode;
 #ifdef RT_SHMEM
 	dsa_pointer dp;
 #endif
@@ -1882,8 +1888,10 @@ RT_CREATE(MemoryContext ctx)
 #endif							/* RT_SHMEM */
 
 	/* add root node now so that RT_SET can assume it exists */
-	rootnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_4, RT_CLASS_4);
-	tree->ctl->root = rootnode.alloc;
+	rootalloc = RT_ALLOC_NODE(tree, RT_CLASS_4);
+	rootnode = RT_PTR_GET_LOCAL(tree, rootalloc);
+	RT_INIT_NODE(rootnode, RT_NODE_KIND_4, RT_CLASS_4);
+	tree->ctl->root = rootalloc;
 	tree->ctl->start_shift = 0;
 	tree->ctl->max_val = RT_SHIFT_GET_MAX_VAL(0);
 
@@ -1950,18 +1958,15 @@ RT_UNLOCK(RT_RADIX_TREE * tree)
 static void
 RT_FREE_RECURSE(RT_RADIX_TREE * tree, RT_PTR_ALLOC ptr, int shift)
 {
-	RT_CHILD_PTR node;
+	RT_NODE    *node = RT_PTR_GET_LOCAL(tree, ptr);
 
 	check_stack_depth();
 
-	node.alloc = ptr;
-	RT_PTR_SET_LOCAL(tree, &node);
-
-	switch (node.local->kind)
+	switch (node->kind)
 	{
 		case RT_NODE_KIND_4:
 			{
-				RT_NODE_4  *n4 = (RT_NODE_4 *) node.local;
+				RT_NODE_4  *n4 = (RT_NODE_4 *) node;
 
 				for (int i = 0; i < n4->base.count; i++)
 				{
@@ -1977,7 +1982,7 @@ RT_FREE_RECURSE(RT_RADIX_TREE * tree, RT_PTR_ALLOC ptr, int shift)
 			}
 		case RT_NODE_KIND_16:
 			{
-				RT_NODE_16 *n16 = (RT_NODE_16 *) node.local;
+				RT_NODE_16 *n16 = (RT_NODE_16 *) node;
 
 				for (int i = 0; i < n16->base.count; i++)
 				{
@@ -1993,7 +1998,7 @@ RT_FREE_RECURSE(RT_RADIX_TREE * tree, RT_PTR_ALLOC ptr, int shift)
 			}
 		case RT_NODE_KIND_48:
 			{
-				RT_NODE_48 *n48 = (RT_NODE_48 *) node.local;
+				RT_NODE_48 *n48 = (RT_NODE_48 *) node;
 
 				for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
 				{
@@ -2014,7 +2019,7 @@ RT_FREE_RECURSE(RT_RADIX_TREE * tree, RT_PTR_ALLOC ptr, int shift)
 			}
 		case RT_NODE_KIND_256:
 			{
-				RT_NODE_256 *n256 = (RT_NODE_256 *) node.local;
+				RT_NODE_256 *n256 = (RT_NODE_256 *) node;
 
 				for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
 				{
@@ -2084,20 +2089,20 @@ RT_SCOPE	RT_ITER *
 RT_BEGIN_ITERATE(RT_RADIX_TREE * tree)
 {
 	RT_ITER    *iter;
-	RT_CHILD_PTR root;
+	RT_PTR_ALLOC root;
 
 	iter = (RT_ITER *) palloc0(sizeof(RT_ITER));
 	iter->tree = tree;
 
 	Assert(RT_PTR_ALLOC_IS_VALID(tree->ctl->root));
-	root.alloc = iter->tree->ctl->root;
-	RT_PTR_SET_LOCAL(tree, &root);
+	root = tree->ctl->root;
 
 	iter->top_level = iter->tree->ctl->start_shift / RT_SPAN;
 
 	/* Set the root to start */
 	iter->cur_level = iter->top_level;
-	iter->node_iters[iter->cur_level].node = root;
+	iter->node_iters[iter->cur_level].nodealloc = root;
+	iter->node_iters[iter->cur_level].node = RT_PTR_GET_LOCAL(tree, root);;
 	iter->node_iters[iter->cur_level].idx = 0;
 
 	return iter;
@@ -2112,7 +2117,7 @@ RT_NODE_ITERATE_NEXT(RT_ITER * iter, int level)
 {
 	uint8		key_chunk = 0;
 	RT_NODE_ITER *node_iter;
-	RT_CHILD_PTR node;
+	RT_NODE    *node;
 	RT_PTR_ALLOC *slot = NULL;
 
 #ifdef RT_SHMEM
@@ -2122,13 +2127,13 @@ RT_NODE_ITERATE_NEXT(RT_ITER * iter, int level)
 	node_iter = &(iter->node_iters[level]);
 	node = node_iter->node;
 
-	Assert(node.local != NULL);
+	Assert(node != NULL);
 
-	switch ((node.local)->kind)
+	switch (node->kind)
 	{
 		case RT_NODE_KIND_4:
 			{
-				RT_NODE_4  *n4 = (RT_NODE_4 *) (node.local);
+				RT_NODE_4  *n4 = (RT_NODE_4 *) node;
 
 				if (node_iter->idx >= n4->base.count)
 					return NULL;
@@ -2140,7 +2145,7 @@ RT_NODE_ITERATE_NEXT(RT_ITER * iter, int level)
 			}
 		case RT_NODE_KIND_16:
 			{
-				RT_NODE_16 *n16 = (RT_NODE_16 *) (node.local);
+				RT_NODE_16 *n16 = (RT_NODE_16 *) node;
 
 				if (node_iter->idx >= n16->base.count)
 					return NULL;
@@ -2152,7 +2157,7 @@ RT_NODE_ITERATE_NEXT(RT_ITER * iter, int level)
 			}
 		case RT_NODE_KIND_48:
 			{
-				RT_NODE_48 *n48 = (RT_NODE_48 *) (node.local);
+				RT_NODE_48 *n48 = (RT_NODE_48 *) node;
 				int			chunk;
 
 				for (chunk = node_iter->idx; chunk < RT_NODE_MAX_SLOTS; chunk++)
@@ -2172,7 +2177,7 @@ RT_NODE_ITERATE_NEXT(RT_ITER * iter, int level)
 			}
 		case RT_NODE_KIND_256:
 			{
-				RT_NODE_256 *n256 = (RT_NODE_256 *) (node.local);
+				RT_NODE_256 *n256 = (RT_NODE_256 *) node;
 				int			chunk;
 
 				for (chunk = node_iter->idx; chunk < RT_NODE_MAX_SLOTS; chunk++)
@@ -2210,33 +2215,25 @@ RT_ITERATE_NEXT(RT_ITER * iter, uint64 *key_p)
 
 	while (iter->cur_level <= iter->top_level)
 	{
-		RT_CHILD_PTR node;
-
 		slot = RT_NODE_ITERATE_NEXT(iter, iter->cur_level);
 
 		if (iter->cur_level == 0 && slot != NULL)
 		{
 			/* Found a value at the leaf node */
 			*key_p = iter->key;
-			node.alloc = *slot;
 
 			if (RT_CHILDPTR_IS_VALUE(*slot))
 				return (RT_VALUE_TYPE *) slot;
 			else
-			{
-				RT_PTR_SET_LOCAL(iter->tree, &node);
-				return (RT_VALUE_TYPE *) node.local;
-			}
+				return (RT_VALUE_TYPE *) RT_PTR_GET_LOCAL(iter->tree, *slot);
 		}
 
 		if (slot != NULL)
 		{
 			/* Found the child slot, move down the tree */
-			node.alloc = *slot;
-			RT_PTR_SET_LOCAL(iter->tree, &node);
-
 			iter->cur_level--;
-			iter->node_iters[iter->cur_level].node = node;
+			iter->node_iters[iter->cur_level].nodealloc = *slot;
+			iter->node_iters[iter->cur_level].node = RT_PTR_GET_LOCAL(iter->tree, *slot);
 			iter->node_iters[iter->cur_level].idx = 0;
 		}
 		else
@@ -2322,19 +2319,21 @@ RT_COPY_ARRAYS_AND_DELETE(uint8 *dst_chunks, RT_PTR_ALLOC * dst_children,
  * in the caller.
  */
 static void pg_noinline
-RT_SHRINK_NODE_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk)
+RT_SHRINK_NODE_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_256 * n256, uint8 chunk)
 {
-	RT_NODE_256 *n256 = (RT_NODE_256 *) node.local;
-	RT_CHILD_PTR newnode;
+	RT_PTR_ALLOC newalloc;
+	RT_NODE    *newnode;
 	RT_NODE_48 *new48;
 	int			slot_idx = 0;
 
 	/* initialize new node */
-	newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_48, RT_CLASS_48);
-	new48 = (RT_NODE_48 *) newnode.local;
+	newalloc = RT_ALLOC_NODE(tree, RT_CLASS_48);
+	newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+	RT_INIT_NODE(newnode, RT_NODE_KIND_48, RT_CLASS_48);
+	new48 = (RT_NODE_48 *) newnode;
 
 	/* copy over the entries */
-	RT_COPY_COMMON(newnode, node);
+	RT_COPY_COMMON((RT_NODE *) new48, (RT_NODE *) n256);
 	for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
 	{
 		if (RT_NODE_256_IS_CHUNK_USED(n256, i))
@@ -2354,15 +2353,14 @@ RT_SHRINK_NODE_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PT
 	new48->isset[0] = (bitmapword) (((uint64) 1 << n256->base.count) - 1);
 
 	/* free old node and update reference in parent */
-	*parent_slot = newnode.alloc;
-	RT_FREE_NODE(tree, node);
+	RT_FREE_NODE(tree, *parent_slot);
+	*parent_slot = newalloc;
 }
 
 static inline void
-RT_REMOVE_CHILD_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk)
+RT_REMOVE_CHILD_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_256 * n256, uint8 chunk)
 {
 	int			shrink_threshold;
-	RT_NODE_256 *n256 = (RT_NODE_256 *) node.local;
 	int			idx = RT_BM_IDX(chunk);
 	int			bitnum = RT_BM_BIT(chunk);
 
@@ -2382,7 +2380,7 @@ RT_REMOVE_CHILD_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_P
 	shrink_threshold = Min(RT_FANOUT_48 / 4 * 3, shrink_threshold);
 
 	if (n256->base.count <= shrink_threshold)
-		RT_SHRINK_NODE_256(tree, parent_slot, node, chunk);
+		RT_SHRINK_NODE_256(tree, parent_slot, n256, chunk);
 }
 
 /*
@@ -2390,10 +2388,10 @@ RT_REMOVE_CHILD_256(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_P
  * in the caller.
  */
 static void pg_noinline
-RT_SHRINK_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk)
+RT_SHRINK_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_48 * n48, uint8 chunk)
 {
-	RT_NODE_48 *n48 = (RT_NODE_48 *) (node.local);
-	RT_CHILD_PTR newnode;
+	RT_PTR_ALLOC newalloc;
+	RT_NODE    *newnode;
 	RT_NODE_16 *new16;
 	int			destidx = 0;
 
@@ -2401,11 +2399,13 @@ RT_SHRINK_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR
 	 * Initialize new node. For now we skip the larger node16 size class for
 	 * simplicity.
 	 */
-	newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_16, RT_CLASS_16_LO);
-	new16 = (RT_NODE_16 *) newnode.local;
+	newalloc = RT_ALLOC_NODE(tree, RT_CLASS_16_LO);
+	newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+	RT_INIT_NODE(newnode, RT_NODE_KIND_16, RT_CLASS_16_LO);
+	new16 = (RT_NODE_16 *) newnode;
 
 	/* copy over all existing entries */
-	RT_COPY_COMMON(newnode, node);
+	RT_COPY_COMMON((RT_NODE *) new16, (RT_NODE *) n48);
 	for (int chunk = 0; chunk < RT_NODE_MAX_SLOTS; chunk++)
 	{
 		if (n48->slot_idxs[chunk] != RT_INVALID_SLOT_IDX)
@@ -2421,14 +2421,13 @@ RT_SHRINK_NODE_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR
 	RT_VERIFY_NODE((RT_NODE *) new16);
 
 	/* free old node and update reference in parent */
-	*parent_slot = newnode.alloc;
-	RT_FREE_NODE(tree, node);
+	RT_FREE_NODE(tree, *parent_slot);
+	*parent_slot = newalloc;
 }
 
 static inline void
-RT_REMOVE_CHILD_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk)
+RT_REMOVE_CHILD_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_48 * n48, uint8 chunk)
 {
-	RT_NODE_48 *n48 = (RT_NODE_48 *) node.local;
 	int			deletepos = n48->slot_idxs[chunk];
 
 	/* For now we skip the larger node16 size class for simplicity */
@@ -2450,7 +2449,7 @@ RT_REMOVE_CHILD_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PT
 	 * node48 anyway.
 	 */
 	if (n48->base.count <= shrink_threshold)
-		RT_SHRINK_NODE_48(tree, parent_slot, node, chunk);
+		RT_SHRINK_NODE_48(tree, parent_slot, n48, chunk);
 }
 
 /*
@@ -2459,18 +2458,20 @@ RT_REMOVE_CHILD_48(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PT
  * node.
  */
 static void pg_noinline
-RT_SHRINK_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 deletepos)
+RT_SHRINK_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_16 * n16, uint8 deletepos)
 {
-	RT_NODE_16 *n16 = (RT_NODE_16 *) (node.local);
-	RT_CHILD_PTR newnode;
+	RT_PTR_ALLOC newalloc;
+	RT_NODE    *newnode;
 	RT_NODE_4  *new4;
 
 	/* initialize new node */
-	newnode = RT_ALLOC_NODE(tree, RT_NODE_KIND_4, RT_CLASS_4);
-	new4 = (RT_NODE_4 *) newnode.local;
+	newalloc = RT_ALLOC_NODE(tree, RT_CLASS_4);
+	newnode = RT_PTR_GET_LOCAL(tree, newalloc);
+	RT_INIT_NODE(newnode, RT_NODE_KIND_4, RT_CLASS_4);
+	new4 = (RT_NODE_4 *) newnode;
 
 	/* copy over existing entries, except for the one at "deletepos" */
-	RT_COPY_COMMON(newnode, node);
+	RT_COPY_COMMON((RT_NODE *) new4, (RT_NODE *) n16);
 	RT_COPY_ARRAYS_AND_DELETE(new4->chunks, new4->children,
 							  n16->chunks, n16->children,
 							  n16->base.count, deletepos);
@@ -2479,14 +2480,13 @@ RT_SHRINK_NODE_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR
 	RT_VERIFY_NODE((RT_NODE *) new4);
 
 	/* free old node and update reference in parent */
-	*parent_slot = newnode.alloc;
-	RT_FREE_NODE(tree, node);
+	RT_FREE_NODE(tree, *parent_slot);
+	*parent_slot = newalloc;
 }
 
 static inline void
-RT_REMOVE_CHILD_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk, RT_PTR_ALLOC * slot)
+RT_REMOVE_CHILD_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_16 * n16, uint8 chunk, RT_PTR_ALLOC * slot)
 {
-	RT_NODE_16 *n16 = (RT_NODE_16 *) node.local;
 	int			deletepos = slot - n16->children;
 
 	/*
@@ -2496,7 +2496,7 @@ RT_REMOVE_CHILD_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PT
 	 */
 	if (n16->base.count <= 4)
 	{
-		RT_SHRINK_NODE_16(tree, parent_slot, node, deletepos);
+		RT_SHRINK_NODE_16(tree, parent_slot, n16, deletepos);
 		return;
 	}
 
@@ -2509,10 +2509,8 @@ RT_REMOVE_CHILD_16(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PT
 }
 
 static inline void
-RT_REMOVE_CHILD_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk, RT_PTR_ALLOC * slot)
+RT_REMOVE_CHILD_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE_4 * n4, uint8 chunk, RT_PTR_ALLOC * slot)
 {
-	RT_NODE_4  *n4 = (RT_NODE_4 *) node.local;
-
 	if (n4->base.count == 1)
 	{
 		Assert(n4->chunks[0] == chunk);
@@ -2535,7 +2533,7 @@ RT_REMOVE_CHILD_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR
 			 * RT_DELETE_RECURSIVE has already freed the value and lower-level
 			 * children.
 			 */
-			RT_FREE_NODE(tree, node);
+			RT_FREE_NODE(tree, *parent_slot);
 
 			/*
 			 * Also null out the parent's slot -- this tells the next higher
@@ -2562,28 +2560,36 @@ RT_REMOVE_CHILD_4(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR
  * Delete the child pointer corresponding to "key" in the given node.
  */
 static inline void
-RT_NODE_DELETE(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_CHILD_PTR node, uint8 chunk, RT_PTR_ALLOC * slot)
+RT_NODE_DELETE(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, RT_NODE * node, uint8 chunk, RT_PTR_ALLOC * slot)
 {
-	switch ((node.local)->kind)
+	switch (node->kind)
 	{
 		case RT_NODE_KIND_4:
 			{
-				RT_REMOVE_CHILD_4(tree, parent_slot, node, chunk, slot);
+				RT_NODE_4  *n4 = (RT_NODE_4 *) node;
+
+				RT_REMOVE_CHILD_4(tree, parent_slot, n4, chunk, slot);
 				return;
 			}
 		case RT_NODE_KIND_16:
 			{
-				RT_REMOVE_CHILD_16(tree, parent_slot, node, chunk, slot);
+				RT_NODE_16 *n16 = (RT_NODE_16 *) node;
+
+				RT_REMOVE_CHILD_16(tree, parent_slot, n16, chunk, slot);
 				return;
 			}
 		case RT_NODE_KIND_48:
 			{
-				RT_REMOVE_CHILD_48(tree, parent_slot, node, chunk);
+				RT_NODE_48 *n48 = (RT_NODE_48 *) node;
+
+				RT_REMOVE_CHILD_48(tree, parent_slot, n48, chunk);
 				return;
 			}
 		case RT_NODE_KIND_256:
 			{
-				RT_REMOVE_CHILD_256(tree, parent_slot, node, chunk);
+				RT_NODE_256 *n256 = (RT_NODE_256 *) node;
+
+				RT_REMOVE_CHILD_256(tree, parent_slot, n256, chunk);
 				return;
 			}
 		default:
@@ -2596,12 +2602,10 @@ static bool
 RT_DELETE_RECURSIVE(RT_RADIX_TREE * tree, RT_PTR_ALLOC * parent_slot, uint64 key, int shift)
 {
 	RT_PTR_ALLOC *slot;
-	RT_CHILD_PTR node;
+	RT_NODE    *node = RT_PTR_GET_LOCAL(tree, *parent_slot);
 	uint8		chunk = RT_GET_KEY_CHUNK(key, shift);
 
-	node.alloc = *parent_slot;
-	RT_PTR_SET_LOCAL(tree, &node);
-	slot = RT_NODE_SEARCH(node.local, chunk);
+	slot = RT_NODE_SEARCH(node, chunk);
 
 	if (slot == NULL)
 		return false;
@@ -2954,7 +2958,6 @@ RT_DUMP_NODE(RT_NODE * node)
 /* type declarations */
 #undef RT_RADIX_TREE
 #undef RT_RADIX_TREE_CONTROL
-#undef RT_CHILD_PTR
 #undef RT_PTR_ALLOC
 #undef RT_INVALID_PTR_ALLOC
 #undef RT_HANDLE
@@ -3014,6 +3017,7 @@ RT_DUMP_NODE(RT_NODE * node)
 #undef RT_GET_SLOT_RECURSIVE
 #undef RT_DELETE_RECURSIVE
 #undef RT_ALLOC_NODE
+#undef RT_INIT_NODE
 #undef RT_ALLOC_LEAF
 #undef RT_FREE_NODE
 #undef RT_FREE_LEAF
@@ -3021,7 +3025,7 @@ RT_DUMP_NODE(RT_NODE * node)
 #undef RT_EXTEND_UP
 #undef RT_EXTEND_DOWN
 #undef RT_COPY_COMMON
-#undef RT_PTR_SET_LOCAL
+#undef RT_PTR_GET_LOCAL
 #undef RT_PTR_ALLOC_IS_VALID
 #undef RT_NODE_16_SEARCH_EQ
 #undef RT_NODE_4_GET_INSERTPOS
-- 
2.50.0

