From: Nicholas Clark Date: Thu, 15 Jul 2004 12:47:50 +0000 (+0000) Subject: for (reverse @foo) now iterates in reverse in place. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e682d7b7fae5a50c5afb147f913a4e88d7261606;p=p5sagit%2Fp5-mst-13.2.git for (reverse @foo) now iterates in reverse in place. p4raw-id: //depot/perl@23115 --- diff --git a/op.c b/op.c index e9ea2e5..ea714eb 100644 --- a/op.c +++ b/op.c @@ -6719,7 +6719,7 @@ Perl_peep(pTHX_ register OP *o) } case OP_REVERSE: { - OP *ourmark, *theirmark, *ourlast, *iter, *expushmark; + OP *ourmark, *theirmark, *ourlast, *iter, *expushmark, *rv2av; OP *gvop = NULL; LISTOP *enter, *exlist; o->op_opt = 1; @@ -6786,6 +6786,15 @@ Perl_peep(pTHX_ register OP *o) if (!ourlast || ourlast->op_next != o) break; + rv2av = ourmark->op_sibling; + if (rv2av && rv2av->op_type == OP_RV2AV && rv2av->op_sibling == 0 + && rv2av->op_flags == (OPf_WANT_LIST | OPf_KIDS) + && enter->op_flags == (OPf_WANT_LIST | OPf_KIDS)) { + /* We're just reversing a single array. */ + rv2av->op_flags = OPf_WANT_SCALAR | OPf_KIDS | OPf_REF; + enter->op_flags |= OPf_STACKED; + } + /* We don't have control over who points to theirmark, so sacrifice ours. */ theirmark->op_next = ourmark->op_next; diff --git a/pod/perltodo.pod b/pod/perltodo.pod index 1560956..0c3e8d6 100644 --- a/pod/perltodo.pod +++ b/pod/perltodo.pod @@ -179,15 +179,6 @@ Clean these up. Move them to mathom.c, and don't compile for blead? The old perltodo notes "This has been done in places, but needs a thorough code review. Also fchdir is available in some platforms." -=head2 foreach reverse - -The old perltodo notes that we could optimise foreach to iterate in reverse. -(instead of making a reversed copy on the stack) -It seems that cx->blk_loop.itermax could be hijacked to act as a go up/go -down flag, with cx->blk_loop.iterix primed in pp_enteriter for the go down -case (ie reverse). However, it looks slightly tricky identifying the shape of -foreach reverse in the optree in Perl_peep. - =head1 Tests =head2 Make Schwern poorer diff --git a/pp_ctl.c b/pp_ctl.c index 1107ad9..0c1067a 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1811,7 +1811,7 @@ PP(pp_enteriter) } } else if (PL_op->op_private & OPpITER_REVERSED) { - cx->blk_loop.itermax = 0; + cx->blk_loop.itermax = -1; cx->blk_loop.iterix = AvFILL(cx->blk_loop.iterary); }