I encountered an m4 program that performed over 20 million iterations of a tail-call recursion paradigm. Without this patch, memory usage grew to over 6 gigabytes, pausing the program for several seconds when the recursion finally ended just to reclaim the memory. But with the patch, m4 never needed more than 3 megabytes of resident memory.
* src/input.c (push_string_init): Prune empty string blocks before starting another one. --- src/input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/input.c b/src/input.c index 23d200bd..f8f57234 100644 --- a/src/input.c +++ b/src/input.c @@ -165,6 +165,9 @@ static struct re_registers regs; #ifdef DEBUG_INPUT static const char *token_type_string (token_type); #endif + +static void pop_input (void); + /*-------------------------------------------------------------------. @@ -250,6 +253,9 @@ push_string_init (void) abort (); } + /* Prefer reusing an older block, for tail-call optimization. */ + while (isp && isp->type == INPUT_STRING && !isp->u.u_s.string[0]) + pop_input (); next = (input_block *) obstack_alloc (current_input, sizeof (struct input_block)); next->type = INPUT_STRING; -- 2.31.1 _______________________________________________ M4-patches mailing list M4-patches@gnu.org https://lists.gnu.org/mailman/listinfo/m4-patches