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
