From c6191d6c52de2604d7809e5216858d5296969778 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Wed, 16 Feb 2022 00:55:24 +0100
Subject: [PATCH v1 1/3] Add known-size pre-aligned special area pointer macro

This removes 1 layer of indirection for special areas of which we know the
type (=size) and location.

Special area access through the page header is an extra cache line that needs
to be fetched. If might only want to look at the special area, it is much
less effort to calculate the offset to the special area directly instead of
first checking the page header - saving one cache line to fetch.

Assertions are added to check that the page has a correctly sized special
area, and that the page is of the expected size. This detects data corruption,
instead of doing random reads/writes into the page or data allocated next to
the page being accessed.

Additionally, updates the GIN, GIST and SP-GIST [Index]PageGetOpaque macros
with the new pre-aligned special area accessor.
---
 src/include/access/ginblock.h       |  3 ++-
 src/include/access/gist.h           |  3 ++-
 src/include/access/spgist_private.h |  3 ++-
 src/include/storage/bufpage.h       | 13 +++++++++++++
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/include/access/ginblock.h b/src/include/access/ginblock.h
index 9347f464f3..9c2af08a27 100644
--- a/src/include/access/ginblock.h
+++ b/src/include/access/ginblock.h
@@ -108,7 +108,8 @@ typedef struct GinMetaPageData
 /*
  * Macros for accessing a GIN index page's opaque data
  */
-#define GinPageGetOpaque(page) ( (GinPageOpaque) PageGetSpecialPointer(page) )
+#define GinPageGetOpaque(page) \
+	( (GinPageOpaque) PageGetSpecialOpaque(page, GinPageOpaqueData) )
 
 #define GinPageIsLeaf(page)    ( (GinPageGetOpaque(page)->flags & GIN_LEAF) != 0 )
 #define GinPageSetLeaf(page)   ( GinPageGetOpaque(page)->flags |= GIN_LEAF )
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index a3337627b8..987f771c4d 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -164,7 +164,8 @@ typedef struct GISTENTRY
 	bool		leafkey;
 } GISTENTRY;
 
-#define GistPageGetOpaque(page) ( (GISTPageOpaque) PageGetSpecialPointer(page) )
+#define GistPageGetOpaque(page) \
+	( (GISTPageOpaque) PageGetSpecialOpaque(page, GISTPageOpaqueData) )
 
 #define GistPageIsLeaf(page)	( GistPageGetOpaque(page)->flags & F_LEAF)
 #define GIST_LEAF(entry) (GistPageIsLeaf((entry)->page))
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
index eb56b1c6b8..b0bdc7df3e 100644
--- a/src/include/access/spgist_private.h
+++ b/src/include/access/spgist_private.h
@@ -75,7 +75,8 @@ typedef SpGistPageOpaqueData *SpGistPageOpaque;
 #define SPGIST_LEAF			(1<<2)
 #define SPGIST_NULLS		(1<<3)
 
-#define SpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
+#define SpGistPageGetOpaque(page) \
+	((SpGistPageOpaque) PageGetSpecialOpaque(page, SpGistPageOpaqueData))
 #define SpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
 #define SpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
 #define SpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h
index e9f253f2c8..aa395d3c39 100644
--- a/src/include/storage/bufpage.h
+++ b/src/include/storage/bufpage.h
@@ -329,6 +329,19 @@ PageValidateSpecialPointer(Page page)
 	(char *) ((char *) (page) + ((PageHeader) (page))->pd_special) \
 )
 
+/*
+ * PageGetSpecialOpaque
+ *		Returns pointer to special space on a page, of the given type.
+ *		This removes the data dependency on the page header in builds
+ *		without asserts enabled.
+ */
+#define PageGetSpecialOpaque(page, OpaqueDataTyp) \
+( \
+	AssertMacro(PageGetPageSize(page) == BLCKSZ && \
+				PageGetSpecialSize(page) == MAXALIGN(sizeof(OpaqueDataTyp))), \
+	(OpaqueDataTyp *) ((char *) (page) + (BLCKSZ - MAXALIGN(sizeof(OpaqueDataTyp)))) \
+)
+
 /*
  * PageGetItem
  *		Retrieves an item on the given page.
-- 
2.30.2

