diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-10-04 13:42:56 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-10-04 13:42:56 -0700 |
commit | 9d637df6daa2f079ac3cd7623ab6694e4692d1b9 (patch) | |
tree | edfe6dddc84d094b83d24e4a609351a4a5105366 | |
parent | 12e46510bc185fff839530bba0c7becaaf307037 (diff) | |
download | nasm-9d637df6daa2f079ac3cd7623ab6694e4692d1b9.tar.gz nasm-9d637df6daa2f079ac3cd7623ab6694e4692d1b9.tar.bz2 nasm-9d637df6daa2f079ac3cd7623ab6694e4692d1b9.zip |
Rewrite the handling of SAA's to allow random access
SAA's were never intended to allow random access, but several backends
do random or semirandom access via saa_fread() and saa_fwrite()
anyway. Rewrite the SAA system to allow for efficient random access.
On "label.pl 10000000" this improves performance by a factor of 12.
-rw-r--r-- | nasm.c | 2 | ||||
-rw-r--r-- | nasmlib.c | 297 | ||||
-rw-r--r-- | nasmlib.h | 35 |
3 files changed, 188 insertions, 146 deletions
@@ -77,7 +77,7 @@ int32_t abs_offset; /* ABSOLUTE offset */ static struct RAA *offsets; static struct SAA *forwrefs; /* keep track of forward references */ -static struct forwrefinfo *forwref; +static const struct forwrefinfo *forwref; static Preproc *preproc; enum op_type { @@ -483,222 +483,251 @@ struct RAA *raa_write(struct RAA *r, int32_t posn, int32_t value) return result; } -#define SAA_MAXLEN 8192 +/* Aggregate SAA components smaller than this */ +#define SAA_BLKLEN 65536 -struct SAA *saa_init(int32_t elem_len) +struct SAA *saa_init(size_t elem_len) { struct SAA *s; + char *data; + + s = nasm_zalloc(sizeof(struct SAA)); - if (elem_len > SAA_MAXLEN) - nasm_malloc_error(ERR_PANIC | ERR_NOFILE, - "SAA with huge elements"); + if (elem_len >= SAA_BLKLEN) + s->blk_len = elem_len; + else + s->blk_len = SAA_BLKLEN - (SAA_BLKLEN % elem_len); - s = nasm_malloc(sizeof(struct SAA)); - s->posn = s->start = 0L; s->elem_len = elem_len; - s->length = SAA_MAXLEN - (SAA_MAXLEN % elem_len); - s->data = nasm_malloc(s->length); - s->next = NULL; - s->end = s; + s->length = s->blk_len; + data = nasm_malloc(s->blk_len); + s->nblkptrs = s->nblks = 1; + s->blk_ptrs = nasm_malloc(sizeof(char *)); + s->blk_ptrs[0] = data; + s->wblk = s->rblk = &s->blk_ptrs[0]; return s; } void saa_free(struct SAA *s) { - struct SAA *t; + char **p; + size_t n; + + for (p = s->blk_ptrs, n = s->nblks; n; p++, n--) + nasm_free(*p); - while (s) { - t = s->next; - nasm_free(s->data); - nasm_free(s); - s = t; + nasm_free(s->blk_ptrs); + nasm_free(s); +} + +/* Add one allocation block to an SAA */ +static void saa_extend(struct SAA *s) +{ + size_t blkn = s->nblks++; + + if (blkn >= s->nblkptrs) { + size_t rindex = s->rblk - s->blk_ptrs; + size_t windex = s->wblk - s->blk_ptrs; + + s->nblkptrs <<= 1; + s->blk_ptrs = nasm_realloc(s->blk_ptrs, s->nblkptrs*sizeof(char *)); + + s->rblk = s->blk_ptrs + rindex; + s->wblk = s->blk_ptrs + windex; } + + s->blk_ptrs[blkn] = nasm_malloc(s->blk_len); + s->length += s->blk_len; } void *saa_wstruct(struct SAA *s) { void *p; - if (s->end->length - s->end->posn < s->elem_len) { - s->end->next = nasm_malloc(sizeof(struct SAA)); - s->end->next->start = s->end->start + s->end->posn; - s->end = s->end->next; - s->end->length = s->length; - s->end->next = NULL; - s->end->posn = 0L; - s->end->data = nasm_malloc(s->length); + if (s->wpos % s->elem_len) + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, + "misaligned wpos in saa_wstruct"); + + if (s->wpos + s->elem_len > s->blk_len) { + if (s->wpos != s->blk_len) + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, + "unfilled block in saa_wstruct"); + + if (s->wptr + s->elem_len > s->length) + saa_extend(s); + s->wblk++; + s->wpos = 0; } - p = s->end->data + s->end->posn; - s->end->posn += s->elem_len; + p = *s->wblk + s->wpos; + s->wpos += s->elem_len; + s->wptr += s->elem_len; + + if (s->wptr > s->datalen) + s->datalen = s->wptr; + return p; } -void saa_wbytes(struct SAA *s, const void *data, int32_t len) +void saa_wbytes(struct SAA *s, const void *data, size_t len) { const char *d = data; - while (len > 0) { - int32_t l = s->end->length - s->end->posn; + while (len) { + size_t l = s->blk_len - s->wpos; if (l > len) l = len; - if (l > 0) { + if (l) { if (d) { - memcpy(s->end->data + s->end->posn, d, l); + memcpy(*s->wblk + s->wpos, d, l); d += l; } else - memset(s->end->data + s->end->posn, 0, l); - s->end->posn += l; + memset(*s->wblk + s->wpos, 0, l); + s->wpos += l; + s->wptr += l; len -= l; + + if (s->datalen < s->wptr) + s->datalen = s->wptr; } - if (len > 0) { - s->end->next = nasm_malloc(sizeof(struct SAA)); - s->end->next->start = s->end->start + s->end->posn; - s->end = s->end->next; - s->end->length = s->length; - s->end->next = NULL; - s->end->posn = 0L; - s->end->data = nasm_malloc(s->length); - } + if (len) { + if (s->wptr >= s->length) + saa_extend(s); + s->wblk++; + s->wpos = 0; + } } } void saa_rewind(struct SAA *s) { - s->rptr = s; - s->rpos = 0L; + s->rblk = s->blk_ptrs; + s->rpos = s->rptr = 0; } void *saa_rstruct(struct SAA *s) { void *p; - if (!s->rptr) - return NULL; + if (s->rptr + s->elem_len < s->datalen) + return NULL; + + if (s->rpos % s->elem_len) + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, + "misaligned rpos in saa_rstruct"); - if (s->rptr->posn - s->rpos < s->elem_len) { - s->rptr = s->rptr->next; - if (!s->rptr) - return NULL; /* end of array */ - s->rpos = 0L; + if (s->rpos + s->elem_len > s->blk_len) { + s->rblk++; + s->rpos = 0; } - p = s->rptr->data + s->rpos; + p = *s->rblk + s->rpos; s->rpos += s->elem_len; + s->rptr += s->elem_len; + return p; } -void *saa_rbytes(struct SAA *s, int32_t *len) +const void *saa_rbytes(struct SAA *s, size_t *lenp) { - void *p; + const void *p; + size_t len; + + if (s->rptr >= s->datalen) { + *lenp = 0; + return NULL; + } + + if (s->rpos >= s->blk_len) { + s->rblk++; + s->rpos = 0; + } + + len = *lenp; + if (len > s->datalen - s->rptr) + len = s->datalen - s->rptr; + if (len > s->blk_len - s->rpos) + len = s->blk_len - s->rpos; - if (!s->rptr) - return NULL; + *lenp = len; + p = *s->rblk + s->rpos; + + s->rpos += len; + s->rptr += len; - p = s->rptr->data + s->rpos; - *len = s->rptr->posn - s->rpos; - s->rptr = s->rptr->next; - s->rpos = 0L; return p; } -void saa_rnbytes(struct SAA *s, void *data, int32_t len) +void saa_rnbytes(struct SAA *s, void *data, size_t len) { char *d = data; - while (len > 0) { - int32_t l; + if (s->rptr + len > s->datalen) { + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_rnbytes"); + return; + } - if (!s->rptr) - return; + while (len) { + size_t l; + const void *p; - l = s->rptr->posn - s->rpos; - if (l > len) - l = len; - if (l > 0) { - memcpy(d, s->rptr->data + s->rpos, l); - d += l; - s->rpos += l; - len -= l; - } - if (len > 0) { - s->rptr = s->rptr->next; - s->rpos = 0L; - } + l = len; + p = saa_rbytes(s, &l); + + memcpy(d, p, l); + d += l; + len -= l; } } -void saa_fread(struct SAA *s, int32_t posn, void *data, int32_t len) +/* Same as saa_rnbytes, except position the counter first */ +void saa_fread(struct SAA *s, size_t posn, void *data, size_t len) { - struct SAA *p; - int64_t pos; - char *cdata = data; - - if (!s->rptr || posn < s->rptr->start) - saa_rewind(s); - p = s->rptr; - while (posn >= p->start + p->posn) { - p = p->next; - if (!p) - return; /* what else can we do?! */ + size_t ix; + + if (posn+len > s->datalen) { + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fread"); + return; } - pos = posn - p->start; - while (len) { - int64_t l = p->posn - pos; - if (l > len) - l = len; - memcpy(cdata, p->data + pos, l); - len -= l; - cdata += l; - p = p->next; - if (!p) - return; - pos = 0LL; - } - s->rptr = p; + ix = posn / s->blk_len; + s->rpos = posn % s->blk_len; + s->rblk = &s->blk_ptrs[ix]; + + saa_rnbytes(s, data, len); } -void saa_fwrite(struct SAA *s, int32_t posn, void *data, int32_t len) +/* Same as saa_wbytes, except position the counter first */ +void saa_fwrite(struct SAA *s, size_t posn, const void *data, size_t len) { - struct SAA *p; - int64_t pos; - char *cdata = data; - - if (!s->rptr || posn < s->rptr->start) - saa_rewind(s); - p = s->rptr; - while (posn >= p->start + p->posn) { - p = p->next; - if (!p) - return; /* what else can we do?! */ + size_t ix; + + if (posn > s->datalen) { + /* Seek beyond the end of the existing array not supported */ + nasm_malloc_error(ERR_PANIC|ERR_NOFILE, "overrun in saa_fwrite"); + return; } - pos = posn - p->start; - while (len) { - int64_t l = p->posn - pos; - if (l > len) - l = len; - memcpy(p->data + pos, cdata, l); - len -= l; - cdata += l; - p = p->next; - if (!p) - return; - pos = 0LL; + ix = posn / s->blk_len; + s->wpos = posn % s->blk_len; + s->wblk = &s->blk_ptrs[ix]; + + if (!s->wpos) { + s->wpos = s->blk_len; + s->wblk--; } - s->rptr = p; + + saa_wbytes(s, data, len); } void saa_fpwrite(struct SAA *s, FILE * fp) { - char *data; - int32_t len; + const char *data; + size_t len; saa_rewind(s); -// while ((data = saa_rbytes(s, &len))) - for (; (data = saa_rbytes(s, &len));) + while ((data = saa_rbytes(s, &len)) != NULL) fwrite(data, 1, len, fp); } @@ -206,8 +206,8 @@ void fwriteint64_t(int64_t data, FILE * fp); * chunk. */ -#define RAA_BLKSIZE 4096 /* this many longs allocated at once */ -#define RAA_LAYERSIZE 1024 /* this many _pointers_ allocated */ +#define RAA_BLKSIZE 65536 /* this many longs allocated at once */ +#define RAA_LAYERSIZE 32768 /* this many _pointers_ allocated */ typedef struct RAA RAA; typedef union RAA_UNION RAA_UNION; @@ -261,21 +261,34 @@ struct SAA { * members `end' and `elem_len' are only valid in first link in * list; `rptr' and `rpos' are used for reading */ - struct SAA *next, *end, *rptr; - int32_t elem_len, length, posn, start, rpos; - char *data; + size_t elem_len; /* Size of each element */ + size_t blk_len; /* Size of each allocation block */ + size_t nblks; /* Total number of allocated blocks */ + size_t nblkptrs; /* Total number of allocation block pointers */ + size_t length; /* Total allocated length of the array */ + size_t datalen; /* Total data length of the array */ + char **wblk; /* Write block pointer */ + size_t wpos; /* Write position inside block */ + size_t wptr; /* Absolute write position */ + char **rblk; /* Read block pointer */ + size_t rpos; /* Read position inside block */ + size_t rptr; /* Absolute read position */ + char **blk_ptrs; /* Pointer to pointer blocks */ }; -struct SAA *saa_init(int32_t elem_len); /* 1 == byte */ +struct SAA *saa_init(size_t elem_len); /* 1 == byte */ void saa_free(struct SAA *); void *saa_wstruct(struct SAA *); /* return a structure of elem_len */ -void saa_wbytes(struct SAA *, const void *, int32_t); /* write arbitrary bytes */ +void saa_wbytes(struct SAA *, const void *, size_t); /* write arbitrary bytes */ void saa_rewind(struct SAA *); /* for reading from beginning */ void *saa_rstruct(struct SAA *); /* return NULL on EOA */ -void *saa_rbytes(struct SAA *, int32_t *); /* return 0 on EOA */ -void saa_rnbytes(struct SAA *, void *, int32_t); /* read a given no. of bytes */ -void saa_fread(struct SAA *s, int32_t posn, void *p, int32_t len); /* fixup */ -void saa_fwrite(struct SAA *s, int32_t posn, void *p, int32_t len); /* fixup */ +const void *saa_rbytes(struct SAA *, size_t *); /* return 0 on EOA */ +void saa_rnbytes(struct SAA *, void *, size_t); /* read a given no. of bytes */ +/* random access */ +void saa_fread(struct SAA *, size_t, void *, size_t); +void saa_fwrite(struct SAA *, size_t, const void *, size_t); + +/* dump to file */ void saa_fpwrite(struct SAA *, FILE *); /* |