diff options
author | H. Peter Anvin <hpa@zytor.com> | 2018-06-03 02:47:06 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2018-06-03 02:47:06 -0700 |
commit | 36e2a0c88741b67edaea35dd059475f9d12ceefb (patch) | |
tree | e7cdf24b81dad8d65b4175add9e121cb1cad3df5 | |
parent | 9d06db9dabc6f829819faeb3789e525508264bfe (diff) | |
download | nasm-36e2a0c88741b67edaea35dd059475f9d12ceefb.tar.gz |
mempool: define standard mempools, fixes to the mempool allocator
Define standard mempools reclaimed at various stages. Fix various
problems with the mempool allocator.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | asm/nasm.c | 13 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | include/compiler.h | 45 | ||||
-rw-r--r-- | include/mempool.h | 35 | ||||
-rw-r--r-- | nasmlib/mempool.c | 95 |
5 files changed, 131 insertions, 66 deletions
@@ -60,6 +60,7 @@ #include "outform.h" #include "listing.h" #include "iflag.h" +#include "mempool.h" #include "ver.h" /* @@ -502,7 +503,6 @@ int main(int argc, char **argv) if (!terminate_after_phase) { ofmt->cleanup(); - cleanup_labels(); fflush(ofile); if (ferror(ofile)) { nasm_error(ERR_NONFATAL|ERR_NOFILE, @@ -525,11 +525,14 @@ int main(int argc, char **argv) if (want_usage) usage(); + cleanup_labels(); raa_free(offsets); saa_free(forwrefs); eval_cleanup(); stdscan_cleanup(); src_free(); + mempool_free(mempool_perm); + mempool_reclaim(); return terminate_after_phase; } @@ -1540,6 +1543,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr) end_of_line: nasm_free(line); + mempool_free(mempool_line); } /* end while (line = preproc->getline... */ if (pass0 == 2 && global_offset_changed && !terminate_after_phase) @@ -1559,10 +1563,12 @@ static void assemble_file(const char *fname, StrList **depend_ptr) stall_count++; } + mempool_free(mempool_pass); if (terminate_after_phase) break; - if ((stall_count > 997U) || (passn >= pass_max)) { + if (!terminate_after_phase && + ((stall_count > 997U) || (passn >= pass_max))) { /* We get here if the labels don't converge * Example: FOO equ FOO + 1 */ @@ -1571,10 +1577,11 @@ static void assemble_file(const char *fname, StrList **depend_ptr) "after %d passes, giving up.", passn); nasm_error(ERR_NONFATAL, "Possible causes: recursive EQUs, macro abuse."); - break; + terminate_after_phase = true; } } + mempool_free(mempool_pass); preproc->cleanup(0); lfmt->cleanup(); if (!terminate_after_phase && opt_verbose_info) { diff --git a/configure.ac b/configure.ac index e707158c..8cd3e902 100644 --- a/configure.ac +++ b/configure.ac @@ -147,6 +147,12 @@ PA_HAVE_FUNC(__builtin_clzll, (0ULL)) PA_HAVE_FUNC(_BitScanReverse, (0)) PA_HAVE_FUNC(_BitScanReverse64, (0)) +dnl alignment stuff +PA_ADD_HEADERS(stdalign.h) +PA_HAVE_FUNC(alignof,(0)) +PA_HAVE_FUNC(_Alignof,(0)) +AC_CHECK_TYPES(max_align_t) + dnl Functions for which we have replacements available in stdlib/ AC_CHECK_FUNCS([vsnprintf _vsnprintf]) AC_CHECK_FUNCS([snprintf _snprintf]) @@ -258,7 +264,8 @@ PA_ARG_ENABLED([sanitizer], [compile with sanitizers enabled], [PA_ADD_CFLAGS([-fno-omit-frame-pointer]) PA_ADD_CLDFLAGS([-fsanitize=address]) - PA_ADD_CLDFLAGS([-fsanitize=undefined])]) + PA_ADD_CLDFLAGS([-fsanitize=undefined]) + AC_DEFINE([WITH_SANITIZER], 1, [Define to 1 to enable sanitizer options])]) dnl dnl Don't make symbols visible, there is no point and it just diff --git a/include/compiler.h b/include/compiler.h index 4178c98e..66c3937f 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2007-2017 The NASM Authors - All Rights Reserved + * Copyright 2007-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -71,18 +71,18 @@ #define __STDC_LIMIT_MACROS 1 #define __STDC_FORMAT_MACROS 1 -#ifdef HAVE_INTTYPES_H -# include <inttypes.h> -#else -# include "nasmint.h" -#endif - #include <assert.h> #include <stddef.h> #include <stdarg.h> #include <stdio.h> #include <limits.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#else +# include "nasmint.h" +#endif + #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif @@ -186,6 +186,37 @@ typedef enum bool { false, true } bool; # define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m))) #endif +/* + * alignof(), and make a best guess at what the maximum alignment we + * may need might be + */ +#ifdef HAVE_STDALIGN_H +# include <stdalign.h> +#endif +#ifdef HAVE_MAX_ALIGN_T +typedef max_align_t nasm_max_align_t; +#else +typedef union { + void *p; + uint64_t i; +} nasm_max_align_t; +#endif +#if !defined(HAVE_ALIGNOF) && !defined(alignof) && defined(HAVE__ALIGNOF) +# define alignof(x) _Alignof(x) +# define HAVE_ALIGNOF 1 +#endif +#ifdef __BIGGEST_ALIGNMENT__ +# define MAX_ALIGNMENT __BIGGEST_ALIGNMENT__ +#elif defined(HAVE_ALIGNOF) +# define MAX_ALIGNMENT alignof(nasm_max_align_t) +#elif +# define MAX_ALIGNMENT sizeof(nasm_max_align_t) +#endif + +#ifndef HAVE_ALIGNOF +# define alignof(x) MAX_ALIGNMENT /* Safe but probably inefficient */ +#endif + /* Some misguided platforms hide the defs for these */ #if defined(HAVE_STRCASECMP) && !HAVE_DECL_STRCASECMP int strcasecmp(const char *, const char *); diff --git a/include/mempool.h b/include/mempool.h index 784d4b96..3e704819 100644 --- a/include/mempool.h +++ b/include/mempool.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2017 The NASM Authors - All Rights Reserved + * Copyright 2017-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -51,15 +51,36 @@ struct mempool { /* A single-member array which can decay to a pointer for simplicity */ typedef struct mempool mempool[1]; -char *mempool_add(struct mempool *pool, const char *str); -char *mempool_cat(struct mempool *pool, const char *str1, const char *str2); -char *mempool_cat3(struct mempool *pool, const char *str1, +char * safe_alloc mempool_cpy(struct mempool *pool, const char *str); +char * safe_alloc mempool_cat(struct mempool *pool, const char *str1, const char *str2); +char * safe_alloc mempool_cat3(struct mempool *pool, const char *str1, const char *str2, const char *str3); -char *mempool_vprintf(struct mempool *pool, const char *fmt, va_list va); -char *mempool_printf(struct mempool *pool, const char *fmt, ...); +char * safe_alloc mempool_vprintf(struct mempool *pool, const char *fmt, va_list va); +char * safe_alloc mempool_printf(struct mempool *pool, const char *fmt, ...); -void *mempool_alloc(struct mempool *pool, size_t bytes); +void * safe_malloc(2) mempool_alloc(struct mempool *pool, size_t bytes); +void * safe_malloc(2) mempool_align(struct mempool *pool, size_t bytes, size_t align); void mempool_free(struct mempool *pool); void mempool_reclaim(void); +#ifdef HAVE_ALIGNOF +#define mempool_new(pool,ptr) \ + ((ptr) = mempool_align(pool, sizeof *(ptr), alignof(*(ptr)))) +#else +#define mempool_new(pool,ptr) \ + ((ptr) = mempool_alloc(pool, sizeof *(ptr))) +#endif + +/* + * Common memory pools that are freed after every line, pass, or session, + * respectively. + */ +extern mempool mempool_perm; +extern mempool mempool_pass; +extern mempool mempool_line; + +/* Routines to copy strings into mempool_perm */ +char *perm_copy(const char *string); +char *perm_copy3(const char *s1, const char *s2, const char *s3); + #endif /* NASM_STRPOOL_H */ diff --git a/nasmlib/mempool.c b/nasmlib/mempool.c index 9d7ea7f3..40c2e694 100644 --- a/nasmlib/mempool.c +++ b/nasmlib/mempool.c @@ -52,37 +52,15 @@ #include "nasmlib.h" #include "ilog2.h" -#define MAX(x,y) ((x) > (y) ? (x) : (y)) -#define MIN(x,y) ((x) < (y) ? (x) : (y)) - -/* - * Make a best guess at what the maximum alignment we may need might be - */ -#ifdef HAVE_STDALIGN_H -# include <stdalign.h> -#endif -#if !defined(HAVE_ALIGNOF) && defined(HAVE__ALIGNOF) -# define HAVE_ALIGNOF 1 -# define alignof(x) _Alignof(x) -#endif -#ifdef __BIGGEST_ALIGNMENT__ /* gcc at least provides this */ -# define SYS_ALIGNMENT __BIGGEST_ALIGNMENT__ -#elif defined(HAVE_ALIGNOF) -# ifdef HAVE_MAX_ALIGN_T -# define SYS_ALIGNMENT alignof(max_align_t) -# else - /* Best guess for what we may actually need */ -# define SYS_ALIGNMENT MAX(alignof(void *), alignof(uint64_t)) -# endif -#else -# define SYS_ALIGNMENT sizeof(void *) +#ifdef WITH_SANITIZER +# undef DEBUG_MEMPOOL #endif -/* Always align to a multiple of uint64_t even if not required by the system */ -#define MY_ALIGNMENT MAX(SYS_ALIGNMENT, sizeof(uint64_t)) /* Chaotic good? */ +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#define ALLOC_ALIGN(x) (((size_t)(x) + MY_ALIGNMENT - 1) & \ - ~((size_t)MY_ALIGNMENT - 1)) +#define ALLOC_ALIGN(x) (((size_t)(x) + MAX_ALIGNMENT - 1) & \ + ~((size_t)MAX_ALIGNMENT - 1)) /* * Sizes of allocation blocks. We default to ALLOC_START, but allocate @@ -132,9 +110,9 @@ void mempool_free(struct mempool *sp) */ void mempool_reclaim(void) { - struct mempool_storage *s; + struct mempool_storage *s, *sn; - list_for_each(s, ssfree) + list_for_each_safe(s, sn, ssfree) nasm_free(s); ssfree = NULL; } @@ -142,14 +120,9 @@ void mempool_reclaim(void) static struct mempool_storage *mempool_more(struct mempool *sp, size_t l) { struct mempool_storage *sps, **ssp; - size_t n; - size_t nmin; - const size_t header = ALLOC_ALIGN(sizeof(struct mempool_storage)); + size_t n, nmin; - sps = sp->sstail; - ssp = sps ? &sps->next : &sp->sshead; - - l += header; + l += ALLOC_ALIGN(sizeof(struct mempool_storage)); nmin = ALLOC_ALIGN(MAX(l, ALLOC_MIN)); /* Is the top block on the free list which is big enough for us? */ @@ -159,7 +132,7 @@ static struct mempool_storage *mempool_more(struct mempool *sp, size_t l) goto have_sps; } - n = sps ? sp->totalbytes : ALLOC_START; + n = MAX(sp->totalbytes, ALLOC_START); n = MIN(n, ALLOC_MAX); n = MAX(n, nmin); n = ((size_t)2) << ilog2_64(n-1); /* Round up to a power of 2 */ @@ -181,44 +154,52 @@ static struct mempool_storage *mempool_more(struct mempool *sp, size_t l) sps->nbytes = nmin; have_sps: + ssp = sp->sstail ? &sps->next : &sp->sshead; *ssp = sp->sstail = sps; if (!sp->sshead) sp->sshead = sp->sstail; sps->next = NULL; - sps->idx = header; + sps->idx = sizeof *sps; sp->totalbytes += sps->nbytes; return sps; } -static inline void * -mempool_get_aligned(struct mempool *sp, size_t l, const size_t align) +void *mempool_align(struct mempool *sp, size_t l, const size_t align) { struct mempool_storage *sps; char *p; size_t idx; sps = sp->sstail; + if (unlikely(!sps)) + goto need_more; + idx = (sps->idx + align - 1) & ~(align - 1); - if (unlikely(l > sps->nbytes - idx)) { - sps = mempool_more(sp, l); - idx = sps->idx; - } + if (unlikely(l > sps->nbytes - idx)) + goto need_more; + +ok: p = (char *)sps + idx; sps->idx = idx+l; return p; + +need_more: + sps = mempool_more(sp, l); + idx = sps->idx; + goto ok; } static inline char *mempool_get(struct mempool *sp, size_t l) { - return mempool_get_aligned(sp, l, 1); + return mempool_align(sp, l, 1); } void *mempool_alloc(struct mempool *sp, size_t l) { - return mempool_get_aligned(sp, l, MY_ALIGNMENT); + return mempool_align(sp, l, MAX_ALIGNMENT); } -char *mempool_add(struct mempool *sp, const char *str) +char *mempool_cpy(struct mempool *sp, const char *str) { char *p; size_t l = strlen(str) + 1; @@ -307,3 +288,21 @@ char *mempool_printf(struct mempool *sp, const char *fmt, ...) return p; } + +/* + * Common memory pools that are freed after every line, pass, or session, + * respectively. + */ +mempool mempool_perm; +mempool mempool_pass; +mempool mempool_line; + +char *perm_copy(const char *string) +{ + return mempool_cpy(mempool_perm, string); +} + +char *perm_copy3(const char *s1, const char *s2, const char *s3) +{ + return mempool_cat3(mempool_perm, s1, s2, s3); +} |