aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2014-01-16 11:10:34 +0100
committerSverker Eriksson <[email protected]>2014-01-17 11:26:35 +0100
commit172ebf11dc455e22b87f742c06fa6344995d7db5 (patch)
tree641ece876e1fdce4286ce2c8983756be97ab0b97 /erts/emulator/beam
parent03493394e8d20591020ce6c8152cb607cb21e967 (diff)
downloadotp-172ebf11dc455e22b87f742c06fa6344995d7db5.tar.gz
otp-172ebf11dc455e22b87f742c06fa6344995d7db5.tar.bz2
otp-172ebf11dc455e22b87f742c06fa6344995d7db5.zip
erts: Refactor ESTACK & WSTACK to use a struct easy to "export"
This is not a clean refactor. It changes the behaviour slightly of E/WSTACK_RESTORE. The allocated stack from E/WSTACK_SAVE is used as-is and not copied into default_stack. This will hopefully fix an illusive memory leak that valgrind is reporting.
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/external.c42
-rwxr-xr-xerts/emulator/beam/global.h346
-rw-r--r--erts/emulator/beam/utils.c44
3 files changed, 211 insertions, 221 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 50831e848e..94acceaaf1 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1732,8 +1732,7 @@ typedef struct TTBSizeContext_ {
int level;
Uint result;
Eterm obj;
- UWord* stack;
- Uint stack_sz;
+ ErtsEStack estack;
} TTBSizeContext;
typedef struct TTBEncodeContext_ {
@@ -1741,8 +1740,7 @@ typedef struct TTBEncodeContext_ {
int level;
byte* ep;
Eterm obj;
- UWord* stack;
- Uint stack_sz;
+ ErtsWStack wstack;
Binary *result_bin;
} TTBEncodeContext;
@@ -1772,16 +1770,10 @@ static void ttb_context_destructor(Binary *context_bin)
context->alive = 0;
switch (context->state) {
case TTBSize:
- if (context->s.sc.stack) {
- erts_free(ERTS_ALC_T_SAVED_ESTACK, context->s.sc.stack);
- context->s.sc.stack = NULL;
- }
+ DESTROY_SAVED_ESTACK(&context->s.sc.estack);
break;
case TTBEncode:
- if (context->s.ec.stack) {
- erts_free(ERTS_ALC_T_SAVED_ESTACK, context->s.ec.stack);
- context->s.ec.stack = NULL;
- }
+ DESTROY_SAVED_WSTACK(&context->s.ec.wstack);
if (context->s.ec.result_bin != NULL) { /* Set to NULL if ever made alive! */
ASSERT(erts_refc_read(&(context->s.ec.result_bin->refc),0) == 0);
erts_bin_free(context->s.ec.result_bin);
@@ -1846,7 +1838,7 @@ static Eterm erts_term_to_binary_int(Process* p, Eterm Term, int level, Uint fla
/* Setup enough to get started */
context->state = TTBSize;
context->alive = 1;
- context->s.sc.stack = NULL;
+ context->s.sc.estack.start = NULL;
context->s.sc.flags = flags;
context->s.sc.level = level;
} else {
@@ -1889,7 +1881,7 @@ static Eterm erts_term_to_binary_int(Process* p, Eterm Term, int level, Uint fla
context->state = TTBEncode;
context->s.ec.flags = flags;
context->s.ec.level = level;
- context->s.ec.stack = NULL;
+ context->s.ec.wstack.wstart = NULL;
context->s.ec.result_bin = result_bin;
break;
}
@@ -2340,8 +2332,8 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
WSTACK_CHANGE_ALLOCATOR(s, ERTS_ALC_T_SAVED_ESTACK);
r = *reds;
- if (ctx->stack) { /* restore saved stacks and byte pointer */
- WSTACK_RESTORE(s, ctx->stack, ctx->stack_sz);
+ if (ctx->wstack.wstart) { /* restore saved stacks and byte pointer */
+ WSTACK_RESTORE(s, &ctx->wstack);
ep = ctx->ep;
obj = ctx->obj;
}
@@ -2412,7 +2404,7 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
*reds = r;
ctx->obj = obj;
ctx->ep = ep;
- WSTACK_SAVE(s, ctx->stack, ctx->stack_sz);
+ WSTACK_SAVE(s, &ctx->wstack);
return -1;
}
switch(tag_val_def(obj)) {
@@ -2767,10 +2759,7 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
}
DESTROY_WSTACK(s);
if (ctx) {
- if (ctx->stack) {
- erts_free(ERTS_ALC_T_SAVED_ESTACK, ctx->stack);
- ctx->stack = NULL;
- }
+ ASSERT(ctx->wstack.wstart == NULL);
*reds = r;
}
*res = ep;
@@ -3752,8 +3741,8 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
ESTACK_CHANGE_ALLOCATOR(s, ERTS_ALC_T_SAVED_ESTACK);
r = *reds;
- if (ctx->stack) { /* restore saved stack */
- ESTACK_RESTORE(s, ctx->stack, ctx->stack_sz);
+ if (ctx->estack.start) { /* restore saved stack */
+ ESTACK_RESTORE(s, &ctx->estack);
result = ctx->result;
obj = ctx->obj;
}
@@ -3787,7 +3776,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
*reds = r;
ctx->obj = obj;
ctx->result = result;
- ESTACK_SAVE(s, ctx->stack, ctx->stack_sz);
+ ESTACK_SAVE(s, &ctx->estack);
return -1;
}
switch (tag_val_def(obj)) {
@@ -3991,10 +3980,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
DESTROY_ESTACK(s);
if (ctx) {
- if (ctx->stack) {
- erts_free(ERTS_ALC_T_SAVED_ESTACK, ctx->stack);
- ctx->stack = NULL;
- }
+ ASSERT(ctx->estack.start == NULL);
*reds = r;
}
*res = result;
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 94bc1b172a..c44f532366 100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2014. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -370,231 +370,233 @@ extern int stackdump_on_exit;
* DESTROY_ESTACK(Stack)
*/
+typedef struct {
+ UWord* start;
+ UWord* sp;
+ UWord* end;
+ ErtsAlcType_t alloc_type;
+}ErtsEStack;
-void erl_grow_stack(ErtsAlcType_t a_type, Eterm** start, Eterm** sp, Eterm** end);
-#define ESTK_CONCAT(a,b) a##b
-#define ESTK_SUBSCRIPT(s,i) *((Eterm *)((byte *)ESTK_CONCAT(s,_start) + (i)))
#define DEF_ESTACK_SIZE (16)
-#define DECLARE_ESTACK(s) \
- Eterm ESTK_CONCAT(s,_default_stack)[DEF_ESTACK_SIZE]; \
- Eterm* ESTK_CONCAT(s,_start) = ESTK_CONCAT(s,_default_stack); \
- Eterm* ESTK_CONCAT(s,_sp) = ESTK_CONCAT(s,_start); \
- Eterm* ESTK_CONCAT(s,_end) = ESTK_CONCAT(s,_start) + DEF_ESTACK_SIZE;\
- ErtsAlcType_t ESTK_CONCAT(s,_alloc_type) = ERTS_ALC_T_ESTACK
+void erl_grow_estack(ErtsEStack*, Eterm* def_stack);
+#define ESTK_CONCAT(a,b) a##b
+#define ESTK_DEF_STACK(s) ESTK_CONCAT(s,_default_estack)
+
+#define DECLARE_ESTACK(s) \
+ UWord ESTK_DEF_STACK(s)[DEF_ESTACK_SIZE]; \
+ ErtsEStack s = { \
+ ESTK_DEF_STACK(s), /* start */ \
+ ESTK_DEF_STACK(s), /* sp */ \
+ ESTK_DEF_STACK(s) + DEF_ESTACK_SIZE, /* end */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
#define ESTACK_CHANGE_ALLOCATOR(s,t) \
do { \
- if (ESTK_CONCAT(s,_start) != ESTK_CONCAT(s,_default_stack)) { \
+ if (s.start != ESTK_DEF_STACK(s)) { \
erl_exit(1, "Internal error - trying to change allocator " \
"type of active estack\n"); \
} \
- ESTK_CONCAT(s,_alloc_type) = (t); \
+ s.alloc_type = (t); \
} while (0)
+#define DESTROY_ESTACK(s) \
+do { \
+ if (s.start != ESTK_DEF_STACK(s)) { \
+ erts_free(s.alloc_type, s.start); \
+ } \
+} while(0)
+
+
/*
- * Do not free the stack after this, it may have pointers into what
- * was saved in 'v'. 'v' and 'vsize' are changed by this macro. If
- * 'v' points to anything, it should have been allocated by a previous
- * call to this macro. Be careful to set a correct allocator prior to
- * saving.
- * 'v' can be any lvalue pointer, it will point to an array of UWord
- * after calling this macro.
+ * Do not free the stack after this, it may have pointers into what
+ * was saved in 'dst'.
*/
-#define ESTACK_SAVE(s,v,vsize) /* v and vsize are "name parameters" */ \
-do { \
- Uint _esz = ESTACK_COUNT(s); \
- if (ESTK_CONCAT(s,_start) == ESTK_CONCAT(s,_default_stack)) { \
- if ((v) == NULL) { \
- (v) = erts_alloc(ESTK_CONCAT(s,_alloc_type), \
- DEF_ESTACK_SIZE * sizeof(Eterm)); \
- } \
- memcpy((v),ESTK_CONCAT(s,_start),_esz*sizeof(Eterm)); \
- } else { \
- (v) = (void *) ESTK_CONCAT(s,_start); \
- } \
- (vsize) = _esz; \
+#define ESTACK_SAVE(s,dst)\
+do {\
+ if (s.start == ESTK_DEF_STACK(s)) {\
+ UWord _wsz = ESTACK_COUNT(s);\
+ (dst)->start = erts_alloc(s.alloc_type,\
+ DEF_ESTACK_SIZE * sizeof(UWord));\
+ memcpy((dst)->start, s.start,_wsz*sizeof(UWord));\
+ (dst)->sp = (dst)->start + _wsz;\
+ (dst)->end = (dst)->start + DEF_ESTACK_SIZE;\
+ (dst)->alloc_type = s.alloc_type;\
+ } else\
+ *(dst) = s;\
} while (0)
-/*
- * Use on empty stack, only the allocator can be changed before this
- * The vector parameter is reset to NULL if the vector is moved to stack,
- * otherwise it's kept for reuse, so a saved and restored vector might
- * need freeing using the correct allocator parameter.
- * 'v' can be any lvalue pointer, it's cast to an (Eterm *).
+#define DESTROY_SAVED_ESTACK(estack)\
+do {\
+ if ((estack)->start) {\
+ erts_free((estack)->alloc_type, (estack)->start);\
+ (estack)->start = NULL;\
+ }\
+} while(0)
+
+/*
+ * Use on empty stack, only the allocator can be changed before this.
+ * The src stack is reset to NULL.
*/
-#define ESTACK_RESTORE(s, v, vsize) /*v is a "name parameter"*/ \
-do { \
- if ((vsize) > DEF_ESTACK_SIZE) { \
- Uint _ca = DEF_ESTACK_SIZE; \
- while (_ca < (vsize)) \
- _ca = _ca * 2; \
- ESTK_CONCAT(s,_start) = (Eterm *) (v); \
- ESTK_CONCAT(s,_end) = ((Eterm *)(v)) + _ca; \
- ESTK_CONCAT(s,_sp) = ESTK_CONCAT(s,_start) + (vsize); \
- (v) = NULL; \
- } else { \
- memcpy(ESTK_CONCAT(s,_start),(v),(vsize)*sizeof(Eterm));\
- ESTK_CONCAT(s,_sp) = ESTK_CONCAT(s,_start) + (vsize); \
- } \
- } while (0)
+#define ESTACK_RESTORE(s, src) \
+do { \
+ ASSERT(s.start == ESTK_DEF_STACK(s)); \
+ s = *(src); /* struct copy */ \
+ (src)->start = NULL; \
+ ASSERT(s.sp >= s.start); \
+ ASSERT(s.sp <= s.end); \
+} while (0)
-#define ESTACK_IS_STATIC(s) (ESTK_CONCAT(s,_start) == ESTK_CONCAT(s,_default_stack))
+#define ESTACK_IS_STATIC(s) (s.start == ESTK_DEF_STACK(s)))
-#define DESTROY_ESTACK(s) \
-do { \
- if (ESTK_CONCAT(s,_start) != ESTK_CONCAT(s,_default_stack)) { \
- erts_free(ESTK_CONCAT(s,_alloc_type), ESTK_CONCAT(s,_start)); \
- } \
+#define ESTACK_PUSH(s, x) \
+do { \
+ if (s.sp == s.end) { \
+ erl_grow_estack(&s, ESTK_DEF_STACK(s)); \
+ } \
+ *s.sp++ = (x); \
} while(0)
-#define ESTACK_PUSH(s, x) \
-do { \
- if (ESTK_CONCAT(s,_sp) == ESTK_CONCAT(s,_end)) { \
- erl_grow_stack(ESTK_CONCAT(s,_alloc_type),&ESTK_CONCAT(s,_start), \
- &ESTK_CONCAT(s,_sp), &ESTK_CONCAT(s,_end)); \
- } \
- *ESTK_CONCAT(s,_sp)++ = (x); \
+#define ESTACK_PUSH2(s, x, y) \
+do { \
+ if (s.sp > s.end - 2) { \
+ erl_grow_estack(&s, ESTK_DEF_STACK(s)); \
+ } \
+ *s.sp++ = (x); \
+ *s.sp++ = (y); \
} while(0)
-#define ESTACK_PUSH2(s, x, y) \
-do { \
- if (ESTK_CONCAT(s,_sp) > ESTK_CONCAT(s,_end) - 2) { \
- erl_grow_stack(ESTK_CONCAT(s,_alloc_type),&ESTK_CONCAT(s,_start), \
- &ESTK_CONCAT(s,_sp), &ESTK_CONCAT(s,_end)); \
- } \
- *ESTK_CONCAT(s,_sp)++ = (x); \
- *ESTK_CONCAT(s,_sp)++ = (y); \
+#define ESTACK_PUSH3(s, x, y, z) \
+do { \
+ if (s.sp > s.end - 3) { \
+ erl_grow_estack(&s, ESTK_DEF_STACK(s)); \
+ } \
+ *s.sp++ = (x); \
+ *s.sp++ = (y); \
+ *s.sp++ = (z); \
} while(0)
-#define ESTACK_PUSH3(s, x, y, z) \
-do { \
- if (ESTK_CONCAT(s,_sp) > ESTK_CONCAT(s,_end) - 3) { \
- erl_grow_stack(&ESTK_CONCAT(s,_start), &ESTK_CONCAT(s,_sp), \
- &ESTK_CONCAT(s,_end)); \
- } \
- *ESTK_CONCAT(s,_sp)++ = (x); \
- *ESTK_CONCAT(s,_sp)++ = (y); \
- *ESTK_CONCAT(s,_sp)++ = (z); \
-} while(0)
+#define ESTACK_COUNT(s) (s.sp - s.start)
+#define ESTACK_ISEMPTY(s) (s.sp == s.start)
+#define ESTACK_POP(s) (*(--s.sp))
-#define ESTACK_COUNT(s) (ESTK_CONCAT(s,_sp) - ESTK_CONCAT(s,_start))
-#define ESTACK_ISEMPTY(s) (ESTK_CONCAT(s,_sp) == ESTK_CONCAT(s,_start))
-#define ESTACK_POP(s) (*(--ESTK_CONCAT(s,_sp)))
+/*
+ * WSTACK: same as ESTACK but with UWord instead of Eterm
+ */
+typedef struct {
+ UWord* wstart;
+ UWord* wsp;
+ UWord* wend;
+ ErtsAlcType_t alloc_type;
+}ErtsWStack;
-void erl_grow_wstack(ErtsAlcType_t a_type, UWord** start, UWord** sp, UWord** end);
-#define WSTK_CONCAT(a,b) a##b
-#define WSTK_SUBSCRIPT(s,i) *((UWord *)((byte *)WSTK_CONCAT(s,_start) + (i)))
#define DEF_WSTACK_SIZE (16)
-#define DECLARE_WSTACK(s) \
- UWord WSTK_CONCAT(s,_default_stack)[DEF_WSTACK_SIZE]; \
- UWord* WSTK_CONCAT(s,_start) = WSTK_CONCAT(s,_default_stack); \
- UWord* WSTK_CONCAT(s,_sp) = WSTK_CONCAT(s,_start); \
- UWord* WSTK_CONCAT(s,_end) = WSTK_CONCAT(s,_start) + DEF_WSTACK_SIZE; \
- ErtsAlcType_t WSTK_CONCAT(s,_alloc_type) = ERTS_ALC_T_ESTACK
+void erl_grow_wstack(ErtsWStack*, Eterm* def_stack);
+#define WSTK_CONCAT(a,b) a##b
+#define WSTK_DEF_STACK(s) WSTK_CONCAT(s,_default_wstack)
+
+#define DECLARE_WSTACK(s) \
+ UWord WSTK_DEF_STACK(s)[DEF_WSTACK_SIZE]; \
+ ErtsWStack s = { \
+ WSTK_DEF_STACK(s), /* wstart */ \
+ WSTK_DEF_STACK(s), /* wsp */ \
+ WSTK_DEF_STACK(s) + DEF_WSTACK_SIZE, /* wend */ \
+ ERTS_ALC_T_ESTACK /* alloc_type */ \
+ }
#define WSTACK_CHANGE_ALLOCATOR(s,t) \
do { \
- if (WSTK_CONCAT(s,_start) != WSTK_CONCAT(s,_default_stack)) { \
+ if (s.wstart != WSTK_DEF_STACK(s)) { \
erl_exit(1, "Internal error - trying to change allocator " \
"type of active wstack\n"); \
} \
- WSTK_CONCAT(s,_alloc_type) = (t); \
+ s.alloc_type = (t); \
} while (0)
-#define DESTROY_WSTACK(s) \
-do { \
- if (WSTK_CONCAT(s,_start) != WSTK_CONCAT(s,_default_stack)) { \
- erts_free(WSTK_CONCAT(s,_alloc_type), WSTK_CONCAT(s,_start)); \
- } \
+#define DESTROY_WSTACK(s) \
+do { \
+ if (s.wstart != WSTK_DEF_STACK(s)) { \
+ erts_free(s.alloc_type, s.wstart); \
+ } \
} while(0)
+
/*
- * Do not free the stack after this, it may have pointers into what
- * was saved in 'v'. 'v' and 'vsize' are changed by this macro. If
- * 'v' points to anything, it should have been allocated by a previous
- * call to this macro. Be careful to set a correct allocator prior to
- * saving.
- * 'v' can be any lvalue pointer, it will point to an array of UWord
- * after calling this macro.
+ * Do not free the stack after this, it may have pointers into what
+ * was saved in 'dst'.
*/
-#define WSTACK_SAVE(s,v,vsize) /* v and vsize are "name parameters" */ \
-do { \
- Uint _wsz = WSTACK_COUNT(s); \
- if (WSTK_CONCAT(s,_start) == WSTK_CONCAT(s,_default_stack)) { \
- if ((v) == NULL) { \
- (v) = erts_alloc(WSTK_CONCAT(s,_alloc_type), \
- DEF_WSTACK_SIZE * sizeof(UWord)); \
- } \
- memcpy((v),WSTK_CONCAT(s,_start),_wsz*sizeof(UWord)); \
- } else { \
- (v) = (void *) WSTK_CONCAT(s,_start); \
- } \
- (vsize) = _wsz; \
+#define WSTACK_SAVE(s,dst)\
+do {\
+ if (s.wstart == WSTK_DEF_STACK(s)) {\
+ UWord _wsz = WSTACK_COUNT(s);\
+ (dst)->wstart = erts_alloc(s.alloc_type,\
+ DEF_WSTACK_SIZE * sizeof(UWord));\
+ memcpy((dst)->wstart, s.wstart,_wsz*sizeof(UWord));\
+ (dst)->wsp = (dst)->wstart + _wsz;\
+ (dst)->wend = (dst)->wstart + DEF_WSTACK_SIZE;\
+ (dst)->alloc_type = s.alloc_type;\
+ } else\
+ *(dst) = s;\
} while (0)
-/*
- * Use on empty stack, only the allocator can be changed before this
- * The vector parameter is reset to NULL if the vector is moved to stack,
- * otherwise it's kept for reuse, so a saved and restored vector might
- * need freeing using the correct allocator parameter.
- * 'v' can be any lvalue pointer, it's cast to an (UWord *).
+#define DESTROY_SAVED_WSTACK(wstack)\
+do {\
+ if ((wstack)->wstart) {\
+ erts_free((wstack)->alloc_type, (wstack)->wstart);\
+ (wstack)->wstart = NULL;\
+ }\
+} while(0)
+
+/*
+ * Use on empty stack, only the allocator can be changed before this.
+ * The src stack is reset to NULL.
*/
-#define WSTACK_RESTORE(s, v, vsize) /*v is a "name parameter"*/ \
-do { \
- if ((vsize) > DEF_WSTACK_SIZE) { \
- Uint _ca = DEF_WSTACK_SIZE; \
- while (_ca < (vsize)) \
- _ca = _ca * 2; \
- WSTK_CONCAT(s,_start) = (UWord *) (v); \
- WSTK_CONCAT(s,_end) = ((UWord *)(v)) + _ca; \
- WSTK_CONCAT(s,_sp) = WSTK_CONCAT(s,_start) + (vsize); \
- (v) = NULL; \
- } else { \
- memcpy(WSTK_CONCAT(s,_start),(v),(vsize)*sizeof(UWord));\
- WSTK_CONCAT(s,_sp) = WSTK_CONCAT(s,_start) + (vsize); \
- } \
- } while (0)
+#define WSTACK_RESTORE(s, src) \
+do { \
+ ASSERT(s.wstart == WSTK_DEF_STACK(s)); \
+ s = *(src); /* struct copy */ \
+ (src)->wstart = NULL; \
+ ASSERT(s.wsp >= s.wstart); \
+ ASSERT(s.wsp <= s.wend); \
+} while (0)
-#define WSTACK_IS_STATIC(s) (WSTK_CONCAT(s,_start) == WSTK_CONCAT(s,_default_stack))
+#define WSTACK_IS_STATIC(s) (s.wstart == WSTK_DEF_STACK(s)))
-#define WSTACK_PUSH(s, x) \
-do { \
- if (WSTK_CONCAT(s,_sp) == WSTK_CONCAT(s,_end)) { \
- erl_grow_wstack(WSTK_CONCAT(s,_alloc_type), &WSTK_CONCAT(s,_start), \
- &WSTK_CONCAT(s,_sp), &WSTK_CONCAT(s,_end)); \
- } \
- *WSTK_CONCAT(s,_sp)++ = (x); \
+#define WSTACK_PUSH(s, x) \
+do { \
+ if (s.wsp == s.wend) { \
+ erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \
+ } \
+ *s.wsp++ = (x); \
} while(0)
-#define WSTACK_PUSH2(s, x, y) \
-do { \
- if (WSTK_CONCAT(s,_sp) > WSTK_CONCAT(s,_end) - 2) { \
- erl_grow_wstack(WSTK_CONCAT(s,_alloc_type), &WSTK_CONCAT(s,_start), \
- &WSTK_CONCAT(s,_sp), &WSTK_CONCAT(s,_end)); \
- } \
- *WSTK_CONCAT(s,_sp)++ = (x); \
- *WSTK_CONCAT(s,_sp)++ = (y); \
+#define WSTACK_PUSH2(s, x, y) \
+do { \
+ if (s.wsp > s.wend - 2) { \
+ erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \
+ } \
+ *s.wsp++ = (x); \
+ *s.wsp++ = (y); \
} while(0)
-#define WSTACK_PUSH3(s, x, y, z) \
-do { \
- if (WSTK_CONCAT(s,_sp) > WSTK_CONCAT(s,_end) - 3) { \
- erl_grow_wstack(WSTK_CONCAT(s,_alloc_type), &WSTK_CONCAT(s,_start), \
- &WSTK_CONCAT(s,_sp), &WSTK_CONCAT(s,_end)); \
- } \
- *WSTK_CONCAT(s,_sp)++ = (x); \
- *WSTK_CONCAT(s,_sp)++ = (y); \
- *WSTK_CONCAT(s,_sp)++ = (z); \
+#define WSTACK_PUSH3(s, x, y, z) \
+do { \
+ if (s.wsp > s.wend - 3) { \
+ erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \
+ } \
+ *s.wsp++ = (x); \
+ *s.wsp++ = (y); \
+ *s.wsp++ = (z); \
} while(0)
-#define WSTACK_COUNT(s) (WSTK_CONCAT(s,_sp) - WSTK_CONCAT(s,_start))
+#define WSTACK_COUNT(s) (s.wsp - s.wstart)
+#define WSTACK_ISEMPTY(s) (s.wsp == s.wstart)
+#define WSTACK_POP(s) (*(--s.wsp))
-#define WSTACK_ISEMPTY(s) (WSTK_CONCAT(s,_sp) == WSTK_CONCAT(s,_start))
-#define WSTACK_POP(s) (*(--WSTK_CONCAT(s,_sp)))
/* binary.c */
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 216952e2ac..7f8bdcb2ca 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -185,39 +185,41 @@ erts_set_hole_marker(Eterm* ptr, Uint sz)
* Helper function for the ESTACK macros defined in global.h.
*/
void
-erl_grow_stack(ErtsAlcType_t a_type, Eterm** start, Eterm** sp, Eterm** end)
+erl_grow_estack(ErtsEStack* s, Eterm* default_estack)
{
- Uint old_size = (*end - *start);
+ Uint old_size = (s->end - s->start);
Uint new_size = old_size * 2;
- Uint sp_offs = *sp - *start;
- if (new_size > 2 * DEF_ESTACK_SIZE) {
- *start = erts_realloc(a_type, (void *) *start, new_size*sizeof(Eterm));
+ Uint sp_offs = s->sp - s->start;
+ if (s->start != default_estack) {
+ s->start = erts_realloc(s->alloc_type, s->start,
+ new_size*sizeof(Eterm));
} else {
- Eterm* new_ptr = erts_alloc(a_type, new_size*sizeof(Eterm));
- sys_memcpy(new_ptr, *start, old_size*sizeof(Eterm));
- *start = new_ptr;
+ Eterm* new_ptr = erts_alloc(s->alloc_type, new_size*sizeof(Eterm));
+ sys_memcpy(new_ptr, s->start, old_size*sizeof(Eterm));
+ s->start = new_ptr;
}
- *end = *start + new_size;
- *sp = *start + sp_offs;
+ s->end = s->start + new_size;
+ s->sp = s->start + sp_offs;
}
/*
- * Helper function for the ESTACK macros defined in global.h.
+ * Helper function for the WSTACK macros defined in global.h.
*/
void
-erl_grow_wstack(ErtsAlcType_t a_type, UWord** start, UWord** sp, UWord** end)
+erl_grow_wstack(ErtsWStack* s, UWord* default_wstack)
{
- Uint old_size = (*end - *start);
+ Uint old_size = (s->wend - s->wstart);
Uint new_size = old_size * 2;
- Uint sp_offs = *sp - *start;
- if (new_size > 2 * DEF_ESTACK_SIZE) {
- *start = erts_realloc(a_type, (void *) *start, new_size*sizeof(UWord));
+ Uint sp_offs = s->wsp - s->wstart;
+ if (s->wstart != default_wstack) {
+ s->wstart = erts_realloc(s->alloc_type, s->wstart,
+ new_size*sizeof(UWord));
} else {
- UWord* new_ptr = erts_alloc(a_type, new_size*sizeof(UWord));
- sys_memcpy(new_ptr, *start, old_size*sizeof(UWord));
- *start = new_ptr;
+ UWord* new_ptr = erts_alloc(s->alloc_type, new_size*sizeof(UWord));
+ sys_memcpy(new_ptr, s->wstart, old_size*sizeof(UWord));
+ s->wstart = new_ptr;
}
- *end = *start + new_size;
- *sp = *start + sp_offs;
+ s->wend = s->wstart + new_size;
+ s->wsp = s->wstart + sp_offs;
}
/* CTYPE macros */