[Nasm-commits] [nasm:mempool] mempool: define standard mempools, fixes to the mempool allocator

nasm-bot for H. Peter Anvin hpa at zytor.com
Thu Jun 4 19:56:40 PDT 2020


Commit-ID:  36e2a0c88741b67edaea35dd059475f9d12ceefb
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=36e2a0c88741b67edaea35dd059475f9d12ceefb
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Sun, 3 Jun 2018 02:47:06 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Sun, 3 Jun 2018 02:47:06 -0700

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 at zytor.com>


---
 asm/nasm.c         | 13 ++++++--
 configure.ac       |  9 +++++-
 include/compiler.h | 45 ++++++++++++++++++++++----
 include/mempool.h  | 35 ++++++++++++++++----
 nasmlib/mempool.c  | 95 +++++++++++++++++++++++++++---------------------------
 5 files changed, 131 insertions(+), 66 deletions(-)

diff --git a/asm/nasm.c b/asm/nasm.c
index a5b8f763..f54ba55d 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -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);
+}


More information about the Nasm-commits mailing list