mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-03-01 17:35:38 +08:00
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>
This commit is contained in:
parent
9d06db9dab
commit
36e2a0c887
13
asm/nasm.c
13
asm/nasm.c
@ -60,6 +60,7 @@
|
|||||||
#include "outform.h"
|
#include "outform.h"
|
||||||
#include "listing.h"
|
#include "listing.h"
|
||||||
#include "iflag.h"
|
#include "iflag.h"
|
||||||
|
#include "mempool.h"
|
||||||
#include "ver.h"
|
#include "ver.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -502,7 +503,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (!terminate_after_phase) {
|
if (!terminate_after_phase) {
|
||||||
ofmt->cleanup();
|
ofmt->cleanup();
|
||||||
cleanup_labels();
|
|
||||||
fflush(ofile);
|
fflush(ofile);
|
||||||
if (ferror(ofile)) {
|
if (ferror(ofile)) {
|
||||||
nasm_error(ERR_NONFATAL|ERR_NOFILE,
|
nasm_error(ERR_NONFATAL|ERR_NOFILE,
|
||||||
@ -525,11 +525,14 @@ int main(int argc, char **argv)
|
|||||||
if (want_usage)
|
if (want_usage)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
cleanup_labels();
|
||||||
raa_free(offsets);
|
raa_free(offsets);
|
||||||
saa_free(forwrefs);
|
saa_free(forwrefs);
|
||||||
eval_cleanup();
|
eval_cleanup();
|
||||||
stdscan_cleanup();
|
stdscan_cleanup();
|
||||||
src_free();
|
src_free();
|
||||||
|
mempool_free(mempool_perm);
|
||||||
|
mempool_reclaim();
|
||||||
|
|
||||||
return terminate_after_phase;
|
return terminate_after_phase;
|
||||||
}
|
}
|
||||||
@ -1540,6 +1543,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
|
|||||||
|
|
||||||
end_of_line:
|
end_of_line:
|
||||||
nasm_free(line);
|
nasm_free(line);
|
||||||
|
mempool_free(mempool_line);
|
||||||
} /* end while (line = preproc->getline... */
|
} /* end while (line = preproc->getline... */
|
||||||
|
|
||||||
if (pass0 == 2 && global_offset_changed && !terminate_after_phase)
|
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++;
|
stall_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mempool_free(mempool_pass);
|
||||||
if (terminate_after_phase)
|
if (terminate_after_phase)
|
||||||
break;
|
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
|
/* We get here if the labels don't converge
|
||||||
* Example: FOO equ FOO + 1
|
* 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);
|
"after %d passes, giving up.", passn);
|
||||||
nasm_error(ERR_NONFATAL,
|
nasm_error(ERR_NONFATAL,
|
||||||
"Possible causes: recursive EQUs, macro abuse.");
|
"Possible causes: recursive EQUs, macro abuse.");
|
||||||
break;
|
terminate_after_phase = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mempool_free(mempool_pass);
|
||||||
preproc->cleanup(0);
|
preproc->cleanup(0);
|
||||||
lfmt->cleanup();
|
lfmt->cleanup();
|
||||||
if (!terminate_after_phase && opt_verbose_info) {
|
if (!terminate_after_phase && opt_verbose_info) {
|
||||||
|
@ -147,6 +147,12 @@ PA_HAVE_FUNC(__builtin_clzll, (0ULL))
|
|||||||
PA_HAVE_FUNC(_BitScanReverse, (0))
|
PA_HAVE_FUNC(_BitScanReverse, (0))
|
||||||
PA_HAVE_FUNC(_BitScanReverse64, (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/
|
dnl Functions for which we have replacements available in stdlib/
|
||||||
AC_CHECK_FUNCS([vsnprintf _vsnprintf])
|
AC_CHECK_FUNCS([vsnprintf _vsnprintf])
|
||||||
AC_CHECK_FUNCS([snprintf _snprintf])
|
AC_CHECK_FUNCS([snprintf _snprintf])
|
||||||
@ -258,7 +264,8 @@ PA_ARG_ENABLED([sanitizer],
|
|||||||
[compile with sanitizers enabled],
|
[compile with sanitizers enabled],
|
||||||
[PA_ADD_CFLAGS([-fno-omit-frame-pointer])
|
[PA_ADD_CFLAGS([-fno-omit-frame-pointer])
|
||||||
PA_ADD_CLDFLAGS([-fsanitize=address])
|
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
|
||||||
dnl Don't make symbols visible, there is no point and it just
|
dnl Don't make symbols visible, there is no point and it just
|
||||||
|
@ -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
|
* See the file AUTHORS included with the NASM distribution for
|
||||||
* the specific copyright holders.
|
* the specific copyright holders.
|
||||||
*
|
*
|
||||||
@ -71,18 +71,18 @@
|
|||||||
#define __STDC_LIMIT_MACROS 1
|
#define __STDC_LIMIT_MACROS 1
|
||||||
#define __STDC_FORMAT_MACROS 1
|
#define __STDC_FORMAT_MACROS 1
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
# include <inttypes.h>
|
|
||||||
#else
|
|
||||||
# include "nasmint.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
# include <inttypes.h>
|
||||||
|
#else
|
||||||
|
# include "nasmint.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
@ -186,6 +186,37 @@ typedef enum bool { false, true } bool;
|
|||||||
# define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
|
# define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
|
||||||
#endif
|
#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 */
|
/* Some misguided platforms hide the defs for these */
|
||||||
#if defined(HAVE_STRCASECMP) && !HAVE_DECL_STRCASECMP
|
#if defined(HAVE_STRCASECMP) && !HAVE_DECL_STRCASECMP
|
||||||
int strcasecmp(const char *, const char *);
|
int strcasecmp(const char *, const char *);
|
||||||
|
@ -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
|
* See the file AUTHORS included with the NASM distribution for
|
||||||
* the specific copyright holders.
|
* the specific copyright holders.
|
||||||
*
|
*
|
||||||
@ -51,15 +51,36 @@ struct mempool {
|
|||||||
/* A single-member array which can decay to a pointer for simplicity */
|
/* A single-member array which can decay to a pointer for simplicity */
|
||||||
typedef struct mempool mempool[1];
|
typedef struct mempool mempool[1];
|
||||||
|
|
||||||
char *mempool_add(struct mempool *pool, const char *str);
|
char * safe_alloc mempool_cpy(struct mempool *pool, const char *str);
|
||||||
char *mempool_cat(struct mempool *pool, const char *str1, const char *str2);
|
char * safe_alloc mempool_cat(struct mempool *pool, const char *str1, const char *str2);
|
||||||
char *mempool_cat3(struct mempool *pool, const char *str1,
|
char * safe_alloc mempool_cat3(struct mempool *pool, const char *str1,
|
||||||
const char *str2, const char *str3);
|
const char *str2, const char *str3);
|
||||||
char *mempool_vprintf(struct mempool *pool, const char *fmt, va_list va);
|
char * safe_alloc mempool_vprintf(struct mempool *pool, const char *fmt, va_list va);
|
||||||
char *mempool_printf(struct mempool *pool, const char *fmt, ...);
|
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_free(struct mempool *pool);
|
||||||
void mempool_reclaim(void);
|
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 */
|
#endif /* NASM_STRPOOL_H */
|
||||||
|
@ -52,37 +52,15 @@
|
|||||||
#include "nasmlib.h"
|
#include "nasmlib.h"
|
||||||
#include "ilog2.h"
|
#include "ilog2.h"
|
||||||
|
|
||||||
|
#ifdef WITH_SANITIZER
|
||||||
|
# undef DEBUG_MEMPOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
/*
|
#define ALLOC_ALIGN(x) (((size_t)(x) + MAX_ALIGNMENT - 1) & \
|
||||||
* Make a best guess at what the maximum alignment we may need might be
|
~((size_t)MAX_ALIGNMENT - 1))
|
||||||
*/
|
|
||||||
#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 *)
|
|
||||||
#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 ALLOC_ALIGN(x) (((size_t)(x) + MY_ALIGNMENT - 1) & \
|
|
||||||
~((size_t)MY_ALIGNMENT - 1))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sizes of allocation blocks. We default to ALLOC_START, but allocate
|
* 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)
|
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);
|
nasm_free(s);
|
||||||
ssfree = NULL;
|
ssfree = NULL;
|
||||||
}
|
}
|
||||||
@ -142,14 +120,9 @@ void mempool_reclaim(void)
|
|||||||
static struct mempool_storage *mempool_more(struct mempool *sp, size_t l)
|
static struct mempool_storage *mempool_more(struct mempool *sp, size_t l)
|
||||||
{
|
{
|
||||||
struct mempool_storage *sps, **ssp;
|
struct mempool_storage *sps, **ssp;
|
||||||
size_t n;
|
size_t n, nmin;
|
||||||
size_t nmin;
|
|
||||||
const size_t header = ALLOC_ALIGN(sizeof(struct mempool_storage));
|
|
||||||
|
|
||||||
sps = sp->sstail;
|
l += ALLOC_ALIGN(sizeof(struct mempool_storage));
|
||||||
ssp = sps ? &sps->next : &sp->sshead;
|
|
||||||
|
|
||||||
l += header;
|
|
||||||
nmin = ALLOC_ALIGN(MAX(l, ALLOC_MIN));
|
nmin = ALLOC_ALIGN(MAX(l, ALLOC_MIN));
|
||||||
|
|
||||||
/* Is the top block on the free list which is big enough for us? */
|
/* 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;
|
goto have_sps;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = sps ? sp->totalbytes : ALLOC_START;
|
n = MAX(sp->totalbytes, ALLOC_START);
|
||||||
n = MIN(n, ALLOC_MAX);
|
n = MIN(n, ALLOC_MAX);
|
||||||
n = MAX(n, nmin);
|
n = MAX(n, nmin);
|
||||||
n = ((size_t)2) << ilog2_64(n-1); /* Round up to a power of 2 */
|
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;
|
sps->nbytes = nmin;
|
||||||
|
|
||||||
have_sps:
|
have_sps:
|
||||||
|
ssp = sp->sstail ? &sps->next : &sp->sshead;
|
||||||
*ssp = sp->sstail = sps;
|
*ssp = sp->sstail = sps;
|
||||||
if (!sp->sshead)
|
if (!sp->sshead)
|
||||||
sp->sshead = sp->sstail;
|
sp->sshead = sp->sstail;
|
||||||
sps->next = NULL;
|
sps->next = NULL;
|
||||||
sps->idx = header;
|
sps->idx = sizeof *sps;
|
||||||
sp->totalbytes += sps->nbytes;
|
sp->totalbytes += sps->nbytes;
|
||||||
return sps;
|
return sps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
void *mempool_align(struct mempool *sp, size_t l, const size_t align)
|
||||||
mempool_get_aligned(struct mempool *sp, size_t l, const size_t align)
|
|
||||||
{
|
{
|
||||||
struct mempool_storage *sps;
|
struct mempool_storage *sps;
|
||||||
char *p;
|
char *p;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
|
|
||||||
sps = sp->sstail;
|
sps = sp->sstail;
|
||||||
|
if (unlikely(!sps))
|
||||||
|
goto need_more;
|
||||||
|
|
||||||
idx = (sps->idx + align - 1) & ~(align - 1);
|
idx = (sps->idx + align - 1) & ~(align - 1);
|
||||||
if (unlikely(l > sps->nbytes - idx)) {
|
if (unlikely(l > sps->nbytes - idx))
|
||||||
sps = mempool_more(sp, l);
|
goto need_more;
|
||||||
idx = sps->idx;
|
|
||||||
}
|
ok:
|
||||||
p = (char *)sps + idx;
|
p = (char *)sps + idx;
|
||||||
sps->idx = idx+l;
|
sps->idx = idx+l;
|
||||||
return p;
|
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)
|
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)
|
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;
|
char *p;
|
||||||
size_t l = strlen(str) + 1;
|
size_t l = strlen(str) + 1;
|
||||||
@ -307,3 +288,21 @@ char *mempool_printf(struct mempool *sp, const char *fmt, ...)
|
|||||||
|
|
||||||
return p;
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user