@@ -10884,7 +10884,9 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont)
1088410884 if (SvIV(rightsv)-SvIV(leftsv) <= PERL_MAX_UNROLL_LOOP_COUNT) {
1088510885 DEBUG_kv(Perl_deb(aTHX_ "TODO unroll loop (%" IVdf "..%" IVdf ")\n",
1088610886 SvIV(leftsv), SvIV(rightsv)));
10887- /* TODO easy with op_clone_oplist from feature/gh23-inline-subs|feature/gh311-opclone */
10887+ /* TODO use op_clone_optree, check the block body for itersv.
10888+ hard-code assignments to the itersv.
10889+ */
1088810890 }
1088910891#endif
1089010892 optype = OP_ITER_LAZYIV;
@@ -11556,6 +11558,26 @@ S_op_fixup(pTHX_ OP *old, OP *newop, U32 init) {
1155611558 return NULL;
1155711559}
1155811560
11561+ #define FIXUP(oa,field) \
11562+ if (((oa*)o)->op_##field) \
11563+ op_fixup(((oa*)o)->op_##field, ((oa*)clone)->op_##field, pass2+2)
11564+
11565+ #define OPCLONE(oa) \
11566+ if (!pass2) { \
11567+ NewOpSz(1102,clone,sizeof(oa)); \
11568+ if (!clone->op_slabbed) { \
11569+ memcpy(clone, o, sizeof(oa)); \
11570+ clone->op_slabbed = 0; \
11571+ } else { \
11572+ memcpy(clone, o, sizeof(oa)); \
11573+ } \
11574+ op_fixup(o, clone, 0); \
11575+ } else { \
11576+ clone = op_fixup(o, NULL, 4); \
11577+ } \
11578+ if (o->op_sibparent) \
11579+ op_fixup(o->op_sibparent, clone->op_sibparent, pass2+2)
11580+
1155911581/*
1156011582=for apidoc op_clone_oplist
1156111583
@@ -11564,7 +11586,8 @@ This is the opposite to C<cv_clone>, which clones that pads, but not the ops.
1156411586If C<last> == NULL, clones the whole sub (i.e. tree), otherwise until C<last>.
1156511587
1156611588Relinks all ops inside this list, but not the ones outside.
11567- TODO: Walking by list will miss op_other LOGOP branches.
11589+ TODO: Walking by list will miss op_other LOGOP branches. See rpeep
11590+ for the other logic.
1156811591We really should walk the tree (first, sibling).
1156911592
1157011593In the first pass visit and store all op_next pointers, and
@@ -11591,26 +11614,6 @@ Perl_op_clone_oplist(pTHX_ OP* o, OP* last, bool init) {
1159111614
1159211615 op_fixup(NULL, NULL, init?1:0); /* init the fixup cache */
1159311616
11594- #define FIXUP(oa,field) \
11595- if (((oa*)o)->op_##field) \
11596- op_fixup(((oa*)o)->op_##field, ((oa*)clone)->op_##field, pass2+2)
11597-
11598- #define OPCLONE(oa) \
11599- if (!pass2) { \
11600- NewOpSz(1102,clone,sizeof(oa)); \
11601- if (!clone->op_slabbed) { \
11602- memcpy(clone, o, sizeof(oa)); \
11603- clone->op_slabbed = 0; \
11604- } else { \
11605- memcpy(clone, o, sizeof(oa)); \
11606- } \
11607- op_fixup(o, clone, 0); \
11608- } else { \
11609- clone = op_fixup(o, NULL, 4); \
11610- } \
11611- if (o->op_sibparent) \
11612- op_fixup(o->op_sibparent, clone->op_sibparent, pass2+2)
11613-
1161411617 /* first pass: fixup and record all the next pointers, in exec order.
1161511618 second pass: the rest first, sibling, last, ... all pointers are now known */
1161611619 for (pass2=0; pass2<2; pass2++) {
@@ -11659,9 +11662,6 @@ Perl_op_clone_oplist(pTHX_ OP* o, OP* last, bool init) {
1165911662 case OA_SVOP:
1166011663 OPCLONE(SVOP);
1166111664 break;
11662- /*case OA_PADOP:
11663- OPCLONE(PADOP);
11664- break;*/
1166511665 case OA_PVOP_OR_SVOP:
1166611666 OPCLONE(PVOP);
1166711667 break;
@@ -11689,6 +11689,117 @@ Perl_op_clone_oplist(pTHX_ OP* o, OP* last, bool init) {
1168911689 }
1169011690 }
1169111691 }
11692+ return first;
11693+ }
11694+
11695+ /*
11696+ =for apidoc op_clone_optree
11697+
11698+ Clones just the op tree/graph, not the data.
11699+ This is the opposite to C<cv_clone>, which clones that pads, but not the ops,
11700+ and different to L</op_clone_oplist>, which walks just the list of op_next pointers.
11701+
11702+ Relinks all ops inside this list, but not the ones outside.
11703+
11704+ In the first pass visit and store all op_next pointers, and
11705+ store all the locations of the to be fixed up other pointers,
11706+ in the 2nd pass all pointers inside the graph are known, and
11707+ fixup the missing other pointers.
11708+
11709+ C<init> = TRUE will re-initialize the op cache.
11710+
11711+ Note that when op_clone_oplist is called outside of the first compiler
11712+ passes, the ops will not be slabbed. The third rpeep pass is already
11713+ to late.
11714+
11715+ =cut
11716+ */
11717+
11718+ OP*
11719+ Perl_op_clone_optree(pTHX_ OP* o, bool init) {
11720+ OP *clone = NULL, *prev = NULL, * first = NULL;
11721+ int pass2;
11722+ PERL_ARGS_ASSERT_OP_CLONE_OPTREE;
11723+
11724+ op_fixup(NULL, NULL, init?1:0); /* init the fixup cache */
11725+
11726+ /* first pass: fixup and record all the next pointers, in exec order.
11727+ second pass: the rest first, sibling, last, ... all pointers are now known */
11728+ for (pass2=0; pass2<2; pass2++) {
11729+ for (; o; o = OpSIBLING(o)) {
11730+ switch (OpCLASS(o->op_type)) {
11731+ case OA_BASEOP:
11732+ OPCLONE(OP);
11733+ break;
11734+ case OA_UNOP:
11735+ case OA_BASEOP_OR_UNOP:
11736+ case OA_FILESTATOP:
11737+ case OA_LOOPEXOP:
11738+ OPCLONE(UNOP);
11739+ FIXUP(UNOP,first);
11740+ break;
11741+ case OA_UNOP_AUX:
11742+ OPCLONE(UNOP_AUX);
11743+ FIXUP(UNOP,first);
11744+ break;
11745+ case OA_BINOP:
11746+ OPCLONE(BINOP);
11747+ FIXUP(BINOP,first);
11748+ FIXUP(BINOP,last);
11749+ break;
11750+ case OA_LISTOP:
11751+ OPCLONE(LISTOP);
11752+ FIXUP(LISTOP,first);
11753+ FIXUP(LISTOP,last);
11754+ break;
11755+ case OA_LOGOP:
11756+ OPCLONE(LOGOP);
11757+ FIXUP(LOGOP,first);
11758+ FIXUP(LOGOP,other);
11759+ break;
11760+ case OA_PMOP:
11761+ OPCLONE(PMOP);
11762+ FIXUP(PMOP,first);
11763+ FIXUP(PMOP,last);
11764+ break;
11765+ case OA_METHOP: /* 14 */
11766+ OPCLONE(METHOP);
11767+ if (o->op_private & 1) {
11768+ FIXUP(METHOP,u.op_first); /* dynamic */
11769+ }
11770+ break;
11771+ case OA_SVOP:
11772+ OPCLONE(SVOP);
11773+ break;
11774+ case OA_PVOP_OR_SVOP:
11775+ OPCLONE(PVOP);
11776+ break;
11777+ case OA_LOOP:
11778+ OPCLONE(LOOP);
11779+ FIXUP(LOOP,first);
11780+ FIXUP(LOOP,last);
11781+ FIXUP(LOOP,redoop);
11782+ FIXUP(LOOP,nextop);
11783+ FIXUP(LOOP,lastop);
11784+ break;
11785+ case OA_COP:
11786+ OPCLONE(COP);
11787+ break;
11788+
11789+ default:
11790+ assert(0 && !"op_clone_optree: missing OA_CLASS case");
11791+ }
11792+ if (!pass2) {
11793+ if (prev)
11794+ prev->op_next = clone;
11795+ else
11796+ first = clone;
11797+ prev = clone;
11798+ }
11799+ }
11800+ if (OpKIDS(o))
11801+ o = OpFIRST(o);
11802+ }
1169211803#undef OPCLONE
1169311804#undef FIXUP
1169411805 return first;
@@ -11824,7 +11935,7 @@ S_cv_do_inline(pTHX_ OP *o, OP *cvop, CV *cv, bool meth)
1182411935 /* we need to clone the optree, as we most likely change the state and args.
1182511936 Note: cv_clone is useless for us. It clones the pad, but not
1182611937 the ops. We need to keep the pads, but clone the ops. */
11827- o = op_clone_oplist(CvSTART (cv), NULL , TRUE);
11938+ o = op_clone_optree(CvROOT (cv), TRUE);
1182811939 firstop = o;
1182911940 /* XXX! walking by list will miss op_other LOGOP branches.
1183011941 we really should walk the tree (first-sibling) */
@@ -20540,14 +20651,6 @@ S_peep_leaveloop(pTHX_ BINOP* leave, OP* from, OP* to)
2054020651 if (IS_CONST_OP(from) && IS_CONST_OP(to)
2054120652 && SvIOK(fromsv = cSVOPx_sv(from)) && SvIOK(tosv = cSVOPx_sv(to)))
2054220653 {
20543- #ifdef DEBUGGING
20544- /* Unrolling is easier in newFOROP? */
20545- if (SvIV(tosv)-SvIV(fromsv) <= PERL_MAX_UNROLL_LOOP_COUNT) {
20546- DEBUG_kv(Perl_deb(aTHX_ "rpeep: possibly unroll loop (%" IVdf "..%" IVdf ")\n",
20547- SvIV(fromsv), SvIV(tosv)));
20548- /* TODO op_clone_oplist from feature/gh23-inline-subs|feature/gh311-opclone */
20549- }
20550- #endif
2055120654 /* 2. Check all aelem if can aelem_u */
2055220655 maxto = SvIV(tosv);
2055320656 }
@@ -23520,7 +23623,7 @@ S_add_isa_fields(pTHX_ HV* klass, AV* isa)
2352023623 char *key;
2352123624 I32 klen;
2352223625 /* wrong pad? */
23523- if (po > AvFILLp(comppad ) || !pn)
23626+ if (po > AvFILLp(PL_comppad ) || !pn)
2352423627 continue;
2352523628 key = PadnamePV(pn);
2352623629 if (!key)
@@ -23725,6 +23828,10 @@ S_add_does_methods(pTHX_ HV* klass, AV* does)
2372523828 CvGV_set(ncv, sym);
2372623829
2372723830 CvSTASH_set(ncv, klass);
23831+ CvROOT(ncv) = op_clone_optree(CvROOT(cv), TRUE);
23832+ CvSTART(ncv) = LINKLIST(CvROOT(ncv));
23833+ if (CvHASSIG(cv))
23834+ CvSIGOP(ncv) = (UNOP_AUX*)CvSTART(ncv)->op_next;
2372823835 if (CvPADLIST(cv)) {
2372923836 PADNAMELIST *pnl = PadlistNAMES(CvPADLIST(cv));
2373023837 pnl = cv_clone_padname0(cv, pnl);
0 commit comments