@@ -9672,6 +9672,17 @@ S_op_is_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
96729672 return CvXSUB(cv) == xsub;
96739673}
96749674
9675+ #define op_is_call_to_cv_xsub(o, xsub) S_op_is_call_to_cv_xsub(aTHX_ o, xsub)
9676+ static bool
9677+ S_op_is_call_to_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
9678+ {
9679+ if(o->op_type != OP_ENTERSUB)
9680+ return false;
9681+
9682+ OP *cvop = cLISTOPx(cUNOPo->op_first)->op_last;
9683+ return op_is_cv_xsub(cvop, xsub);
9684+ }
9685+
96759686/*
96769687=for apidoc newFOROP
96779688
@@ -9812,45 +9823,64 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont)
98129823 enteriterpflags |= OPpITER_DEF;
98139824 }
98149825
9815- if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
9816- expr = op_lvalue(op_force_list(scalar(ref(expr, OP_ITER))), OP_GREPSTART);
9817- enteriterflags |= OPf_STACKED;
9818- }
9819- else if (padoff != 0 && how_many_more == 1 && /* two lexical vars */
9820- expr->op_type == OP_ENTERSUB) {
9826+ if (padoff != 0 && how_many_more == 1 && /* two lexical vars */
9827+ op_is_call_to_cv_xsub(expr, &Perl_XS_builtin_indexed)) { /* expr is a call to builtin::indexed */
9828+ /* Turn the OP_ENTERSUB into a regular OP_LIST without the final CV,
9829+ * and set the OPpITER_INDEXED flag instead */
98219830 OP *args = cUNOPx(expr)->op_first;
98229831 assert(OP_TYPE_IS_OR_WAS(args, OP_LIST));
98239832
9824- OP *pre_firstarg = NULL;
9825- OP *firstarg = cLISTOPx(args)->op_first;
9826- OP *lastarg = cLISTOPx(args)->op_last;
9833+ OP *first = cLISTOPx(args)->op_first;
9834+ /* OP_PUSHMARK must remain */
9835+ assert(first->op_type == OP_PUSHMARK);
9836+ first = OpSIBLING(first);
98279837
9828- if(firstarg->op_type == OP_PUSHMARK)
9829- pre_firstarg = firstarg, firstarg = OpSIBLING(firstarg);
9830- if(firstarg == lastarg)
9831- firstarg = NULL;
9838+ OP *pre_last = NULL, *last = first;
9839+ while(OpHAS_SIBLING(last))
9840+ pre_last = last, last = OpSIBLING(last);
9841+ if(pre_last) {
9842+ /* splice out the final CV op */
9843+ cLISTOPx(args)->op_last = pre_last;
9844+ OpLASTSIB_set(pre_last, args);
98329845
9833- if (op_is_cv_xsub(lastarg, &Perl_XS_builtin_indexed) && /* a call to builtin::indexed */
9834- firstarg && OpSIBLING(firstarg) == lastarg && /* with one arg */
9835- (firstarg->op_type == OP_RV2AV || firstarg->op_type == OP_PADAV) /* ... which is an array */
9836- ) {
9837- /* Turn for my ($idx, $val) (indexed @arr) into a similar OPf_STACKED
9838- * loop on the array itself as the case above, plus a flag to tell
9839- * pp_iter to set the index directly
9840- */
9846+ op_free(last);
98419847
9842- /* Cut the array arg out of the args list and discard the rest of
9843- * the original expr
9844- */
9845- op_sibling_splice(args, pre_firstarg, 1, NULL);
9848+ last = pre_last;
9849+ }
9850+
9851+ if(first == last && (first->op_type == OP_PADAV || first->op_type == OP_RV2AV)) {
9852+ /* Preserve the ARRAY shortcut */
9853+ OpLASTSIB_set(cLISTOPx(args)->op_first, args);
98469854 op_free(expr);
98479855
9848- expr = op_lvalue(op_force_list(scalar(ref(firstarg, OP_ITER))), OP_GREPSTART);
9849- enteriterflags |= OPf_STACKED;
9850- iterpflags |= OPpITER_INDEXED;
9856+ OpLASTSIB_set(first, NULL);
9857+ expr = first;
98519858 }
9852- else
9853- goto expr_not_special;
9859+ else {
9860+ /* the op_targ slot contained the "was" op_type for an
9861+ * OP_NULL; clear it or op_free() will get very confused */
9862+ args->op_targ = 0;
9863+ OpTYPE_set(args, OP_LIST);
9864+ OpLASTSIB_set(args, NULL);
9865+
9866+ expr->op_flags &= ~OPf_KIDS;
9867+ cUNOPx(expr)->op_first = NULL;
9868+ op_free(expr);
9869+
9870+ expr = args;
9871+ }
9872+
9873+ /* expr's parent has currently been set to NULL, but that's OK. When
9874+ * it gets consumed by the LOOP* structure later to make the loop op
9875+ * itself this will get set correctly.
9876+ */
9877+
9878+ iterpflags |= OPpITER_INDEXED;
9879+ }
9880+
9881+ if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) {
9882+ expr = op_lvalue(op_force_list(scalar(ref(expr, OP_ITER))), OP_GREPSTART);
9883+ enteriterflags |= OPf_STACKED;
98549884 }
98559885 else if (expr->op_type == OP_NULL &&
98569886 (expr->op_flags & OPf_KIDS) &&
@@ -9882,7 +9912,6 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont)
98829912 enteriterflags |= OPf_STACKED;
98839913 }
98849914 else {
9885- expr_not_special:
98869915 expr = op_lvalue(op_force_list(expr), OP_GREPSTART);
98879916 }
98889917
0 commit comments