Skip to content

Commit 7d3bb7a

Browse files
committed
make Perl_op_linklist() non-recursive
1 parent 5e21b4f commit 7d3bb7a

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

op.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,37 +1600,58 @@ not be called directly.
16001600
=cut
16011601
*/
16021602

1603+
16031604
OP *
16041605
Perl_op_linklist(pTHX_ OP *o)
16051606
{
1607+
1608+
OP **prevp;
1609+
OP *kid;
1610+
OP * top_op = o;
1611+
16061612
PERL_ARGS_ASSERT_OP_LINKLIST;
16071613

1608-
if (o->op_next)
1609-
return o->op_next;
1614+
while (1) {
1615+
/* Descend down the tree looking for any unprocessed subtrees to
1616+
* do first */
1617+
if (!o->op_next) {
1618+
if (o->op_flags & OPf_KIDS) {
1619+
o = cUNOPo->op_first;
1620+
continue;
1621+
}
1622+
o->op_next = o; /* leaf node; link to self initially */
1623+
}
16101624

1611-
/* establish postfix order */
1612-
if (o->op_flags & OPf_KIDS) {
1613-
OP *kid;
1614-
OP *first = cUNOPo->op_first;
1615-
o->op_next = LINKLIST(first);
1616-
kid = first;
1617-
for (;;) {
1618-
OP *sibl = OpSIBLING(kid);
1619-
if (sibl) {
1620-
kid->op_next = LINKLIST(sibl);
1621-
kid = sibl;
1622-
} else {
1623-
kid->op_next = o;
1624-
break;
1625-
}
1626-
}
1627-
}
1628-
else
1629-
o->op_next = o;
1625+
/* if we're at the top level, there either weren't any children
1626+
* to process, or we've worked our way back to the top. */
1627+
if (o == top_op)
1628+
return o->op_next;
1629+
1630+
/* o is now processed. Next, process any sibling subtrees */
1631+
1632+
if (OpHAS_SIBLING(o)) {
1633+
o = OpSIBLING(o);
1634+
continue;
1635+
}
1636+
1637+
/* Done all the subtrees at this level. Go back up a level and
1638+
* link the parent in with all its (processed) children.
1639+
*/
16301640

1631-
return o->op_next;
1641+
o = o->op_sibparent;
1642+
assert(!o->op_next);
1643+
prevp = &(o->op_next);
1644+
kid = (o->op_flags & OPf_KIDS) ? cUNOPo->op_first : NULL;
1645+
while (kid) {
1646+
*prevp = kid->op_next;
1647+
prevp = &(kid->op_next);
1648+
kid = OpSIBLING(kid);
1649+
}
1650+
*prevp = o;
1651+
}
16321652
}
16331653

1654+
16341655
static OP *
16351656
S_scalarkids(pTHX_ OP *o)
16361657
{

0 commit comments

Comments
 (0)