diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 0135ba0e0b34701bb8693f946c74cac43da631d5..5e97ebe89694a3d16cad56bc2020a2b61a6c5050 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.69 2006/11/08 19:27:24 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.70 2006/12/27 22:30:48 tgl Exp $
  *
  * NOTE:
  *	This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -141,6 +141,7 @@ typedef struct AllocSetContext
 	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;			/* if not NULL, keep this block over resets */
 } AllocSetContext;
 
@@ -328,6 +329,20 @@ AllocSetContextCreate(MemoryContext parent,
 	context->maxBlockSize = maxBlockSize;
 	context->nextBlockSize = initBlockSize;
 
+	/*
+	 * Compute the allocation chunk size limit for this context.  It can't
+	 * be more than ALLOC_CHUNK_LIMIT because of the fixed number of
+	 * freelists.  If maxBlockSize is small then requests exceeding the
+	 * maxBlockSize should be treated as large chunks, too.  We have to
+	 * have allocChunkLimit a power of two, because the requested and
+	 * actually-allocated sizes of any chunk must be on the same side of
+	 * the limit, else we get confused about whether the chunk is "big".
+	 */
+	context->allocChunkLimit = ALLOC_CHUNK_LIMIT;
+	while (context->allocChunkLimit >
+		   (Size) (maxBlockSize - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ))
+		context->allocChunkLimit >>= 1;
+
 	/*
 	 * Grab always-allocated space, if requested
 	 */
@@ -512,7 +527,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 	 * If requested size exceeds maximum for chunks, allocate an entire block
 	 * for this request.
 	 */
-	if (size > ALLOC_CHUNK_LIMIT)
+	if (size > set->allocChunkLimit)
 	{
 		chunk_size = MAXALIGN(size);
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
@@ -775,7 +790,7 @@ AllocSetFree(MemoryContext context, void *pointer)
 				 set->header.name, chunk);
 #endif
 
-	if (chunk->size > ALLOC_CHUNK_LIMIT)
+	if (chunk->size > set->allocChunkLimit)
 	{
 		/*
 		 * Big chunks are certain to have been allocated as single-chunk
@@ -868,7 +883,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
 		return pointer;
 	}
 
-	if (oldsize > ALLOC_CHUNK_LIMIT)
+	if (oldsize > set->allocChunkLimit)
 	{
 		/*
 		 * The chunk must have been allocated as a single-chunk block.	Find
@@ -943,7 +958,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
 		 */
 		AllocPointer newPointer;
 
-		if (size <= ALLOC_CHUNK_LIMIT)
+		if (size <= set->allocChunkLimit)
 		{
 			AllocBlock	block = set->blocks;
 			char	   *chunk_end;
@@ -1122,7 +1137,7 @@ AllocSetCheck(MemoryContext context)
 					 name, (unsigned long) chsize, chunk, block);
 
 			/* single-chunk block? */
-			if (chsize > ALLOC_CHUNK_LIMIT &&
+			if (chsize > set->allocChunkLimit &&
 				chsize + ALLOC_CHUNKHDRSZ != blk_used)
 				elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
 					 name, chunk, block);