diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/global.h | 48 | ||||
-rw-r--r-- | erts/emulator/beam/utils.c | 20 |
2 files changed, 54 insertions, 14 deletions
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 1fb069232a..dcba8bbba8 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -372,7 +372,7 @@ extern int stackdump_on_exit; * DESTROY_ESTACK(Stack) */ -typedef struct { +typedef struct ErtsEStack_ { Eterm* start; Eterm* sp; Eterm* end; @@ -381,7 +381,7 @@ typedef struct { #define DEF_ESTACK_SIZE (16) -void erl_grow_estack(ErtsEStack*, Eterm* def_stack); +void erl_grow_estack(ErtsEStack*, Eterm* def_stack, Uint need); #define ESTK_CONCAT(a,b) a##b #define ESTK_DEF_STACK(s) ESTK_CONCAT(s,_default_estack) @@ -457,7 +457,7 @@ do { \ #define ESTACK_PUSH(s, x) \ do { \ if (s.sp == s.end) { \ - erl_grow_estack(&s, ESTK_DEF_STACK(s)); \ + erl_grow_estack(&s, ESTK_DEF_STACK(s), 1); \ } \ *s.sp++ = (x); \ } while(0) @@ -465,7 +465,7 @@ do { \ #define ESTACK_PUSH2(s, x, y) \ do { \ if (s.sp > s.end - 2) { \ - erl_grow_estack(&s, ESTK_DEF_STACK(s)); \ + erl_grow_estack(&s, ESTK_DEF_STACK(s), 2); \ } \ *s.sp++ = (x); \ *s.sp++ = (y); \ @@ -474,7 +474,7 @@ do { \ #define ESTACK_PUSH3(s, x, y, z) \ do { \ if (s.sp > s.end - 3) { \ - erl_grow_estack(&s, ESTK_DEF_STACK(s)); \ + erl_grow_estack(&s, ESTK_DEF_STACK(s), 3); \ } \ *s.sp++ = (x); \ *s.sp++ = (y); \ @@ -492,6 +492,20 @@ do { \ *s.sp++ = (E4); \ } while(0) +#define ESTACK_RESERVE(s, push_cnt) \ +do { \ + if (s.sp > s.end - (push_cnt)) { \ + erl_grow_estack(&s, ESTK_DEF_STACK(s), (push_cnt)); \ + } \ +} while(0) + +/* Must be preceded by ESTACK_RESERVE */ +#define ESTACK_FAST_PUSH(s, x) \ +do { \ + ASSERT(s.sp < s.end); \ + *s.sp++ = (x); \ +} while(0) + #define ESTACK_COUNT(s) (s.sp - s.start) #define ESTACK_ISEMPTY(s) (s.sp == s.start) #define ESTACK_POP(s) (*(--s.sp)) @@ -501,7 +515,7 @@ do { \ * WSTACK: same as ESTACK but with UWord instead of Eterm */ -typedef struct { +typedef struct ErtsWStack_ { UWord* wstart; UWord* wsp; UWord* wend; @@ -510,7 +524,7 @@ typedef struct { #define DEF_WSTACK_SIZE (16) -void erl_grow_wstack(ErtsWStack*, UWord* def_stack); +void erl_grow_wstack(ErtsWStack*, UWord* def_stack, Uint need); #define WSTK_CONCAT(a,b) a##b #define WSTK_DEF_STACK(s) WSTK_CONCAT(s,_default_wstack) @@ -592,7 +606,7 @@ do { \ #define WSTACK_PUSH(s, x) \ do { \ if (s.wsp == s.wend) { \ - erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \ + erl_grow_wstack(&s, WSTK_DEF_STACK(s), 1); \ } \ *s.wsp++ = (x); \ } while(0) @@ -600,7 +614,7 @@ do { \ #define WSTACK_PUSH2(s, x, y) \ do { \ if (s.wsp > s.wend - 2) { \ - erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \ + erl_grow_wstack(&s, WSTK_DEF_STACK(s), 2); \ } \ *s.wsp++ = (x); \ *s.wsp++ = (y); \ @@ -609,7 +623,7 @@ do { \ #define WSTACK_PUSH3(s, x, y, z) \ do { \ if (s.wsp > s.wend - 3) { \ - erl_grow_wstack(&s, WSTK_DEF_STACK(s)); \ + erl_grow_wstack(&s, WSTK_DEF_STACK(s), 3); \ } \ *s.wsp++ = (x); \ *s.wsp++ = (y); \ @@ -652,6 +666,20 @@ do { \ *s.wsp++ = (A6); \ } while(0) +#define WSTACK_RESERVE(s, push_cnt) \ +do { \ + if (s.wsp > s.wend - (push_cnt)) { \ + erl_grow_wstack(&s, WSTK_DEF_STACK(s), (push_cnt)); \ + } \ +} while(0) + +/* Must be preceded by WSTACK_RESERVE */ +#define WSTACK_FAST_PUSH(s, x) \ +do { \ + ASSERT(s.wsp < s.wend); \ + *s.wsp++ = (x); \ +} while(0) + #define WSTACK_COUNT(s) (s.wsp - s.wstart) #define WSTACK_ISEMPTY(s) (s.wsp == s.wstart) #define WSTACK_POP(s) ((ASSERT(s.wsp > s.wstart)),*(--s.wsp)) diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index cea20a6002..bd90ec2fba 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -190,11 +190,17 @@ erts_set_hole_marker(Eterm* ptr, Uint sz) * Helper function for the ESTACK macros defined in global.h. */ void -erl_grow_estack(ErtsEStack* s, Eterm* default_estack) +erl_grow_estack(ErtsEStack* s, Eterm* default_estack, Uint need) { Uint old_size = (s->end - s->start); - Uint new_size = old_size * 2; + Uint new_size; Uint sp_offs = s->sp - s->start; + + if (need < old_size) + new_size = 2*old_size; + else + new_size = ((need / old_size) + 2) * old_size; + if (s->start != default_estack) { s->start = erts_realloc(s->alloc_type, s->start, new_size*sizeof(Eterm)); @@ -210,11 +216,17 @@ erl_grow_estack(ErtsEStack* s, Eterm* default_estack) * Helper function for the WSTACK macros defined in global.h. */ void -erl_grow_wstack(ErtsWStack* s, UWord* default_wstack) +erl_grow_wstack(ErtsWStack* s, UWord* default_wstack, Uint need) { Uint old_size = (s->wend - s->wstart); - Uint new_size = old_size * 2; + Uint new_size; Uint sp_offs = s->wsp - s->wstart; + + if (need < old_size) + new_size = 2 * old_size; + else + new_size = ((need / old_size) + 2) * old_size; + if (s->wstart != default_wstack) { s->wstart = erts_realloc(s->alloc_type, s->wstart, new_size*sizeof(UWord)); |