In perl.git, the branch smoke-me/davem/non_recursive_op_fns has been created

<https://perl5.git.perl.org/perl.git/commitdiff/2ca12115bbf6c0c97c46b8e3dd3290d6572ed649?hp=0000000000000000000000000000000000000000>

        at  2ca12115bbf6c0c97c46b8e3dd3290d6572ed649 (commit)

- Log -----------------------------------------------------------------
commit 2ca12115bbf6c0c97c46b8e3dd3290d6572ed649
Author: David Mitchell <[email protected]>
Date:   Fri Jun 14 11:26:37 2019 +0100

    Perl_op_lvalue_flags(): make mostly non-recursive
    
    Recursion is left in a few places where is necessary to call itself
    with a different value for 'type'.

commit a3aff17244b981bf4931ba5360de612708ace498
Author: David Mitchell <[email protected]>
Date:   Wed Jun 12 12:03:52 2019 +0100

    Perl_op_lvalue_flags() add blank lines
    
    ... between switch cases for readability.

commit be57a3b2104353d70387ff2da92230b1c1302b70
Author: David Mitchell <[email protected]>
Date:   Wed Jun 12 11:57:54 2019 +0100

    Perl_op_lvalue_flags(): skip OPf_WANT_VOID ops.
    
    Currently this function asserts that its 'o' argument is non-VOID;
    later when recursing an OP_LIST, it skips any kids which are VOID.
    
    This commit changes it so that the assert becomes a return, and
    OP_LIST doesn't check whether its kids are VOID.
    
    Doing it this way makes it easier to shortly make Perl_op_lvalue_flags()
    non-recursive.
    
    The only functional difference is that on debugging builds,
    Perl_op_lvalue_flags() will no longer fail an assert if inadvertently
    called with a VOID op.

commit 1c302f78623c29527cbfc9904252cd35f1e511f5
Author: David Mitchell <[email protected]>
Date:   Thu Jun 6 13:32:25 2019 +0100

    Perl_op_lvalue_flags(): fixup documentation
    
    First, move the apidoc text for op_lvalue() to be directly above
    Perl_op_lvalue_flags() (it had wandered).
    
    Secondly, add a brief non-API note explaining what the extra 'flags'
    parameter does

commit b76844d1ac726186ba5d04477b29a1eea8257380
Author: David Mitchell <[email protected]>
Date:   Thu Jun 6 13:01:41 2019 +0100

    reindent op.c:S_lvref()
    
    ...  after the previous commit wrapped most if it in a while loop.  Also
    put a blank line after each switch case for readability.

commit b7835d12d3f1ca21a53144cce78f12b756b8dc73
Author: David Mitchell <[email protected]>
Date:   Thu Jun 6 13:00:18 2019 +0100

    make op.c:S_lvref() non-recursive

commit 276e3542fdf305b1b23596135e5db5c57a4409b8
Author: David Mitchell <[email protected]>
Date:   Tue Jun 4 13:41:21 2019 +0100

    document what op.c:S_lvref() does

commit 6fc1964513be352f535453667cf6f7b3c48a2a5e
Author: David Mitchell <[email protected]>
Date:   Tue Jun 4 13:33:22 2019 +0100

    op.c: S_lvref(): handle all kids on OP_NULL
    
    For an OP_NULL, his function formerly recursed into *all* its kids
    if was an ex-list, otherwise only the first one.
    
    To simplify making this function non-recursive, make it so that it
    unconditionally recurses into all the kids.
    
    However for now, also add an assertion that a non ex-list OP_NULL
    will only have one child at most. If we find some code which violates
    this, then we can nmake a more informed decision as to whether
    non ex-list OP_NULL's should have all, or only their first child
    examined.

commit a84bbb7031e89092217c4e4b3da488c39076db6f
Author: David Mitchell <[email protected]>
Date:   Fri May 31 16:59:53 2019 +0100

    Clarify purpose of S_looks_like_bool()

commit 05d8ee5751ff0f31e7cf5512efb13237562a2105
Author: David Mitchell <[email protected]>
Date:   Fri May 31 16:53:42 2019 +0100

    make op.c:S_find_and_forget_pmops() non-recursive
    
    For every CV that's freed which has a shared optree (e.g. a closure
    or between threads), the whole optree is walked looking for PMOPs.
    Make that walk non-recursive.
    
    Contrived code that triggers a stack overflow:
    
    {
        my $outer;
        my $e = 'sub { $outer && '
                . join('&&', ('$x') x 100_000)
                . " }";
        #print $e, "\n";
        eval $e;
    }
    
    Even after this commit, that code still SEGVs due to a separate stack
    blow in Perl_rpeep().

commit 4f40fb6c45ac44fe3bf0464bbec9b88181864020
Author: David Mitchell <[email protected]>
Date:   Fri May 31 16:02:19 2019 +0100

    Perl_doref(): reindent
    
    Previous commit added a while loop.

commit b78eb133353f3e6a9e5c6936ed121936f5ae0c12
Author: David Mitchell <[email protected]>
Date:   Fri May 31 11:58:11 2019 +0100

    Perl_doref(): make non-recursive
    
    This stops the following code from SEGVing for example:
    
        my $e = "\$r";
        $e = "+do{$e}" for 1..70_000;
        $e = "push \@{$e}, 1";
        eval $e;
    
    Similarly with a long
    
        $a[0][0][0][0].....
    
    This commit causes a slight change in behaviour, in that scalar(o)
    is now only called once at the end of the top-level doref() call,
    rather than at the end of processing each child. This should make no
    functional difference, apart from speeding up compiling infinitesimally.

commit 559bebdbbad524d64c5dd00aeb4aa764bb24b730
Author: David Mitchell <[email protected]>
Date:   Fri May 31 10:27:25 2019 +0100

    document what Perl_doref does

commit e27c299bc45623cac7de74d72b778c3acfef1b78
Author: David Mitchell <[email protected]>
Date:   Thu May 30 14:22:09 2019 +0100

    make op.c:S_aassign_scan() non-recursive
    
    With this commit and some previous ones, the following code no longer
    blows the stack:
    
        my $e = "1";
        $e = "do { \$x; $e}" for 1..100_000;
        $e = "\@x = $e";
        eval $e;

commit e6daae36fff3f8f5f989b3d7d53df53783bb8541
Author: David Mitchell <[email protected]>
Date:   Wed May 29 15:57:06 2019 +0100

    make Perl_op_linklist() non-recursive

commit 5782a04ed3459598b591fffa0f3d200f0cc1af25
Author: David Mitchell <[email protected]>
Date:   Wed May 29 15:03:42 2019 +0100

    Perl_op_linklist(): use OPf_KIDS flags
    
    This function just blindly assumes that cUNOPo->op_first is a valid
    indication that the op has at least one child. This is successful *most*
    of the time. Putting in an assertion caused t/op/lvref.t to fail.
    
    Instead, check the OPf_KIDS flag.

commit 12a8530e59501d82b6a445f1b61674c08901b4dd
Author: David Mitchell <[email protected]>
Date:   Wed May 29 09:49:19 2019 +0100

    Perl_scalarvoid(): add comment saying what it does
    
    It applies void context, which isn't all that obvious just from the
    name.

commit aef18482a889552928b107013219981eeeb687fb
Author: David Mitchell <[email protected]>
Date:   Tue May 28 17:37:43 2019 +0100

    op.c: S_search_const: remove recursion
    
    There are a couple of places where this function recurses, but they
    are both effectively tail recursion and can be easily eliminated.

commit 8c5faf5c0e7e69a81c9bb4bdbd0080ba09ca1348
Author: David Mitchell <[email protected]>
Date:   Tue May 28 17:25:33 2019 +0100

    op.c: add code comments to S_search_const()
    
    plus a few blank lines for readability.

commit 4a289f057aaae2e1f9d6bebe2ee553f1948f0319
Author: David Mitchell <[email protected]>
Date:   Tue May 28 15:39:50 2019 +0100

    op.c: S_assignment_type(): make truly trinary
    
    Commit 4fec880468dad87517895b935b19a8d51e98b5a6 converted the
    static boolean function S_is_list_assignment() into a 3-valued
    function: S_assignment_type().
    
    However, much of the code body still did things like 'return TRUE'.
    Replace these with 'return ASSIGN_LIST' etc. These have the same
    physical values, so there's no functional change here. But it makes the
    code more consistent and readable.

commit e646861a28fd4ffd544eb8d6713c455e37d8500f
Author: David Mitchell <[email protected]>
Date:   Wed May 29 11:03:26 2019 +0100

    Perl_scalar() tail-call optimise
    
    The part of this function that scans the children of e.g.
    
        $scalar = do { void; void; scalar }
    
    applying scalar context only to the last child: tail call optimise that
    call to Perl_scalar().
    
    It also adds some extra 'warnings' tests. An earlier attempt at this
    patch caused some unrelated tests to start emitting spurious 'useless in
    void context' messages, which are covered by the new tests.
    
    This also showed up that the current method for updating PL_curcop
    while descending optrees in Perl_scalar/scalarvoid/S_scalarseq is a bit
    broken. It gets updated every time a newstate op is seen, but haphazardly
    (and sometimes wrongly) restored to &PL_compiling when going back up the
    tree. One of the tests is TODO based on PL_curcop being wrong and so the
    'no warnings "void"' leaking into an outer scope.
    
    This commit maintains the status quo.

commit 3a33039002628c31291d8727ba3cb99d5e99bad4
Author: David Mitchell <[email protected]>
Date:   Wed May 29 10:32:41 2019 +0100

    Perl_scalar(): doc and reorganise complex bool
    
    The if statement that scans children applying void context to all except
    the last child:
    
    1) document what it does;
    2) reorganise it (without changing its logical meaning) to make it
    simpler to understand, and to make the next commit easier.

commit 5bc7c586697efe003cd469e35deda6eb20c8f098
Author: David Mitchell <[email protected]>
Date:   Tue May 28 15:25:48 2019 +0100

    Perl_scalar(): indent block
    
    .. that has just been wrapped in a while loop.
    Whitespace-only change.

commit 8b39054a7cd21a37003ed92bf4ed7ad9fbfbee2f
Author: David Mitchell <[email protected]>
Date:   Tue May 28 15:23:44 2019 +0100

    make Perl_scalar() mostly non-recursive
    
    Where it just recursively calls scalar() on all its children, instead
    iteratively walk the sub-tree, using o->op_sibparent to work back
    upwards.
    
    Where it is more complex, such as OP_REPEAT imposing scalar context on its
    first arg but not its second, recurse as before.

commit 471f9123e273b9d991bb5a9b543cf6f51115c82b
Author: David Mitchell <[email protected]>
Date:   Tue May 28 12:23:10 2019 +0100

    fix type in Perl_list()

commit c77cae4b762c33485a05d175d21ee5111ecea8f4
Author: David Mitchell <[email protected]>
Date:   Tue May 28 12:22:19 2019 +0100

    Perl_scalar(): re-order a few switch cases
    
    Just a cosmetic change.

commit 2f4520d895ee576b94d81381b57ddec1b0baeab4
Author: David Mitchell <[email protected]>
Date:   Tue May 28 12:19:23 2019 +0100

    Perl_scalar(): remove redundant switch labels
    
    Remove some explicit cases that just do the same as 'default:'

commit b2a25845ca7e6282163f56cc024727344f88bd22
Author: David Mitchell <[email protected]>
Date:   Tue May 28 12:17:12 2019 +0100

    Document what Perl_scalar() does
    
    and add blank lines for e.g. better readability between switch() cases.
    Also remove a lying /* FALLTHROUGH */

commit 9563d0db80589792d86488c5544e1f3571f3ac8d
Author: David Mitchell <[email protected]>
Date:   Tue Jun 18 15:11:12 2019 +0100

    Perl_list() tail-call optimise
    
    The part of this function that scans the children of e.g.
    
        @a = do { void; void; list }
    
    applying list context only to the last child, tail call optimise that
    call to list().
    
    (See also a few commits later entitled "Perl_scalar() tail-call
    optimise" for a discourse on setting PL_curcop (in)correctly.)

commit 4ee97c0aa3d674a464c6e8e11fad13b0edd00b54
Author: David Mitchell <[email protected]>
Date:   Wed May 29 11:22:48 2019 +0100

    Perl_list(): doc and reorganise complex bool
    
    The if statement that scans children applying void context to all except
    the last child:
    
    1) document what it does;
    2) reorganise it (without changing its logical meaning) to make the next
    commit easier.

commit 6693d42e7c8dfc934fceec5a18f0b57779b1d367
Author: David Mitchell <[email protected]>
Date:   Tue May 28 11:25:22 2019 +0100

    reindent Perl_list()
    
    The previous commit wrapped most of the body of this function in a while
    loop.

commit f7fe8a1eda421a6c983e7b0e2fdee8b88c7a151d
Author: David Mitchell <[email protected]>
Date:   Tue May 28 10:57:46 2019 +0100

    make Perl_list() mostly non-recursive
    
    Where it just recursively calls list() on all its children, instead
    iteratively walk the sub-tree, using o->op_sibparent to work back
    upwards.
    
    Where it is more complex, such as OP_REPEAT imposing list context on its
    first arg but not its second, recurse as before.

commit f0bc03a9f813aed1c20d2e5f65d7400a3c3ac47a
Author: David Mitchell <[email protected]>
Date:   Tue May 28 10:08:45 2019 +0100

    Perl_list(): re-order a few switch cases
    
    Just a cosmetic change.

commit c4e18218f2a7ee5139a49c7f9b3c89dd2e201e24
Author: David Mitchell <[email protected]>
Date:   Tue May 28 09:57:04 2019 +0100

    Perl_list(): re-order recursion in OP_LIST
    
    Call list() on an OP_LIST's children, *after* potentially nulling out
    the OP_LIST and an OP_PUSHMARK. This will make removing recursion
    easier. Should be no functional difference.

commit 969b3e85fb26a1601a6b0349abc48d38e2e358e3
Author: David Mitchell <[email protected]>
Date:   Wed May 22 11:31:06 2019 +0100

    Perl_list(): add blank lines
    
    ... between switch cases for readability.

commit a166adcb41cb2067685e58365cc63de8baddd859
Author: David Mitchell <[email protected]>
Date:   Wed May 22 11:27:20 2019 +0100

    Perl_list(): simplify some branches
    
    Remove some explicit cases that just do the same as 'default:'
    
    Also, remove OP_FLOP as a special case and just let it do the default.
    This is the same behaviour (apply list() to its one child), except
    that it also now does a harmless but (always false) check whether it's
    child is an OP_FLOP too.

commit 45e12159b954838d181308bb83fe5b91aaa29bf5
Author: David Mitchell <[email protected]>
Date:   Fri May 17 13:01:35 2019 +0100

    make S_gen_constant_list() void return
    
    Its gen_constant_list(o) returns an OP*, but the thing it returns is
    currently always o.
    
    So just assume it returns it arg.
    
    This will shortly make making Perl_list() non-recursive easier.

commit b30796c616c05baf85c2c246c3cd2fbff14cafb4
Author: David Mitchell <[email protected]>
Date:   Fri May 17 12:58:38 2019 +0100

    Document what Perl_list() and its helper do

commit ff17e0bc443454c6ea5c3840937b06f373f2c9a8
Author: David Mitchell <[email protected]>
Date:   Wed May 15 11:06:49 2019 +0100

    remove DEFER_OP macros from op.c
    
    the previous commit removed the last use of them

commit cfd8f9937696ba7625a8db5790a71407d5f3f11b
Author: David Mitchell <[email protected]>
Date:   Tue May 14 16:47:06 2019 +0100

    S_optimize_op(): remove anti-recursion deferring
    
    S_optimize_op() used to recursively work its way down an optree
    marking ops as being in the appropriate context.
    
    This commit removes the deferred mechanism, and instead makes use of the
    newish OP_PARENT mechanism to iterate over the optree, following each
    kid, then back up via the parent pointer to the next sibling etc.

commit 49c0e1428e8a24de57fe8d995dc545f805cda714
Author: David Mitchell <[email protected]>
Date:   Mon Apr 8 14:17:59 2019 +0100

    Make op_free() non-recursive
    
    Stop using the DEFER mechanism (which could leak if something croaks)
    and instead tree walk using the new OP_PARENT link to allow walking
    back up the tree.
    
    The freeing is done depth-first: children are freed before their
    parents.

commit f0fd1665f64427627478b6bc9b6da657ca92b41e
Author: David Mitchell <[email protected]>
Date:   Fri Apr 5 15:38:24 2019 +0100

    scalarvoid(): remove anti-recursion deferring
    
    Perl_scalarvoid() used to recursively work its way down an optree
    marking ops as being in the appropriate context.
    
    Around 5.22.0 the code was changed to avoid recursion, and instead to
    malloc a buffer (if necessary) to maintain a list of deferred child ops
    that need visiting. This stopped perl crashing if the optree (and thus
    the recursion) was too deep, but it introduced a potential leak.
    For example
    
        use warnings FATAL => qw(void);
        $a = "abc";
        length $a ;
    
    The fatal warning causes scalarvoid() to leak the deferred buffer.
    
    This commit removes the deferred mechanism, and instead makes use of the
    newish OP_PARENT mechanism to iterate over the optree, following each
    kid, then back up via the parent pointer to the next sibling etc.

-----------------------------------------------------------------------

-- 
Perl5 Master Repository

Reply via email to