From 836b90884f9abff3a82b2cee8bada16b23f7ddf7 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Mar 2018 17:21:04 +0100 Subject: erts: Make sys_memcpy and friends inline functions to avoid argument-evaluated-twice bugs like in macro DMC_PUSH. Had to shuffle around some #include and #define to make erl_child_setup build debug target. --- erts/emulator/beam/hash.c | 4 +- erts/emulator/beam/sys.h | 88 ++++++++++++++++++++++++-------- erts/emulator/sys/unix/erl_child_setup.c | 2 + erts/emulator/sys/unix/sys_drivers.c | 3 ++ erts/emulator/sys/unix/sys_uds.c | 36 +++++++++++++ erts/emulator/sys/unix/sys_uds.h | 14 ----- 6 files changed, 110 insertions(+), 37 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c index 8548e30e8b..6a31489473 100644 --- a/erts/emulator/beam/hash.c +++ b/erts/emulator/beam/hash.c @@ -152,7 +152,7 @@ Hash* hash_init(int type, Hash* h, char* name, int size, HashFunctions fun) h->bucket = (HashBucket**) fun.meta_alloc(h->meta_alloc_type, sz); - sys_memzero(h->bucket, sz); + memzero(h->bucket, sz); h->is_allocated = 0; h->name = name; h->fun = fun; @@ -224,7 +224,7 @@ static void rehash(Hash* h, int grow) sz = h->size*sizeof(HashBucket*); new_bucket = (HashBucket **) h->fun.meta_alloc(h->meta_alloc_type, sz); - sys_memzero(new_bucket, sz); + memzero(new_bucket, sz); for (i = 0; i < old_size; i++) { HashBucket* b = h->bucket[i]; diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 13ae80e4a5..152da8c9e1 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -994,7 +994,8 @@ erts_refc_read(erts_refc_t *refcp, erts_aint_t min_val) return val; } -#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ +#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ + /* Thin wrappers around memcpy and friends, which should always be used in * place of plain memcpy, memset, etc. @@ -1006,26 +1007,71 @@ erts_refc_read(erts_refc_t *refcp, erts_aint_t min_val) * * (The weird casts in the assertions silence an "always evaluates to true" * warning when an operand is the address of an lvalue) */ -#define sys_memcpy(s1,s2,n) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), memcpy(s1,s2,n)) -#define sys_memmove(s1,s2,n) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), memmove(s1,s2,n)) -#define sys_memcmp(s1,s2,n) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), memcmp(s1,s2,n)) -#define sys_memset(s,c,n) \ - (ASSERT((void*)(s) != NULL), memset(s,c,n)) -#define sys_memzero(s, n) \ - (ASSERT((void*)(s) != NULL), memset(s,'\0',n)) -#define sys_strcmp(s1,s2) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), strcmp(s1,s2)) -#define sys_strncmp(s1,s2,n) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), strncmp(s1,s2,n)) -#define sys_strcpy(s1,s2) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), strcpy(s1,s2)) -#define sys_strncpy(s1,s2,n) \ - (ASSERT((void*)(s1) != NULL && (void*)(s2) != NULL), strncpy(s1,s2,n)) -#define sys_strlen(s) \ - (ASSERT((void*)(s) != NULL), strlen(s)) +ERTS_GLB_INLINE void *sys_memcpy(void *dest, const void *src, size_t n); +ERTS_GLB_INLINE void *sys_memmove(void *dest, const void *src, size_t n); +ERTS_GLB_INLINE int sys_memcmp(const void *s1, const void *s2, size_t n); +ERTS_GLB_INLINE void *sys_memset(void *s, int c, size_t n); +ERTS_GLB_INLINE void *sys_memzero(void *s, size_t n); +ERTS_GLB_INLINE int sys_strcmp(const char *s1, const char *s2); +ERTS_GLB_INLINE int sys_strncmp(const char *s1, const char *s2, size_t n); +ERTS_GLB_INLINE char *sys_strcpy(char *dest, const char *src); +ERTS_GLB_INLINE char *sys_strncpy(char *dest, const char *src, size_t n); +ERTS_GLB_INLINE size_t sys_strlen(const char *s); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE void *sys_memcpy(void *dest, const void *src, size_t n) +{ + ASSERT(dest != NULL && src != NULL); + return memcpy(dest,src,n); +} +ERTS_GLB_INLINE void *sys_memmove(void *dest, const void *src, size_t n) +{ + ASSERT(dest != NULL && src != NULL); + return memmove(dest,src,n); +} +ERTS_GLB_INLINE int sys_memcmp(const void *s1, const void *s2, size_t n) +{ + ASSERT(s1 != NULL && s2 != NULL); + return memcmp(s1,s2,n); +} +ERTS_GLB_INLINE void *sys_memset(void *s, int c, size_t n) +{ + ASSERT(s != NULL); + return memset(s,c,n); +} +ERTS_GLB_INLINE void *sys_memzero(void *s, size_t n) +{ + ASSERT(s != NULL); + return memset(s,'\0',n); +} +ERTS_GLB_INLINE int sys_strcmp(const char *s1, const char *s2) +{ + ASSERT(s1 != NULL && s2 != NULL); + return strcmp(s1,s2); +} +ERTS_GLB_INLINE int sys_strncmp(const char *s1, const char *s2, size_t n) +{ + ASSERT(s1 != NULL && s2 != NULL); + return strncmp(s1,s2,n); +} +ERTS_GLB_INLINE char *sys_strcpy(char *dest, const char *src) +{ + ASSERT(dest != NULL && src != NULL); + return strcpy(dest,src); + +} +ERTS_GLB_INLINE char *sys_strncpy(char *dest, const char *src, size_t n) +{ + ASSERT(dest != NULL && src != NULL); + return strncpy(dest,src,n); +} +ERTS_GLB_INLINE size_t sys_strlen(const char *s) +{ + ASSERT(s != NULL); + return strlen(s); +} +#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ /* define function symbols (needed in sys_drv_api) */ #define sys_fp_alloc sys_alloc diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c index 57973b10d7..10601529a4 100644 --- a/erts/emulator/sys/unix/erl_child_setup.c +++ b/erts/emulator/sys/unix/erl_child_setup.c @@ -56,6 +56,8 @@ #include #include #include +#include +#include #define WANT_NONBLOCKING diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c index b7ac89d89a..117855acf0 100644 --- a/erts/emulator/sys/unix/sys_drivers.c +++ b/erts/emulator/sys/unix/sys_drivers.c @@ -50,6 +50,9 @@ #include #endif +#include +#include + #define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */ #include "sys.h" diff --git a/erts/emulator/sys/unix/sys_uds.c b/erts/emulator/sys/unix/sys_uds.c index dd0a3b03ff..278c6b6ba1 100644 --- a/erts/emulator/sys/unix/sys_uds.c +++ b/erts/emulator/sys/unix/sys_uds.c @@ -18,6 +18,42 @@ * %CopyrightEnd% */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(__sun__) && !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 500 +#endif + +#include + +#include +#include + +#ifdef HAVE_SYS_SOCKETIO_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif + +#ifdef HAVE_NET_ERRNO_H +#include +#endif + +#ifdef HAVE_DIRENT_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + #include "sys_uds.h" int diff --git a/erts/emulator/sys/unix/sys_uds.h b/erts/emulator/sys/unix/sys_uds.h index a598102d5c..26c91d6a00 100644 --- a/erts/emulator/sys/unix/sys_uds.h +++ b/erts/emulator/sys/unix/sys_uds.h @@ -21,18 +21,6 @@ #ifndef _ERL_UNIX_UDS_H #define _ERL_UNIX_UDS_H -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#if defined(__sun__) && !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 500 -#endif - -#include - -#include -#include #include #if defined IOV_MAX @@ -43,8 +31,6 @@ #define MAXIOV 16 #endif -#include "sys.h" - int sys_uds_readv(int fd, struct iovec *iov, size_t iov_len, int *fds, int fd_count, int flags); int sys_uds_read(int fd, char *buff, size_t len, -- cgit v1.2.3 From 2bdd0ba8f6046301778ea3673716d8df9fdd42fa Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Mar 2018 20:10:39 +0100 Subject: erts: Optimize macro DMC_PUSH to call a common static function dmc_stack_grow() and reduce the code bloat. and did a combined DMC_PUSH2 --- erts/emulator/beam/erl_db_util.c | 102 ++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 49 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 956662aefa..f21db4b65b 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -74,12 +74,35 @@ DBIF_TABLE_GUARD | DBIF_TABLE_BODY | DBIF_TRACE_GUARD | DBIF_TRACE_BODY typedef struct DMC_STACK_TYPE(Type) { \ int pos; \ int siz; \ - Type def[DMC_DEFAULT_SIZE]; \ + int bytes; \ Type *data; \ + Type def[DMC_DEFAULT_SIZE]; \ } DMC_STACK_TYPE(Type) + + +typedef int Dummy; +DMC_DECLARE_STACK_TYPE(Dummy); + +static void dmc_stack_grow(DMC_Dummy_stack* s) +{ + int was_bytes = s->bytes; + s->siz *= 2; + s->bytes *= 2; + if (s->data == s->def) { + s->data = erts_alloc(ERTS_ALC_T_DB_MC_STK, s->bytes); + sys_memcpy(s->data, s->def, was_bytes); + } + else { + s->data = erts_realloc(ERTS_ALC_T_DB_MC_STK, s->data, s->bytes); + } +} -#define DMC_INIT_STACK(Name) \ - (Name).pos = 0; (Name).siz = DMC_DEFAULT_SIZE; (Name).data = (Name).def +#define DMC_INIT_STACK(Name) do { \ + (Name).pos = 0; \ + (Name).siz = DMC_DEFAULT_SIZE; \ + (Name).bytes = sizeof((Name).def); \ + (Name).data = (Name).def; \ +} while (0) #define DMC_STACK_DATA(Name) (Name).data @@ -87,21 +110,19 @@ typedef struct DMC_STACK_TYPE(Type) { \ #define DMC_PUSH(On, What) \ do { \ - if ((On).pos >= (On).siz) { \ - (On).siz *= 2; \ - (On).data \ - = (((On).def == (On).data) \ - ? sys_memcpy(erts_alloc(ERTS_ALC_T_DB_MC_STK, \ - (On).siz*sizeof(*((On).data))), \ - (On).def, \ - DMC_DEFAULT_SIZE*sizeof(*((On).data))) \ - : erts_realloc(ERTS_ALC_T_DB_MC_STK, \ - (void *) (On).data, \ - (On).siz*sizeof(*((On).data)))); \ - } \ + if ((On).pos >= (On).siz) \ + dmc_stack_grow((DMC_Dummy_stack*)&(On)); \ (On).data[(On).pos++] = What; \ } while (0) +#define DMC_PUSH2(On, A, B) \ +do { \ + if ((On).pos+1 >= (On).siz) \ + dmc_stack_grow((DMC_Dummy_stack*)&(On)); \ + (On).data[(On).pos++] = A; \ + (On).data[(On).pos++] = B; \ +} while (0) + #define DMC_POP(From) (From).data[--(From).pos] #define DMC_TOP(From) (From).data[(From).pos - 1] @@ -1537,8 +1558,7 @@ restart: if (is_flatmap(t)) { num_iters = flatmap_get_size(flatmap_val(t)); if (!structure_checked) { - DMC_PUSH(text, matchMap); - DMC_PUSH(text, num_iters); + DMC_PUSH2(text, matchMap, num_iters); } structure_checked = 0; for (i = 0; i < num_iters; ++i) { @@ -1558,8 +1578,7 @@ restart: } goto error; } - DMC_PUSH(text, matchKey); - DMC_PUSH(text, dmc_private_copy(&context, key)); + DMC_PUSH2(text, matchKey, dmc_private_copy(&context, key)); { int old_stack = ++(context.stack_used); Eterm value = flatmap_get_values(flatmap_val(t))[i]; @@ -1587,8 +1606,7 @@ restart: Eterm *kv; num_iters = hashmap_size(t); if (!structure_checked) { - DMC_PUSH(text, matchMap); - DMC_PUSH(text, num_iters); + DMC_PUSH2(text, matchMap, num_iters); } structure_checked = 0; @@ -1614,8 +1632,7 @@ restart: DESTROY_WSTACK(wstack); goto error; } - DMC_PUSH(text, matchKey); - DMC_PUSH(text, dmc_private_copy(&context, key)); + DMC_PUSH2(text, matchKey, dmc_private_copy(&context, key)); { int old_stack = ++(context.stack_used); res = dmc_one_term(&context, &heap, &stack, &text, @@ -1645,8 +1662,7 @@ restart: num_iters = arityval(*tuple_val(t)); if (!structure_checked) { /* i.e. we did not pop it */ - DMC_PUSH(text,matchTuple); - DMC_PUSH(text,num_iters); + DMC_PUSH2(text, matchTuple, num_iters); } structure_checked = 0; for (i = 1; i <= num_iters; ++i) { @@ -3535,20 +3551,17 @@ static DMCRet dmc_one_term(DMCContext *context, return retRestart; } if (heap->vars[n].is_bound) { - DMC_PUSH(*text,matchCmp); - DMC_PUSH(*text,n); + DMC_PUSH2(*text, matchCmp, n); } else { /* Not bound, bind! */ if (n >= heap->vars_used) heap->vars_used = n + 1; - DMC_PUSH(*text,matchBind); - DMC_PUSH(*text,n); + DMC_PUSH2(*text, matchBind, n); heap->vars[n].is_bound = 1; } } else if (c == am_Underscore) { DMC_PUSH(*text, matchSkip); } else { /* Any immediate value */ - DMC_PUSH(*text, matchEq); - DMC_PUSH(*text, (Uint) c); + DMC_PUSH2(*text, matchEq, (Uint) c); } break; case TAG_PRIMARY_LIST: @@ -3561,9 +3574,8 @@ static DMCRet dmc_one_term(DMCContext *context, switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_ARITYVAL >> _TAG_PRIMARY_SIZE): n = arityval(*tuple_val(c)); - DMC_PUSH(*text, matchPushT); + DMC_PUSH2(*text, matchPushT, n); ++(context->stack_used); - DMC_PUSH(*text, n); DMC_PUSH(*stack, c); break; case (_TAG_HEADER_MAP >> _TAG_PRIMARY_SIZE): @@ -3571,9 +3583,8 @@ static DMCRet dmc_one_term(DMCContext *context, n = flatmap_get_size(flatmap_val(c)); else n = hashmap_size(c); - DMC_PUSH(*text, matchPushM); + DMC_PUSH2(*text, matchPushM, n); ++(context->stack_used); - DMC_PUSH(*text, n); DMC_PUSH(*stack, c); break; case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE): @@ -3598,8 +3609,7 @@ static DMCRet dmc_one_term(DMCContext *context, break; } case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): - DMC_PUSH(*text,matchEqFloat); - DMC_PUSH(*text, (Uint) float_val(c)[1]); + DMC_PUSH2(*text, matchEqFloat, (Uint) float_val(c)[1]); #ifdef ARCH_64 DMC_PUSH(*text, (Uint) 0); #else @@ -3607,8 +3617,7 @@ static DMCRet dmc_one_term(DMCContext *context, #endif break; default: /* BINARY, FUN, VECTOR, or EXTERNAL */ - DMC_PUSH(*text, matchEqBin); - DMC_PUSH(*text, dmc_private_copy(context, c)); + DMC_PUSH2(*text, matchEqBin, dmc_private_copy(context, c)); break; } break; @@ -3658,8 +3667,7 @@ static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text, emb->next = context->save; context->save = emb; } - DMC_PUSH(*text,matchPushC); - DMC_PUSH(*text,(Uint) tmp); + DMC_PUSH2(*text, matchPushC, (Uint)tmp); if (++context->stack_used > context->stack_need) context->stack_need = context->stack_used; } @@ -3797,8 +3805,7 @@ dmc_tuple(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(UWord) *text, *constant = 1; return retOk; } - DMC_PUSH(*text, matchMkTuple); - DMC_PUSH(*text, nelems); + DMC_PUSH2(*text, matchMkTuple, nelems); context->stack_used -= (nelems - 1); *constant = 0; return retOk; @@ -3825,13 +3832,11 @@ dmc_map(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(UWord) *text, *constant = 1; return retOk; } - DMC_PUSH(*text, matchPushC); - DMC_PUSH(*text, dmc_private_copy(context, m->keys)); + DMC_PUSH2(*text, matchPushC, dmc_private_copy(context, m->keys)); if (++context->stack_used > context->stack_need) { context->stack_need = context->stack_used; } - DMC_PUSH(*text, matchMkFlatMap); - DMC_PUSH(*text, nelems); + DMC_PUSH2(*text, matchMkFlatMap, nelems); context->stack_used -= nelems; *constant = 0; return retOk; @@ -3883,8 +3888,7 @@ dmc_map(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(UWord) *text, do_emit_constant(context, text, CDR(kv)); } } - DMC_PUSH(*text, matchMkHashMap); - DMC_PUSH(*text, nelems); + DMC_PUSH2(*text, matchMkHashMap, nelems); context->stack_used -= nelems; DESTROY_WSTACK(wstack); return retOk; -- cgit v1.2.3