[DEV-8947] Guided TCO: Reassign argument values after processing all expressions

I did say it was _experimental_ guided TRO.

This waits to perform the actual argument reassignment until after
processing the expressions associated with the new arguments, since they
will otherwise be replaced when their original values are still needed.
master
Mike Gerwitz 2020-12-02 14:56:38 -05:00
parent f175042f41
commit cb93f4c02a
2 changed files with 41 additions and 15 deletions

View File

@ -13,6 +13,17 @@ TAME developers: Add new changes under a "NEXT" heading as part of the
commits that introduce the changes. To make a new release, run
`tools/mkrelease`, which will handle updating the heading for you.
NEXT
====
This release provides tail-call optimizations aimed at the query system in
core.
Compiler
--------
- [bugfix] Recursive calls using TCO will wait to overwrite their function
arguments until all expressions calculating the new argument values have
completed.
v17.6.5 (2020-12-03)
====================
This release improves Summary Page performance when populating the page with

View File

@ -960,27 +960,42 @@
<variable name="arg-prefix" select="concat( ':', $name, ':' )" />
<text>(/*TCO*/function(){</text>
<!-- reassign function arguments -->
<for-each select="
root(.)/preproc:symtable/preproc:sym[
@type='func'
and @name=$name
]/preproc:sym-ref
">
<variable name="args" as="element(c:arg)*">
<for-each select="
root(.)/preproc:symtable/preproc:sym[
@type='func'
and @name=$name
]/preproc:sym-ref
">
<variable name="pname" select="substring-after( @name, $arg-prefix )" />
<variable name="arg" select="$self/c:arg[@name=$pname]" />
<variable name="pname" select="substring-after( @name, $arg-prefix )" />
<variable name="arg" select="$self/c:arg[@name=$pname]" />
<!-- if the call specified this argument, then use it -->
<if test="$arg">
<sequence select="concat( '/*TCO*/', $pname, '=' )" />
<apply-templates select="$arg/c:*[1]" mode="compile" />
<text>,</text>
</if>
<!-- if the call specified this argument, then use it -->
<sequence select="$arg" />
</for-each>
</variable>
<!-- store reassignments first in a temporary variable, since the
expressions may reference the original arguments and we do not want
to overwrite yet -->
<for-each select="$args">
<sequence select="concat( 'const __tco_', @name, '=' )" />
<apply-templates select="c:*[1]" mode="compile" />
<text>;</text>
</for-each>
<!-- perform final reassignments, now that expressions no longer need the
original values -->
<for-each select="$args">
<sequence select="concat( @name, '=__tco_', @name, ';' )" />
</for-each>
<!-- return value, which doesn't matter since it won't be used -->
<text>0</text>
<text>return 0;})()</text>
<!-- don't support c:when here; not worth the effort -->
<if test="./c:when">