This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[MERGE] make optree-walking mostly non-recursive
authorDavid Mitchell <davem@iabyn.com>
Mon, 24 Jun 2019 10:40:30 +0000 (11:40 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 24 Jun 2019 10:40:30 +0000 (11:40 +0100)
commit362d2cd85ebfe95231952e6fccbaadc26915db9d
treeaacc0226cd3395e4175a0a5119b3f39225a81692
parentec121dacb4d1d7f6aa78abbd19bf388858bf5095
parent625e589c312fe504e4ad66b1777068806658eb77
[MERGE] make optree-walking mostly non-recursive

This branch updates many of the functions in op.c which recursively
walk an op tree during compilation.  This avoids SEGVs from stack
overflow when the op tree is deeply nested, such as
    $n == 1 ? "one" : $n == 2 ? "two" : ....
(especially in code which is auto-generated)

This is particularly noticeable where the code is compiled within a
separate thread, as threads tend to have small stacks by default.

Some functions already avoided recursion by mallocing a buffer
containing a list of ops to visit, but this could be leaked if the code
died during compilation.

Making the functions non-recursive is a lot easier now that the last
node in each OpSIBLING chain holds a pointer back to the parent node.
Where the function needs to recursively visit *every* node, its just a
case of following each child link, then every OpSIBLING link then the
parent link. Where the recursion is more selective, it becomes more
tricky. In some cases I have followed the policy that a node has N kids
and kids I..N need visiting, then start at I and iterate as usual; but
if just kids I and J  needs visiting (but not J+1..N), then do old-style
recursion on nodes I and J. These cases are hopefully rare.