|
11 | 11 | * Portions Copyright (c) 1994, Regents of the University of California
|
12 | 12 | *
|
13 | 13 | * IDENTIFICATION
|
14 |
| - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.37 2001/01/12 21:54:01 tgl Exp $ |
| 14 | + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.38 2001/01/23 01:01:36 tgl Exp $ |
15 | 15 | *
|
16 | 16 | * NOTE:
|
17 | 17 | * This is a new (Feb. 05, 1999) implementation of the allocation set
|
@@ -879,10 +879,60 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
879 | 879 | }
|
880 | 880 | else
|
881 | 881 | {
|
| 882 | + /* |
| 883 | + * Small-chunk case. If the chunk is the last one in its block, |
| 884 | + * there might be enough free space after it that we can just |
| 885 | + * enlarge the chunk in-place. It's relatively painful to find |
| 886 | + * the containing block in the general case, but we can detect |
| 887 | + * last-ness quite cheaply for the typical case where the chunk |
| 888 | + * is in the active (topmost) allocation block. (At least with |
| 889 | + * the regression tests and code as of 1/2001, realloc'ing the last |
| 890 | + * chunk of a non-topmost block hardly ever happens, so it's not |
| 891 | + * worth scanning the block list to catch that case.) |
| 892 | + * |
| 893 | + * NOTE: must be careful not to create a chunk of a size that |
| 894 | + * AllocSetAlloc would not create, else we'll get confused later. |
| 895 | + */ |
| 896 | + AllocPointer newPointer; |
| 897 | + |
| 898 | + if (size <= ALLOC_CHUNK_LIMIT) |
| 899 | + { |
| 900 | + AllocBlock block = set->blocks; |
| 901 | + char *chunk_end; |
| 902 | + |
| 903 | + chunk_end = (char *) chunk + (oldsize + ALLOC_CHUNKHDRSZ); |
| 904 | + if (chunk_end == block->freeptr) |
| 905 | + { |
| 906 | + /* OK, it's last in block ... is there room? */ |
| 907 | + Size freespace = block->endptr - block->freeptr; |
| 908 | + int fidx; |
| 909 | + Size newsize; |
| 910 | + Size delta; |
| 911 | + |
| 912 | + fidx = AllocSetFreeIndex(size); |
| 913 | + newsize = 1 << (fidx + ALLOC_MINBITS); |
| 914 | + Assert(newsize >= oldsize); |
| 915 | + delta = newsize - oldsize; |
| 916 | + if (freespace >= delta) |
| 917 | + { |
| 918 | + /* Yes, so just enlarge the chunk. */ |
| 919 | + block->freeptr += delta; |
| 920 | + chunk->size += delta; |
| 921 | +#ifdef MEMORY_CONTEXT_CHECKING |
| 922 | + chunk->requested_size = size; |
| 923 | + /* set mark to catch clobber of "unused" space */ |
| 924 | + if (size < chunk->size) |
| 925 | + ((char *) pointer)[size] = 0x7E; |
| 926 | +#endif |
| 927 | + return pointer; |
| 928 | + } |
| 929 | + } |
| 930 | + } |
| 931 | + |
882 | 932 | /* Normal small-chunk case: just do it by brute force. */
|
883 | 933 |
|
884 | 934 | /* allocate new chunk */
|
885 |
| - AllocPointer newPointer = AllocSetAlloc((MemoryContext) set, size); |
| 935 | + newPointer = AllocSetAlloc((MemoryContext) set, size); |
886 | 936 |
|
887 | 937 | /* transfer existing data (certain to fit) */
|
888 | 938 | memcpy(newPointer, pointer, oldsize);
|
|
0 commit comments