From 6b12d4f726b9578d5c878fa765d5c167c9d71618 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Wed, 25 Jan 2017 14:58:35 -0500 Subject: Minor rewrite of block allocator to improve clarity. --- ChangeLog | 19 +++++++++++++++++++ awk.h | 18 +++++++++++------- node.c | 17 +++++++++-------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 944b26e9..eb601525 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2017-01-25 Andrew J. Schorr + + * awk.h (BLOCK): Remove typedef. BLOCK was used for 2 different + purposes: to contain a block allocation list header, and to hold + each individual allocated item. This was confusing, because the "size" + field was set only in the header, but not in each element. + (struct block_header): The block header contains a pointer to the first + element and the element size. + (struct block_item): Represent a single allocated item. This contains + only a pointer to the next element. This reduces the minimum allocated + item size from 2 pointers to 1 (16 bytes to 8 bytes on x86_64). + (nextfree): Change array item type from BLOCK to struct block_header. + (getblock, freeblock): Change cast from 'BLOCK' to 'struct block_item'. + * node.c (nextfree): Now an array of 'struct block_header' instead of + BLOCK. Switch the ordering to put the next pointer before the size. + (more_blocks): Replace 'BLOCK' with 'struct block_item', and add + an assert to ensure that the allocation size is at least as large + as 'struct block_item', i.e. 1 pointer. + 2017-01-22 Andrew J. Schorr * awk.h (numtype_choose): New backend macro used to implement diff --git a/awk.h b/awk.h index 34c0e07d..66163519 100644 --- a/awk.h +++ b/awk.h @@ -1050,10 +1050,14 @@ struct flagtab { }; -typedef struct block_item { - size_t size; +struct block_item { + struct block_item *freep; +}; + +struct block_header { struct block_item *freep; -} BLOCK; + size_t size; +}; enum block_id { BLOCK_INVALID = 0, /* not legal */ @@ -1118,7 +1122,7 @@ extern afunc_t int_array_func[]; /* special node used to indicate success in array routines (not NULL) */ extern NODE *success_node; -extern BLOCK nextfree[]; +extern struct block_header nextfree[]; extern bool field0_valid; extern int do_flags; @@ -1305,10 +1309,10 @@ DEREF(NODE *r) &((n)->var_value) : r_get_lhs((n), (r)) #define getblock(p, id, ty) (void) ((p = (ty) nextfree[id].freep) ? \ - (ty) (nextfree[id].freep = ((BLOCK *) p)->freep) \ + (ty) (nextfree[id].freep = ((struct block_item *) p)->freep) \ : (p = (ty) more_blocks(id))) -#define freeblock(p, id) (void) (((BLOCK *) p)->freep = nextfree[id].freep, \ - nextfree[id].freep = (BLOCK *) p) +#define freeblock(p, id) (void) (((struct block_item *) p)->freep = nextfree[id].freep, \ + nextfree[id].freep = (struct block_item *) p) #define getnode(n) getblock(n, BLOCK_NODE, NODE *) #define freenode(n) freeblock(n, BLOCK_NODE) diff --git a/node.c b/node.c index 97f65fa3..f1f80177 100644 --- a/node.c +++ b/node.c @@ -1001,32 +1001,33 @@ void init_btowc_cache() #define BLOCKCHUNK 100 -BLOCK nextfree[BLOCK_MAX] = { - { 0, NULL}, /* invalid */ - { sizeof(NODE), NULL }, - { sizeof(BUCKET), NULL }, +struct block_header nextfree[BLOCK_MAX] = { + { NULL, 0}, /* invalid */ + { NULL, sizeof(NODE) }, + { NULL, sizeof(BUCKET) }, }; /* more_blocks --- get more blocks of memory and add to the free list; - size of a block must be >= sizeof(BLOCK) + size of a block must be >= sizeof(struct block_item) */ void * more_blocks(int id) { - BLOCK *freep, *np, *next; + struct block_item *freep, *np, *next; char *p, *endp; size_t size; size = nextfree[id].size; - emalloc(freep, BLOCK *, BLOCKCHUNK * size, "more_blocks"); + assert(size >= sizeof(struct block_item)); + emalloc(freep, struct block_item *, BLOCKCHUNK * size, "more_blocks"); p = (char *) freep; endp = p + BLOCKCHUNK * size; for (np = freep; ; np = next) { - next = (BLOCK *) (p += size); + next = (struct block_item *) (p += size); if (p >= endp) { np->freep = NULL; break; -- cgit v1.2.3