On Tue, 11 Jul 2023 at 02:41, Melih Mutlu <m.melihmu...@gmail.com> wrote:
> > - Afaics AllocSet->keeper is unnecessary these days, as it is always 
> > allocated
> >   together with the context itself. Saves 8 bytes.
>
> This seemed like a safe change and removed the keeper field in
> AllocSet and Generation contexts. It saves an additional 8 bytes.

Seems like a good idea for an additional 8-bytes.

I looked at your v2 patch. The only thing that really looked wrong
were the (Size) casts in the context creation functions.  These should
have been casts to uint32 rather than Size. Basically, all the casts
do is say to the compiler "Yes, I know this could cause truncation due
to assigning to a size smaller than the source type's size". Some
compilers will likely warn without that and the cast will stop them.
We know there can't be any truncation due to the Asserts. There's also
the fundamental limitation that MemoryChunk can't store block offsets
larger than 1GBs anyway, so things will go bad if we tried to have
blocks bigger than 1GB.

Aside from that, I thought that a couple of other slab.c fields could
be shrunken to uint32 as the v2 patch just reduces the size of 1 field
which just creates a 4-byte hole in SlabContext.  The fullChunkSize
field is just the MAXALIGN(chunkSize) + sizeof(MemoryChunk).  We
should never be using slab contexts for any chunks anywhere near that
size. aset.c would be a better context for that, so it seems fine to
me to further restrict the maximum supported chunk size by another 8
bytes.

I've attached your patch again along with a small delta of what I adjusted.

My thoughts on these changes are that it's senseless to have Size
typed fields for storing a value that's never larger than 2^30.
Getting rid of the keeper pointer seems like a cleanup as it's pretty
much a redundant field.   For small sized contexts like the ones used
for storing index relcache entries, I think it makes sense to save 20
more bytes.  Each backend can have many thousand of those and there
could be many hundred backends. If we can fit more allocations on that
initial 1 kilobyte keeper block without having to allocate any
additional blocks, then that's great.

I feel that Andres's results showing several hundred fewer block
allocations shows this working.  Albeit, his patch reduced the size of
the structs even further than what v3 does. I think v3 is enough for
now as the additional changes Andres mentioned require some more
invasive code changes to make work.

If nobody objects or has other ideas about this, modulo commit
message, I plan to push the attached on Monday.

David
From e5e7da6a9880b0cbc7fa96d26cdd73d8bb02c88f Mon Sep 17 00:00:00 2001
From: Melih Mutlu <m.melihmu...@gmail.com>
Date: Mon, 12 Jun 2023 08:50:28 +0300
Subject: [PATCH v3 1/2] Change memory context fields to uint32

Block sizes and chunk sizes can be upper bounded by
MEMORYCHUNK_MAX_BLOCKOFFSET and MEMORYCHUNK_MAX_VALUE respectively.
Values of both bounds correspond to 1 less than 1GB. This allows us
to store the sizes of any block or chunk size limited by those bounds
in 32 bits.

This patch changes types of such fields that represents block or chunk sizes
from 64-bit Size to 32-bit unsigned integers.

Also; keeper fields from AllocSet and Generation structs are removed and
added AllocSetKeeper/GenerationKeeper macros where needed.
---
 src/backend/utils/mmgr/aset.c       | 52 +++++++++++++++++------------
 src/backend/utils/mmgr/generation.c | 51 ++++++++++++++++------------
 src/backend/utils/mmgr/slab.c       |  6 ++--
 3 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 0bbbf93672..797abef1b5 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -156,11 +156,10 @@ typedef struct AllocSetContext
        AllocBlock      blocks;                 /* head of list of blocks in 
this set */
        MemoryChunk *freelist[ALLOCSET_NUM_FREELISTS];  /* free chunk lists */
        /* Allocation parameters for this context: */
-       Size            initBlockSize;  /* initial block size */
-       Size            maxBlockSize;   /* maximum block size */
-       Size            nextBlockSize;  /* next block size to allocate */
-       Size            allocChunkLimit;        /* effective chunk size limit */
-       AllocBlock      keeper;                 /* keep this block over resets 
*/
+       uint32          initBlockSize;  /* initial block size */
+       uint32          maxBlockSize;   /* maximum block size */
+       uint32          nextBlockSize;  /* next block size to allocate */
+       uint32          allocChunkLimit;        /* effective chunk size limit */
        /* freelist this context could be put in, or -1 if not a candidate: */
        int                     freeListIndex;  /* index in 
context_freelists[], or -1 */
 } AllocSetContext;
@@ -241,6 +240,14 @@ typedef struct AllocBlockData
  */
 #define MAX_FREE_CONTEXTS 100  /* arbitrary limit on freelist length */
 
+/* Obtain the keeper block for an allocation set */
+#define AllocSetKeeper(set) \
+       ((AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext))))
+
+/* Check if the block is the keeper block of the given allocation set */
+#define IsKeeperBlock(set, block) \
+       ((block) == (AllocSetKeeper(set)))
+
 typedef struct AllocSetFreeList
 {
        int                     num_free;               /* current list length 
*/
@@ -345,7 +352,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
                                                          Size maxBlockSize)
 {
        int                     freeListIndex;
-       Size            firstBlockSize;
+       uint32          firstBlockSize;
        AllocSet        set;
        AllocBlock      block;
 
@@ -417,7 +424,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
                                                                name);
 
                        ((MemoryContext) set)->mem_allocated =
-                               set->keeper->endptr - ((char *) set);
+                               AllocSetKeeper(set)->endptr - ((char *) set);
 
                        return (MemoryContext) set;
                }
@@ -452,8 +459,11 @@ AllocSetContextCreateInternal(MemoryContext parent,
         * we'd leak the header/initial block if we ereport in this stretch.
         */
 
-       /* Fill in the initial block's block header */
-       block = (AllocBlock) (((char *) set) + 
MAXALIGN(sizeof(AllocSetContext)));
+       /*
+        * Fill in the initial block's block header. The initial block is not 
to be
+        * released at reset time, considered as keeper block.
+        */
+       block = AllocSetKeeper(set);
        block->aset = set;
        block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
        block->endptr = ((char *) set) + firstBlockSize;
@@ -465,15 +475,13 @@ AllocSetContextCreateInternal(MemoryContext parent,
 
        /* Remember block as part of block list */
        set->blocks = block;
-       /* Mark block as not to be released at reset time */
-       set->keeper = block;
 
        /* Finish filling in aset-specific parts of the context header */
        MemSetAligned(set->freelist, 0, sizeof(set->freelist));
 
-       set->initBlockSize = initBlockSize;
-       set->maxBlockSize = maxBlockSize;
-       set->nextBlockSize = initBlockSize;
+       set->initBlockSize = (Size) initBlockSize;
+       set->maxBlockSize = (Size) maxBlockSize;
+       set->nextBlockSize = (Size) initBlockSize;
        set->freeListIndex = freeListIndex;
 
        /*
@@ -544,7 +552,7 @@ AllocSetReset(MemoryContext context)
 #endif
 
        /* Remember keeper block size for Assert below */
-       keepersize = set->keeper->endptr - ((char *) set);
+       keepersize = AllocSetKeeper(set)->endptr - ((char *) set);
 
        /* Clear chunk freelists */
        MemSetAligned(set->freelist, 0, sizeof(set->freelist));
@@ -552,13 +560,13 @@ AllocSetReset(MemoryContext context)
        block = set->blocks;
 
        /* New blocks list will be just the keeper block */
-       set->blocks = set->keeper;
+       set->blocks = AllocSetKeeper(set);
 
        while (block != NULL)
        {
                AllocBlock      next = block->next;
 
-               if (block == set->keeper)
+               if (IsKeeperBlock(set, block))
                {
                        /* Reset the block, but don't return it to malloc */
                        char       *datastart = ((char *) block) + 
ALLOC_BLOCKHDRSZ;
@@ -614,7 +622,7 @@ AllocSetDelete(MemoryContext context)
 #endif
 
        /* Remember keeper block size for Assert below */
-       keepersize = set->keeper->endptr - ((char *) set);
+       keepersize = AllocSetKeeper(set)->endptr - ((char *) set);
 
        /*
         * If the context is a candidate for a freelist, put it into that 
freelist
@@ -663,14 +671,14 @@ AllocSetDelete(MemoryContext context)
        {
                AllocBlock      next = block->next;
 
-               if (block != set->keeper)
+               if (!IsKeeperBlock(set, block))
                        context->mem_allocated -= block->endptr - ((char *) 
block);
 
 #ifdef CLOBBER_FREED_MEMORY
                wipe_mem(block, block->freeptr - ((char *) block));
 #endif
 
-               if (block != set->keeper)
+               if (!IsKeeperBlock(set, block))
                        free(block);
 
                block = next;
@@ -1547,7 +1555,7 @@ AllocSetCheck(MemoryContext context)
                long            nchunks = 0;
                bool            has_external_chunk = false;
 
-               if (set->keeper == block)
+               if (IsKeeperBlock(set, block))
                        total_allocated += block->endptr - ((char *) set);
                else
                        total_allocated += block->endptr - ((char *) block);
@@ -1557,7 +1565,7 @@ AllocSetCheck(MemoryContext context)
                 */
                if (!blk_used)
                {
-                       if (set->keeper != block)
+                       if (!IsKeeperBlock(set, block))
                                elog(WARNING, "problem in alloc set %s: empty 
block %p",
                                         name, block);
                }
diff --git a/src/backend/utils/mmgr/generation.c 
b/src/backend/utils/mmgr/generation.c
index 4fb8663cd6..d6a0811a72 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -61,17 +61,16 @@ typedef struct GenerationContext
        MemoryContextData header;       /* Standard memory-context fields */
 
        /* Generational context parameters */
-       Size            initBlockSize;  /* initial block size */
-       Size            maxBlockSize;   /* maximum block size */
-       Size            nextBlockSize;  /* next block size to allocate */
-       Size            allocChunkLimit;        /* effective chunk size limit */
+       uint32          initBlockSize;  /* initial block size */
+       uint32          maxBlockSize;   /* maximum block size */
+       uint32          nextBlockSize;  /* next block size to allocate */
+       uint32          allocChunkLimit;        /* effective chunk size limit */
 
        GenerationBlock *block;         /* current (most recently allocated) 
block, or
                                                                 * NULL if 
we've just freed the most recent
                                                                 * block */
        GenerationBlock *freeblock; /* pointer to a block that's being recycled,
                                                                 * or NULL if 
there's no such block. */
-       GenerationBlock *keeper;        /* keep this block over resets */
        dlist_head      blocks;                 /* list of blocks */
 } GenerationContext;
 
@@ -120,6 +119,14 @@ struct GenerationBlock
 #define ExternalChunkGetBlock(chunk) \
        (GenerationBlock *) ((char *) chunk - Generation_BLOCKHDRSZ)
 
+/* Obtain the keeper block for a generation context */
+#define GenerationKeeper(set) \
+       ((GenerationBlock *) (((char *) set) + 
MAXALIGN(sizeof(GenerationContext))))
+
+/* Check if the block is the keeper block of the given generation context */
+#define IsKeeperBlock(set, block) \
+       ((block) == (GenerationKeeper(set)))
+
 /* Inlined helper functions */
 static inline void GenerationBlockInit(GenerationContext *context,
                                                                           
GenerationBlock *block,
@@ -153,8 +160,8 @@ GenerationContextCreate(MemoryContext parent,
                                                Size initBlockSize,
                                                Size maxBlockSize)
 {
-       Size            firstBlockSize;
-       Size            allocSize;
+       uint32          firstBlockSize;
+       uint32          allocSize;
        GenerationContext *set;
        GenerationBlock *block;
 
@@ -213,8 +220,11 @@ GenerationContextCreate(MemoryContext parent,
         */
        dlist_init(&set->blocks);
 
-       /* Fill in the initial block's block header */
-       block = (GenerationBlock *) (((char *) set) + 
MAXALIGN(sizeof(GenerationContext)));
+       /*
+        * Fill in the initial block's block header. The initial block is not 
to be
+        * released at reset time, considered as keeper block.
+        */
+       block = GenerationKeeper(set);
        /* determine the block size and initialize it */
        firstBlockSize = allocSize - MAXALIGN(sizeof(GenerationContext));
        GenerationBlockInit(set, block, firstBlockSize);
@@ -228,13 +238,10 @@ GenerationContextCreate(MemoryContext parent,
        /* No free block, yet */
        set->freeblock = NULL;
 
-       /* Mark block as not to be released at reset time */
-       set->keeper = block;
-
        /* Fill in GenerationContext-specific header fields */
-       set->initBlockSize = initBlockSize;
-       set->maxBlockSize = maxBlockSize;
-       set->nextBlockSize = initBlockSize;
+       set->initBlockSize = (Size) initBlockSize;
+       set->maxBlockSize = (Size) maxBlockSize;
+       set->nextBlockSize = (Size) initBlockSize;
 
        /*
         * Compute the allocation chunk size limit for this context.
@@ -294,14 +301,14 @@ GenerationReset(MemoryContext context)
        {
                GenerationBlock *block = dlist_container(GenerationBlock, node, 
miter.cur);
 
-               if (block == set->keeper)
+               if (IsKeeperBlock(set, block))
                        GenerationBlockMarkEmpty(block);
                else
                        GenerationBlockFree(set, block);
        }
 
        /* set it so new allocations to make use of the keeper block */
-       set->block = set->keeper;
+       set->block = GenerationKeeper(set);
 
        /* Reset block size allocation sequence, too */
        set->nextBlockSize = set->initBlockSize;
@@ -440,10 +447,10 @@ GenerationAlloc(MemoryContext context, Size size)
                         */
                        set->freeblock = NULL;
                }
-               else if (GenerationBlockIsEmpty(set->keeper) &&
-                                GenerationBlockFreeBytes(set->keeper) >= 
required_size)
+               else if (GenerationBlockIsEmpty(GenerationKeeper(set)) &&
+                                
GenerationBlockFreeBytes(GenerationKeeper(set)) >= required_size)
                {
-                       block = set->keeper;
+                       block = GenerationKeeper(set);
                }
                else
                {
@@ -594,7 +601,7 @@ static inline void
 GenerationBlockFree(GenerationContext *set, GenerationBlock *block)
 {
        /* Make sure nobody tries to free the keeper block */
-       Assert(block != set->keeper);
+       Assert(!IsKeeperBlock(set, block));
        /* We shouldn't be freeing the freeblock either */
        Assert(block != set->freeblock);
 
@@ -691,7 +698,7 @@ GenerationFree(void *pointer)
        set = block->context;
 
        /* Don't try to free the keeper block, just mark it empty */
-       if (block == set->keeper)
+       if (IsKeeperBlock(set, block))
        {
                GenerationBlockMarkEmpty(block);
                return;
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 718dd2ba03..d5e0edbede 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -104,7 +104,7 @@ typedef struct SlabContext
 {
        MemoryContextData header;       /* Standard memory-context fields */
        /* Allocation parameters for this context: */
-       Size            chunkSize;              /* the requested (non-aligned) 
chunk size */
+       uint32          chunkSize;              /* the requested (non-aligned) 
chunk size */
        Size            fullChunkSize;  /* chunk size with chunk header and 
alignment */
        Size            blockSize;              /* the size to make each block 
of chunks */
        int32           chunksPerBlock; /* number of chunks that fit in 1 block 
*/
@@ -374,7 +374,7 @@ SlabContextCreate(MemoryContext parent,
         */
 
        /* Fill in SlabContext-specific header fields */
-       slab->chunkSize = chunkSize;
+       slab->chunkSize = (Size) chunkSize;
        slab->fullChunkSize = fullChunkSize;
        slab->blockSize = blockSize;
        slab->chunksPerBlock = chunksPerBlock;
@@ -506,7 +506,7 @@ SlabAlloc(MemoryContext context, Size size)
 
        /* make sure we only allow correct request size */
        if (unlikely(size != slab->chunkSize))
-               elog(ERROR, "unexpected alloc chunk size %zu (expected %zu)",
+               elog(ERROR, "unexpected alloc chunk size %zu (expected %u)",
                         size, slab->chunkSize);
 
        /*
-- 
2.39.2

From 81825c3d3f7d12b5f5d68f3e132e5284f823e393 Mon Sep 17 00:00:00 2001
From: David Rowley <dgrow...@gmail.com>
Date: Thu, 13 Jul 2023 16:41:29 +1200
Subject: [PATCH v3 2/2] fixup! Change memory context fields to uint32

---
 src/backend/utils/mmgr/aset.c       | 25 ++++++++++++-------------
 src/backend/utils/mmgr/generation.c | 29 ++++++++++++++---------------
 src/backend/utils/mmgr/slab.c       | 18 +++++++++++-------
 3 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 797abef1b5..9b556396ee 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -241,12 +241,11 @@ typedef struct AllocBlockData
 #define MAX_FREE_CONTEXTS 100  /* arbitrary limit on freelist length */
 
 /* Obtain the keeper block for an allocation set */
-#define AllocSetKeeper(set) \
+#define KeeperBlock(set) \
        ((AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext))))
 
 /* Check if the block is the keeper block of the given allocation set */
-#define IsKeeperBlock(set, block) \
-       ((block) == (AllocSetKeeper(set)))
+#define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set)))
 
 typedef struct AllocSetFreeList
 {
@@ -424,7 +423,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
                                                                name);
 
                        ((MemoryContext) set)->mem_allocated =
-                               AllocSetKeeper(set)->endptr - ((char *) set);
+                               KeeperBlock(set)->endptr - ((char *) set);
 
                        return (MemoryContext) set;
                }
@@ -460,10 +459,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
         */
 
        /*
-        * Fill in the initial block's block header. The initial block is not 
to be
-        * released at reset time, considered as keeper block.
+        * Fill in the initial block's block header.  The initial block is not 
to
+        * be released at reset time, considered as keeper block.
         */
-       block = AllocSetKeeper(set);
+       block = KeeperBlock(set);
        block->aset = set;
        block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
        block->endptr = ((char *) set) + firstBlockSize;
@@ -479,9 +478,9 @@ AllocSetContextCreateInternal(MemoryContext parent,
        /* Finish filling in aset-specific parts of the context header */
        MemSetAligned(set->freelist, 0, sizeof(set->freelist));
 
-       set->initBlockSize = (Size) initBlockSize;
-       set->maxBlockSize = (Size) maxBlockSize;
-       set->nextBlockSize = (Size) initBlockSize;
+       set->initBlockSize = (uint32) initBlockSize;
+       set->maxBlockSize = (uint32) maxBlockSize;
+       set->nextBlockSize = (uint32) initBlockSize;
        set->freeListIndex = freeListIndex;
 
        /*
@@ -552,7 +551,7 @@ AllocSetReset(MemoryContext context)
 #endif
 
        /* Remember keeper block size for Assert below */
-       keepersize = AllocSetKeeper(set)->endptr - ((char *) set);
+       keepersize = KeeperBlock(set)->endptr - ((char *) set);
 
        /* Clear chunk freelists */
        MemSetAligned(set->freelist, 0, sizeof(set->freelist));
@@ -560,7 +559,7 @@ AllocSetReset(MemoryContext context)
        block = set->blocks;
 
        /* New blocks list will be just the keeper block */
-       set->blocks = AllocSetKeeper(set);
+       set->blocks = KeeperBlock(set);
 
        while (block != NULL)
        {
@@ -622,7 +621,7 @@ AllocSetDelete(MemoryContext context)
 #endif
 
        /* Remember keeper block size for Assert below */
-       keepersize = AllocSetKeeper(set)->endptr - ((char *) set);
+       keepersize = KeeperBlock(set)->endptr - ((char *) set);
 
        /*
         * If the context is a candidate for a freelist, put it into that 
freelist
diff --git a/src/backend/utils/mmgr/generation.c 
b/src/backend/utils/mmgr/generation.c
index d6a0811a72..a152fbf0c5 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -120,12 +120,11 @@ struct GenerationBlock
        (GenerationBlock *) ((char *) chunk - Generation_BLOCKHDRSZ)
 
 /* Obtain the keeper block for a generation context */
-#define GenerationKeeper(set) \
+#define KeeperBlock(set) \
        ((GenerationBlock *) (((char *) set) + 
MAXALIGN(sizeof(GenerationContext))))
 
 /* Check if the block is the keeper block of the given generation context */
-#define IsKeeperBlock(set, block) \
-       ((block) == (GenerationKeeper(set)))
+#define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set)))
 
 /* Inlined helper functions */
 static inline void GenerationBlockInit(GenerationContext *context,
@@ -160,8 +159,8 @@ GenerationContextCreate(MemoryContext parent,
                                                Size initBlockSize,
                                                Size maxBlockSize)
 {
-       uint32          firstBlockSize;
-       uint32          allocSize;
+       Size            firstBlockSize;
+       Size            allocSize;
        GenerationContext *set;
        GenerationBlock *block;
 
@@ -221,10 +220,10 @@ GenerationContextCreate(MemoryContext parent,
        dlist_init(&set->blocks);
 
        /*
-        * Fill in the initial block's block header. The initial block is not 
to be
-        * released at reset time, considered as keeper block.
+        * Fill in the initial block's block header.  The initial block is not 
to
+        * be released at reset time, considered as keeper block.
         */
-       block = GenerationKeeper(set);
+       block = KeeperBlock(set);
        /* determine the block size and initialize it */
        firstBlockSize = allocSize - MAXALIGN(sizeof(GenerationContext));
        GenerationBlockInit(set, block, firstBlockSize);
@@ -239,9 +238,9 @@ GenerationContextCreate(MemoryContext parent,
        set->freeblock = NULL;
 
        /* Fill in GenerationContext-specific header fields */
-       set->initBlockSize = (Size) initBlockSize;
-       set->maxBlockSize = (Size) maxBlockSize;
-       set->nextBlockSize = (Size) initBlockSize;
+       set->initBlockSize = (uint32) initBlockSize;
+       set->maxBlockSize = (uint32) maxBlockSize;
+       set->nextBlockSize = (uint32) initBlockSize;
 
        /*
         * Compute the allocation chunk size limit for this context.
@@ -308,7 +307,7 @@ GenerationReset(MemoryContext context)
        }
 
        /* set it so new allocations to make use of the keeper block */
-       set->block = GenerationKeeper(set);
+       set->block = KeeperBlock(set);
 
        /* Reset block size allocation sequence, too */
        set->nextBlockSize = set->initBlockSize;
@@ -447,10 +446,10 @@ GenerationAlloc(MemoryContext context, Size size)
                         */
                        set->freeblock = NULL;
                }
-               else if (GenerationBlockIsEmpty(GenerationKeeper(set)) &&
-                                
GenerationBlockFreeBytes(GenerationKeeper(set)) >= required_size)
+               else if (GenerationBlockIsEmpty(KeeperBlock(set)) &&
+                                GenerationBlockFreeBytes(KeeperBlock(set)) >= 
required_size)
                {
-                       block = GenerationKeeper(set);
+                       block = KeeperBlock(set);
                }
                else
                {
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index d5e0edbede..40c1d401c4 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -105,8 +105,8 @@ typedef struct SlabContext
        MemoryContextData header;       /* Standard memory-context fields */
        /* Allocation parameters for this context: */
        uint32          chunkSize;              /* the requested (non-aligned) 
chunk size */
-       Size            fullChunkSize;  /* chunk size with chunk header and 
alignment */
-       Size            blockSize;              /* the size to make each block 
of chunks */
+       uint32          fullChunkSize;  /* chunk size with chunk header and 
alignment */
+       uint32          blockSize;              /* the size to make each block 
of chunks */
        int32           chunksPerBlock; /* number of chunks that fit in 1 block 
*/
        int32           curBlocklistIndex;      /* index into the blocklist[] 
element
                                                                         * 
containing the fullest, blocks */
@@ -314,7 +314,9 @@ SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block)
  * blockSize: allocation block size
  * chunkSize: allocation chunk size
  *
- * The MAXALIGN(chunkSize) may not exceed MEMORYCHUNK_MAX_VALUE
+ * The Slab_CHUNKHDRSZ + MAXALIGN(chunkSize + 1) may not exceed
+ * MEMORYCHUNK_MAX_VALUE.
+ * 'blockSize' may not exceed MEMORYCHUNK_MAX_BLOCKOFFSET.
  */
 MemoryContext
 SlabContextCreate(MemoryContext parent,
@@ -330,7 +332,7 @@ SlabContextCreate(MemoryContext parent,
        /* ensure MemoryChunk's size is properly maxaligned */
        StaticAssertDecl(Slab_CHUNKHDRSZ == MAXALIGN(Slab_CHUNKHDRSZ),
                                         "sizeof(MemoryChunk) is not 
maxaligned");
-       Assert(MAXALIGN(chunkSize) <= MEMORYCHUNK_MAX_VALUE);
+       Assert(blockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
 
        /*
         * Ensure there's enough space to store the pointer to the next free 
chunk
@@ -347,6 +349,8 @@ SlabContextCreate(MemoryContext parent,
        fullChunkSize = Slab_CHUNKHDRSZ + MAXALIGN(chunkSize);
 #endif
 
+       Assert(fullChunkSize <= MEMORYCHUNK_MAX_VALUE);
+
        /* compute the number of chunks that will fit on each block */
        chunksPerBlock = (blockSize - Slab_BLOCKHDRSZ) / fullChunkSize;
 
@@ -374,9 +378,9 @@ SlabContextCreate(MemoryContext parent,
         */
 
        /* Fill in SlabContext-specific header fields */
-       slab->chunkSize = (Size) chunkSize;
-       slab->fullChunkSize = fullChunkSize;
-       slab->blockSize = blockSize;
+       slab->chunkSize = (uint32) chunkSize;
+       slab->fullChunkSize = (uint32) fullChunkSize;
+       slab->blockSize = (uint32) blockSize;
        slab->chunksPerBlock = chunksPerBlock;
        slab->curBlocklistIndex = 0;
 
-- 
2.39.2

Reply via email to