aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2017-01-25 14:58:35 -0500
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2017-01-25 14:58:35 -0500
commit6b12d4f726b9578d5c878fa765d5c167c9d71618 (patch)
treea568048349602ff1be7dfd5c439e569e016f9545
parent4c19bff0e44c358deb8efacf2cda0dbaf4a45823 (diff)
downloadegawk-6b12d4f726b9578d5c878fa765d5c167c9d71618.tar.gz
egawk-6b12d4f726b9578d5c878fa765d5c167c9d71618.tar.bz2
egawk-6b12d4f726b9578d5c878fa765d5c167c9d71618.zip
Minor rewrite of block allocator to improve clarity.
-rw-r--r--ChangeLog19
-rw-r--r--awk.h18
-rw-r--r--node.c17
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 <aschorr@telemetry-investments.com>
+
+ * 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 <aschorr@telemetry-investments.com>
* 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;