diff --git a/historic/jam/src/newstr.c b/historic/jam/src/newstr.c index 470f2a9a0..e33d176fd 100644 --- a/historic/jam/src/newstr.c +++ b/historic/jam/src/newstr.c @@ -7,6 +7,8 @@ # include "jam.h" # include "newstr.h" # include "hash.h" +# include +# include /* * newstr.c - string manipulation routines @@ -33,6 +35,61 @@ typedef char *STRING; static struct hash *strhash = 0; static int strtotal = 0; +/* + * Immortal string allocator implementation speeds string allocation + * and cuts down on internal fragmentation + */ + +# define STRING_BLOCK 4096 +typedef struct strblock +{ + struct strblock* next; + char data[STRING_BLOCK]; +} strblock; + +static strblock* strblock_chain = 0; + +/* Storage remaining in the current strblock */ +static char* storage_start = 0; +static char* storage_finish = 0; + +/* + * allocate() - Allocate n bytes of immortal string storage + */ +static char* allocate(size_t n) +{ + /* See if we can grab storage from an existing block */ + size_t remaining = storage_finish - storage_start; + if ( remaining >= n ) + { + char* result = storage_start; + storage_start += n; + return result; + } + else /* Must allocate a new block */ + { + strblock* new_block; + size_t nalloc = n; + if ( nalloc < STRING_BLOCK ) + nalloc = STRING_BLOCK; + + /* allocate a new block and link into the chain */ + new_block = malloc( offsetof( strblock, data[nalloc] ) ); + if ( new_block == 0 ) + return 0; + new_block->next = strblock_chain; + strblock_chain = new_block; + + /* Take future allocations out of the larger remaining space */ + if ( remaining < nalloc - n ) + { + storage_start = new_block->data + n; + storage_finish = new_block->data + nalloc; + } + return new_block->data; + } +} + /* * newstr() - return a malloc'ed copy of a string */ @@ -50,7 +107,7 @@ newstr( char *string ) if( hashenter( strhash, (HASHDATA **)&s ) ) { int l = strlen( string ); - char *m = (char *)malloc( l + 1 ); + char *m = (char *)allocate( l + 1 ); strtotal += l + 1; memcpy( m, string, l + 1 ); @@ -86,8 +143,16 @@ freestr( char *s ) void donestr() { - hashdone( strhash ); - - if( DEBUG_MEM ) - printf( "%dK in strings\n", strtotal / 1024 ); + /* Reclaim string blocks */ + while ( strblock_chain != 0 ) + { + strblock* n = strblock_chain->next; + free(strblock_chain); + strblock_chain = n; + } + + hashdone( strhash ); + + if( DEBUG_MEM ) + printf( "%dK in strings\n", strtotal / 1024 ); } diff --git a/jam_src/newstr.c b/jam_src/newstr.c index 470f2a9a0..e33d176fd 100644 --- a/jam_src/newstr.c +++ b/jam_src/newstr.c @@ -7,6 +7,8 @@ # include "jam.h" # include "newstr.h" # include "hash.h" +# include +# include /* * newstr.c - string manipulation routines @@ -33,6 +35,61 @@ typedef char *STRING; static struct hash *strhash = 0; static int strtotal = 0; +/* + * Immortal string allocator implementation speeds string allocation + * and cuts down on internal fragmentation + */ + +# define STRING_BLOCK 4096 +typedef struct strblock +{ + struct strblock* next; + char data[STRING_BLOCK]; +} strblock; + +static strblock* strblock_chain = 0; + +/* Storage remaining in the current strblock */ +static char* storage_start = 0; +static char* storage_finish = 0; + +/* + * allocate() - Allocate n bytes of immortal string storage + */ +static char* allocate(size_t n) +{ + /* See if we can grab storage from an existing block */ + size_t remaining = storage_finish - storage_start; + if ( remaining >= n ) + { + char* result = storage_start; + storage_start += n; + return result; + } + else /* Must allocate a new block */ + { + strblock* new_block; + size_t nalloc = n; + if ( nalloc < STRING_BLOCK ) + nalloc = STRING_BLOCK; + + /* allocate a new block and link into the chain */ + new_block = malloc( offsetof( strblock, data[nalloc] ) ); + if ( new_block == 0 ) + return 0; + new_block->next = strblock_chain; + strblock_chain = new_block; + + /* Take future allocations out of the larger remaining space */ + if ( remaining < nalloc - n ) + { + storage_start = new_block->data + n; + storage_finish = new_block->data + nalloc; + } + return new_block->data; + } +} + /* * newstr() - return a malloc'ed copy of a string */ @@ -50,7 +107,7 @@ newstr( char *string ) if( hashenter( strhash, (HASHDATA **)&s ) ) { int l = strlen( string ); - char *m = (char *)malloc( l + 1 ); + char *m = (char *)allocate( l + 1 ); strtotal += l + 1; memcpy( m, string, l + 1 ); @@ -86,8 +143,16 @@ freestr( char *s ) void donestr() { - hashdone( strhash ); - - if( DEBUG_MEM ) - printf( "%dK in strings\n", strtotal / 1024 ); + /* Reclaim string blocks */ + while ( strblock_chain != 0 ) + { + strblock* n = strblock_chain->next; + free(strblock_chain); + strblock_chain = n; + } + + hashdone( strhash ); + + if( DEBUG_MEM ) + printf( "%dK in strings\n", strtotal / 1024 ); }