gawk/gawk-4.2.1-001-remove-the-t...

310 lines
8.3 KiB
Diff

From 47316d294571673a8dbf1e9e435893e2660f46a8 Mon Sep 17 00:00:00 2001
From: "Arnold D. Robbins" <arnold@skeeve.com>
Date: Mon, 26 Mar 2018 10:45:01 +0300
Subject: [PATCH] Remove the tail recursion optimization.
---
awk.h | 4 ----
awkgram.y | 27 ++-------------------------
eval.c | 49 +++++++------------------------------------------
test/Makefile.am | 4 +++-
test/Makefile.in | 9 ++++++++-
test/Maketests | 5 +++++
test/tailrecurse.awk | 15 +++++++++++++++
test/tailrecurse.ok | 5 +++++
8 files changed, 45 insertions(+), 73 deletions(-)
create mode 100644 test/tailrecurse.awk
create mode 100644 test/tailrecurse.ok
diff --git a/awk.h b/awk.h
index 3b351c2..36e71f2 100644
--- a/awk.h
+++ b/awk.h
@@ -527,7 +527,6 @@ typedef struct exp_node {
#define func_node sub.nodep.x.extra
#define prev_frame_size sub.nodep.reflags
#define reti sub.nodep.l.li
-#define num_tail_calls sub.nodep.cnt
/* Node_var: */
#define var_value lnode
@@ -862,9 +861,6 @@ typedef struct exp_instruction {
/* Op_func_call, Op_func */
#define func_body x.xn
-/* Op_func_call */
-#define tail_call d.dl
-
/* Op_subscript */
#define sub_count d.dl
diff --git a/awkgram.y b/awkgram.y
index ad830a5..caed09e 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -993,20 +993,9 @@ non_compound_stmt
$$ = list_create($1);
(void) list_prepend($$, instruction(Op_push_i));
$$->nexti->memory = dupnode(Nnull_string);
- } else {
- if (do_optimize
- && $3->lasti->opcode == Op_func_call
- && strcmp($3->lasti->func_name, in_function) == 0
- ) {
- /* Do tail recursion optimization. Tail
- * call without a return value is recognized
- * in mk_function().
- */
- ($3->lasti + 1)->tail_call = true;
- }
-
+ } else
$$ = list_append($3, $1);
- }
+
$$ = add_pending_comment($$);
}
| simple_stmt statement_term
@@ -4736,18 +4725,6 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
thisfunc = fi->func_body;
assert(thisfunc != NULL);
- if (do_optimize && def->lasti->opcode == Op_pop) {
- /* tail call which does not return any value. */
-
- INSTRUCTION *t;
-
- for (t = def->nexti; t->nexti != def->lasti; t = t->nexti)
- ;
- if (t->opcode == Op_func_call
- && strcmp(t->func_name, thisfunc->vname) == 0)
- (t + 1)->tail_call = true;
- }
-
/* add any pre-function comment to start of action for profile.c */
if (function_comment != NULL) {
diff --git a/eval.c b/eval.c
index 6ece236..34ba174 100644
--- a/eval.c
+++ b/eval.c
@@ -674,7 +674,7 @@ void
dump_fcall_stack(FILE *fp)
{
NODE *f, *func;
- long i = 0, j, k = 0;
+ long i = 0, k = 0;
if (fcall_count == 0)
return;
@@ -682,15 +682,13 @@ dump_fcall_stack(FILE *fp)
/* current frame */
func = frame_ptr->func_node;
- for (j = 0; j <= frame_ptr->num_tail_calls; j++)
- fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
+ fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
/* outer frames except main */
for (i = 1; i < fcall_count; i++) {
f = fcall_list[i];
func = f->func_node;
- for (j = 0; j <= f->num_tail_calls; j++)
- fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
+ fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
}
fprintf(fp, "\t# %3ld. -- main --\n", k);
@@ -1242,38 +1240,16 @@ setup_frame(INSTRUCTION *pc)
NODE *m, *f, *fp;
NODE **sp = NULL;
int pcount, arg_count, i, j;
- bool tail_optimize = false;
f = pc->func_body;
pcount = f->param_cnt;
fp = f->fparms;
arg_count = (pc + 1)->expr_count;
- /* tail recursion optimization */
- tail_optimize = ((pc + 1)->tail_call && do_optimize
- && ! do_debug && ! do_profile);
-
- if (tail_optimize) {
- /* free local vars of calling frame */
-
- NODE *func;
- int n;
-
- func = frame_ptr->func_node;
- for (n = func->param_cnt, sp = frame_ptr->stack; n > 0; n--) {
- r = *sp++;
- if (r->type == Node_var) /* local variable */
- DEREF(r->var_value);
- else if (r->type == Node_var_array) /* local array */
- assoc_clear(r);
- }
- sp = frame_ptr->stack;
-
- } else if (pcount > 0) {
+ if (pcount > 0) {
ezalloc(sp, NODE **, pcount * sizeof(NODE *), "setup_frame");
}
-
/* check for extra args */
if (arg_count > pcount) {
warning(
@@ -1287,13 +1263,9 @@ setup_frame(INSTRUCTION *pc)
}
for (i = 0, j = arg_count - 1; i < pcount; i++, j--) {
- if (tail_optimize)
- r = sp[i];
- else {
- getnode(r);
- memset(r, 0, sizeof(NODE));
- sp[i] = r;
- }
+ getnode(r);
+ memset(r, 0, sizeof(NODE));
+ sp[i] = r;
if (i >= arg_count) {
/* local variable */
@@ -1348,11 +1320,6 @@ setup_frame(INSTRUCTION *pc)
stack_adj(-arg_count); /* adjust stack pointer */
- if (tail_optimize) {
- frame_ptr->num_tail_calls++;
- return f->code_ptr;
- }
-
if (pc->opcode == Op_indirect_func_call) {
r = POP(); /* indirect var */
DEREF(r);
@@ -1372,7 +1339,6 @@ setup_frame(INSTRUCTION *pc)
frame_ptr->stack = sp;
frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the previous stack frame */
frame_ptr->func_node = f;
- frame_ptr->num_tail_calls = 0;
frame_ptr->vname = NULL;
frame_ptr->reti = pc; /* on return execute pc->nexti */
@@ -1774,7 +1740,6 @@ init_interpret()
frame_ptr->type = Node_frame;
frame_ptr->stack = NULL;
frame_ptr->func_node = NULL; /* in main */
- frame_ptr->num_tail_calls = 0;
frame_ptr->vname = NULL;
/* initialize true and false nodes */
diff --git a/test/Makefile.am b/test/Makefile.am
index bf1dbd3..40e25b2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1134,6 +1134,8 @@ EXTRA_DIST = \
synerr1.ok \
synerr2.awk \
synerr2.ok \
+ tailrecurse.awk \
+ tailrecurse.ok \
testext.ok \
time.awk \
time.ok \
@@ -1253,7 +1255,7 @@ BASIC_TESTS = \
sigpipe1 sortempty sortglos splitargv splitarr \
splitdef splitvar splitwht status-close strcat1 strnum1 strnum2 strtod \
subamp subback subi18n subsepnm subslash substr swaplns synerr1 synerr2 \
- tradanch tweakfld \
+ tailrecurse tradanch tweakfld \
uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs uplus \
wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \
zero2 zeroe0 zeroflag
diff --git a/test/Makefile.in b/test/Makefile.in
index f96151b..74405f8 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1392,6 +1392,8 @@ EXTRA_DIST = \
synerr1.ok \
synerr2.awk \
synerr2.ok \
+ tailrecurse.awk \
+ tailrecurse.ok \
testext.ok \
time.awk \
time.ok \
@@ -1510,7 +1512,7 @@ BASIC_TESTS = \
sigpipe1 sortempty sortglos splitargv splitarr \
splitdef splitvar splitwht status-close strcat1 strnum1 strnum2 strtod \
subamp subback subi18n subsepnm subslash substr swaplns synerr1 synerr2 \
- tradanch tweakfld \
+ tailrecurse tradanch tweakfld \
uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs uplus \
wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \
zero2 zeroe0 zeroflag
@@ -3919,6 +3921,11 @@ synerr2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+tailrecurse:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
uninit2:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index e449dd3..4a90e3e 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1002,6 +1002,11 @@ synerr2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+tailrecurse:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
uninit2:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/tailrecurse.awk b/test/tailrecurse.awk
new file mode 100644
index 0000000..b287d16
--- /dev/null
+++ b/test/tailrecurse.awk
@@ -0,0 +1,15 @@
+BEGIN {
+ abc(2)
+}
+
+
+function abc(c, A, B)
+{
+ print "abc(" c ", " length(A) ")"
+ if (! c--) {
+ return
+ }
+ B[""]
+ print length(B)
+ return abc(c, B)
+}
diff --git a/test/tailrecurse.ok b/test/tailrecurse.ok
new file mode 100644
index 0000000..73ce1ed
--- /dev/null
+++ b/test/tailrecurse.ok
@@ -0,0 +1,5 @@
+abc(2, 0)
+1
+abc(1, 1)
+1
+abc(0, 1)
--
2.14.4