]> git.pld-linux.org Git - packages/gawk.git/blame - gawk-4.2.1-001-remove-the-tail-recursion-optimization.patch
- rel 2; upstream fixes used in fc
[packages/gawk.git] / gawk-4.2.1-001-remove-the-tail-recursion-optimization.patch
CommitLineData
9169c9b5
AM
1From 47316d294571673a8dbf1e9e435893e2660f46a8 Mon Sep 17 00:00:00 2001
2From: "Arnold D. Robbins" <arnold@skeeve.com>
3Date: Mon, 26 Mar 2018 10:45:01 +0300
4Subject: [PATCH] Remove the tail recursion optimization.
5
6---
7 awk.h | 4 ----
8 awkgram.y | 27 ++-------------------------
9 eval.c | 49 +++++++------------------------------------------
10 test/Makefile.am | 4 +++-
11 test/Makefile.in | 9 ++++++++-
12 test/Maketests | 5 +++++
13 test/tailrecurse.awk | 15 +++++++++++++++
14 test/tailrecurse.ok | 5 +++++
15 8 files changed, 45 insertions(+), 73 deletions(-)
16 create mode 100644 test/tailrecurse.awk
17 create mode 100644 test/tailrecurse.ok
18
19diff --git a/awk.h b/awk.h
20index 3b351c2..36e71f2 100644
21--- a/awk.h
22+++ b/awk.h
23@@ -527,7 +527,6 @@ typedef struct exp_node {
24 #define func_node sub.nodep.x.extra
25 #define prev_frame_size sub.nodep.reflags
26 #define reti sub.nodep.l.li
27-#define num_tail_calls sub.nodep.cnt
28
29 /* Node_var: */
30 #define var_value lnode
31@@ -862,9 +861,6 @@ typedef struct exp_instruction {
32 /* Op_func_call, Op_func */
33 #define func_body x.xn
34
35-/* Op_func_call */
36-#define tail_call d.dl
37-
38 /* Op_subscript */
39 #define sub_count d.dl
40
41diff --git a/awkgram.y b/awkgram.y
42index ad830a5..caed09e 100644
43--- a/awkgram.y
44+++ b/awkgram.y
45@@ -993,20 +993,9 @@ non_compound_stmt
46 $$ = list_create($1);
47 (void) list_prepend($$, instruction(Op_push_i));
48 $$->nexti->memory = dupnode(Nnull_string);
49- } else {
50- if (do_optimize
51- && $3->lasti->opcode == Op_func_call
52- && strcmp($3->lasti->func_name, in_function) == 0
53- ) {
54- /* Do tail recursion optimization. Tail
55- * call without a return value is recognized
56- * in mk_function().
57- */
58- ($3->lasti + 1)->tail_call = true;
59- }
60-
61+ } else
62 $$ = list_append($3, $1);
63- }
64+
65 $$ = add_pending_comment($$);
66 }
67 | simple_stmt statement_term
68@@ -4736,18 +4725,6 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
69 thisfunc = fi->func_body;
70 assert(thisfunc != NULL);
71
72- if (do_optimize && def->lasti->opcode == Op_pop) {
73- /* tail call which does not return any value. */
74-
75- INSTRUCTION *t;
76-
77- for (t = def->nexti; t->nexti != def->lasti; t = t->nexti)
78- ;
79- if (t->opcode == Op_func_call
80- && strcmp(t->func_name, thisfunc->vname) == 0)
81- (t + 1)->tail_call = true;
82- }
83-
84 /* add any pre-function comment to start of action for profile.c */
85
86 if (function_comment != NULL) {
87diff --git a/eval.c b/eval.c
88index 6ece236..34ba174 100644
89--- a/eval.c
90+++ b/eval.c
91@@ -674,7 +674,7 @@ void
92 dump_fcall_stack(FILE *fp)
93 {
94 NODE *f, *func;
95- long i = 0, j, k = 0;
96+ long i = 0, k = 0;
97
98 if (fcall_count == 0)
99 return;
100@@ -682,15 +682,13 @@ dump_fcall_stack(FILE *fp)
101
102 /* current frame */
103 func = frame_ptr->func_node;
104- for (j = 0; j <= frame_ptr->num_tail_calls; j++)
105- fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
106+ fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
107
108 /* outer frames except main */
109 for (i = 1; i < fcall_count; i++) {
110 f = fcall_list[i];
111 func = f->func_node;
112- for (j = 0; j <= f->num_tail_calls; j++)
113- fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
114+ fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
115 }
116
117 fprintf(fp, "\t# %3ld. -- main --\n", k);
118@@ -1242,38 +1240,16 @@ setup_frame(INSTRUCTION *pc)
119 NODE *m, *f, *fp;
120 NODE **sp = NULL;
121 int pcount, arg_count, i, j;
122- bool tail_optimize = false;
123
124 f = pc->func_body;
125 pcount = f->param_cnt;
126 fp = f->fparms;
127 arg_count = (pc + 1)->expr_count;
128
129- /* tail recursion optimization */
130- tail_optimize = ((pc + 1)->tail_call && do_optimize
131- && ! do_debug && ! do_profile);
132-
133- if (tail_optimize) {
134- /* free local vars of calling frame */
135-
136- NODE *func;
137- int n;
138-
139- func = frame_ptr->func_node;
140- for (n = func->param_cnt, sp = frame_ptr->stack; n > 0; n--) {
141- r = *sp++;
142- if (r->type == Node_var) /* local variable */
143- DEREF(r->var_value);
144- else if (r->type == Node_var_array) /* local array */
145- assoc_clear(r);
146- }
147- sp = frame_ptr->stack;
148-
149- } else if (pcount > 0) {
150+ if (pcount > 0) {
151 ezalloc(sp, NODE **, pcount * sizeof(NODE *), "setup_frame");
152 }
153
154-
155 /* check for extra args */
156 if (arg_count > pcount) {
157 warning(
158@@ -1287,13 +1263,9 @@ setup_frame(INSTRUCTION *pc)
159 }
160
161 for (i = 0, j = arg_count - 1; i < pcount; i++, j--) {
162- if (tail_optimize)
163- r = sp[i];
164- else {
165- getnode(r);
166- memset(r, 0, sizeof(NODE));
167- sp[i] = r;
168- }
169+ getnode(r);
170+ memset(r, 0, sizeof(NODE));
171+ sp[i] = r;
172
173 if (i >= arg_count) {
174 /* local variable */
175@@ -1348,11 +1320,6 @@ setup_frame(INSTRUCTION *pc)
176
177 stack_adj(-arg_count); /* adjust stack pointer */
178
179- if (tail_optimize) {
180- frame_ptr->num_tail_calls++;
181- return f->code_ptr;
182- }
183-
184 if (pc->opcode == Op_indirect_func_call) {
185 r = POP(); /* indirect var */
186 DEREF(r);
187@@ -1372,7 +1339,6 @@ setup_frame(INSTRUCTION *pc)
188 frame_ptr->stack = sp;
189 frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the previous stack frame */
190 frame_ptr->func_node = f;
191- frame_ptr->num_tail_calls = 0;
192 frame_ptr->vname = NULL;
193 frame_ptr->reti = pc; /* on return execute pc->nexti */
194
195@@ -1774,7 +1740,6 @@ init_interpret()
196 frame_ptr->type = Node_frame;
197 frame_ptr->stack = NULL;
198 frame_ptr->func_node = NULL; /* in main */
199- frame_ptr->num_tail_calls = 0;
200 frame_ptr->vname = NULL;
201
202 /* initialize true and false nodes */
203diff --git a/test/Makefile.am b/test/Makefile.am
204index bf1dbd3..40e25b2 100644
205--- a/test/Makefile.am
206+++ b/test/Makefile.am
207@@ -1134,6 +1134,8 @@ EXTRA_DIST = \
208 synerr1.ok \
209 synerr2.awk \
210 synerr2.ok \
211+ tailrecurse.awk \
212+ tailrecurse.ok \
213 testext.ok \
214 time.awk \
215 time.ok \
216@@ -1253,7 +1255,7 @@ BASIC_TESTS = \
217 sigpipe1 sortempty sortglos splitargv splitarr \
218 splitdef splitvar splitwht status-close strcat1 strnum1 strnum2 strtod \
219 subamp subback subi18n subsepnm subslash substr swaplns synerr1 synerr2 \
220- tradanch tweakfld \
221+ tailrecurse tradanch tweakfld \
222 uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs uplus \
223 wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \
224 zero2 zeroe0 zeroflag
225diff --git a/test/Makefile.in b/test/Makefile.in
226index f96151b..74405f8 100644
227--- a/test/Makefile.in
228+++ b/test/Makefile.in
229@@ -1392,6 +1392,8 @@ EXTRA_DIST = \
230 synerr1.ok \
231 synerr2.awk \
232 synerr2.ok \
233+ tailrecurse.awk \
234+ tailrecurse.ok \
235 testext.ok \
236 time.awk \
237 time.ok \
238@@ -1510,7 +1512,7 @@ BASIC_TESTS = \
239 sigpipe1 sortempty sortglos splitargv splitarr \
240 splitdef splitvar splitwht status-close strcat1 strnum1 strnum2 strtod \
241 subamp subback subi18n subsepnm subslash substr swaplns synerr1 synerr2 \
242- tradanch tweakfld \
243+ tailrecurse tradanch tweakfld \
244 uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs uplus \
245 wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \
246 zero2 zeroe0 zeroflag
247@@ -3919,6 +3921,11 @@ synerr2:
248 @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
249 @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
250
251+tailrecurse:
252+ @echo $@
253+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
254+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
255+
256 uninit2:
257 @echo $@
258 @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
259diff --git a/test/Maketests b/test/Maketests
260index e449dd3..4a90e3e 100644
261--- a/test/Maketests
262+++ b/test/Maketests
263@@ -1002,6 +1002,11 @@ synerr2:
264 @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
265 @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
266
267+tailrecurse:
268+ @echo $@
269+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
270+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
271+
272 uninit2:
273 @echo $@
274 @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
275diff --git a/test/tailrecurse.awk b/test/tailrecurse.awk
276new file mode 100644
277index 0000000..b287d16
278--- /dev/null
279+++ b/test/tailrecurse.awk
280@@ -0,0 +1,15 @@
281+BEGIN {
282+ abc(2)
283+}
284+
285+
286+function abc(c, A, B)
287+{
288+ print "abc(" c ", " length(A) ")"
289+ if (! c--) {
290+ return
291+ }
292+ B[""]
293+ print length(B)
294+ return abc(c, B)
295+}
296diff --git a/test/tailrecurse.ok b/test/tailrecurse.ok
297new file mode 100644
298index 0000000..73ce1ed
299--- /dev/null
300+++ b/test/tailrecurse.ok
301@@ -0,0 +1,5 @@
302+abc(2, 0)
303+1
304+abc(1, 1)
305+1
306+abc(0, 1)
307--
3082.14.4
309
This page took 0.121881 seconds and 4 git commands to generate.