I have another little idea that fits well here: repalloc0 and repalloc0_array. These zero out the space added by repalloc. This is a common pattern in the backend code that is quite hairy to code by hand. See attached patch.
From fa611ecf7c8a7b99d37c77da66b421d2f9ebfec3 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 14 Sep 2022 06:05:46 +0200
Subject: [PATCH] Add repalloc0 and repalloc0_array

These zero out the space added by repalloc.  This is a common pattern
that is quite hairy to code by hand.
---
 src/backend/executor/nodeHash.c          |  8 ++-----
 src/backend/libpq/be-fsstubs.c           |  9 +++-----
 src/backend/optimizer/util/placeholder.c | 13 ++++-------
 src/backend/optimizer/util/relnode.c     | 29 +++++++-----------------
 src/backend/parser/parse_param.c         | 10 +++-----
 src/backend/storage/lmgr/lwlock.c        |  9 ++------
 src/backend/utils/adt/ruleutils.c        |  9 ++------
 src/backend/utils/cache/typcache.c       | 10 ++------
 src/backend/utils/mmgr/mcxt.c            | 15 ++++++++++++
 src/include/utils/palloc.h               |  2 ++
 10 files changed, 43 insertions(+), 71 deletions(-)

diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 77dd1dae8b..674802a4ff 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -940,12 +940,8 @@ ExecHashIncreaseNumBatches(HashJoinTable hashtable)
        else
        {
                /* enlarge arrays and zero out added entries */
-               hashtable->innerBatchFile = 
repalloc_array(hashtable->innerBatchFile, BufFile *, nbatch);
-               hashtable->outerBatchFile = 
repalloc_array(hashtable->outerBatchFile, BufFile *, nbatch);
-               MemSet(hashtable->innerBatchFile + oldnbatch, 0,
-                          (nbatch - oldnbatch) * sizeof(BufFile *));
-               MemSet(hashtable->outerBatchFile + oldnbatch, 0,
-                          (nbatch - oldnbatch) * sizeof(BufFile *));
+               hashtable->innerBatchFile = 
repalloc0_array(hashtable->innerBatchFile, BufFile *, nbatch, oldnbatch);
+               hashtable->outerBatchFile = 
repalloc0_array(hashtable->outerBatchFile, BufFile *, nbatch, oldnbatch);
        }
 
        MemoryContextSwitchTo(oldcxt);
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index 3e5cada7eb..bf901a9cdc 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -696,19 +696,16 @@ newLOfd(void)
                newsize = 64;
                cookies = (LargeObjectDesc **)
                        MemoryContextAllocZero(fscxt, newsize * 
sizeof(LargeObjectDesc *));
-               cookies_size = newsize;
        }
        else
        {
                /* Double size of array */
                i = cookies_size;
                newsize = cookies_size * 2;
-               cookies = (LargeObjectDesc **)
-                       repalloc(cookies, newsize * sizeof(LargeObjectDesc *));
-               MemSet(cookies + cookies_size, 0,
-                          (newsize - cookies_size) * sizeof(LargeObjectDesc 
*));
-               cookies_size = newsize;
+               cookies =
+                       repalloc0_array(cookies, LargeObjectDesc *, newsize, 
cookies_size);
        }
+       cookies_size = newsize;
 
        return i;
 }
diff --git a/src/backend/optimizer/util/placeholder.c 
b/src/backend/optimizer/util/placeholder.c
index c7bfa293c9..e40b3a12fd 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -133,16 +133,11 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar 
*phv)
                while (phinfo->phid >= new_size)
                        new_size *= 2;
                if (root->placeholder_array)
-               {
-                       root->placeholder_array = (PlaceHolderInfo **)
-                               repalloc(root->placeholder_array,
-                                                sizeof(PlaceHolderInfo *) * 
new_size);
-                       MemSet(root->placeholder_array + 
root->placeholder_array_size, 0,
-                                  sizeof(PlaceHolderInfo *) * (new_size - 
root->placeholder_array_size));
-               }
+                       root->placeholder_array =
+                               repalloc0_array(root->placeholder_array, 
PlaceHolderInfo *, new_size, root->placeholder_array_size);
                else
-                       root->placeholder_array = (PlaceHolderInfo **)
-                               palloc0(new_size * sizeof(PlaceHolderInfo *));
+                       root->placeholder_array =
+                               palloc0_array(PlaceHolderInfo *, new_size);
                root->placeholder_array_size = new_size;
        }
        root->placeholder_array[phinfo->phid] = phinfo;
diff --git a/src/backend/optimizer/util/relnode.c 
b/src/backend/optimizer/util/relnode.c
index edcdd0a360..3ea40ff1b6 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -157,31 +157,18 @@ expand_planner_arrays(PlannerInfo *root, int add_size)
 
        new_size = root->simple_rel_array_size + add_size;
 
-       root->simple_rel_array = (RelOptInfo **)
-               repalloc(root->simple_rel_array,
-                                sizeof(RelOptInfo *) * new_size);
-       MemSet(root->simple_rel_array + root->simple_rel_array_size,
-                  0, sizeof(RelOptInfo *) * add_size);
+       root->simple_rel_array =
+               repalloc0_array(root->simple_rel_array, RelOptInfo *, new_size, 
root->simple_rel_array_size);
 
-       root->simple_rte_array = (RangeTblEntry **)
-               repalloc(root->simple_rte_array,
-                                sizeof(RangeTblEntry *) * new_size);
-       MemSet(root->simple_rte_array + root->simple_rel_array_size,
-                  0, sizeof(RangeTblEntry *) * add_size);
+       root->simple_rte_array =
+               repalloc0_array(root->simple_rte_array, RangeTblEntry *, 
new_size, root->simple_rel_array_size);
 
        if (root->append_rel_array)
-       {
-               root->append_rel_array = (AppendRelInfo **)
-                       repalloc(root->append_rel_array,
-                                        sizeof(AppendRelInfo *) * new_size);
-               MemSet(root->append_rel_array + root->simple_rel_array_size,
-                          0, sizeof(AppendRelInfo *) * add_size);
-       }
+               root->append_rel_array =
+                       repalloc0_array(root->append_rel_array, AppendRelInfo 
*, new_size, root->simple_rel_array_size);
        else
-       {
-               root->append_rel_array = (AppendRelInfo **)
-                       palloc0(sizeof(AppendRelInfo *) * new_size);
-       }
+               root->append_rel_array =
+                       palloc0_array(AppendRelInfo *, new_size);
 
        root->simple_rel_array_size = new_size;
 }
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index f668abfcb3..4efec211c5 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -145,14 +145,10 @@ variable_paramref_hook(ParseState *pstate, ParamRef *pref)
        {
                /* Need to enlarge param array */
                if (*parstate->paramTypes)
-                       *parstate->paramTypes = (Oid *) 
repalloc(*parstate->paramTypes,
-                                                                               
                         paramno * sizeof(Oid));
+                       *parstate->paramTypes = 
repalloc0_array(*parstate->paramTypes, Oid,
+                                                                               
                        paramno, *parstate->numParams);
                else
-                       *parstate->paramTypes = (Oid *) palloc(paramno * 
sizeof(Oid));
-               /* Zero out the previously-unreferenced slots */
-               MemSet(*parstate->paramTypes + *parstate->numParams,
-                          0,
-                          (paramno - *parstate->numParams) * sizeof(Oid));
+                       *parstate->paramTypes = palloc0_array(Oid, paramno);
                *parstate->numParams = paramno;
        }
 
diff --git a/src/backend/storage/lmgr/lwlock.c 
b/src/backend/storage/lmgr/lwlock.c
index 38317edaf9..a36dcf1a00 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -668,13 +668,8 @@ LWLockRegisterTranche(int tranche_id, const char 
*tranche_name)
                                MemoryContextAllocZero(TopMemoryContext,
                                                                           
newalloc * sizeof(char *));
                else
-               {
-                       LWLockTrancheNames = (const char **)
-                               repalloc(LWLockTrancheNames, newalloc * 
sizeof(char *));
-                       memset(LWLockTrancheNames + LWLockTrancheNamesAllocated,
-                                  0,
-                                  (newalloc - LWLockTrancheNamesAllocated) * 
sizeof(char *));
-               }
+                       LWLockTrancheNames =
+                               repalloc0_array(LWLockTrancheNames, const char 
*, newalloc, LWLockTrancheNamesAllocated);
                LWLockTrancheNamesAllocated = newalloc;
        }
 
diff --git a/src/backend/utils/adt/ruleutils.c 
b/src/backend/utils/adt/ruleutils.c
index 2b7b1b0c0f..0cd63383ec 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -4855,14 +4855,9 @@ expand_colnames_array_to(deparse_columns *colinfo, int n)
        if (n > colinfo->num_cols)
        {
                if (colinfo->colnames == NULL)
-                       colinfo->colnames = (char **) palloc0(n * sizeof(char 
*));
+                       colinfo->colnames = palloc0_array(char *, n);
                else
-               {
-                       colinfo->colnames = (char **) 
repalloc(colinfo->colnames,
-                                                                               
                   n * sizeof(char *));
-                       memset(colinfo->colnames + colinfo->num_cols, 0,
-                                  (n - colinfo->num_cols) * sizeof(char *));
-               }
+                       colinfo->colnames = repalloc0_array(colinfo->colnames, 
char *, n, colinfo->num_cols);
                colinfo->num_cols = n;
        }
 }
diff --git a/src/backend/utils/cache/typcache.c 
b/src/backend/utils/cache/typcache.c
index 808f9ebd0d..739765cb09 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -1714,14 +1714,8 @@ ensure_record_cache_typmod_slot_exists(int32 typmod)
        {
                int32           newlen = pg_nextpower2_32(typmod + 1);
 
-               RecordCacheArray = (TupleDesc *) repalloc(RecordCacheArray,
-                                                                               
                  newlen * sizeof(TupleDesc));
-               memset(RecordCacheArray + RecordCacheArrayLen, 0,
-                          (newlen - RecordCacheArrayLen) * sizeof(TupleDesc));
-               RecordIdentifierArray = (uint64 *) 
repalloc(RecordIdentifierArray,
-                                                                               
                        newlen * sizeof(uint64));
-               memset(RecordIdentifierArray + RecordCacheArrayLen, 0,
-                          (newlen - RecordCacheArrayLen) * sizeof(uint64));
+               RecordCacheArray = repalloc0_array(RecordCacheArray, TupleDesc, 
newlen, RecordCacheArrayLen);
+               RecordIdentifierArray = repalloc0_array(RecordIdentifierArray, 
uint64, newlen, RecordCacheArrayLen);
                RecordCacheArrayLen = newlen;
        }
 }
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 115a64cfe4..027af1e5de 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -1297,6 +1297,21 @@ repalloc(void *pointer, Size size)
        return ret;
 }
 
+/*
+ * repalloc
+ *             Adjust the size of a previously allocated chunk and zero out 
the added
+ *             space.
+ */
+void *
+repalloc0(void *pointer, Size size, Size oldsize)
+{
+       void       *ret;
+
+       ret = repalloc(pointer, size);
+       memset((char *) ret + oldsize, 0, (size - oldsize));
+       return ret;
+}
+
 /*
  * MemoryContextAllocHuge
  *             Allocate (possibly-expansive) space within the specified 
context.
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index a0b62aa7b0..af7a4a2311 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -78,6 +78,7 @@ extern void *palloc(Size size);
 extern void *palloc0(Size size);
 extern void *palloc_extended(Size size, int flags);
 extern pg_nodiscard void *repalloc(void *pointer, Size size);
+extern pg_nodiscard void *repalloc0(void *pointer, Size size, Size oldsize);
 extern void pfree(void *pointer);
 
 /*
@@ -101,6 +102,7 @@ extern void pfree(void *pointer);
  * objects of type "type"
  */
 #define repalloc_array(pointer, type, count) ((type *) repalloc(pointer, 
sizeof(type) * (count)))
+#define repalloc0_array(pointer, type, count, oldcount) ((type *) 
repalloc0(pointer, sizeof(type) * (count), sizeof(type) * (oldcount)))
 
 /*
  * The result of palloc() is always word-aligned, so we can skip testing
-- 
2.37.3

Reply via email to